Coding style

In free form Fortran files, indentation is 3 spaces.

Indentation/whitespace rules are codified in an EditorConfig file located in the root of the repository (.editorconfig).

Exponents

When raising a number to a power of something use the pow() routines provided by the mathlib:

pow(x,1.5d0)

instead of

x**1.5d0

There are short cut routines for raising a number to a integer powers pow2, pow3, etc.

Errors

In general a subroutine should return as its last argument a integer ierr which denotes whether the subroutine succeeded or not. A value of ierr=0 is to be used to show the subroutine succeeded, any other value of ierr denotes an error. Any meaning in different non-zero values of ierr can only be determined by inspecting the subroutine that set the ierr.

The typical way to handle things is:

integer, intent(inout) :: ierr
ierr = 0

call my_subroutine(x,ierr)
if (ierr /= 0) return

for non-critical errors.

Stop

When signalling a critical error which can not be recovered from you should use:

use utils_lib, only mesa_error

call mesa_error(__FILE__,__LINE__)

Which will generate a backtrace where the error occurs, which aids in debugging. The subroutine mesa_error can also have a optional error message:

use utils_lib, only mesa_error

call mesa_error(__FILE__,__LINE__,"An error occurred")

Do not use:

stop 1

As it can become difficult to distinguish where in the code called stop if multiple functions use stop 1

Doubles

The preferred manner to declare a double precision variable is:

real(dp) :: x

instead of

double precision :: x

When using a numerical value in an expression you must make sure it is evaluated as a double. Thus use:

y1 = 1.5d0 * x
! or
y2 = 1.5_dp * x

Do not leave values as a bare float:

y3 = 1.5 * x

As the 1.5 gets interpreted as a single precision value, and will lead y3 to have a different value to y1 or y2.

OMP critical blocks

OMP critical blocks allow the programmer to specify that a section of code should only be executed by one thread at a time. They can also be given a name:

!$omp critical my_block

Each named critical block will be executed by one thread at a time. Different named critical blocks can be executed at the same time. However, all unnamed critical blocks act like one block and thus can not be executed in parallel. Therefore you should always named your OMP critical blocks to ensure the best performance.

Do not name your OMP critical block with a name that has already been used for a variable, procedure, module or any other object.