Version 10 (modified by acc, 2 months ago) (diff)

Namelist Integrity checks

Misplaced or mis-spelt variables in configuration namelist files can be a source of frustration when porting configurations used with older releases of NEMO to more modern versions. The code will report these occurrences and stop during start-up; but only one instance is reported each time. Finding them all this way can be a time-consuming business. Part 1 of this page details a simple Python script which can be used to find mis-matches between a configuration namelist and its reference counterpart before attempting to run the model.

For most users, this should be sufficient but developers of new features have the added uncertainty of not knowing if the reference namelist correctly contains all the namelist options available in the code. Part 2 of this page suggests further tools which can can construct a 'pseudo reference namelist' by parsing the fortran code base. The actual reference namelist and the 'pseudo' version can then be used with the integrity checker from part 1. By using the integrity checker twice, with the roles of the two namelists swapped, it is possible to confirm that:

  • The actual reference namelist is compatible with the code base
  • The actual reference namelist contains examples of all the namelist variables defined in the code base.

All the scripts mentioned are attached to this page.

Part 1 Integrity checker

If we assume the following conventions for NEMO namelists:

  • namelists are started with &name_of_namelist appearing as the first non-whitespace on a line (and not followed by anything other than an optional comment)
  • Only one variable is set on each line
  • namelists are closed with / appearing as the first non-whitespace on a line

then the attached nemo_nml_check.py script will:

  • read supplied namelist files
  • construct lists of namelist blocks and their contents (the latter being a list of lists)
  • compare the contents lists for matching named blocks to confirm membership
  • report any mis-matches together with the line number in the configuration namelist
  • where possible, suggest close matches that may indicate typos

By default, the script will compare namelist_cfg and namelist_ref from the current directory. Alternative pairs can be named using the -c and -r command-line options:

python nemo_nml_check.py --help
usage: nemo_nml_check.py [-h] [--cfg [CFGFILE]]  [--ref [REFFILE]]

Check for consistency between cfg namelists and ref versions e.g. 
python nemo_nml_check.py --cfg <cfg namelist> --ref <ref namelist>

optional arguments:
  -h, --help            show this help message and exit
  --cfg [CFGFILE], -c [CFGFILE]  configuration namelist
  --ref [REFFILE], -r [REFFILE]  reference namelist
  --match [MFACTOR], -m [MFACTOR]   closeness factor (0-1)

A typical example of an error found between the default pairing is:

python nemo_nml_check.py
No match in matching blocks for:                           |  Possible close match:
rn_rdt                 in namdom       (at line no.   39)  |  rn_dt

and a quick check in the namelist_ref file will confirm that this is because rn_rdt has been renamed as rn_Dt.

Part 2 Constructing a pseudo-reference namelist

Parsing the source code to extract information to build a pseudo reference namelist is simpler if we assume adherence to some coding conventions:

  • The namelist opening declaration: namelist / name_of_namelist / occurs on one line
  • The name_of_namelist string contains only alphanumeric characters and underscores
  • subsequent continuation lines have a leading ampersand and a trailing ampersand is placed on the preceding line (comments are allowed after the trailing ampersand)

With these (seemingly safe) assumptions the attached Perl script: nemo_list_nmls.pl can be used to extract namelist templates from the source. For example:

perl nemo_list_nmls.pl OCE/nemogcm.F90
&namctl
  ln_ctl =
  sn_cfctl =
  nn_print =
  nn_ictls =
  nn_ictle =
  nn_isplt =
  nn_jsplt =
  nn_jctls =
  nn_jctle =
  ln_timing =
  ln_diacfl =
/
&namcfg
  ln_read_cfg =
  cn_domcfg =
  ln_closea =
  ln_write_cfg =
  cn_domcfg_out =
  ln_use_jattr =
/

Combined with a few lines of bash, this can be used to construct a pseudo-namelist_ref:

for f in `find ./OCE -name '*.[Fh]90'`
do
  echo "! "$f >> pseudo_nml_ref
  perl nemo_list_nmls.pl $f >> pseudo_nml_ref
done

(this does assume scanning OCE is sufficient; how about OFF, SAS etc.?)

Part 3 Checking reference namelist and source compatibility

The pseudo-namelist_ref produced this way should contain all the variables that can be set via namelists (at least for the 'blue ocean'). Treating the actual namelist_ref as a configuration namelist and checking its integrity against the pseudo version should confirm the validity of everything in the reference namelist.

