Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rule banning reliance on preprocessing for valid interfaces. #23

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fortran/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ points (Sy), and Single-Column related rules (SCz).
rules/L17
rules/L18
rules/L19
rules/L20
rules/I1
rules/I2
rules/I3
Expand Down
13 changes: 10 additions & 3 deletions fortran/rules/L10.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
L10 : declaration syntax
************************
L10 : preprocessing of interfaces
**********************************

All declarations shall use the “::” notation.
Subroutine signatures shall not require preprocessing to be valid.

Interfaces to routines internal to the IFS/Arpege codebase are auto-generated
by a script which reads
* ```USE XXX_MOD``` module statements
* argument declarations

These two code sections should be valid fortran without requiring preprocessing.
14 changes: 3 additions & 11 deletions fortran/rules/L11.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
L11 : array syntax
******************
L11 : declaration syntax
************************

Fortran array syntax, eg :

``ZX(:)=ZY(:)+ZZ(:)``

is forbidden, except for the two following trivial cases:

* Array initialization: ``X(:)=constant``

* Array copy : ``X(:)=Y(:)``
All declarations shall use the “::” notation.
21 changes: 7 additions & 14 deletions fortran/rules/L12.rst
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
L12 : array declarations in NPROMA routines
*******************************************
L12 : array syntax
******************

NPROMA routines (those processing a single NPROMA block) should only declare arrays of basic
data types whose kinds are taken from parkind1.F90 and parkind2.F90, eg:
Fortran array syntax, eg :

* ``REAL(KIND=JPRB)``
* ``REAL(KIND=JPRD)``
* ``INTEGER(KIND=JPIM)``
* ``LOGICAL``
``ZX(:)=ZY(:)+ZZ(:)``

The leading dimensions of these array should be ``NPROMA``.
is forbidden, except for the two following trivial cases:

Any other arrays are forbidden in NPROMA routines. These other arrays (not depending on
the meteorological situation) should be computed in the setup and passed as arguments
to NPROMA compute routines, or integrated into sub-components of YDMODEL.
* Array initialization: ``X(:)=constant``

Arrays declared in NPROMA routines be automatic arrays; ALLOCATABLEs and POINTERs are
forbidden.
* Array copy : ``X(:)=Y(:)``
24 changes: 16 additions & 8 deletions fortran/rules/L13.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
L13 : array declarations in parallel routines
*********************************************
L13 : array declarations in NPROMA routines
*******************************************

Parallel routines (those processing a list of NPROMA blocks) should wrap their field data
into Field API objects.
NPROMA routines (those processing a single NPROMA block) should only declare arrays of basic
data types whose kinds are taken from parkind1.F90 and parkind2.F90, eg:

In particular the legacy data representation for model state (PGMV/PGFL arrays) should be
considered obsolescent and replaced by YDVARS wherever possible.
* ``REAL(KIND=JPRB)``
* ``REAL(KIND=JPRD)``
* ``INTEGER(KIND=JPIM)``
* ``LOGICAL``

Parallel routines should never declare an array that will be involved in calculations
(ie passed to NPROMA routines or used in OpenMP sections).
The leading dimensions of these array should be ``NPROMA``.

Any other arrays are forbidden in NPROMA routines. These other arrays (not depending on
the meteorological situation) should be computed in the setup and passed as arguments
to NPROMA compute routines, or integrated into sub-components of YDMODEL.

Arrays declared in NPROMA routines be automatic arrays; ALLOCATABLEs and POINTERs are
forbidden.
14 changes: 8 additions & 6 deletions fortran/rules/L14.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
L14 : notations
***************
L14 : array declarations in parallel routines
*********************************************

Notations should homogeneous for the loop index, NPROMA array leading dimension, first iteration, last iteration:
Parallel routines (those processing a list of NPROMA blocks) should wrap their field data
into Field API objects.

* ``JLON/KLON/KIDIA/KFDIA`` in ARPEGE physics
* ``JL/KLON/KIDIA/KFDIA`` in ECMWF physics
* ``JROF/NPROMA/KST/KEND`` in dynamics routines (call_sl.F90, cpg_gp.F90, cpg_dyn.F90)
In particular the legacy data representation for model state (PGMV/PGFL arrays) should be
considered obsolescent and replaced by YDVARS wherever possible.

