Skip to content

2. Options of every kind ​

A real solver needs more than numbers: a choice of scheme, a stability limit, a verbosity level, an optional output.

f90
call cli%add(switch='--nx', help='Cells along each direction', required=.false., act='store', def='64', metavar='N')
call cli%add(switch='--steps', help='Time steps', required=.false., act='store', def='100', metavar='N')
! a range: the explicit scheme is stable for cfl <= 0.5
call cli%add(switch='--cfl', help='CFL number', required=.false., act='store', def='0.25', metavar='CFL', &
             min='0', min_open=.true., max='0.5')
! choices, in any case: CN is cn
call cli%add(switch='--scheme', switch_ab='-s', help='Time scheme: explicit Euler or Crank-Nicolson', required=.false., &
             act='store', def='fe', choices='fe,cn', case_sensitive=.false.)
! a clamped range: more threads than cores are pointless
call cli%add(switch='--threads', help='OpenMP threads', required=.false., act='store', def='1', min='1', max='64', &
             clamp=.true.)
! a counter: -v, -vv, -v -v ...
call cli%add(switch='--verbose', switch_ab='-v', help='Verbosity (repeatable)', required=.false., act='count')
! an optional value: --save alone saves in the default format
call cli%add(switch='--save', help='Save the solution (format: vtk, csv)', required=.false., act='store*', def='vtk', &
             choices='vtk,csv')
OptionWhat it shows
--nx, --steps, --cflmetavar: the placeholder of the value in the help (N, CFL instead of value)
--cfla numeric range, (0, 0.5]: the explicit scheme is unstable above 0.5
--schemechoices, matched in any case (case_sensitive=.false.), with an abbreviation -s
--threadsa clamped range: 1000 threads become 64, without an error
--verbosea counter (act='count'): -v, -vv, -v -v
--savean optional value (act='store*'): --save alone uses the default format

The values are read as before; is_passed tells whether an option was on the command line:

f90
call cli%get(switch='--nx', val=nx, error=error)           ; if (error /= 0) stop 1, quiet=.true.
call cli%get(switch='--steps', val=steps, error=error)     ; if (error /= 0) stop 1, quiet=.true.
call cli%get(switch='--cfl', val=cfl, error=error)         ; if (error /= 0) stop 1, quiet=.true.
call cli%get(switch='--scheme', val=scheme, error=error)   ; if (error /= 0) stop 1, quiet=.true.
call cli%get(switch='--threads', val=threads, error=error) ; if (error /= 0) stop 1, quiet=.true.
call cli%get(switch='--verbose', val=verbose, error=error) ; if (error /= 0) stop 1, quiet=.true.
call cli%get(switch='--save', val=save, error=error)       ; if (error /= 0) stop 1, quiet=.true.
saving = cli%is_passed(switch='--save')
$ heat -vv --scheme CN --cfl 0.4 --nx 100
heat: 100x100 cells, 100 steps, cfl 0.40, scheme cn
threads 1, verbosity 2
$ heat --threads 1000 --save
heat: 64x64 cells, 100 steps, cfl 0.25, scheme fe
threads 64, verbosity 0
saving the solution as vtk

CN became cn, the declared spelling: the program compares with one spelling only. The help shows every rule:

$ heat --help
usage: heat [--nx N] [--steps N] [--cfl CFL] [--scheme value] [--threads value] [--verbose]... [--save [value]] [--help] [--markdown] [--version]

Solve the 2D heat equation on a square plate

Optional switches:
  --nx N
      default value 64
      Cells along each direction
  --steps N
      default value 100
      Time steps
  --cfl CFL
      range (0, 0.5]
      default value 0.25
      CFL number
  --scheme value, -s value
      choices: fe, cn
      default value fe
      Time scheme: explicit Euler or Crank-Nicolson
  --threads value
      range [1, 64]
      default value 1
      OpenMP threads
  --verbose, -v
      default value 0
      Verbosity (repeatable)
  --save [value]
      choices: vtk, csv
      default value vtk
      Save the solution (format: vtk, csv)
  --help, -h
      Print this help message
  --markdown, -md
      Save this help message in a Markdown file
  --version
      Print version

Since -v is now --verbose, the builtin --version keeps only its long name.

When a value breaks a rule ​

Choices and ranges are checked by get, when the value is converted:

$ heat --scheme euler
heat: error: value of named option "--scheme" must be chosen in: (fe,cn) but "euler" has been passed!

[exit status 1]
$ heat --cfl 0.8
heat: error: value "0.8" of "--cfl" is out of range (0, 0.5]!

[exit status 1]

What you learned

Choices, ranges and clamping, counters, optional values, placeholders, is_passed. Reference: Defining Arguments, Numeric ranges.

Next: 3. Lists and parameters.