Fortran code conventions

Facts, news, and guidance about ROMS software

Moderators: arango, robertson

Post Reply
Message
Author
csherwood
Posts: 39
Joined: Fri Apr 02, 2004 4:46 pm
Location: USGS, Woods Hole, USA

Fortran code conventions

#1 Unread post by csherwood »

I am developing some code that will eventually be included in ROMS, but right now, I am compiling and testing outside the ROMS environment. To make life easier later, I want to write the code using ROMS code conventions. So:

1) Can I (should I) use intrinsic array operators like

Code: Select all

integer :: IMAX = 100, JMAX = 100
real :: a(IMAX,JMAX), b(IMAX,JMAX), c(IMAX,JMAX)
...
c = a*b
or should I use for loops?

2) I'd like to use the _r8 suffix on numbers...but would rather not get involved with CPP...is there some quick way to do this?

3) Any list of "best practice" coding for ROMS?

User avatar
arango
Site Admin
Posts: 1367
Joined: Wed Feb 26, 2003 4:41 pm
Location: DMCS, Rutgers University
Contact:

#2 Unread post by arango »

Well because of parallelism, you need to use loop structure in ROMS according to the C-grid type. In ROMS, all the horizontal array dimensions (LBi:UBi,LBj:UBj) are the same for all arrays to facilitate parallelization. Some of the elements are never used (U- and V-type variables). For example, a RHO-type variable interior point values are assigned using the following loop structure and horizontal computational indices (Istr:Iend,Jstr:Jend):

Code: Select all

         DO j=Jstr,Jend
            DO i=Istr,Iend
...
            END DO
         END DO
Notice that (LBi:UBi,LBj:UBj) and (Istr:Iend,Jstr:Jend) are not the same :!: The former has local (global) values in distributed-memory (serial and shared-memory) applications. There is a difference between global and private variables. In private variables, we need to follow the rules of parallelism for ghost-points. In some cases vales are needed for i-1, i+1, j-1, and j+1 operations. Now, there is also the issue of land/sea masking. Notice that almost all the executable code is pretty much in F77 with a F90 superstructure. Therefore, advanced F90/F95 syntax is not used. This syntax performs differently in various compilers.

The command for array operation c = a*b is illegal in any of adjoint-based codes.

A good guideline is to check any of the ROMS kernel routines and follow the few roules. Notice that we have a special continuation roules:

Code: Select all

      CALL omega_tile (ng, tile,                                        & 
     &                 LBi, UBi, LBj, UBj,                              & 
     &                 ...)
Last edited by arango on Thu Jun 12, 2008 6:04 am, edited 4 times in total.

User avatar
kate
Posts: 4091
Joined: Wed Jul 02, 2003 5:29 pm
Location: CFOS/UAF, USA

#3 Unread post by kate »

What Hernan is saying is that he's obeying both the free- and fixed-format Fortran rules. Then you don't have to know how to tell the compiler which to use.

User avatar
arango
Site Admin
Posts: 1367
Joined: Wed Feb 26, 2003 4:41 pm
Location: DMCS, Rutgers University
Contact:

#4 Unread post by arango »

Here is a guidance for style:
  • Documentation is always welcome.
  • Implicit none must be use in all program units.
  • Use uppercase for all standard fortran commands and intrinsic functions.
  • Use lowercase for mostly all the executable code. Recall that some compilers are not case sensitive.
  • To improve readability indent code within DO, DO WHILE, block IF and other constructs by 2 characters.
  • Do not use tab characters. This will ensure that the code looks as intended when ported.
  • Use meaningful variable names, preferably in English. Avoid Fortran intrinsic name variables.
  • Commented lines should have ! in the first column.
  • To insure both fixed- and free-format compiling, use the following conventions about comments and and line continuations:
    a) Comments must begin only with ! at first column.
    b) Line continuations must have the following form:

    Code: Select all

                 line.first     &
               & line.second    &
               & line.third     &
               & ...            &
               & line.last
    
    The '&' on the left (right) side of the line must be located at column 6 (73) to insure it is not read by the F77 compiler.
    c) Avoid comments to the right of continuation because they must be pushed after column 73. Otherwise, it will prevent a correct continuation by the F90 compiler. This is illegal:

    Code: Select all

    line.first   ! comment here   &
  • It is highly recommended to set the precision and range of Fortran real computations in mod_kinds.F. The promotion of real precision from compiler flags is not recommended. This is a very important issue since it will affect the efficiency of the computations. Users should experiment with the correct values for the F90/F95 intrinsic function SELECTED_REAL_KIND. In some instances, technical expertise is required. See sample program Programs/types.F which is provided to explore precision and range. Special care is needed in some Cray computers. The values provided by default pretty much will work on mostly all computers. By default we recommend to perform all the computations in double precision.
  • All numeric floating-point (real) constants should have the _r4, _r8, or _r16 subscript for 32 (single precision), 64 (double precision), and 128 (quadruple precision) bit representation, respectively, as defined in mod_kinds.F. For example: g=9.81_r8 (acceleration due to gravity).
  • The state arrays are arranged in structures, according to nested grid, and are dynamically allocated. The allocation is via dereferenced pointer structures. All private (scratch) arrays are automatic. All the state arrays are passed as arguments to the computational routines to facilitate nesting. The main computation routines are also included in modules to exploit the strong typing capabilities of F90/F95. That is, the compiler checks all the arguments passed to subroutines during compilation.
  • All routines must allow both parallel paradigms: shared-memory and distributed-memory. ROMS has a coarse-grained parallel design. The shared-memory option follows OpenMP 2.0 standard. The distribute-memory code is via MPI. Both parallel paradigms coexist in the same code and are activated with C-preprocessing options during compilation.
I will continue updating this list and then we add this information to WikiRoms...
Last edited by arango on Thu Jun 12, 2008 6:08 am, edited 2 times in total.

User avatar
m.hadfield
Posts: 521
Joined: Tue Jul 01, 2003 4:12 am
Location: NIWA

#5 Unread post by m.hadfield »

By the way, the "_r8" stuff is not done via CPP these days. r8 is a parameter defined in mod_kinds.F:

Code: Select all

integer, parameter :: r8 = selected_real_kind(12,300)

User avatar
kate
Posts: 4091
Joined: Wed Jul 02, 2003 5:29 pm
Location: CFOS/UAF, USA

Re: Fortran code conventions

#6 Unread post by kate »

Special care is needed in Cray computers.
Not all Cray computers - they now make Linux clusters too (we're getting one).

User avatar
arango
Site Admin
Posts: 1367
Joined: Wed Feb 26, 2003 4:41 pm
Location: DMCS, Rutgers University
Contact:

Re: Fortran code conventions

#7 Unread post by arango »

Here is the guidance for coding:
  • When possible, use automatic arrays in preference to other forms of dynamic memory allocation.
  • Avoid using COMMON blocks, use MODULE instead.
  • Avoid using EQUIVALENCE, use POINTER or derived data types instead.
  • Avoid using assigned and computed GO TOs, use the CASE construct instead.
  • Avoid using arithmetic IF statements, use the block IF construct instead.
  • Avoid using labeled DO constructs, use END DO instead.
  • Always compile once with array bounds (-C in some compilers) to insure that we are not getting computations with out range variables. Recall that computations are very expensive with array bound checking. However, you need to compute only couple of time steps.

Post Reply