Coding Conventions#
Fortran#
Discouraged Functions and Syntax#
- line numbers
They are a relict of the deprecated
goto
statement and not needed.write(*,*)
A
print*
statement is easier to read thanwrite(*,*)
.return
This statement is superfluous at the end of a subroutine/function.
.lt.
,.le.
,.eq.
,.ne.
,.gt.
, and.ge.
The more readable comparison symbols
<
,<=
,==
,!=
,>
, and>=
are preferred.(/
and/)
The more readable
[
and]
are preferred.
Data Declaration#
Modules#
Public variables are discouraged in favor of object-oriented
get
andset
functionality.Unless the whole module is
public
,implicit none
needs to be followed byprivate
.
Functions#
Functions have no
intent(out)
orintent(inout)
dummy variables.Functions without side effects should be declared
pure
.Possible specifications of return value
real(pReal) | integer [pure] function f(...)
[pure] function f(...) result (res)
Variable declarations follow the order
intent(in)
result
local variables
Subroutines#
Subroutines without side effects should be declared
pure
.Subroutine dummy arguments are sorted
intent(out)
intent(inout)
intent(in)
Variable declarations follow the order
intent(in)
intent(inout)
intent(out)
local variables
Naming Scheme#
Global variables are prefixed by the name of the module.
Parameters are written in CAPITALS.
Common Variable Names#
ho
: homogenization IDph
: phase IDen
: entryce
: cellco
: constituentel
: elementip
: integration point
Indentation and Line Format#
No indentation for modules/programs and functions/subroutines.
Two spaces (no tab stops) per each additional level.
Line should end around 100 characters; a 132 character limit is enforced.
OpenMP directives maintain the current indentation level.
Code Documentation#
Functions, variables, and parameters are described by doxygen tags.
Readable code (e.g. explanative variable names) is preferred over in-line comments.
Recommendations#
Nested control structures (
do
,if
,where
, orselect case
) should be named.IncLooping: do i = 1_pInt, 10_pInt subIncLooping: do s = 1_pInt, 1000_pInt a = a + time(i,s) end do subIncLooping a = 1/a end do IncLooping
instead of
do i = 1_pInt, 10_pInt do s = 1_pInt, 1000_pInt a = a + time(i,s) end do a = 1/a end do
Field initialization with
spread
is preferred over explicit loops.real(pReal), dimension(3,3,10) :: a a = spread(math_I3,3,10)
instead of
real(pReal), dimension(3,3,10) :: a a = 0.0_pReal do i = 1_pInt, 10_pInt a(1:3,1:3,i) = math_I3 end do
Calculations over entire fields should use intrinsic functions (such as
sum
orprod
) instead of explicit loops.real(pReal), dimension(3,3,10) :: a real(pReal), dimension(3,3) :: b b = sum(a)
instead of
real(pReal), dimension(3,3,10) :: a real(pReal), dimension(3,3) :: b b = 0.0_pReal do i = 1_pInt, 10_pInt b = b + a(1:3,1:3,i) end do
Explicit range specifications are preferred over assumed size/shape.
integer(pInt), dimension(3,3,5,5) :: field integer(pInt), dimension(3,3) :: tensor field(1:3,1:3,1,1) = tensor
instead of
integer(pInt), dimension(3,3,5,5) :: field integer(pInt), dimension(3,3) :: tensor field(:,:,1,1) = tensor
Resources#
Python#
Code follows losely PEP 8.
Documentation follows numpydoc style guide