Welcome to the Arpege/IFS coding standard!¶
Developments to the Arpege/IFS codebase should aim to adhere to the standards and rules presented in this document.
Standards and rules described here are designed to make code easier to read, easier to maintain, easier to extend, and less prone to bugs. The code review process for submissions to Arpege and IFS should aim to check code against these standards. Rules are also written so as to allow implementation of automatic checking.
Guidelines and recommendations¶
Good code should not require large amounts of comments to be intelligible. Nevertheless targeted explanations of particular segments of interest are desirable. Each source file should have a homogeneous coding style.
Contours of a routine or module should be considered with care, avoiding excessive length or complexity.
Routine call signatures or interfaces should be designed with care, respecting library contouring. Interfaces that are not internal to a component should privilege as much as possible native fortran datatypes rather than derived types.
Naming of new variables, routines and modules should help the reader understand code as efficiently as possible. Renaming of legacy / existing code?
Large arrays should be declared as allocatable, to avoid excessive stack usage. Small arrays, and in particular those declared in tight code (this should be avoided wherever possible!) should be automatic, to benefit from faster stack handling.
If an allocatable variable can be used rather than a pointer, opt for the allocatable for safety reasons.
In order to make domain decomposition easier to follow, global variable names are suffixed by G, while subdomain-local variables are suffixed by L.
Different meteorological data formats are used at ECMWF and Meteo-France. The choice between these formats should be based on logical keys LARPEGEF or LARPEGEF_xx (and not LECMWF).
Aladin routines that are counterparts of IFS/Arpege ones should have the same name but prefixed with E. Aladin counterparts to IFS/Arpege SUxxx setup routines should be named SUE.
Output that should appear in the main text output file should be written to NULOUT. Output to NULOUT must be deterministic and should not change according to the parallel distribution or the time at which the job is run. Error messages should be written to unit NULERR.
Conditional clauses with multiple cases should be handled with SELECT CASE rather than IF statements followed by multiple ELSEIF statements.
If execution is to be aborted by the code, a call to ABOR1, with a meaningful message, should be used.
Rules (as checked by norms checker)¶
Some of the rules relate to the idea of Single Column code, where algorithmic tasks can be expressed independently of horizontal position, and no horizontal dependencies exist. Code which maps to this concept can be modified at compile time by tooling (Loki, Fxtran) in line with architecture-specific requirements. Such tooling relies heavily on code formatting to determine required transformations, explaining the prescriptive rules for these areas of code.
Rules are organised into general language rules (Lw), IFS-specific rules (Ix), stylistic points (Sy), and Single-Column related rules (SCz).
- L1 : implicit none
- L2 : use module, only
- L3 : global variables
- L4 : new language features
- L5 : argument INTENT
- L6 : OPTIONAL argument position
- L7 : OPTIONAL argument keyword usage
- L8 : copying allocatable arrays
- L9 : interfaces for routines
- L10 : declaration syntax
- L11 : array syntax
- L12 : array declarations in NPROMA routines
- L13 : array declarations in parallel routines
- L14 : notations
- L15 : dummy/actual array dimensions
- L16 : INTENT attribute in NPROMA routines
- L17 : Pointers in NPROMA routines
- L18 : Design of NPROMA routines
- L19 : Design of derived types
- I1 : naming of variables, subroutines, modules
- I2 : KIND specification
- I3 : derived types in modules
- I4 : Excessively long interfaces
- I5 : MPL and message passing
- I6 : MPL and string argument
- I7 : DRHOOK instrumentation
- SC1 : horizontal indexing
- SC2 : horizontal looping
- SC3 : function calls from inside KPROMA loops
- SC4 : no horizontal indirection
- S1 : END IF / ENDIF
- S2: order of argument declarations
- S3 : line continuation
- S4: no unqualified END statements
- S5 : unused variables
- S6 : no TABS
- Coding norms 2011 rules
- R1 : Encapsulation rules
- R2 : Subroutine length
- R3 : Cosmetic changes
- R4 : Unused variables
- R5 : Variable name suffixes
- R6 : Array syntax
- R7 : Cut-n-paste
- R8 : LECMWF variable
- R9 : LELAM variable
- R10 : LFI or GRIB
- R11 : message passing
- R12 : Derived types in a module
- R13 : Code must be threadsafe
- R14 : Abnormal termination
- R15 : The save statement
- R16 : argument passing characteristics
- R17 : SELECT CASE
- R18 : include interfaces
- R19 : number of arguments to routines
- R20 : names of variables
- R21 : Name prefixes and suffixes
- R22 : Aladin routine names
- R23 : NULOUT & NULERR usage
- R24 : universal constants
- R25 : MPL string argument
- R26 : code structure and file location
- R27 : namelist usage
- R28 : DATA statement
- R29 : F90 free format
- R30 : consistent style
- R31 : no TAB usage
- R32 : IMPLICIT NONE
- R33 : no hard-coded array dimensions
- R34 : “::” notation
- R35 : mandatory KIND specification
- R36 : USE, ONLY
- R37 : PARAMETER wherever possible
- R38 : variable name prefixes
- R39 : banned statements
- R40 : no implicit array sizing
- R41 : automatic and allocatable arrays
- R42 : deallocation of allocatables
- R43 : comparison operators
- R44 : value comparisons
- R45 : argument intents are compulsory
- R46 : order of optional arguments
- R47 : ENDIF / END IF
- R48 : removal of dead code