Changes between Version 14 and Version 15 of doc/tec/developerrules/palmstandard


Ignore:
Timestamp:
Nov 13, 2018 5:20:26 PM (6 years ago)
Author:
kanani
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • doc/tec/developerrules/palmstandard

    v14 v15  
    11= PALM coding rules =
     2
     3\\
    24= (0) Why to follow some standards? =
    35Because everyone has her/his own programming style, sort of a dialect, making it difficult for other developers to understand, extend, debug, or optimize the code. So what do we do? We learn and apply the coding standard to make PALM more easily readable for all current and future developers. Let's all work on that together. We are aware that the PALM core doesn't completely comply with the following rules yet, but we are working on that.
     
    1820|| '''AVOID''' || '''USE INSTEAD''' ||
    1921|| COMMON blocks || ... ||
     22{{{#!comment
     23Examples for Fortran 95 are:
     24        ◦ COMMON blocks - use the declaration part of MODULEs instead.
     25        ◦ EQUIVALENCE - use POINTERs or derived data types instead to form data structures. Please try to avoid this anyway as it is usually a source of bugs.
     26        ◦ Assigned and computed GOTOs - use the CASE construct instead.
     27        ◦ Arithmetic IF statements - use the block IF, ELSE, ELSEIF, ENDIF or SELECT CASE construct instead.
     28        ◦ Labeled DO constructs - use unlabeled ENDDO instead. Nevertheless non-number label can be used for big iterative loop of recurcive algorithm.
     29        ◦ I/O routines END and ERR - use IOSTAT instead (the use is somehow restricted due to compiler implementation dependent error numbering). (This is not yet done throughout the PALM code  action!)
     30        ◦ FORMAT statements: use character parameters or explicit format- specifiers inside the READ or WRITE statement instead. (This is not yet done throughout the PALM code  action!)
     31        ◦ GOTO and CONTINUE statement - use IF, CASE, DO WHILE, EXIT or CYCLE statements or a contained SUBROUTINE instead. If you feel you cannot avoid a GOTO and or CONTINUE statement, then add a clear comment to explain what is going on and why you need to use GOTO.
     32        ◦ PAUSE – just never use it.
     33        ◦ ENTRY statements: a subprogram must only have one entry point.
     34        ◦ RETURN – it is obsolete and so not necessary at the end of program units.
     35        ◦ Fixed source form – use free form instead.
     36        ◦ Avoid functions with side effects. There are good reasons to avoid this. First, the code is easier to understand, if you can rely on the rule that functions don't change their arguments, second, some compilers generate more efficient code for PURE (in Fortran 2003 there are the attributes PURE and ELEMENTAL) functions, because they can store the arguments in different places. This is especially important on massive parallel and on vector machines as well.
     37        ◦ DATA and BLOCK DATA - initialisers in Fortran 2003 give this functionality.
     38}}}
    2039
    2140== (1.2) Implementing new features to PALM ==
     
    2544
    2645\\
    27 = (5) Coding =
    28 == (5.1) Variable & parameter declarations ==
     46= (2) Coding =
     47
     48== (2.1) Code structure ==
     49* One MODULE per file (only exception: modules.f90)
     50* Clarify program entities, i.e. use {{{SUBROUTINE <name> ... END SUBROUTINE <name>}}}, same holds for INTERFACE, MODULE, PROGRAM statements
     51
     52== (2.2) Variable & parameter declarations ==
    2953* Clear structure in declaration part, in this order: USE --> IMPLICIT NONE --> declarations --> SAVE --> PRIVATE --> PUBLIC list_of_public_variables
    3054* '''IMPLICIT NONE''' | All subroutines and functions must include this statement, i.e all variables must be explicitly typed. It also allows the compiler to detect typographical errors in variable names. For MODULEs, one IMPLICIT NONE statement in the modules definition section is sufficient.
     
    4670  }}}
    4771* '''INTENT clause''' | All dummy arguments must include the INTENT clause in their declaration. This is extremely valuable to someone reading the code, and can be checked by compilers. A common mistake is to put the wrong type of variable in a routine call. So, develop the habit of checking types of arguments in parameter lists. Many modern compilers, especially for FORTRAN 2003, check for consistent use within a file or across files using inter-procedural analysis. Compilers for FORTRAN 2003 will also flag up errors at link time if there are explicit or implicit interfaces.
    48 * '''Private attribute''' | Modules variables and routines should be encapsulated by using the PRIVATE attribute. What shall be used outside the module can be declared PUBLIC instead. Use USE with the ONLY attribute to specify which of the variables, type definitions etc. defined in a module are to be made available to the using routine. Of course you do not need to add the ONLY attribute if you include all or nearly all public declarations of a module.
     72* '''PRIVATE attribute''' | Modules variables and routines should be encapsulated by using the PRIVATE attribute. What shall be used outside the module can be declared PUBLIC instead. Use USE with the ONLY attribute to specify which of the variables, type definitions etc. defined in a module are to be made available to the using routine. Of course you do not need to add the ONLY attribute if you include all or nearly all public declarations of a module.
    4973* '''Data initialization''' | Improper data initialization is another common source of errors. A variable could contain an initial value you did not expect. This can happen for several reasons, e.g. the variable has never been assigned a value, its value is outdated, memory has been allocated for a pointer but you have forgotten to initialize the variable pointed to. Some compilers initialize variables to zero but when you port your code to another computer that does not do this previously working code will no longer work this can take some time to diagnose and longer to resolve. To avoid such mishaps, '''initialize''' variables as close as possible to where they are first used. If possible, give a default initial value in the declaration statement.
    5074* '''Constants and magic numbers''' | Magic numbers should be avoided. Physical constants (e.g. pi, gas constants) must never be hardwired into the executable portion of a code. Instead, a mnemonically named variable or parameter should be set to the appropriate value, probably in the setup routine for the package. We realize that many parametrizations rely on empirically derived constants or fudge factors, which are not easy to name. In these cases it is not forbidden to leave such factors coded as magic numbers buried in executable code, but comments should be included referring to the source of the empirical formula. Hard-coded numbers should never be passed through argument lists. One good reason for this rule is that a compiler flag, which defines a default precision for constants, cannot be guaranteed. FORTRAN 2003 allows specification of the precision of constants through the "_" compile-time operator (e.g. 3.14_dp or 365_i8). So if you insist on passing a constant through an argument list, you must also include a precision specification in the calling routine. If this is not done, a called routine that declares the resulting dummy argument as, say, real(dp) or 8 bytes, will produce erroneous results if the default floating point precision is 4 byte.
    5175* '''INTERFACE blocks''' | Explicit interface blocks are required between routines if optional or keyword arguments are to be used. They also allow the compiler to check that the type, shape and number of arguments specified in the CALL are the same as those specified in the subprogram itself. FORTRAN 2003 compilers can automatically provide explicit INTERFACE blocks for routines contained in a MODULE.
    5276
    53 == (5.2) Allowed operators ==
     77== (2.3) Pre-processor directives ==
     78PALM works with the C Pre-Processor (CPP), available on any UNIX platform, and covered by most FORTRAN compilers. The use of pre-processor directives inside the code allow to specifically exclude or include parts of the code for compilation.
     79Only few pre-processor directives are used in PALM ([wiki:doc/app/cpp_options list of directives]), and activated by the {{{%cpp_options}}} variable in the .palm.config.<configuration_identifier> file.
     80
     81In the code, use this syntax (starting at first character of a line):\\
     82{{{
     83#if defined(__parallel)
     84    some code
     85#endif
     86}}}
     87together with the standard logical operators {{{!}}} (instead of .NOT.), {{{||}}} (instead of .OR.), {{{&&}}} (instead of .AND.), e.g.
     88{{{
     89#if ! defined(__parallel) && (__netcdf)
     90}}}
     91
     92== (2.4) Allowed operators ==
    5493* Use /=, <, <=, ==, >, >=, etc. as relational operators instead of .GE., .LT., etc.
    5594* Use .AND., .OR., .NOT. as logical operators
    5695
    57 == (5.3) Preprocessor directives ==
    58 PALM works with the C Pre-Processor (CPP), available on any UNIX platform, and covered by most FORTRAN compilers.
    59 Only few pre-processor directives are used in PALM ([wiki:doc/app/cpp_options list of directives]), and activated by the {{{%cpp_options}}} variable in the .palm.config.<configuration_identifier> file.
    60 
    61 In the code, use this syntax (starting at first character of a line):
    62 {{{#if defined(__parallel)
    63       some code
    64 #endif}}}
    65 together with the standard logical operators '''!''' (instead of .NOT.), '''||''' (instead of .OR.), '''&&''' (instead of .AND.), e.g.
    66 {{{#if ! defined(__parallel) && (__netcdf)}}}
    67 
    68 == (5.4) Code structure ==
    69 '''(move somewhere else)'''
    70 * one module per file (only exception: modules.f90)
    71 * clarify program entities, i.e. use {{{SUBROUTINE <name> ... END SUBROUTINE <name>}}}, same holds for INTERFACE, MODULE, PROGRAM
    72 
    73 == (5.5) Error messages ==
     96== (2.5) Error messages ==
     97(will follow)
    7498* Use message routine (explain parameters here...)
    7599* I/O error conditions via IOSTAT (is this fail-safe for different compilers?)
    76100
    77 == (5.6) Code optimization ==
    78 ???
    79 
    80 \\
    81 = (2) Documenting & commenting =
    82 {{{
    83 #!div style="align:'left'; width: 450px; border: 0px solid; float:right"
    84 [[Image(rules_header.png, 450px, right, margin-right=2, margin-top=0, border=0)]]\\
    85 '''Fig. 4''' PALM source-code header example. Click to enlarge.
     101== (2.6) Code optimization ==
     102(will follow)
     103
     104\\
     105= (3) Documenting & commenting =
     106{{{
     107#!div style="align:'left'; width: 450px; border: 0px solid; float:right"
     108[[Image(rules_header.png, 450px, right, margin-right=2, margin-top=0, border=2)]]\\
     109'''Fig. 1''' PALM source-code header example. Click to enlarge.
    86110}}}
    87111Documentation consists of putting information both internally and externally of the source code. Comments should give a good idea of what the code does and where to look for any special activity. PALM supports the use of [wiki:doc/tec/doxygen Doxygen], a tool for generating documentation and flow charts from annotated source code. This requires some special formatting, as described below.
    88112
    89 == (2.1) External documentation ==
     113== (3.1) External documentation ==
    90114You are in the middle of it. We have an extensive online documentation wiki embedded into a [https://trac.edgewall.org/ trac] project management system, directly connected to the svn repository, allowing to [browser browse the PALM code] @ all its former and of course current revision in a web-based environment.\\\\
    91115Your carefully developed code can only be used, if there is a documentation that tells the PALM user how to use and steer the feature. All pages can be accessed from the main [wiki:doc Documentation] page (see index on the left). There are pages for [wiki:doc#Modeldescription model/code description], and [wiki:doc#Usermanual user-manual] pages that explain about model steering, data analysis and debugging. Have a look at and discuss with us where your documentation material fits in best.
    92116
    93 == (2.2) Internal documentation ==
     117== (3.2) Internal documentation ==
    94118'''File header section'''
    95 (see Fig. 4)
     119(see Fig. 1)
    96120a. Doxygen command for FORTRAN file name ('''!>''' starts a doxygen command line)
    97121b. PALM license section (you may have to add other licenses if allowedly implementing code from other models)
     
    151175
    152176\\
    153 = (3) Naming conventions =
    154 == (3.1) Use of lower & upper case letters ==
     177= (4) Naming conventions =
     178== (4.1) Use of lower & upper case letters ==
    155179* '''Upper case:''' FORTRAN keywords and intrinsic functions or routines, e.g.
    156180  * SUBROUTINE, MODULE, etc.
     
    161185* '''Lower case:''' Everything else!
    162186
    163 == (3.2) Names for routines and variables ==
     187== (4.2) Names for routines and variables ==
    164188Use clear, unambiguous naming in '''lower-case letters''', with  individual words separated by underscore.
    165189* MODULE/SUBROUTINE: name is constructed (if applicable) as verb followed by object, e.g.\\
     
    178202
    179203\\
    180 = (4) Formatting & sorting =
     204= (5) Formatting & sorting =
    181205Line length limit: '''132''' characters (hard limit)
    182206
    183 == (4.1) Indentation, spaces & line breaks ==
     207== (5.1) Indentation, spaces & line breaks ==
    184208'''__General module/subroutine structure'''
    185 (see Fig. 1)
    186 {{{
    187 #!div style="align:'left'; width: 450px; border: 0px solid; float:right"
    188 [[Image(rules_indent_general.png, 450px, right, margin-right=2, margin-top=0, border=0)]]\\
    189 '''Fig. 1''' Indentation example with highlighted whitespaces. Click to enlarge.
     209(see Fig. 2)
     210{{{
     211#!div style="align:'left'; width: 450px; border: 0px solid; float:right"
     212[[Image(rules_indent_general.png, 450px, right, margin-right=2, margin-top=0, border=2)]]\\
     213'''Fig. 2''' Indentation example with highlighted whitespaces. Click to enlarge.
    190214}}}
    191215* '''0 whitespace''' in front of pre-processor directives
     
    201225
    202226'''__Whitespaces between brackets'''
    203 (see Fig. 1)
     227(see Fig. 2)
    204228* '''0 whitespace''' between string and '''('''
    205229* '''1 whitespace''' after '''(''' and before ''')'''\\(only exception: '''0 whitespace''' for brackets containing array indices)
     
    207231\\\\\\\\\\\\\\\\\\\\\\\\
    208232'''__Whitespaces in DO loops, IF blocks, CASE structures'''
    209 (see Fig. 2)
    210 {{{
    211 #!div style="align:'left'; width: 450px; border: 0px solid; float:right"
    212 [[Image(rules_indent_loops.png, 450px, right, margin-right=2, margin-top=0, border=0)]]\\
    213 '''Fig. 2''' Indentation & whitespaces in loops. Click to enlarge.
     233(see Fig. 3)
     234{{{
     235#!div style="align:'left'; width: 450px; border: 0px solid; float:right"
     236[[Image(rules_indent_loops.png, 450px, right, margin-right=2, margin-top=0, border=2)]]\\
     237'''Fig. 3''' Indentation & whitespaces in loops. Click to enlarge.
    214238}}}
    215239* In general: '''1 whitespace''' everywhere and '''3 whitespace''' for each indentation level
     
    221245
    222246\\\\\\\\\\
    223 == (4.2) Alignment ==
    224 (see Fig. 3)
    225 {{{
    226 #!div style="align:'left'; width: 450px; border: 0px solid; float:right"
    227 [[Image(rules_align.png, 450px, right, margin-right=2, margin-top=0, border=0)]]\\
    228 '''Fig. 3''' Alignment example. Click to enlarge.
     247== (5.2) Alignment ==
     248(see Fig. 4)
     249{{{
     250#!div style="align:'left'; width: 450px; border: 0px solid; float:right"
     251[[Image(rules_align.png, 450px, right, margin-right=2, margin-top=0, border=2)]]\\
     252'''Fig. 4''' Alignment example. Click to enlarge.
    229253}}}
    230254* Block-wise alignment of continuation line mark '''&'''
     
    235259* Alignment of related code, e.g. in complex equations or setting of initial values for variables '''(missing in png)'''
    236260
    237 == (4.3) Alphabetical sorting ==
    238 * Members in ONLY lists of USE statements (see e.g. Fig. 3)
     261== (5.3) Alphabetical sorting ==
     262* Members in ONLY lists of USE statements (see e.g. Fig. 4)
    239263* Parameters in NAMELISTS (see e.g. initialization_parameters NAMELIST in parin.f90)
    240 * Declaration types (first CHARACTERs, then INTEGERs, etc., see Fig. 3)
    241 * Variables in declaration statements (see Fig. 3)
     264* Declaration types (first CHARACTERs, then INTEGERs, etc., see Fig. 4)
     265* Variables in declaration statements (see Fig. 4)
    242266
    243267
    244268
    245269\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    246 == (6) Final steps ==
    247 '''Good practice'''
    248 * no warning/error message should remain during compile (also try debug options)
    249 
    250 '''Clean up'''
    251 * PRINT/WRITE statements for debugging
     270= (6) Final steps =
     271== Good practice ===
     272* No warning/error message should remain during compile (also try debug options)
     273
     274== Clean up ==
     275* Remove PRINT/WRITE statements for used for debugging
    252276* Check that all parameters are used
    253 
    254 
    255 
    256 -------------
    257 * place '''&''' character for line continuation at position 80 (minimum), max at position 120\\('''Note:''' FORTRAN-2003 defines a limit of 39 continuation lines)
     277* Check that you have applied all the above listed rules