Branch data Line data Source code
1 : : !!****m* ABINIT/m_argparse
2 : : !! NAME
3 : : !! m_argparse
4 : : !!
5 : : !! FUNCTION
6 : : !! Simple argument parser used in main programs
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 2008-2026 ABINIT group (MG)
10 : : !! This file is distributed under the terms of the
11 : : !! GNU General Public License, see ~abinit/COPYING
12 : : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : : !!
14 : : !! SOURCE
15 : :
16 : : #if defined HAVE_CONFIG_H
17 : : #include "config.h"
18 : : #endif
19 : :
20 : : #include "abi_common.h"
21 : :
22 : : module m_argparse
23 : :
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_errors
27 : : use m_xmpi
28 : : use m_xomp
29 : : use m_xieee
30 : : use m_abi_linalg
31 : : use m_fft
32 : : use m_exit
33 : : use m_clib
34 : : use m_nctk
35 : :
36 : : use m_build_info, only : dump_config, abinit_version
37 : : use m_io_tools, only : open_file, file_exists, enforce_fortran_io
38 : : use m_cppopts_dumper, only : dump_cpp_options
39 : : use m_optim_dumper, only : dump_optim
40 : : use m_fstrings, only : atoi, atof, itoa, firstchar, startswith, endswith, sjoin, find_and_select
41 : : use m_time, only : str2sec
42 : : use m_libpaw_tools, only : libpaw_log_flag_set
43 : : use m_ipi, only : ipi_setup
44 : :
45 : : implicit none
46 : :
47 : : private
48 : :
49 : : public :: get_arg ! Parse scalar argument from command line. Return exit code.
50 : :
51 : : interface get_arg
52 : : module procedure get_arg_int
53 : : module procedure get_arg_dp
54 : : module procedure get_arg_str
55 : : module procedure get_arg_bool
56 : : end interface get_arg
57 : :
58 : : public :: get_arg_list ! Parse array argument from command line. Return exit code.
59 : :
60 : : interface get_arg_list
61 : : module procedure get_arg_list_int
62 : : module procedure get_arg_list_dp
63 : : end interface get_arg_list
64 : :
65 : : public :: get_start_step_num ! Parse string from command line in the format "start:step:num"
66 : : ! defining an arithmetic progression.
67 : : public :: parse_kargs ! Parse command line arguments, return options related to k-point sampling
68 : : !!***
69 : :
70 : : !!****t* m_argparse/args_t
71 : : !! NAME
72 : : !! args_t
73 : : !!
74 : : !! FUNCTION
75 : : !! Stores command line options
76 : : !!
77 : : !! SOURCE
78 : :
79 : : type,public :: args_t
80 : :
81 : : integer :: exit = 0
82 : : ! /=0 to exit after having parsed the command line options.
83 : :
84 : : integer :: abimem_level = 0
85 : : ! Options for memory profiling. See m_profiling_abi
86 : :
87 : : integer :: dry_run = 0
88 : : ! /= 0 to exit after the validation of the input file.
89 : :
90 : : real(dp) :: abimem_limit_mb = 20.0_dp
91 : : ! Optional memory limit in Mb. used when abimem_level == 3
92 : :
93 : : character(len=500) :: cmdline = ""
94 : : ! The entire command line
95 : :
96 : : character(len=fnlen) :: input_path = ""
97 : :
98 : : !! Below are for multibinit
99 : : integer :: multibinit_F03_mode = 0
100 : : !1: legacy mode
101 : : !0: use full F03 implementation mode
102 : : ! TODO: It will be deprecated when everything is ready in and the new mode will be default.
103 : :
104 : : end type args_t
105 : :
106 : : public :: args_parser ! Parse command line options.
107 : : !!***
108 : :
109 : : contains
110 : :
111 : : !----------------------------------------------------------------------
112 : :
113 : : !!****f* m_argparse/args_parser
114 : : !! NAME
115 : : !! args_parser
116 : : !!
117 : : !! FUNCTION
118 : : !! Simple command line argument parser for abinit and other main programs.
119 : : !!
120 : : !! SOURCE
121 : :
122 : 1663 : type(args_t) function args_parser() result(args)
123 : :
124 : : !Local variables-------------------------------
125 : : integer :: ii, ierr, ntasks_per_node = -1
126 : : logical :: iam_master, verbose
127 : : real(dp) :: timelimit, memb_per_node = -one, memb_per_cpu = -one
128 : : character(len=500) :: arg !,msg
129 : :
130 : : ! *************************************************************************
131 : :
132 : 1663 : args%exit = 0; ierr=0; verbose = .False.
133 : :
134 : : #ifndef HAVE_FC_COMMAND_ARGUMENT
135 : : call wrtout(std_out,"get_command_argument is not supported by FC. Ignoring command lines options!")
136 : : return ! Nothing to do
137 : : #else
138 : :
139 [ + + ]: 1663 : if (command_argument_count() == 0) return
140 : :
141 : 1660 : iam_master = xmpi_comm_rank(xmpi_world) == 0
142 : :
143 : : ! Store full command line for future reference.
144 : 1660 : call get_command(args%cmdline)
145 : :
146 [ + + ]: 3335 : do ii=1,command_argument_count()
147 : 1675 : call get_command_argument(ii, arg)
148 : : !write(std_out,*)"arg", trim(arg)
149 : :
150 [ + + + + ]: 1675 : if (ii == 1 .and. .not. firstchar(arg, "-")) then
151 : : ! `abinit path` syntax reads input from path and deactivates files file mode.
152 : 1659 : args%input_path = trim(arg)
153 [ + + ]: 1659 : if (iam_master) then
154 [ - + ]: 1354 : ABI_CHECK(file_exists(args%input_path), sjoin("Cannot find input file:", args%input_path))
155 : : end if
156 : : cycle
157 : : end if
158 : :
159 [ + - - + ]: 1676 : if (arg == "-v" .or. arg == "--version") then
160 : 0 : call wrtout(std_out, trim(abinit_version))
161 : 0 : args%exit = args%exit + 1
162 : :
163 [ + + - + ]: 16 : else if (arg == "-b" .or. arg == "--build") then
164 : 1 : call print_kinds(unit=std_out)
165 : 1 : call xmpi_show_info(unit=std_out)
166 : 1 : call dump_cpp_options(std_out)
167 : 1 : call dump_config(std_out)
168 : 1 : call dump_optim(std_out)
169 : :
170 : 1 : args%exit = args%exit + 1
171 : :
172 [ + - + + ]: 15 : else if (arg == "-d" .or. arg == "--dry-run") then
173 : 1 : args%dry_run = 1
174 : :
175 [ - + ]: 14 : else if (arg == "--abimem-level") then
176 : 0 : call get_command_argument(ii + 1, arg)
177 : 0 : args%abimem_level = atoi(arg)
178 : :
179 [ - + ]: 14 : else if (arg == "--abimem-limit-mb") then
180 : 0 : call get_command_argument(ii + 1, arg)
181 : 0 : args%abimem_limit_mb = atof(arg)
182 : :
183 [ + - - + ]: 14 : else if (arg == "-j" .or. arg == "--omp-num-threads") then
184 : 0 : call get_command_argument(ii + 1, arg)
185 : 0 : call xomp_set_num_threads(atoi(arg))
186 : :
187 [ + - + + ]: 14 : else if (arg == "-t" .or. arg == "--timelimit") then
188 : : ! timelimit handler.
189 : 4 : call get_command_argument(ii + 1, arg)
190 : 4 : timelimit = str2sec(arg)
191 [ - + ]: 4 : if (timelimit < zero) then
192 : 0 : write(std_out,*)"Wrong timelimit argument: ",trim(arg)
193 : 0 : args%exit = args%exit + 1
194 : : else
195 : 4 : call exit_init(timelimit)
196 : : end if
197 : :
198 [ - + ]: 10 : else if (arg == "--ieee-halt") then
199 : : ! IEEE exceptions.
200 : 0 : call xieee_halt_ifexc(.True.)
201 : :
202 [ - + ]: 10 : else if (arg == "--ieee-signal") then
203 : 0 : call xieee_signal_ifexc(.True.)
204 : :
205 : 10 : else if (begins_with(arg, "--fft-ialltoall")) then
206 : : ! Enable/disable non-blocking ialltoall in MPI-FFT
207 : 0 : call fft_allow_ialltoall(parse_yesno(arg, "--fft-ialltoall"))
208 : :
209 : 10 : else if (begins_with(arg, "--ipi")) then
210 : 0 : call get_command_argument(ii + 1, arg)
211 : 0 : call ipi_setup(arg, xmpi_world)
212 : :
213 : 10 : else if (begins_with(arg, "--use-xgemm3m")) then
214 : : ! Enable/disable [Z,C]GEMM3
215 : 0 : call linalg_allow_gemm3m(parse_yesno(arg, "--use-xgemm3m"), write_msg=iam_master)
216 : :
217 : 10 : else if (begins_with(arg, "--use-mpi-in-place")) then
218 : : ! Enable/disable usage of MPI_IN_PLACE.
219 : 0 : call xmpi_set_inplace_operations(parse_yesno(arg, "--use-mpi-in-place"))
220 : :
221 : 10 : else if (begins_with(arg, "--plasma")) then
222 : : ! Enable/disable PLASMA
223 : 0 : call linalg_allow_plasma(parse_yesno(arg, "--plasma"))
224 : :
225 [ - + ]: 10 : else if (arg == "--gnu-mtrace") then
226 [ # # ]: 0 : if (iam_master) then
227 : 0 : call clib_mtrace(ierr)
228 [ # # ]: 0 : ABI_CHECK(ierr == 0, sjoin("clib_mtrace returned ierr:", itoa(ierr)))
229 : : end if
230 : :
231 [ - + ]: 10 : else if (arg == "--log") then
232 : : ! Enable logging
233 : 0 : call abi_log_status_state(new_do_write_log=.True., new_do_write_status=.True.)
234 : 0 : call libpaw_log_flag_set(.True.)
235 : :
236 [ - + ]: 10 : else if (arg == "--netcdf-classic") then
237 : : ! Use netcdf classic mode for new files when only sequential-IO needs to be performed
238 : 0 : call nctk_use_classic_for_seq()
239 : :
240 [ - + ]: 10 : else if (arg == "--enforce-fortran-io") then
241 : 0 : call enforce_fortran_io(.True.)
242 : :
243 : 10 : else if (begins_with(arg, "--mem-per-cpu=")) then
244 : 0 : memb_per_cpu = parse_slurm_mem(arg, "--mem-per-cpu=")
245 : 0 : call set_mem_per_cpu_mb(memb_per_cpu)
246 : :
247 : 10 : else if (begins_with(arg, "--mem=")) then
248 : 0 : memb_per_node = parse_slurm_mem(arg, "--mem=")
249 : :
250 : 10 : else if (begins_with(arg, "--ntasks-per-node=")) then
251 : 0 : call get_command_argument(ii + 1, arg)
252 : 0 : ntasks_per_node = atoi(arg)
253 : :
254 [ + + ]: 10 : else if (arg == "--F03") then
255 : : ! For multibinit only
256 : 6 : args%multibinit_F03_mode = 1
257 : :
258 [ + - - + ]: 4 : else if (arg == "-h" .or. arg == "--help") then
259 [ # # ]: 0 : if (iam_master) then
260 : : ! Document the options.
261 : 0 : write(std_out,*)"-v, --version Show version number and exit."
262 : 0 : write(std_out,*)"-b, --build Show build parameters and exit."
263 : 0 : write(std_out,*)"-d, --dry-run Validate input file and exit."
264 : 0 : write(std_out,*)"-j, --omp-num-threads Set the number of OpenMp threads."
265 : 0 : write(std_out,*)"--use-xgemm3m[=yesno] Use ZGEMM3M routines instead of ZGEMM. Default: no "
266 : 0 : write(std_out,*)"--use-mpi-in-place[=yesno] Enable/disable usage of MPI_IN_PLACE in e.g. xmpi_sum. Default: no"
267 : 0 : write(std_out,*)" Note that some MPI libs e.g. intel-mpi may not implement this feature"
268 : 0 : write(std_out,*)" correctly so it is adviced to test this option with e.g. structural"
269 : 0 : write(std_out,*)" relaxations before running production calculations."
270 : 0 : write(std_out,*)"--ipi Activate socket-driven calculation using i-pi protocol."
271 : 0 : write(std_out,*)" For UNIX socket, use: --ipi {unixsocket}:UNIX"
272 : 0 : write(std_out,*)" For INET socket, use --ipi {host}:{port}. Usage example:"
273 : 0 : write(std_out,*)" `abinit run.abi --ipi {unixsocket}:UNIX > run.log`"
274 : 0 : write(std_out,*)" NB: Requires ionmov 28 and some tuning of input variables. See:"
275 : 0 : write(std_out,*)" https://wiki.fysik.dtu.dk/ase/dev/ase/calculators/socketio/socketio.html"
276 : 0 : write(std_out,*)"--log Enable log files and status files in parallel execution."
277 : 0 : write(std_out,*)"--netcdf-classic Use netcdf classic mode for new files if parallel-IO is not needed."
278 : 0 : write(std_out,*)" Default is netcdf4/hdf5"
279 : 0 : write(std_out,*)"--enforce-fortran-io Use Fortran-IO instead of MPI-IO when operating on Fortran files"
280 : 0 : write(std_out,*)" Useful to read files when the MPI-IO library is not efficient."
281 : 0 : write(std_out,*)" DON'T USE this option when the code needs to write large files e.g. WFK"
282 : 0 : write(std_out,*)"-t, --timelimit Set the timelimit for the run. Accepts time in Slurm syntax:"
283 : 0 : write(std_out,*)" days-hours"
284 : 0 : write(std_out,*)" days-hours:minutes"
285 : 0 : write(std_out,*)" days-hours:minutes:seconds"
286 : 0 : write(std_out,*)" minutes"
287 : 0 : write(std_out,*)" minutes:seconds"
288 : 0 : write(std_out,*)" hours:minutes:seconds"
289 : 0 : write(std_out,*)" At present only GS, relaxations and MD runs support this option"
290 : 0 : write(std_out,*)"--mem-per-cpu=<size>[units] Set memory per cpu using Slurm syntax. Default units are megabytes."
291 : 0 : write(std_out,*)" Different units can be specified using the suffix [K|M|G|T]."
292 : 0 : write(std_out,*)"--mem=<size>[units] Set memory per node using Slurm syntax. Default units are megabytes."
293 : 0 : write(std_out,*)" Requires `ntasks-per-node`. Not compatibile with `-mem-per-cpu`."
294 : 0 : write(std_out,*)"--ntasks-per-node=INT Set number of tasks per node. Used in conjunction with --mem`"
295 : 0 : write(std_out,*)"--verbose Enable verbose mode in argparse"
296 : 0 : write(std_out,*)"-h, --help Show this help and exit."
297 : :
298 : 0 : write(std_out,*)""
299 : 0 : write(std_out,*)""
300 : 0 : write(std_out,*)"=============================="
301 : 0 : write(std_out,*)"=== Options for developers ==="
302 : 0 : write(std_out,*)"=============================="
303 : 0 : write(std_out,*)"--abimem-level NUM Set memory profiling level. Requires HAVE_MEM_PROFILING in config.h"
304 : 0 : write(std_out,*)" 0 -> no file abimem.mocc is created, only memory allocation counters running."
305 : 0 : write(std_out,*)" 1 -> light version. Only memory peaks are written."
306 : 0 : write(std_out,*)" 2 -> file abimem.mocc is created with full information inside."
307 : 0 : write(std_out,*)" 3 -> Write info only if allocation/deallocation is larger or smaller than limit_mb"
308 : 0 : write(std_out,*)" depending on of the sign of abimem-limit-mb."
309 : 0 : write(std_out,*)" NOTE: By default, only master node writes, use negative values to make all MPI procs write info to disk."
310 : 0 : write(std_out,*)"--abimem-limit-mb NUM Log malloc/free only if size > limit in Megabytes. Requires abimem-level 3"
311 : 0 : write(std_out,*)"--fft-ialltoall[=yesno] Use non-blocking ialltoall in MPI-FFT (used only if ndat > 1 and MPI2+)."
312 : 0 : write(std_out,*)"--gnu-mtrace Enable mtrace (requires GNU and clib)."
313 : 0 : write(std_out,*)"--ieee-halt Halt the code if one of the *usual* IEEE exceptions is raised."
314 : 0 : write(std_out,*)"--ieee-signal Signal the occurrence of the *usual* IEEE exceptions."
315 : : ! Multibinit
316 : 0 : write(std_out,*)"--F03 Run F03 mode (Multibinit only)."
317 : : end if
318 : 0 : args%exit = args%exit + 1
319 : :
320 [ + - ]: 4 : else if (arg == "--verbose") then
321 : 1675 : verbose = .True.
322 : :
323 : : else
324 [ - + ]: 4 : if (firstchar(arg, "-")) then
325 [ # # ]: 0 : ABI_WARNING("Unsupported option: "//trim(arg))
326 : 0 : args%exit = args%exit + 1
327 : : else
328 : : continue
329 : : end if
330 : : end if
331 : : end do
332 : :
333 [ + - - + ]: 1660 : if (ntasks_per_node /= -1 .or. memb_per_node /= -one) then
334 : : ! Set mem_per_cpu from node info.
335 [ # # ]: 0 : ABI_CHECK(ntasks_per_node /= -1, "`mem-per-node` requires `ntasks-per-node`")
336 [ # # ]: 0 : ABI_CHECK(memb_per_node /= -one, "`ntasks-per-node` requires `mem-per-node`")
337 [ # # ]: 0 : ABI_CHECK(memb_per_cpu == -one, "`mem-per-cpu` and `mem-per-node` are mutually exclusive!")
338 : 0 : call set_mem_per_cpu_mb(memb_per_node / ntasks_per_node)
339 : : end if
340 : :
341 : : #endif
342 : :
343 : 3323 : end function args_parser
344 : : !!***
345 : :
346 : : !!****f* m_argparse/begins_with
347 : : !! NAME
348 : : !! begins_with
349 : : !!
350 : : !! FUNCTION
351 : : !! Returns true if argument arg begins with string
352 : : !!
353 : : !! SOURCE
354 : :
355 : 80 : pure logical function begins_with(arg, string) result(bool)
356 : :
357 : : !Arguments ------------------------------------
358 : : character(len=*),intent(in) :: arg,string
359 : : ! *************************************************************************
360 : :
361 [ - + - + : 20 : bool = .False.; if (len(arg) >= len(string)) bool = (arg(1:len(string)) == string)
- + - + -
+ - + - +
- + - - ]
362 : :
363 : 0 : end function begins_with
364 : : !!***
365 : :
366 : : !----------------------------------------------------------------------
367 : :
368 : : !!****f* m_argparse/parse_yesno
369 : : !! NAME
370 : : !! parse_yesno
371 : : !!
372 : : !! FUNCTION
373 : : !! This function receives an argument, arg of the form --foo[=bool_value]
374 : : !! that begins with optname (i.e. --foo) and returns the value of bool_value
375 : : !! If bool_value is not present, returns default (.True. if not specified)
376 : : !!
377 : : !! SOURCE
378 : :
379 : 0 : logical function parse_yesno(arg, optname, default) result(bool)
380 : :
381 : : !Arguments ------------------------------------
382 : : character(len=*),intent(in) :: arg,optname
383 : : logical,optional,intent(in) :: default
384 : : ! *************************************************************************
385 : :
386 [ # # ]: 0 : bool = .True.; if (present(default)) bool = default
387 : :
388 : : ! Assume default if value is not given
389 [ # # ]: 0 : if (len_trim(optname) == len_trim(arg)) return
390 : :
391 : 0 : select case (arg(len(optname)+1:))
392 : : case ("=yes", "=y")
393 : 0 : bool = .True.
394 : : case ("=no", "=n")
395 : 0 : bool = .False.
396 : : case default
397 : 0 : write(std_out,*)"Wrong option ",trim(arg),". Will default to ",bool
398 [ # # # ]: 0 : ABI_ERROR("Aborting now")
399 : : end select
400 : :
401 : 0 : end function parse_yesno
402 : : !!***
403 : :
404 : : !----------------------------------------------------------------------
405 : :
406 : : !!****f* m_argparse/parse_slurm_mem
407 : : !! NAME
408 : : !! parse_slurm_mem
409 : : !!
410 : : !! FUNCTION
411 : : !! Parse `arg` string with memory given in Slurm syntax. Return value in Mb.
412 : : !! From https://slurm.schedmd.com/sbatch.html
413 : : !!
414 : : !! --mem=<size>[units]
415 : : !!
416 : : !! Default units are megabytes. Different units can be specified using the suffix [K|M|G|T].
417 : : !!
418 : : !! For a list of slurm env variables that can be used to pass options to Abinit via the submission script, see:
419 : : !! https://docs.hpc.shef.ac.uk/en/latest/referenceinfo/scheduler/SLURM/SLURM-environment-variables.html
420 : : !!
421 : : !! SOURCE
422 : :
423 : 0 : real(dp) function parse_slurm_mem(arg, optname) result(mem_mb)
424 : :
425 : : !Arguments ------------------------------------
426 : : character(len=*),intent(in) :: arg,optname
427 : :
428 : : !Local variables-------------------------------
429 : : integer :: istop, istat
430 : : real(dp) :: fact
431 : : character(len=500) :: iomsg
432 : : ! *************************************************************************
433 : :
434 : : fact = one
435 : : istop = find_and_select(arg, &
436 : : ["K", "M", "G", "T"], &
437 [ # # ]: 0 : [one/1024._dp, one, 1024._dp, 1024._dp ** 2], fact, iomsg, default=one)
438 : :
439 [ # # ]: 0 : ABI_CHECK(istop /= -1, iomsg)
440 [ # # ]: 0 : istop = merge(len_trim(arg), istop - 1, istop == 0)
441 : :
442 : 0 : read(arg(len(optname) + 1: istop), *, iostat=istat, iomsg=iomsg) mem_mb
443 [ # # ]: 0 : ABI_CHECK(istat == 0, sjoin("Invalid syntax for memory string:", arg, ch10, "iomsg", iomsg))
444 [ # # ]: 0 : ABI_CHECK(mem_mb > zero, "mem_mb must be positive!")
445 : 0 : mem_mb = mem_mb * fact
446 : :
447 : 0 : end function parse_slurm_mem
448 : : !!***
449 : :
450 : : !----------------------------------------------------------------------
451 : :
452 : : !!****f* m_argparse/get_arg_int
453 : : !! NAME
454 : : !! get_arg_int
455 : : !!
456 : : !! FUNCTION
457 : : !! Parse scalar argument from command line. Return exit code.
458 : : !!
459 : : !! INPUT
460 : : !! argname= Argument name
461 : : !! [default]= Default value.
462 : : !! [exclude]= argname and exclude are mutually exclusive.
463 : : !!
464 : : !! OUTPUT
465 : : !! argval= Value of argname
466 : : !! msg= Error message
467 : : !!
468 : : !! SOURCE
469 : :
470 : 65 : integer function get_arg_int(argname, argval, msg, default, exclude) result(ierr)
471 : :
472 : : !Arguments ------------------------------------
473 : : !scalars
474 : : character(len=*),intent(in) :: argname
475 : : integer,intent(out) :: argval
476 : : character(len=*),intent(out) :: msg
477 : : integer,optional,intent(in) :: default
478 : : character(len=*),optional,intent(in) :: exclude
479 : :
480 : : !Local variables-------------------------------
481 : : integer :: ii, istat
482 : : logical :: found_argname, found_excl
483 : : character(len=500) :: arg, iomsg
484 : :
485 : : ! *************************************************************************
486 : :
487 [ + - ]: 65 : ierr = 0; msg = ""; if (present(default)) argval = default
488 : 65 : found_argname = .False.; found_excl = .False.
489 : :
490 [ + + ]: 83 : do ii=1,command_argument_count()
491 : 18 : call get_command_argument(ii, arg)
492 [ + - ]: 18 : if (present(exclude)) then
493 [ # # ]: 0 : if (arg == "--" // trim(exclude)) found_excl = .True.
494 : : end if
495 [ - + ]: 83 : if (arg == "--" // trim(argname)) then
496 : 0 : found_argname = .True.
497 : 0 : call get_command_argument(ii + 1, arg, status=istat)
498 [ # # ]: 0 : if (istat == 0) then
499 : 0 : read(arg, *, iostat=istat, iomsg=iomsg) argval
500 [ # # ]: 0 : if (istat /= 0) then
501 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, iomsg)
502 : : end if
503 : : else
504 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, "Error in get_command_argument")
505 : : end if
506 : : end if
507 : : end do
508 : :
509 [ - + - - : 65 : if (ierr /= 0) msg = sjoin("Error while reading argument: ", argname, ch10, msg)
- - ]
510 [ - + ]: 65 : if (found_argname .and. found_excl) then
511 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin("Variables", argname, "and", exclude, "are mutually exclusive", ch10, msg)
512 : : end if
513 : :
514 [ + - ]: 65 : end function get_arg_int
515 : : !!***
516 : :
517 : : !!****f* m_argparse/get_arg_dp
518 : : !! NAME
519 : : !! get_arg_dp
520 : : !!
521 : : !! FUNCTION
522 : : !! Parse scalar argument from command line. Return exit code.
523 : : !!
524 : : !! INPUTS
525 : : !! argname= Argument name
526 : : !! [default]= Default value
527 : : !! [exclude]= argname and exclude are mutually exclusive.
528 : : !!
529 : : !! OUTPUT
530 : : !! argval= Value of argname
531 : : !! msg= Error message
532 : : !!
533 : : !! SOURCE
534 : :
535 : 44 : integer function get_arg_dp(argname, argval, msg, default, exclude) result(ierr)
536 : :
537 : : !Arguments ------------------------------------
538 : : !scalars
539 : : character(len=*),intent(in) :: argname
540 : : real(dp),intent(out) :: argval
541 : : character(len=*),intent(out) :: msg
542 : : real(dp),optional,intent(in) :: default
543 : : character(len=*),optional,intent(in) :: exclude
544 : :
545 : : !Local variables-------------------------------
546 : : integer :: ii, istat
547 : : logical :: found_argname, found_excl
548 : : character(len=500) :: arg, iomsg
549 : :
550 : : ! *************************************************************************
551 : :
552 [ + - ]: 44 : ierr = 0; msg = ""; if (present(default)) argval = default
553 : 44 : found_argname = .False.; found_excl = .False.
554 : :
555 [ - + ]: 44 : do ii=1,command_argument_count()
556 : 0 : call get_command_argument(ii, arg)
557 [ # # ]: 0 : if (present(exclude)) then
558 [ # # ]: 0 : if (arg == "--" // trim(exclude)) found_excl = .True.
559 : : end if
560 [ - - ]: 44 : if (arg == "--" // trim(argname)) then
561 : 0 : found_argname = .True.
562 : 0 : call get_command_argument(ii + 1, arg, status=istat)
563 [ # # ]: 0 : if (istat == 0) then
564 : 0 : read(arg, *, iostat=istat, iomsg=iomsg) argval
565 [ # # ]: 0 : if (istat /= 0) then
566 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, iomsg)
567 : : end if
568 : : else
569 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, "Error in get_command_argument")
570 : : end if
571 : : end if
572 : : end do
573 : :
574 [ - + - - : 44 : if (ierr /= 0) msg = sjoin("Error while reading argument: ", argname, ch10, msg)
- - ]
575 [ - + ]: 44 : if (found_argname .and. found_excl) then
576 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin("Variables", argname, "and", exclude, "are mutually exclusive", ch10, msg)
577 : : end if
578 : :
579 [ + - ]: 44 : end function get_arg_dp
580 : : !!***
581 : :
582 : : !----------------------------------------------------------------------
583 : :
584 : : !!****f* m_argparse/get_arg_str
585 : : !! NAME
586 : : !! get_arg_str
587 : : !!
588 : : !! FUNCTION
589 : : !! Parse scalar string argument from command line. Return exit code.
590 : : !!
591 : : !! INPUTS
592 : : !! argname= Argument name
593 : : !! [default]= Default value
594 : : !! [exclude]= argname and exclude are mutually exclusive.
595 : : !!
596 : : !! OUTPUT
597 : : !! argval= Value of argname
598 : : !! msg= Error message
599 : : !!
600 : : !! SOURCE
601 : :
602 : 0 : integer function get_arg_str(argname, argval, msg, default, exclude) result(ierr)
603 : :
604 : : !Arguments ------------------------------------
605 : : !scalars
606 : : character(len=*),intent(in) :: argname
607 : : character(len=*),intent(out) :: argval, msg
608 : : character(len=*),optional,intent(in) :: default
609 : : character(len=*),optional,intent(in) :: exclude
610 : :
611 : : !Local variables-------------------------------
612 : : integer :: ii, istat
613 : : logical :: found_argname, found_excl
614 : : character(len=500) :: arg
615 : :
616 : : ! *************************************************************************
617 : :
618 [ # # # # : 0 : ierr = 0; msg = ""; if (present(default)) argval = default
# # ]
619 : 0 : found_argname = .False.; found_excl = .False.
620 : :
621 [ # # ]: 0 : do ii=1,command_argument_count()
622 : 0 : call get_command_argument(ii, arg)
623 [ # # ]: 0 : if (present(exclude)) then
624 [ # # ]: 0 : if (arg == "--" // trim(exclude)) found_excl = .True.
625 : : end if
626 [ # # ]: 0 : if (arg == "--" // trim(argname)) then
627 : 0 : found_argname = .True.
628 : 0 : call get_command_argument(ii + 1, argval, status=istat)
629 [ # # ]: 0 : if (istat /= 0) then
630 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, "Error in get_command_argument")
631 : : end if
632 : : end if
633 : : end do
634 : :
635 [ # # # # : 0 : if (ierr /= 0) msg = sjoin("Error while reading argument: ", argname, ch10, msg)
# # ]
636 [ # # ]: 0 : if (found_argname .and. found_excl) then
637 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin("Variables", argname, "and", exclude, "are mutually exclusive", ch10, msg)
638 : : end if
639 : :
640 [ # # ]: 0 : end function get_arg_str
641 : : !!***
642 : :
643 : : !----------------------------------------------------------------------
644 : :
645 : : !!****f* m_argparse/get_arg_bool
646 : : !! NAME
647 : : !! get_arg_bool
648 : : !!
649 : : !! FUNCTION
650 : : !! Parse scalar boolean argument from command line. Return exit code.
651 : : !!
652 : : !! INPUTS
653 : : !! argname= Argument name
654 : : !! [default]= Default value
655 : : !! [exclude]= argname and exclude are mutually exclusive.
656 : : !!
657 : : !! OUTPUT
658 : : !! argval= Value of argname
659 : : !! msg= Error message
660 : : !!
661 : : !! SOURCE
662 : :
663 : 0 : integer function get_arg_bool(argname, argval, msg, default, exclude) result(ierr)
664 : :
665 : : !Arguments ------------------------------------
666 : : !scalars
667 : : character(len=*),intent(in) :: argname
668 : : logical,intent(out) :: argval
669 : : character(len=*),intent(out) :: msg
670 : : logical,optional,intent(in) :: default
671 : : character(len=*),optional,intent(in) :: exclude
672 : :
673 : : !Local variables-------------------------------
674 : : integer :: ii
675 : : logical :: found_argname, found_excl
676 : : character(len=500) :: arg
677 : :
678 : : ! *************************************************************************
679 : :
680 : 0 : ierr = 0; msg = ""; if (present(default)) argval = default
681 : 0 : found_argname = .False.; found_excl = .False.
682 : 0 : argval = .False.
683 : :
684 [ # # ]: 0 : do ii=1,command_argument_count()
685 : 0 : call get_command_argument(ii, arg)
686 [ # # ]: 0 : if (present(exclude)) then
687 [ # # ]: 0 : if (arg == "--" // trim(exclude)) found_excl = .True.
688 : : end if
689 [ # # ]: 0 : if (begins_with(arg, "--" // trim(argname))) then
690 : 0 : argval = parse_yesno(arg, "--" // trim(argname), default=.True.)
691 : 0 : found_argname = .True.
692 : : end if
693 : : end do
694 : :
695 : : if (ierr /= 0) msg = sjoin("Error while reading argument: ", argname, ch10, msg)
696 [ # # ]: 0 : if (found_argname .and. found_excl) then
697 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin("Variables", argname, "and", exclude, "are mutually exclusive", ch10, msg)
698 : : end if
699 : :
700 [ # # ]: 0 : end function get_arg_bool
701 : : !!***
702 : :
703 : : !----------------------------------------------------------------------
704 : :
705 : : !!****f* m_argparse/get_start_step_num
706 : : !! NAME
707 : : !! get_start_step_num
708 : : !!
709 : : !! FUNCTION
710 : : !! Parse string from command line in the format "start:step:num" defining an arithmetic progression.
711 : : !! Return exit code.
712 : : !!
713 : : !! INPUTS
714 : : !! argname= Argument name
715 : : !! [default]= Default value
716 : : !! [exclude]= argname and exclude are mutually exclusive.
717 : : !!
718 : : !! OUTPUT
719 : : !! ilist= [start, step, num]
720 : : !! msg= Error message
721 : : !!
722 : : !! SOURCE
723 : :
724 : 0 : integer function get_start_step_num(argname, ilist, msg, default, exclude) result(ierr)
725 : :
726 : : !Arguments ------------------------------------
727 : : !scalars
728 : : character(len=*),intent(in) :: argname
729 : : integer,intent(out) :: ilist(3)
730 : : character(len=*),intent(out) :: msg
731 : : integer,optional,intent(in) :: default(3)
732 : : character(len=*),optional,intent(in) :: exclude
733 : :
734 : : !Local variables-------------------------------
735 : : integer :: ii, jj
736 : : character(len=500) :: str
737 : :
738 : : ! *************************************************************************
739 : :
740 : 0 : if (present(exclude)) then
741 : 0 : ierr = get_arg_str(argname, str, msg, default="", exclude=exclude)
742 : : else
743 : 0 : ierr = get_arg_str(argname, str, msg, default="")
744 : : end if
745 [ # # ]: 0 : if (ierr /= 0) return
746 : :
747 [ # # ]: 0 : if (len_trim(str) == 0) then
748 [ # # ]: 0 : if (present(default)) then
749 : 0 : ilist = default
750 : : else
751 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin("Variables", argname, "is not found and default is not given")
752 : : end if
753 : 0 : return
754 : : end if
755 : :
756 : : ! We got a non-empty string. Let's parse it.
757 : 0 : ii = index(str, ":")
758 [ # # ]: 0 : if (ii <= 1) then
759 [ # # # # ]: 0 : msg = sjoin("Cannot find first `:` in string:", str)
760 : 0 : ierr = ierr + 1; return
761 : : end if
762 : 0 : ilist(1) = atoi(str(1:ii-1))
763 : :
764 : 0 : jj = index(str(ii+1:), ":")
765 [ # # ]: 0 : if (jj == 0) then
766 [ # # # # ]: 0 : msg = sjoin("Cannot find second `:` in string:", str)
767 : 0 : ierr = ierr + 1; return
768 : : end if
769 : :
770 : 0 : ilist(2) = atoi(str(ii+1: jj+ii-1))
771 : 0 : ilist(3) = atoi(str(jj+ii+1:))
772 : : !print *, "ilist:", ilist
773 : :
774 [ # # ]: 0 : end function get_start_step_num
775 : : !!***
776 : :
777 : : !!****f* m_argparse/get_arg_list_int
778 : : !! NAME
779 : : !! get_arg_list_int
780 : : !!
781 : : !! FUNCTION
782 : : !! Parse array argument from command line. Return exit code.
783 : : !!
784 : : !! INPUT
785 : : !! argname= Argument name
786 : : !! [default]= Default value (scalar)
787 : : !! [default_list]= Default value (vector)
788 : : !! [exclude]= argname and exclude are mutually exclusive.
789 : : !! [want_len]= Require want_len items in CLI.
790 : : !!
791 : : !! OUTPUT
792 : : !! argval= Value of argname
793 : : !! msg= Error message
794 : : !!
795 : : !! SOURCE
796 : :
797 [ # # # # : 0 : integer function get_arg_list_int(argname, argval, lenr, msg, default, default_list, exclude, want_len) result(ierr)
# # ]
798 : :
799 : : !Arguments ------------------------------------
800 : : !scalars
801 : : character(len=*),intent(in) :: argname
802 : : integer,intent(out) :: argval(:)
803 : : integer,intent(out) :: lenr
804 : : character(len=*),intent(out) :: msg
805 : : character(len=*),optional,intent(in) :: exclude
806 : : integer,optional,intent(in) :: default
807 : : integer,optional,intent(in) :: default_list(:)
808 : : integer,optional,intent(in) :: want_len
809 : :
810 : : !Local variables-------------------------------
811 : : integer :: ii, istat, iarg, maxlen
812 : : logical :: found_argname, found_excl
813 : : character(len=500) :: arg, iomsg
814 : :
815 : : ! *************************************************************************
816 : :
817 [ # # ]: 0 : ierr = 0; msg = ""; lenr = 0
818 : 0 : found_argname = .False.; found_excl = .False.
819 : :
820 : 0 : maxlen = size(argval);
821 [ # # ]: 0 : if (maxlen == 0) then
822 [ # # # # ]: 0 : ierr = ierr + 1; msg = "zero-sized argval!"; return
823 : : end if
824 : :
825 [ # # # # ]: 0 : if (present(default)) argval = default
826 [ # # # # ]: 0 : if (present(default_list)) argval = default_list
827 : :
828 [ # # ]: 0 : do ii=1,command_argument_count()
829 : 0 : call get_command_argument(ii, arg)
830 [ # # ]: 0 : if (present(exclude)) then
831 [ # # ]: 0 : if (arg == "--" // trim(exclude)) found_excl = .True.
832 : : end if
833 [ # # ]: 0 : if (arg == "--" // trim(argname)) then
834 : : ! Read list of values
835 : 0 : found_argname = .True.
836 [ # # ]: 0 : do iarg=1,maxlen
837 : 0 : call get_command_argument(ii + iarg, arg, status=istat)
838 [ # # ]: 0 : if (istat == 0) then
839 : : !write(std_out, *)"arg:", trim(arg)
840 [ # # ]: 0 : if (startswith(arg, "--")) exit
841 : 0 : read(arg,*, iostat=istat, iomsg=iomsg) argval(iarg)
842 [ # # ]: 0 : if (istat == 0) then
843 : 0 : lenr = lenr + 1
844 : : else
845 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, iomsg)
846 : : end if
847 : : else
848 : : ! If there are less than NUMBER arguments specified at the command line, VALUE will be filled with blanks.
849 [ # # ]: 0 : if (arg == "") exit
850 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, "Error in get_command_argument")
851 : : end if
852 : : end do
853 : : end if
854 : : end do
855 : :
856 [ # # # # : 0 : if (ierr /= 0) msg = sjoin("Error while reading argument: ", argname, ch10, msg)
# # ]
857 [ # # ]: 0 : if (found_argname .and. found_excl) then
858 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin("Variables", argname, "and", exclude, "are mutually exclusive", ch10, msg)
859 : : end if
860 : :
861 [ # # ]: 0 : if (present(want_len)) then
862 [ # # ]: 0 : if (found_argname) then
863 [ # # ]: 0 : if (want_len /= lenr) then
864 : 0 : ierr = ierr + 1
865 [ # # # # ]: 0 : msg = sjoin(argname, "requires", itoa(want_len), " tokens while found ", itoa(lenr), ch10, msg)
866 : : end if
867 : : else
868 : 0 : ierr = ierr + 1
869 [ # # # # ]: 0 : msg = sjoin("Cannot find --", argname, "option in CLI and want_len:", itoa(want_len), ch10, msg)
870 : : end if
871 : : end if
872 : :
873 [ # # ]: 0 : end function get_arg_list_int
874 : : !!***
875 : :
876 : : !----------------------------------------------------------------------
877 : :
878 : : !!****f* m_argparse/get_arg_list_dp
879 : : !! NAME
880 : : !! get_arg_list_dp
881 : : !!
882 : : !! FUNCTION
883 : : !!
884 : : !! INPUT
885 : : !! argname
886 : : !! [default]
887 : : !! [default_list]
888 : : !! [exclude]
889 : : !! [want_len]
890 : : !!
891 : : !! OUTPUT
892 : : !! argval
893 : : !! msg
894 : : !!
895 : : !! SOURCE
896 : :
897 [ # # # # : 0 : integer function get_arg_list_dp(argname, argval, lenr, msg, default, default_list, exclude, want_len) result(ierr)
# # ]
898 : :
899 : : !Arguments ------------------------------------
900 : : !scalars
901 : : character(len=*),intent(in) :: argname
902 : : real(dp),intent(out) :: argval(:)
903 : : integer,intent(out) :: lenr
904 : : character(len=*),intent(out) :: msg
905 : : character(len=*),optional,intent(in) :: exclude
906 : : real(dp),optional,intent(in) :: default
907 : : real(dp),optional,intent(in) :: default_list(:)
908 : : integer,optional,intent(in) :: want_len
909 : :
910 : : !Local variables-------------------------------
911 : : integer :: ii, istat, iarg, maxlen
912 : : logical :: found_argname, found_excl
913 : : character(len=500) :: arg, iomsg
914 : :
915 : : ! *************************************************************************
916 : :
917 [ # # ]: 0 : ierr = 0; msg = ""; lenr = 0
918 : 0 : found_argname = .False.; found_excl = .False.
919 : :
920 : 0 : maxlen = size(argval);
921 [ # # ]: 0 : if (maxlen == 0) then
922 [ # # # # ]: 0 : ierr = ierr + 1; msg = "zero-sized argval!"; return
923 : : end if
924 : :
925 [ # # # # ]: 0 : if (present(default)) argval = default
926 [ # # # # ]: 0 : if (present(default_list)) argval = default_list
927 : :
928 [ # # ]: 0 : do ii=1,command_argument_count()
929 : 0 : call get_command_argument(ii, arg)
930 [ # # ]: 0 : if (present(exclude)) then
931 [ # # ]: 0 : if (arg == "--" // trim(exclude)) found_excl = .True.
932 : : end if
933 [ # # ]: 0 : if (arg == "--" // trim(argname)) then
934 : : ! Read list of values
935 : 0 : found_argname = .True.
936 [ # # ]: 0 : do iarg=1,maxlen
937 : 0 : call get_command_argument(ii + iarg, arg, status=istat)
938 [ # # ]: 0 : if (istat == 0) then
939 : : !write(std_out, *)"arg:", trim(arg)
940 [ # # ]: 0 : if (startswith(arg, "--")) exit
941 : 0 : read(arg,*, iostat=istat, iomsg=iomsg) argval(iarg)
942 [ # # ]: 0 : if (istat == 0) then
943 : 0 : lenr = lenr + 1
944 : : else
945 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, iomsg)
946 : : end if
947 : : else
948 : : ! If there are less than NUMBER arguments specified at the command line, VALUE will be filled with blanks.
949 [ # # ]: 0 : if (arg == "") exit
950 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin(msg, ch10, "Error in get_command_argument")
951 : : end if
952 : : end do
953 : : end if
954 : : end do
955 : :
956 [ # # # # : 0 : if (ierr /= 0) msg = sjoin("Error while reading argument: ", argname, ch10, msg)
# # ]
957 [ # # ]: 0 : if (found_argname .and. found_excl) then
958 [ # # # # ]: 0 : ierr = ierr + 1; msg = sjoin("Variables", argname, "and", exclude, "are mutually exclusive", ch10, msg)
959 : : end if
960 : :
961 [ # # ]: 0 : if (present(want_len)) then
962 [ # # ]: 0 : if (found_argname) then
963 [ # # ]: 0 : if (want_len /= lenr) then
964 : 0 : ierr = ierr + 1
965 [ # # # # ]: 0 : msg = sjoin(argname, "requires", itoa(want_len), " tokens while found ", itoa(lenr), ch10, msg)
966 : : end if
967 : : else
968 : 0 : ierr = ierr + 1
969 [ # # # # ]: 0 : msg = sjoin("Cannot find --", argname, " option in CLI and want_len:", itoa(want_len), ch10, msg)
970 : : end if
971 : : end if
972 : :
973 [ # # ]: 0 : end function get_arg_list_dp
974 : : !!***
975 : :
976 : : !----------------------------------------------------------------------
977 : :
978 : : !!****f* ABINIT/parse_kargs
979 : : !! NAME
980 : : !! parse_kargs
981 : : !!
982 : : !! FUNCTION
983 : : !! Parse command line arguments, return options related to k-point sampling
984 : : !!
985 : : !! INPUTS
986 : : !!
987 : : !! OUTPUT
988 : : !!
989 : : !! SOURCE
990 : :
991 : 0 : subroutine parse_kargs(kptopt, kptrlatt, nshiftk, shiftk, chksymbreak)
992 : :
993 : : !Arguments ------------------------------------
994 : : integer,intent(out) :: kptopt, nshiftk, chksymbreak
995 : : integer,intent(out) :: kptrlatt(3,3)
996 : : real(dp),allocatable,intent(out) :: shiftk(:,:)
997 : :
998 : : !Local variables-------------------------------
999 : : integer :: ii, lenr, ierr
1000 : : character(len=500) :: msg
1001 : : integer :: ivec9(9), ngkpt(3)
1002 : : real(dp) :: my_shiftk(3 * MAX_NSHIFTK)
1003 : :
1004 : : ! *************************************************************************
1005 : :
1006 [ # # ]: 0 : ABI_CHECK(get_arg("kptopt", kptopt, msg, default=1) == 0, msg)
1007 [ # # ]: 0 : ABI_CHECK(get_arg("chksymbreak", chksymbreak, msg, default=1) == 0, msg)
1008 : :
1009 : 0 : ierr = get_arg_list("ngkpt", ngkpt, lenr, msg, exclude="kptrlatt", want_len=3)
1010 [ # # ]: 0 : if (ierr == 0) then
1011 : : !if (lenr == 3) then
1012 : 0 : kptrlatt = 0
1013 [ # # ]: 0 : do ii=1,3
1014 : 0 : kptrlatt(ii, ii) = ngkpt(ii)
1015 : : end do
1016 : : else
1017 [ # # ]: 0 : ABI_CHECK(get_arg_list("kptrlatt", ivec9, lenr, msg, exclude="ngkpt", want_len=9) == 0, msg)
1018 [ # # ]: 0 : ABI_CHECK(lenr == 9, "Expecting 9 values for kptrlatt")
1019 [ # # # # ]: 0 : kptrlatt = transpose(reshape(ivec9, [3, 3]))
1020 : : end if
1021 : :
1022 : : ! Init default
1023 [ # # ]: 0 : ABI_CHECK(get_arg_list("shiftk", my_shiftk, lenr, msg) == 0, msg)
1024 [ # # ]: 0 : if (lenr /= 0) then
1025 [ # # ]: 0 : ABI_CHECK(mod(lenr, 3) == 0, "Expecting 3 * nshift array")
1026 : 0 : nshiftk = lenr / 3
1027 [ # # # # : 0 : ABI_MALLOC(shiftk, (3, nshiftk))
# # # # #
# # # #
# ]
1028 [ # # # # : 0 : shiftk = reshape(my_shiftk(1:lenr), [3, nshiftk])
# # # # ]
1029 : : else
1030 : 0 : nshiftk = 1
1031 [ # # # # : 0 : ABI_CALLOC(shiftk, (3, nshiftk))
# # # # ]
1032 : : !shiftk(:, 1) = [half, half, half]
1033 : : end if
1034 : : !write(std_out, *)"kptopt = ", kptopt, ", chksymbreak = ", chksymbreak, ", nshiftk = ", nshiftk, ", kptrlatt = ", kptrlatt
1035 : :
1036 : 0 : end subroutine parse_kargs
1037 : : !!***
1038 : :
1039 : 0 : end module m_argparse
1040 : : !!***
|