A computer language is not just a way of getting a computer to perform operations … it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.
These notes can be useful in writing Fortran programs that are clean, portable, and modern. Beyond these qualities, it is also nice to look at code that is easy to read as well as maintain. Standardization is important in computer programming because it promotes compatibility, interoperability, and repeatability. Also, please help yourself to this Fortran template.
Formula Translating System Standard
Some Programming Guidelines
Use free source formIndent two spaces after the line continuation character &. You can put & anywhere, but I like to put them in column 132—I just think it makes the code look nicer.
Replace DO WHILE statementsDO WHILE becomes DO ... IF() EXIT ... END DO for better control; need opposite relational operators, e.g., <= becomes >. Be careful about over-counting.
Use generic intrinsic functionsAlways use generic intrinsic functions—e.g., ABS, SIN, COS, EXP, LOG, SQRT, etc.—for mathematical operations. This rightly gives the compiler the task of how to handle their arguments (real, complex, etc.).
Use white space between mathematical operatorsPut spaces between the mathematical operators +, −, *, and /.
Use lowercase edit descriptorsEdit descriptors for PRINT, READ, and WRITE statements should be lowercase; see Rule 29.
Manage variables using MODULECollect variables into MODULE Shared with modern declaration syntax; if possible, include PARAMETER constants to 15 decimal places (double precision) and employ derived-type objects using TYPE.
USE only what you needImport as many module entities as is practical into functions and subroutines with USE Shared, ONLY :. The statement IMPLICIT NONE always follows a USE statement. Aside: functions and subroutines are collectively referred to as procedures, which can be thought of as subprograms.
Double precision everywhereUSE, INTRINSIC :: ISO_Fortran_env, dp=>REAL64. Also, use the suffix _dp as a way of casting a single precision literal using a KIND parameter, e.g., 1.234_dp. It can be nicer to look at in some cases; please see more at Stack Overflow.
Text labels on DO loopsGive your DO loop a name: my_loop: DO ... END DO my_loop.
Use ALLOCATABLE arraysALLOCATABLE arrays offer significant advantages in memory management and execution speed when the functionality of pointers is not needed.
Use uppercase exponent notatione+ becomes E+; e− becomes E−. Of course, one could go a step further and replace all Es with Ds—see Rule 8. Make sure to pad single-digit exponents, e.g., D+02 instead of D+2.
Release files from their associated UNIT numbersAlways pair a CLOSE statement with an OPEN statement; .dat extension on file names.
Don't have bare END statements'Tis better for all END statements to specify what they are ending, e.g., END MODULE Shared.
PROGRAM name and file name should be the same
Use a consistent set of rules for caseKEYWORD; variable; Function; Subroutine; Module; Type; option; ATTRIBUTE; specifier; STATEMENT; INTRINSIC.
Use optional white space in statements and keywordsTake advantage of separating blanks in (and around) statements and keywords. Things like IF (...) and == , etc.
Place a space after all commasAlso: use single quotes, ', for internal strings and double quotes, ", for external strings.
Use symbolic relational operatorsMake your code more closely resemble the mathematics by adopting the symbolic relational operators <, <=, /=, ==, >=, and >.
Use square bracket notation for array constructorsFor rank 1 arrays, Fortran 2003 introduces the use of square brackets  to delimit an array constructor. For arrays of rank 2 or greater, the DATA statement needs to be used … usually declared in a module.
Reduce long argument listsPass derived-type objects between procedures. (These don't need to be passed as dummy arguments.) Especially handy if a group of parameters has an identifiable theme.
Use assumed-shape arrays as dummy array arguments in subprogramsThese can be tricky. For example, REAL, INTENT(IN OUT) :: dummy_array(:); see Rule 25. The compiler may request that you write an explicit interface for your subprogram: Explicit interface required for ... assumed-shape argument. In doing so, you will be assisting the compiler in looking for potential problems. Please see the Notes for more details. If assumed-shape arrays are not working (I don't blame you), then just pass the size of the array as an argument to your procedure—it's not graceful, but it works.
Allow strings of varying lengthDeclare an assumed-length string: CHARACTER(LEN=*), INTENT(IN) :: string; use a deferred-length parameter specification: CHARACTER(LEN=:), INTENT(IN OUT), ALLOCATABLE :: dummy_string. Rule 29. has more info on usage.
Write all loops that index arrays of rank 2 or greater (nested loops) such that the innermost rank varies firstTo avoid large jumps in memory references, arrange loops to vary indices in "reverse" order.
Assign the CONTIGUOUS attribute to assumed-shape arraysAssist the complier in generating optimized code by avoiding unnecessary copying of data when invoking subprograms.
Manage UNIT numbers as a resourceGive your file a name: INTEGER, PARAMETER :: my_file = 10; avoid using single-digit unit numbers. Remember that Fortran reserves two unit numbers for user I/O with respect to the READ and WRITE statements: 5 for input (read) from the keyboard and 6 for output (write) to the screen. Also, consider replacing PRINT * statements with formatted WRITE(6, '(...)', advance='no') output statements if you happen to be reading input from the user.
Use recommended specifiers in OPEN statementsEspecially recommended are the specifiers file, access, status, and action. See Rule 28.
Use ASYNCHRONOUS I/O in OPEN statementsDeclare: REAL, DIMENSION(:), ALLOCATABLE, ASYNCHRONOUS :: my_array; implement: OPEN(..., asynchronous='yes').
Use named character constants for format specificationsGive your format a name: CHARACTER(*), PARAMETER :: my_format = '(a, i0, a, g14.7, a)'.
Make dummy arguments predictable and informativeAppend the characters f and s to dummy arguments to specify a FUNCTION and SUBROUTINE, respectively. This has the benefit of informing the programmer how many "levels deep" these parameters are within the overall context of your program. For example, my_variablefsf is buried function-subroutine-function "below" the main program.
Metcalf, Michael. Modern Fortran Explained. Oxford: Oxford University Press, 2011.
Clerman, Norman. Modern Fortran: Style and Usage. New York: Cambridge University Press, 2012.
"What does "Error: Explicit interface required for '*' at (1): assumed-shape argument" mean?" Computer Groups.