Special considerations

The example presented so far was a simple one that required no manual intervention to complete the processing chain. Unfortunately there are examples within the NEMO source tree that fail at the first hurdle by not producing a valid submod.list file. There are several reasons why this can occur and in each case a quick hand edit is usually sufficient to resolve the issue. In no particular order of priority, the issues that can occur are listed here. The reason why they occur and the simplest fix to each is provided in the subsequent sections:

  • Multiple CONTAINS statements and duplicate declarations
  • No MODULE statement
  • INTERFACE statements occurring before the CONTAINS statement
  • Apparently empty modules

Multiple CONTAINS statements

This one occurs because of modules that still contain preprocessor keys which can remove large blocks of code. Often in these circumstances alternative, ‘dummy’ routines are provided to satisfy the linker. Unfortunately this means two CONTAINS statements and duplicate SUBROUTINE declarations. Take this example (albeit a rather obsolete one) from the SBC directory:

sbcice_cice.F90
MODULE sbcice_cice
CONTAINS
   INTEGER FUNCTION sbc_ice_cice_alloc
   SUBROUTINE sbc_ice_cice
   SUBROUTINE cice_sbc_init
   SUBROUTINE cice_sbc_in
   SUBROUTINE cice_sbc_out
   SUBROUTINE cice_sbc_hadgam
   SUBROUTINE cice_sbc_final
   SUBROUTINE cice_sbc_force
   SUBROUTINE nemo2cice
   SUBROUTINE cice2nemo
CONTAINS
   SUBROUTINE sbc_ice_cice      ! Dummy routine
   SUBROUTINE cice_sbc_init     ! Dummy routine
   SUBROUTINE cice_sbc_final     ! Dummy routine

The submod.sh script handles this situation by ignoring the second CONTAINS and any lines between this statement and the next blank (i.e. whitespace only) line. Users may prefer a more explicit solution which, in this example, is obviously just to delete the second CONTAINS statement and duplicate subroutine names. Of course this snippet is taken from a lengthy newsubmod.list file so spotting this issue isn’t necessarily straight-forward. To assist, there is an additional script: sanity_submod.sh that does its best to discover issues and pinpoint line numbers. More on that later though after all the potential issues have been discussed.

No MODULE statement

This one occurs primarily in .h90 files that aren’t whole files. Here is one example from the SBC directory:

sbcwave.F90
MODULE sbcwave
CONTAINS
   SUBROUTINE sbc_stokes
   SUBROUTINE sbc_wstress
   SUBROUTINE sbc_wave
   SUBROUTINE sbc_wave_init

tide.h90

tideini.F90
MODULE tideini
CONTAINS
   SUBROUTINE tide_init

(note tide.h90 hidden in the middle there). There are also a few examples in the NST directory of non-modular programs with subroutines but no modules. E.g.:

agrif2model.F90
SUBROUTINE Agrif2Model
SUBROUTINE Agrif_Set_numberofcells
SUBROUTINE Agrif_Get_numberofcells
SUBROUTINE Agrif_Allocationcalls
SUBROUTINE Agrif_probdim_modtype_def
SUBROUTINE Agrif_clustering_def
SUBROUTINE Agrif2Model

the best solution here is to insert a MODULE none statement followed by a CONTAINS statement before the first SUBROUTINE statement.

INTERFACE statements occurring before the CONTAINS statement

This one doesn’t indicate any non-conformity to the coding convention but is rather an indication that generic subroutines are present and human interaction is required to decide how the module contents are to be presented. Take this example from the OCE main directory:

lib_fortran.F90
MODULE lib_fortran
   INTERFACE glob_sum
   INTERFACE glob_sum_full
   INTERFACE local_sum
   INTERFACE sum3x3
   INTERFACE glob_min
   INTERFACE glob_max
   INTERFACE SIGN