Update:There is at least one namelist declared in the code with multiple declarations, namely:

      NAMELIST/nambdy_dta/ cn_dir, bn_tem, bn_sal, bn_u3d, bn_v3d, bn_ssh, bn_u2d, bn_v2d
      NAMELIST/nambdy_dta/ bn_a_i, bn_h_i, bn_h_s, bn_t_i, bn_t_s, bn_tsu, bn_s_i, bn_aip, bn_hip
      NAMELIST/nambdy_dta/ rn_ice_tem, rn_ice_sal, rn_ice_age, rn_ice_apnd, rn_ice_hpnd
      NAMELIST/nambdy_dta/ ln_full_vel, ln_zinterp

The Perl script has been adapted to handle this but each entry will appear in the pseudo file as a separate block. These blocks should be combined by hand into a single block before running the integrity checks.

Surprisingly a few variables are flagged even for a fresh copy of r4.0-HEAD (Rev: 13029):

python nemo_nml_check.py -r pseudo_nml_ref -c namelist_ref -m 0.75
No match in matching blocks for:                           |  Possible close match:
sn_wnum                in namsbc_wave  (at line no.  497)  |  sn_wmp
sn_tauwoc              in namsbc_wave  (at line no.  498)  |
sn_tauwx               in namsbc_wave  (at line no.  499)  |
sn_tauwy               in namsbc_wave  (at line no.  500)  |
clname(1)              in nam_tide     (at line no.  581)  |  clname
tname(1)               in nam_diaharm  (at line no. 1188)  |  tname
tname(2)               in nam_diaharm  (at line no. 1189)  |  tname
sn_cfctl%l_config      in namctl       (at line no. 1322)  |
sn_cfctl%l_runstat     in namctl       (at line no. 1323)  |
sn_cfctl%l_trcstat     in namctl       (at line no. 1324)  |
sn_cfctl%l_oceout      in namctl       (at line no. 1325)  |
sn_cfctl%l_layout      in namctl       (at line no. 1326)  |
sn_cfctl%l_mppout      in namctl       (at line no. 1327)  |
sn_cfctl%l_mpptop      in namctl       (at line no. 1328)  |
sn_cfctl%procmin       in namctl       (at line no. 1329)  |
sn_cfctl%procmax       in namctl       (at line no. 1330)  |
sn_cfctl%procincr      in namctl       (at line no. 1331)  |
sn_cfctl%ptimincr      in namctl       (at line no. 1332)  |

It is probably the case that the structure variables flagged (sn_*) are false positives. This is because only the structure name is declared in the namelist but individual members of the structure may be (and are) set in the namelist_ref. Nonetheless, there are a few normal variables to investigate and this does illustrate the potential usefulness of this tool. Note, the 'possible close matches' are provided by a simple string comparator. By default, only matches exceeding a closeness factor of 0.75 are reported. More (or fewer) possibilities can be provided by decreasing (or increasing) this factor between 0 and 1. This is done by providing the additional command line argument '-m fatc' as shown here (although it was unnecessary since 0.75 is the default value).

Secondly, reversing the roles of the input namelists allows a check on whether or not all the available namelist variables have a default setting in namelist_ref:

python nemo_nml_check.py -r namelist_ref -c pseudo_nml_ref 
No match in matching blocks for:                           |  Possible close match:
ln_rnf_icb             in namsbc_rnf   (at line no.  172)  |
sn_i_rnf               in namsbc_rnf   (at line no.  175)  |  sn_t_rnf
clname                 in nam_tide     (at line no.  198)  |  clname(1)
ln_time_average_weight in namberg      (at line no.  594)  |
tname                  in nam_diaharm  (at line no.  826)  |  tname(2)
sn_cfctl               in namctl       (at line no.  984)  |
ln_sto_ldf             in namsto       (at line no. 1100)  |
rn_ldf_std             in namsto       (at line no. 1101)  |
rn_ldf_tcor            in namsto       (at line no. 1102)  |
ln_sto_hpg             in namsto       (at line no. 1103)  |
rn_hpg_std             in namsto       (at line no. 1104)  |
rn_hpg_tcor            in namsto       (at line no. 1105)  |
ln_sto_pstar           in namsto       (at line no. 1106)  |
rn_pstar_std           in namsto       (at line no. 1107)  |
rn_pstar_tcor          in namsto       (at line no. 1108)  |
nn_pstar_flt           in namsto       (at line no. 1109)  |
nn_pstar_ord           in namsto       (at line no. 1110)  |
ln_sto_trd             in namsto       (at line no. 1111)  |
rn_trd_std             in namsto       (at line no. 1112)  |
rn_trd_tcor            in namsto       (at line no. 1113)  |
ln_sto_trc             in namsto       (at line no. 1122)  |
nn_sto_trc             in namsto       (at line no. 1123)  |
rn_trc_stdxy           in namsto       (at line no. 1124)  |
rn_trc_stdz            in namsto       (at line no. 1125)  |
rn_trc_tcor            in namsto       (at line no. 1126)  |
nn_trc_ord             in namsto       (at line no. 1127)  |
nn_trc_flt             in namsto       (at line no. 1128)  |
rn_trc_lim             in namsto       (at line no. 1129)  |

