Guide for good coding
Contents
How to create a new module/subroutine
Subroutines should be integrated inside a module. A good writing habit is to add the line "IMPLICIT NONE", in the beginning of the module and subroutine.
First you can define all the variable that belongs to the module and could be used at another place. A good thing is also to create a subroutine that allocate and initialise module variables. If the variable is only modified inside the module it should be taged as protected. If the variable belongs only to the module it can be specified to be private.
You can now start the definition of the subroutine. Start by variable and function from other module if necessary. Comment the purpose of the subroutine directly. Declare the variables, first the one pass in arguments. Use the intent to specify the status of the variable inside the subroutine. Continue with the local and saved variables. Then you can define local variables. Remember to comment all of them, you can specify the dimension if the variable is an allocatable variable as well as the units and everything that seems appropriate.
You can finally write the code.
1 MODULE aquarium_mod
2
3 IMPLICIT NONE
4
5 INTEGER :: water ! Define what is the variable, the dimension, units (°) etc...
6 REAL,SAVE,ALLOCATABLE,DIMENSION(:) :: kre1 ! Another comment
7
8 CONTAINS
9
10 SUBROUTINE ini_aquarium(ngrid)
11 c=======================================================================
12 c Initialise module s variable
13 c=======================================================================
14 IMPLICIT NONE
15 INTEGER, INTENT(IN) :: ngrid
16
17 allocate(kre1(ngrid+1))
18
19 END SUBROUTINE ini_aquarium
20
21 SUBROUTINE end_aquarium
22 c=======================================================================
23 c Deallocate module s variable
24 c=======================================================================
25
26 IMPLICIT NONE
27
28 IF (allocated(kre1)) deallocate(kre1)
29
30 END SUBROUTINE end_aquarium
31
32 SUBROUTINE aquarium(kre, grass, other_things
33 & really_anything)
34
35 use another_module_mod, only: fct, variable
36
37 c=======================================================================
38 c subject:
39 c --------
40 c What is the subroutine doing
41 c
42 c author: Someone smart
43 c ------
44 c update: Someone smarter, march 2012:
45 c - I change something here
46 c
47 c=======================================================================
48
49 IMPLICIT NONE
50
51 c-----------------------------------------------------------------------
52 c
53 c Declarations :
54 c --------------
55 c
56 c Input/Output
57 c ------------
58
59 REAL, INTENT(IN) :: something(ngrid,nlayer) ! 2D tabular used as an input only (W/m^2)
60 REAL, INTENT(OUT) :: kre(ngrid) ! 1D tabular output by the subroutine
61 REAL, INTENT(INOUT) :: grass(ngrid,nlayer) ! Variable that is modified by the subroutine
62 ! it is an input and output
63 LOGICAL,INTENT(IN) :: really_anything ! Boolean variable
64
65 c Local saved variables :
66 c -----------------
67 INTEGER, PARAMETER :: nb_kre = 6 ! Number of kre
68 INTEGER, SAVE :: rock ! Another variable
69 LOGICAL,SAVE :: firstcall=.true. ! Another variable
70
71 c Local variables :
72 c -----------------
73 REAL tabular(ngrid) ! Local var
74 INTEGER i ! Loop var
75
76 c Beginning of the code :
77 c -----------------
78
79 IF (firstcall) THEN
80 ! identify where are the kre
81 DO i=1,nb_kre
82 kre(i)=i
83 write(*,*) "the Kre ", i, "is behind the rock"
84 ENDDO !end of the loop nb_kre
85 ENDIF !end firstcall
86
87 END SUBROUTINE aeropacity
88
89 END MODULE aeropacity_mod
How to pass variable to subroutine (by argument or by module)
Define when we should use argument and when to use modules
Naming variables convention
What is the naming convention. In vdifc_mod for exemple.
Loop index convention
Index name for loops through:
- physical grid : ig (max ngrid)
- vertical levels : l (max nlayer)
- tracer : iq (max nq)
- subslopes : islope (max nslope)
iaer=1,naerkind
Efficient loop coding
The more outside loop should correcpond to the last index of an array.
Example:
DO l=1,nlayer
DO ig=1,ngrid
array(ig,l)=l*ig
ENDDO
ENDDO
How to use the Intent
Argument of a function can come in 3 different way: IN, OUT, INOUT.
How to comment code
- In english
- As much as possible
- Variable definition : explain what it is, the dimension, the units etc...
- Subroutine : Explain what it does, who wrote it, who modify it and why if it is a big change
- Loops : if the enddo is far away you can comment to which index it correspond to.
- Chapter your code : you can add section to your code to make it clearer.
General guide
- Create .F90 instead of .F
- Delete unused argument in a function call if you see one
- Delete unused variables
- Choose meaningful names of variables
- Don't hesitate to comment at much as possible, a code is never too commented
- Delete unused commented code lines