Skip to content

6. Validation ​

A simulation that fails after an hour because of a typo in a file name is a wasted hour. heat checks its command line before doing anything.

f90
! the initial condition: exactly one of an analytical field or a restart file, which must be readable
call cli%add(switch='--init', help='Initial field', required=.false., act='store', def='', choices='gauss,step')
call cli%add(switch='--restart', help='Restart file', required=.false., act='store', def='', readable=.true., &
             metavar='FILE')
call cli%set_mutually_exclusive_switches(switches='--init,--restart', required=.true.)
call cli%add(switch='--nx', help='Cells along each direction (even)', required=.false., act='store', def='64')
! an old option, still accepted with a warning
call cli%add(switch='--dt', help='Time step', required=.false., act='store', def='0', deprecated='use --cfl')
! an auxiliary action: works without the required options
call cli%add(switch='--list-schemes', help='List the time schemes and exit', act='alternate')
  • The initial field comes from exactly one of --init and --restart: a required mutually exclusive set.
  • readable=.true. makes parse check that the restart file exists and can be read.
  • --dt is deprecated: still accepted, with a warning.
  • --list-schemes is an alternate action: parse returns STATUS_ALTERNATE, skipping the value checks, so it works without --init.
  • usage_on_error='usage' (in init) prints the usage line after a missing option, instead of the whole help.
f90
! after an error, print the usage line rather than the whole help
call cli%init(progname='heat', version='v0.6', description='Solve the 2D heat equation on a square plate', &
              usage_on_error='usage')
f90
call cli%parse(error=error)
if (error == STATUS_ALTERNATE) then
  print '(A)', 'fe: explicit Euler (cfl <= 0.5)'
  print '(A)', 'cn: Crank-Nicolson (any cfl)'
  stop
endif
if (error /= 0) stop 1, quiet=.true.
! a check only the program can do, reported in FLAP's style
call cli%get(switch='--nx', val=nx, error=error)
if (mod(nx, 2) /= 0) error = cli%raise_error('must be even', switch='--nx', show_usage=.false.)
if (error /= 0) stop 1, quiet=.true.

The checks at work ​

$ heat --init gauss --nx 64
heat: nx 64
$ heat --restart heat.h5 --nx 64
heat: nx 64
$ heat --nx 64
heat: error: one of "--init", "--restart" is required!

usage: heat (--init value | --restart FILE) [--nx value] [--dt value] [--list-schemes] [--help] [--markdown] [--version]
Try 'heat --help' for help.
[exit status 1]
$ heat --init gauss --restart heat.h5
heat: error: switches "--init", "--restart" are mutually exclusive!

usage: heat (--init value | --restart FILE) [--nx value] [--dt value] [--list-schemes] [--help] [--markdown] [--version]
Try 'heat --help' for help.
[exit status 1]
$ heat --restart haet.h5
heat: error: option "--restart": path "haet.h5" does not exist!

Try 'heat --help' for help.
[exit status 1]
$ heat --init gauss --dt 0.1
heat: warning: option "--dt" is deprecated: use --cfl
heat: nx 64
$ heat --list-schemes
fe: explicit Euler (cfl <= 0.5)
cn: Crank-Nicolson (any cfl)

A check only the program knows (--nx must be even) is reported with raise_error, in FLAP's style:

$ heat --init gauss --nx 63
heat: error: switch "--nx": must be even

[exit status 1]

What you learned

Exclusive sets, path checks, deprecations, alternate actions, raise_error, usage_on_error. Reference: Advanced Features, Error Codes.

Next: 7. Shipping it.