PFLOTRAN Fortran Formatting Protocol¶
Guidelines¶
Free format
Use
&
for continuationUse
==
,>
,<
,>=
,<=
instead of.eq.
,.eqv.
,.gt.
,.lt.
,.ge.
,.le.
.Do not use goto statements (may not be possible in legacy code blocks)
Use two-space indentation with no tabs.
subroutine PrintIJK() PetscInt :: i do k = 1, 100 do j = 1, 100 do i = 1, 100 print *, i, j, k enddo enddo enddo end subroutine PrintIJK
Use a maximum source width of 80 characters. Use a continuation line beyond.
!123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+ print *, 'This sentence is just barely too long for a single & &line.' call LongSubroutineWithManyArguments(argument1, argument2, & argument3, argument4)
Use a maximum of 32 characters for module/subroutine/variable names. Try to be as concise as possible.
Capitalization
All Fortran syntax should be lower case.
module File_IO_module use Print_module contains subroutine PrintInfo() if () then else elseif endif end subroutine PrintInfoParameters are all caps.
PetscInt, parameter, public :: MAXWORDLENGTH = 32 character(len=MAXWORDLENGTH) :: wordAll subroutines/function names should be CamelCase without underscores.
call FileIOInit() call FileIODestroy()All variable/class/derived type names should be lower case with underscores between words.
PetscMPIInt :: my_rank type(abc_type) :: new_abc class(xyz_class_type), pointer :: new_xyz
All Fortran syntax with multiple words should have a space between words, except for conditionals and loops:
elseif
,endif
,enddo
.select case end select end subroutine
Exceptions:
elseif endif enddo
Pin all module, subroutine, function, and contains declarations up against the left side. This leaves more room for indentation.
The default private/public attribute for modules is
private
.Place
implicit none
at the top of every module.Use
PetscReal
instead ofdouble precision
orreal*8
.Use
PetscInt
instead ofinteger
.Use
PetscBool
instead oflogical
.Use
PETSC_TRUE/PETSC_FALSE
instead of.true./.false.
.For array declarations, use the most concise and flexible format without the dimension statement.
PetscReal :: array(6) PetscInt :: array_1D(6), array_2D(3,100)
instead of
PetscReal, dimension(6) :: array PetscInt, dimension(6) :: array_1D PetscInt, dimension(3,100) :: array_2D
Note that arrays of the same data type may be declared on separate lines for clarity.
All variables in the function/subroutine argument list should be at the top of the routine with a blank line separating them from the ‘implicit none’. The local variables should come below with a blank line separating them from the variables in the subroutine argument list.
subroutine Example(integer_in, real_in) implicit none ! subroutine arguments declared first PetscInt :: integer_in PetscReal :: real_in ! blank line separating local variables PetscBool :: whatever PetscInt :: i PetscInt :: integer1, integer2 PetscInt :: iarray(5) PetscReal, pointer :: array(:)
All pointers used in with PETSc Vec data structures have an _p appended.
PetscReal, pointer :: array_p
User appropriate spacing to improve readability:
if(one_number>another_number.and.a_logical==PETSC_TRUE)then
or
if ( one_number>another_number.and.a_logical==PETSC_TRUE ) then
are better viewed as
if (one_number > another_number .and. a_logical == PETSC_TRUE) then
pressure=rho*gravity*distance
is better viewed as
pressure = rho*gravity*distance
Use integer exponents (e.g., x**3) instead of real exponents (e.g., x**3.d0) whenever possible. With the integer approach, the compiler creates a series of multiplication (i.e., x*x*x) which is less expensive to calculate than the \(x^3 = e^{3 \ln x}\).
Filename and Module/Class Naming Convention¶
Modules and classes are Camel_Case with underscores between words and
_module
(or_class
for Fortran 20XX classes) appended.Reaction_Sandbox_module Reaction_Sandbox_Example_class Reaction_Sandbox_Base_class
The corresponding filename is the module/class name with (1)
_module
or_class
removed, (2) all lower case, and (3) ‘.F90’ appended.reaction_sandbox.F90 reaction_sandbox_example.F90 reaction_sandbox_base.F90
Files containing base classes are always named
XXX_base.F90
.simulation_base.F90 reaction_sandbox_base.F90
Files containing functions/subroutines/modules that are often commonly shared between simulation modes, process models, or implementations are named
XXX_common.F90
.output_common.F90 richards_common.F90
Files containing low level functions/subroutines or non-extended derived types are named
XXX_aux.F90
.output_aux.F90 richards_aux.F90
Files containing functions/subroutines that serve as drivers for all classes of a derived type, should be named
XXX.F90
where XXX is the root function.dataset.F90 reaction_sandbox.F90
Example Fortran Source Code¶
An example source would be
module Example_module implicit none private ! all variables/subroutines, etc. are private by default #include "whatever.h" public :: ExampleCreate, ExampleGetTime PetscReal, save :: file_global_variable contains !************************************************************************** ! subroutine ExampleSetup(integer_in, real_in) ! ! Initializes the grid. ! Author: Jane Doe ! Date: 01/01/23 ! use whatever_module #include "whatever.h" PetscInt :: integer_in ! note that the subroutine arguments are PetscReal :: real_in ! declared first PetscBool :: whatever ! note that declarations are group by type PetscInt :: i PetscInt :: integer1, integer2 PetscReal :: real1, real2 PetscReal :: real3, real4 character(len=MAXWORDLENGTH) :: word PetscReal, pointer :: real_p(:) ... ! use the newer relational operators in logical expressions if (grid%ndof >= 2 .and. (.not.logical_whatever .or. & integer1 /= integer2)) then do i=1,2 call Whatever() enddo elseif (grid%ndof == 1 .and. & (.not.logical_whatever .or. integer1 == integer2)) then call SomethingElse() endif ! fortran select case (similar to C switch) select case (word) case ('flow') call Whatever case ('transport') call Whatever2(argument1, argument2, argument3, argument4, & argument5) end select ... nullify(real_p) end subroutine ExampleSetup !************************************************************************** ! PetscReal function ExampleGetTime(...) ! ! Returns the current time in the simulation. ! Author: John Doe ! Date: 01/01/23 ! use another_module implicit none #include "whatever.h" PetscInt :: integer1 PetscReal :: real1 character(len=MAXWORDLENGTH) :: word ... ... ExampleGetTime = x end function ExampleGetTime end module Example_module