The same caveats apply but there are a few issues warranting further investigation.

Full marks for Clem though since repeating this process for ICE:

for f in `find ./ICE -name '*.[Fh]90'`
do   
   echo "! "$f >> pseudo_nml_ice_ref
   perl nemo_list_nmls.pl $f >> pseudo_nml_ice_ref
done
python nemo_nml_check.py -c ../cfgs/SHARED/namelist_ice_ref -r pseudo_nml_ice_ref
python nemo_nml_check.py -r ../cfgs/SHARED/namelist_ice_ref -c pseudo_nml_ice_ref

finds no mismatches

For TOP we have to be more selective about which directories to search when building the pseudo file:

for f in `find -f  ./TOP ./TOP/TRP  -name '*.[Fh]90' -depth 1`
do
  echo "! "$f >> pseudo_nml_top_ref
  perl nemo_list_nmls.pl $f >> pseudo_nml_top_ref
done

and the following potential issues are flagged:

python nemo_nml_check.py -c ../cfgs/SHARED/namelist_top_ref -r pseudo_nml_top_ref
No match in matching blocks for:                           |  Possible close match:
sn_trcdta(1)           in namtrc_dta   (at line no.   61)  |  sn_trcdta
ln_trdmld_trc_restart  in namtrc_trd   (at line no.  124)  |  ln_trdmxl_trc_restart
ln_trdmld_trc_instant  in namtrc_trd   (at line no.  125)  |  ln_trdmxl_trc_instant
ln_trdtrc( 1)          in namtrc_trd   (at line no.  126)  |  ln_trdtrc
ln_trdtrc( 2)          in namtrc_trd   (at line no.  127)  |  ln_trdtrc
ln_trdtrc(23)          in namtrc_trd   (at line no.  128)  |  ln_trdtrc

python nemo_nml_check.py -r ../cfgs/SHARED/namelist_top_ref -c pseudo_nml_top_ref
No match in matching blocks for:                           |  Possible close match:
sn_trcobc              in namtrc_bc    (at line no.    4)  |
rn_trofac              in namtrc_bc    (at line no.    5)  |
sn_trcsbc              in namtrc_bc    (at line no.    7)  |
rn_trsfac              in namtrc_bc    (at line no.    8)  |
sn_trccbc              in namtrc_bc    (at line no.   10)  |
rn_trcfac              in namtrc_bc    (at line no.   11)  |
sn_tri_tracer          in namtrc_ice   (at line no.   25)  |
sn_tracer              in namtrc       (at line no.   48)  |
ln_trdmxl_trc_restart  in namtrc_trd   (at line no.   59)  |  ln_trdmld_trc_restart
ln_trdmxl_trc_instant  in namtrc_trd   (at line no.   60)  |  ln_trdmld_trc_instant
cn_trdrst_trc_in       in namtrc_trd   (at line no.   61)  |
cn_trdrst_trc_out      in namtrc_trd   (at line no.   62)  |
ln_trdtrc              in namtrc_trd   (at line no.   63)  |  nn_trd_trc
sn_trcdta              in namtrc_dta   (at line no.   67)  |  sn_trcdta(1)
rn_trfac               in namtrc_dta   (at line no.   69)  |

and finally for PISCES:

for f in `find ./TOP/PISCES  -name '*.[Fh]90'`
do   
  echo "! "$f >> pseudo_nml_pisces_ref
  perl nemo_list_nmls.pl $f >> pseudo_nml_pisces_ref
done
python nemo_nml_check.py -c ../cfgs/SHARED/namelist_pisces_ref -r pseudo_nml_pisces_ref
No match in matching blocks for:                           |  Possible close match:
mprat2                 in namp5zmort   (at line no.  199)  |  mpratd
xpref2p                in namp5zmes    (at line no.  233)  |  xpref2d

python nemo_nml_check.py -r ../cfgs/SHARED/namelist_pisces_ref -c pseudo_nml_pisces_ref
No match in matching blocks for:                           |  Possible close match:
mpratd                 in namp5zmort   (at line no.  357)  |  mprat2
xpref2n                in namp5zmes    (at line no.  398)  |  xpref2c

Attachments (2)

Download all attachments as: .zip