Coding Conventions#
Fortran#
Discouraged Functions and Syntax#
- line numbers
They are a relict of the deprecated
gotostatement and not needed.write(*,*)A
print*statement is easier to read thanwrite(*,*).returnThis 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
getandsetfunctionality.Unless the whole module is
public,implicit noneneeds 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
spreadis 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
sumorprod) 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