CONTAINS
   FUNCTION local_sum_2d
   FUNCTION local_sum_3d
   SUBROUTINE sum3x3_2d
   SUBROUTINE sum3x3_3d
   SUBROUTINE DDPDD
   SUBROUTINE glob_sum_1d
   SUBROUTINE glob_sum_2d
   SUBROUTINE glob_sum_full_2d
   SUBROUTINE glob_sum_3d
   SUBROUTINE glob_sum_full_3d
   FUNCTION SIGN_SCALAR
   FUNCTION SIGN_ARRAY_1D
   FUNCTION SIGN_ARRAY_2D
   FUNCTION SIGN_ARRAY_3D
   FUNCTION SIGN_ARRAY_1D_A
   FUNCTION SIGN_ARRAY_2D_A
   FUNCTION SIGN_ARRAY_3D_A
   FUNCTION SIGN_ARRAY_1D_B
   FUNCTION SIGN_ARRAY_2D_B
   FUNCTION SIGN_ARRAY_3D_B

showing all the component variations that make up the generic routines and functions is probably not required. If it is then just delete the INTERFACE statements, but a better solution is probably to delete the internal variants and just present the generic names. This is achieved by moving the INTERFACE statements below the CONTAINS statements and deleting any surplus. I.e.:

lib_fortran.F90
MODULE lib_fortran
CONTAINS
   INTERFACE glob_sum
   INTERFACE glob_sum_full
   INTERFACE local_sum
   INTERFACE sum3x3
   INTERFACE glob_min
   INTERFACE glob_max
   INTERFACE SIGN
   SUBROUTINE DDPDD

Apparently empty modules

Some modules are intentionally empty of any contained routines. For example:

par_kind.F90
MODULE par_kind

these cases are not errors and are handled correctly.

Some others are apparently empty because they rely on the preprocessor to include content from h90 files. These are primarily in the OBS directory and can be fixed by suitably combining the list entries for the relevant .F90 and .h90 files.

The sanity_submod.sh script

As mentioned earlier some of these issues can be difficult to spot in lengthy submod list files. To assist, the sanity_submod.sh script can be run immediately after generating the newsubmod.list file. It should catch most issues and pinpoint the first occurrence in the file. A null return indicates no errors were detected. Here are some examples of its output whilst iteratively fixing issues in OCE:

mksubmodlist
sanity_submod.sh
===================================
|      Errors detected            |
===================================
# files      = 12
# modules    = 10
# contains   = 7
# interfaces = 7
===================================
Some files do not contain a MODULE statement.     First suspect occurs near line: 28
See full list of line numbers for filename(+1) and MODULE statements below:
files  :    2   28   38   48   53   56   59   65   68   73   89   97
Modules:    2   38   48   53   56   59   65   68   73   89
===================================

vi newsubmod.list   #remove files without MODULES

sanity_submod.sh
Error detected: misplaced INTERFACE statement at line: 3

vi newsubmod.list   # Sort out misplaced interface statements

sanity_submod.sh
# No return. Job done

mv newsubmod.list OCE_submod.list

Just one caution here though because this file contained 10 MODULE statements but only 7 CONTAINS statements. This is not necessarily an error but worth checking just in case. sanity_submod.sh has a warning mode that can be useful to narrow the search:

./sanity_submod.sh -w OCE_submod.list
===================================
|          File stats             |
===================================
# files      = 10
# modules    = 10
# contains   = 7
# interfaces = 7
===================================
===================================
|          Warnings               |
===================================
Some files do not contain a CONTAINS statements.  First suspect occurs near line: 35
See full list of line numbers for MODULE and CONTAINS(-1) statements below:
Modules :    2   14   24   29   32   35   41   44   49   65
Contains:    2   14   24   35   44   49   65
===================================

(note sanity_submod.sh will also accept an alternative input filename). An investigation is unneccessary in this case since the three modules without a CONTAINS statement are genuine examples (par_kind, par_oce and step_oce).