Parallel routines should never declare an array that will be involved in calculations
(ie passed to NPROMA routines or used in OpenMP sections).
19 changes: 6 additions & 13 deletions fortran/rules/L15.rst
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
L15 : dummy/actual array dimensions
***********************************
L15 : notations
***************

If an actual argument is an array, then :
Notations should homogeneous for the loop index, NPROMA array leading dimension, first iteration, last iteration:

- its rank should match the rank of the corresponding dummy argument
* ``JLON/KLON/KIDIA/KFDIA`` in ARPEGE physics
* ``JL/KLON/KIDIA/KFDIA`` in ECMWF physics
* ``JROF/NPROMA/KST/KEND`` in dynamics routines (call_sl.F90, cpg_gp.F90, cpg_dyn.F90)

- its dimensions should match those of the corresponding dummy argument

Notable exceptions are the interpolation routines of the Semi-Lagrangian:

* ``laitli.F90``

* ``laitri.F90``

* etc.
25 changes: 9 additions & 16 deletions fortran/rules/L16.rst
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
L16 : INTENT attribute in NPROMA routines
*****************************************
L16 : dummy/actual array dimensions
***********************************

In NPROMA routines (those processing a single NPROMA block), only NPROMA data should
be allowed to have an INTENT different of IN.
All other argument data should have the ``INTENT(IN)`` attribute.
If an actual argument is an array, then :

This, for instance should be forbidden:
- its rank should match the rank of the corresponding dummy argument

.. code-block:: fortran
- its dimensions should match those of the corresponding dummy argument

SUBROUTINE LAPINEA(&
& YDGEOMETRY, YDML_GCONF,YDML_DYN,KST,KPROF,YDSL,KIBL,PB1,PB2,PWRL9,&
& KVSEPC,KVSEPL,&
& PSAVEDP,PCCO,PUF,PVF,KL0,KLH0,PLSCAW,PRSCAW,KL0H,PLSCAWH,PRSCAWH,&
& PSCO,PGFLT1,KNOWENO)
Notable exceptions are the interpolation routines of the Semi-Lagrangian:

INTEGER(KIND=JPIM),INTENT(INOUT) :: KVSEPC
INTEGER(KIND=JPIM),INTENT(INOUT) :: KVSEPL
* ``laitli.F90``

In particular, ``YDMODEL`` and ``YDGEOMETRY`` as well as all their sub-components passed as arguments (eg ``YDDYNA``) should
have the ``INTENT(IN)`` attribute in NPROMA routines.
* ``laitri.F90``

* etc.
34 changes: 15 additions & 19 deletions fortran/rules/L17.rst
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
L17 : Pointers in NPROMA routines
*********************************
L17 : INTENT attribute in NPROMA routines
*****************************************

The use of Fortran pointers in compute NPROMA routines should be forbidden except for the following pattern:
In NPROMA routines (those processing a single NPROMA block), only NPROMA data should
be allowed to have an INTENT different of IN.
All other argument data should have the ``INTENT(IN)`` attribute.

This, for instance should be forbidden:

.. code-block:: fortran

SUBROUTINE GPRCP_EXPL (YDCST, YDCPG_BNDS, YDCPG_OPTS, PCP, PR, PKAP, YDVARS, KGFLTYP)
SUBROUTINE LAPINEA(&
& YDGEOMETRY, YDML_GCONF,YDML_DYN,KST,KPROF,YDSL,KIBL,PB1,PB2,PWRL9,&
& KVSEPC,KVSEPL,&
& PSAVEDP,PCCO,PUF,PVF,KL0,KLH0,PLSCAW,PRSCAW,KL0H,PLSCAWH,PRSCAWH,&
& PSCO,PGFLT1,KNOWENO)

REAL(KIND=JPRB),OPTIONAL,TARGET,INTENT(OUT) :: PCP(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)
REAL(KIND=JPRB),OPTIONAL,TARGET,INTENT(OUT) :: PR(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)
REAL(KIND=JPRB),OPTIONAL, INTENT(OUT) :: PKAP(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)
INTEGER(KIND=JPIM),INTENT(INOUT) :: KVSEPC
INTEGER(KIND=JPIM),INTENT(INOUT) :: KVSEPL

REAL(KIND=JPRB), POINTER :: ZR(:,:)
REAL(KIND=JPRB), TARGET :: ZR0(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)
In particular, ``YDMODEL`` and ``YDGEOMETRY`` as well as all their sub-components passed as arguments (eg ``YDDYNA``) should
have the ``INTENT(IN)`` attribute in NPROMA routines.

IF (PRESENT (PR)) THEN
ZR => PR
ELSEIF (PRESENT (PKAP)) THEN
ZR => ZR0
ELSE
CALL ABOR1 ('GPRCP_EXPL: EXPECTED PR OR PKAP')
ENDIF


And such pointers should always point to arrays with the same shapes.
31 changes: 21 additions & 10 deletions fortran/rules/L18.rst
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
L18 : Design of NPROMA routines
*******************************
L18 : Pointers in NPROMA routines
*********************************

NPROMA routines should be individual subroutines, allowing for :
The use of Fortran pointers in compute NPROMA routines should be forbidden except for the following pattern:

- automatic interface generation
- separate compilation
- easiness of automatic analysis and transformation

In particular implementing a routine or a set of subroutines inside a module in
order to benefit from the automatic generation of an interface in a .mod file
should be prohibited.
.. code-block:: fortran

The use of modules should be restricted to derived types definition and implementation (methods).
SUBROUTINE GPRCP_EXPL (YDCST, YDCPG_BNDS, YDCPG_OPTS, PCP, PR, PKAP, YDVARS, KGFLTYP)

REAL(KIND=JPRB),OPTIONAL,TARGET,INTENT(OUT) :: PCP(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)
REAL(KIND=JPRB),OPTIONAL,TARGET,INTENT(OUT) :: PR(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)
REAL(KIND=JPRB),OPTIONAL, INTENT(OUT) :: PKAP(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)

REAL(KIND=JPRB), POINTER :: ZR(:,:)
REAL(KIND=JPRB), TARGET :: ZR0(YDCPG_OPTS%KLON,YDCPG_OPTS%KFLEVG)

IF (PRESENT (PR)) THEN
ZR => PR
ELSEIF (PRESENT (PKAP)) THEN
ZR => ZR0
ELSE
CALL ABOR1 ('GPRCP_EXPL: EXPECTED PR OR PKAP')
ENDIF


And such pointers should always point to arrays with the same shapes.
21 changes: 14 additions & 7 deletions fortran/rules/L19.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
L19 : Design of derived types
*****************************
L19 : Design of NPROMA routines
*******************************

NPROMA routines should be individual subroutines, allowing for :

- automatic interface generation
- separate compilation
- easiness of automatic analysis and transformation

In particular implementing a routine or a set of subroutines inside a module in
order to benefit from the automatic generation of an interface in a .mod file
should be prohibited.

The use of modules should be restricted to derived types definition and implementation (methods).

Dervived types should be implemented in modules. Their methods (the minimal code accessing their private attributes)
should be implemented in the module where they are defined.

The SEQUENCE statement is forbidden in the definition of complex (embedding some POINTER or ALLOCATABLE members) derived types
meant to be used on accelerators, as the SEQUENCE statement
forbids the implementation of object methods.
9 changes: 9 additions & 0 deletions fortran/rules/L20.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
L20 : Design of derived types
*****************************

Dervived types should be implemented in modules. Their methods (the minimal code accessing their private attributes)
should be implemented in the module where they are defined.

The SEQUENCE statement is forbidden in the definition of complex (embedding some POINTER or ALLOCATABLE members) derived types
meant to be used on accelerators, as the SEQUENCE statement
forbids the implementation of object methods.
4 changes: 2 additions & 2 deletions fortran/rules/L9.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
L9 : interfaces for routines
****************************
*****************************

Calls to subroutines and functions that are provided neither by a module nor by a CONTAINS statement,
must have a matching explicit interface block.

Routines that may be called from outside the IFS should have an interface in the codebase, while
routines called exclusively internally have their interfaces generated at build time.
routines called exclusively internally have their interfaces generated at build time.