There are many possible programming conventions. Example here should not be considered the correct answer.
In languages where procedure and/or variable names have global scope, it is useful to define a common prefix to avoid namespace collisions. Modern languages provide namespace hierarchies that preclude the need for an explicit prefix on every entity.
Fortran Modules are global scope. Module names for a given code project should include a common prefix. For example, a module named ‘constants’ is likely to cause problems.
Entities within a module do not need a namespace prefix. Doing so just makes the code more verbose.
If you want to USE a module without explicit ONLY statements, and still avoid the potential namepsace collisions, one method is to use a namespace-prefix wrapper module. For example:
module zzz_module_prefixed use zzz_module, only: & zzz_sub1 => sub1, & zzz_sub2 => sub2 end module zzz_module_prefixed
Now, “use zzz_module_prefixed” imports the entire module, but with namespace prefixes on all entities.
Fortran entities all share a common namespace. You cannot have a procedure and a type with the same name. Therefore, type suffixes are useful. The Fortran convention is to prefer full words, so it seems reasonable to use full words whenever it would not become too verbose. I use the following:
* The subroutine and function suffixes are obviously too verbose. These are only used when there is a reason to have subroutine and function versions of the same routine. I typically add a suffix only for the less-used variant. This could be avoided if Fortran allowed specific procedures to share the same generic name.
I do not use a suffix for allocatables because they behave more like normal variables. Pointers need more care, because they can leak memory.
(Joe Krahn) Logical Units should never be defined by a literal integer, including standard I/O units 5 and 6. Traditionally, this required user-defined procedures to allocate a free UNIT, and parameters to define standard I/O units. F2003 defines the units in ISO_FORTRAN_ENV, and F2008 include the OPEN NEWUNIT specifier to automatically allocate a free unit.
UNIT=* to read or write to standard I/O.
Use the values from ISO_FORTRAN_ENV for standard I/O units when necessary.
Always allocate units using F2008 NEWUNIT=, when it is available. Until then, use a function to locate an available unit number.
IMPLICIT NONE has been strongly encouraged for some time. Joe Krahn instead always uses compiler options that disable the default implicit-none. Maybe the next Fortran standard will define IMPLICIT-NONE as the default? Meanwhile, it is just another line of extra verbosity.
Use ‘.f’ for all Fortran source formats. Traditionally, Fortran source always had the ‘.f’ suffix. With Fortran90, ‘.f90’ became the convention, Fortran95 still used ‘.f90’. The ‘.f90’ is really more to indicate free-format source rather than the appropriate language version. Fixed-format should no longer be used for new code. Rather than complicate the suffix issue further by including ‘.f03’ and ‘.f08’, Fortran should revert to the single common suffix, as is the convention in most languages. For example, C99 code still uses the ‘.c’ suffix.
On the other hand, compilers use the suffix to detect whether the source is fixed-form or free-form. If you are using only free-form source, then the above convention is appropriate, and a compiler option must be used to tell the compiler to interpret all files as free-form. If you are mixing fixed and free source, then the most practical solution, until compilers can detect it automatically, is to use ‘.f’ for all fixed-form source and ‘.f90’ for all free-form, regardless of which language specification is being used, thus avoiding the proliferation of version-specific suffixes.
For code intended to be portable, it is useful to compile code under multiple compilers. It is also useful to build both debug and optimized versions. Rather than copying or symlinking source files to multiple build locations, all builds can be done in the same location using subdirectories for intermediate and output files.
This is an example Makefile fragment. It is trimmed down from the actual Makefile to reduce verbosity. It defines $(OUTDIR) to be a subdirectory specific to a given compiler and build option, where all object amd .mod files are written. You can make a small change, then re-build any of the build forms without cleaning and starting from scratch each time.
#BUILD options: openmp, release, profile, debug #FC options: ifort, gfortran ifeq ($(BUILD),) BUILD=release endif ifeq ($(FC),) FC=gfortran endif OUTDIR = $(FC).$(BUILD) #=================================================================== ifeq ($(FC),ifort) CC = icc FFLAGS = -implicitnone -free -module $(OUTDIR) -sox FPPFLAGS = -cpp -I $(OUTDIR) ifeq ($(BUILD),debug) FFLAGS += -g -mp -traceback -debug extended else ifeq ($(BUILD),profile) FFLAGS += -O2 -p -prof-genx else # release or openmp FFLAGS += -O3 -IPF-fp-relaxed ifeq ($(BUILD),openmp) FFLAGS += -openmp LDFLAGS += -openmp endif endif endif ifneq ($(BUILD),openmp) FFLAGS += -stand f03 endif endif #ifort #=================================================================== ifeq ($(FC),gfortran) CC = gcc FFLAGS = -fimplicit-none -ffree-form -J$(OUTDIR) FPPFLAGS = -xf77-cpp-input -I $(OUTDIR) ifeq ($(BUILD),debug) FFLAGS += -g -fbounds-check FFLAGS += -Wunused-parameter -Wunused-variable -Wuninitialized else FFLAGS += -O2 endif endif #gfortran #=================================================================== ifeq ($(FFLAGS),) $(error unknown compiler) endif
Good C programming generally includes status return values for all functions that can produce an error, and proper code should check the error status from every call. Checking and passing back status codes in a call hierarchy can add overhead.
C++ removes the overhead by error handler support that can catch all errors in a hierarchy in one place. Unfortunately, making the errors recoverable also adds overhead, and the throw/catch mechanism can become quite complex for the compiler to handle,
In procedural code, the end result is normally aborted program execution, so all of the error-handling hierarchy is an unnecessary hassle. In this case, the most efficient error-handling system is to simply stop at the point of the error, possibly calling a routine to print information about the error context.
One approach is to make status return codes an optional argument. If the status return is present, the caller can decide how to handle the error. If it is absent, abort with an error message. This is how many Fortran intrinsics work, and it is an effective design that lets the caller choose either a simple procedural method, or a some form of error handling.
Fortran 95 and earlier had no standard support for obtaining command-line arguments. However, with Fortran 2003, several new standard procedures were added to help parse command-line arguments: get_command_argument, get_command, and command_argument_count.
kracken is an open-source library for parsing Unix-like command-line arguments.
f2kcli is an implementation of the Fortran 2003 command line interface for compilers which do not support Fortran 2003.
CLAF90 is a f90-module for parsing command line arguments.
If you are new to the wiki, here is how to start:
Edit this page by clicking the “Edit” link at the bottom and add your name to the list below surrounded by square brackets to create a wiki link.
Type your name again in the “Submit as” field at the bottom of the page and save your changes by clicking the “Submit” button.
When the page reloads, your name should appear in the list followed by a question mark, indicating a link to a page which doesn’t exist yet. Follow this link to create your user page.
Edit and save your user page, optionally adding some information about yourself such how you use Fortran or a link to your homepage.
This page is for linking to available Fortran libraries and source code repositories. See Software repositories for collections of libraries and see Library distribution for methods for packaging and distributing Fortran libraries.
Libraries linked here are classified as follows:
When available, the above tags should link to the license page for a particular library, or to the text of the license itself.
This page is for selected links to source code for or descriptions of applications written in Fortran. These might be examples of contemporary “real-world” programs, or educational older codes. There are thousands of currently active examples across the sciences.
http://www.easterbrook.ca/steve/?p=1558 discusses why a lot of climate models are written in Fortran.
This is 830k LOC
http://www.nemo-ocean.eu NEMO (Nucleus for European Modelling of the Ocean)
http://www.nemo-ocean.eu/content/download/250/1629/file/coding_rules_OPA9.pdf Their Fortran 95 Coding Rules.
http://www.giss.nasa.gov/tools/modelE/ The most recent GISS model.
http://ftp.giss.nasa.gov/pub/modelE/modelE1.tar.gz Source code.
http://igcmg.ipsl.jussieu.fr/Doc/IPSLCM4 IPSL Climate model documentation.
OFF an Open source Finite volumes Fluid dynamics code.
http://aa.usno.navy.mil/software/novas/novas_f/novasf_intro.phpNaval Observatory Vector Astrometry Software. Used to prepare the U.S. parts of The Astronomical Almanac.
Several versions of Zork were ported to Fortran:
And of course, Star Trek:
You can edit this website using the Edit Page link at the bottom of each page. Feel free to use the Sandbox to experiment. The HowTo contains more information on getting started. For questions, see Fortran Wiki discussion.
FoByS.py is a Python script written by Stefano Zaghi for automatic building of modern complex Fortran projects. It is a (poor) replacement of GNU make but with the auto-configuration ability
It is available at https://github.com/szaghi/FoBiS
It is an open-source project distributed under GPLv3
From the FoBiS.py home page:
Proposal: allow a common generic procedure name to contain both subroutines and functions. There is no good rationale for requiring generic procedures to be exclusively subroutines or functions. Currently, that restriction applies to the entire program, even is generic names come from independent modules. Even within a single scope, the CALL statement prevents ambiguity between subroutine and function references.
Regardless of personal options that mixing subroutines and functions would be confusing, this is useful for interfacing C++ classes, where both procedure forms are allowed under the same generic name. (Joe thinks this is just another example of an unnecessary restriction aimed at “forcing” good programming practice.)
|Fortran 2008 features||Absoft||Cray||g95||GNU||HP||IBM||Intel||NAG||Oracle||PathScale||PGI|
|Compiler Version Number||14||8.1.1||4.7/4.8||14.1||14||5.3.1||4||13.7|
|Simply contiguous arrays||N||Y||?||Y||N||Y||Y||N||N||N||N|
|Long integers||Y (100)||Y||?||Y||N||Y||Y (100)||Y||Y||Y||Y|
|Allocatable components of recursive type||N||Y||?||N||N||N||P||N||N||N||N|
|Data statement restrictions lifted||?||Y||?||?||?||N||N||N||?||N||N|
|Kind of a forall index||N||Y||?||N||N||N||Y||N||N||N||N|
|Type statement for intrinsic types||?||Y||?||Y||?||Y||N||N||?||N||N|
|Declaring type-bound procedures||?||Y||?||Y||?||Y||Y||Y||?||N||N|
|Accessing data objects||Absoft||Cray||g95||GNU||HP||IBM||Intel||NAG||Oracle||PathScale||PGI|
|Omitting an allocatable component in a structure component||?||Y||?||N||?||N||Y||Y||?||N||?|
|Copying bounds of source array in allocate||?||?||?||N||?||Y||Y||N||?||N||?|
|Allocating a polymorphic variable||N||Y||?||P (210)||N||P (213)||Y||Y||N||N||?|
|Accessing real and imaginary parts||N||Y||?||N||N||Y||N||N||N||N||Y|
|Elemental dummy argument restrictions lifted||?||Y||?||Y||?||N||N||N||?||?||Y|
|Finding a unit when opening a file||N||Y||?||Y||N||Y||Y||Y||N||N||N|
|g0 edit descriptor||N||Y||?||Y||N||N||Y||N||N||N||N|
|Unlimited format item||N||Y||?||Y||N||N||Y||N||N||N||N|
|The block construct||N||Y||?||Y||N||Y||N||Y||N||N||N|
|Intrinsic procedures for bit processsing||Absoft||Cray||g95||GNU||HP||IBM||Intel||NAG||Oracle||PathScale||PGI|
|Bit sequence comparison||N||Y||?||Y||N||N||Y||Y||N||N||N|
|Counting bits||Y||Y||?||Y||N||Y||Y||Y||N||P (212)||P (214)|
|Bit transformational functions||N||Y||?||Y||N||N||Y||Y||N||N||N|
|Intrinsic procedures and modules||Absoft||Cray||g95||GNU||HP||IBM||Intel||NAG||Oracle||PathScale||PGI|
|Taking radix into account when selecting a real kind||N||Y||?||Y||N||Y||Y||Y||N||N||N|
|Extensions to trigonometric hyperbolic intrinsics||Y||Y||?||Y||N||Y||Y||Y||N||N||Y|
|Error and gamma functions||P||Y||?||Y||N||Y||Y||N||N||P||N|
|Euclidean vector norms||N||Y||?||Y||N||N||Y||Y||N||N||N|
|Execute command line||N||Y||?||Y||N||Y||N||Y||N||N||N|
|Location of max. or min. value in an array||N||Y||?||N||N||N||N||N||N||N||N|
|Find location in an array||?||Y||?||N||N||N||N||N||N||N||N|
|Programs and procedures||Absoft||Cray||g95||GNU||HP||IBM||Intel||NAG||Oracle||PathScale||PGI|
|Save attribute for module and submodule data||?||Y||?||Y||?||Y||Y||Y||?||N||N|
|Empty contains section||Y||Y||?||Y||N||Y||Y||Y||N||N||N|
|Form of end statement for internal and module procedures||?||Y||?||Y||?||Y||N||Y||?||N||Y|
|Internal procedure as an actual argument||N||Y||?||Y||N||Y||Y||N||N||N||N|
|Null pointer or unallocated allocatable as absent dummy arg.||N||Y||?||Y||N||Y||Y||N||N||N||N|
|Generic resolution by pointer or alloc. attr. - procedure||N||Y||?||N||N||N||N||Y||N||N||N|
|Generic resolution by pointer or alloc. attr. - data obj.||N||Y||?||N||N||N||N||Y||N||N||N|
|Elemental procedures that are not pure||N||Y||?||Y||N||N||N||Y||N||N||Y|
|Entry statement becomes obsolescent||N||Y||?||Y||N||Y||Y||Y||N||N||N|
|Semicolon at line start||Y||Y||?||Y||?||Y||N||Y||?||Y||Y|
Legend: Y = Yes, N = No, P = Partial, U = Unconfirmed
integer(kind=8); (200) Only for a single image; (202) Only MOLD=; (203) int and real, and coarray. (210) gfortran via allocate but not via intrinsic assignment (211) NAG has ALLOCATE(MOLD=), but not polymorphic assignment (212) Pathscale, counting bits, not trailz (213) Waiting for update from IBM (214) leads, popent, and poppar supproted. No trailz.
Changes January 2013:
Changes between December 2010 and April 2011:
Extended list of Fortran 2008 features.
Absoft: first issue with available data.
Partial support: Allocatable components of recursive type.
Full support: Coarrays, DO CONCURRENT, CONTIGUOUS attribute, Simply contiguous arrays, Maximum rank, Implied-shape array, Pointer initialization, Kind of a forall index, Allocating a polymorphic variable, MOLD= in ALLOCATE, NEWUNIT= in OPEN, G0 and G0.d edit descriptor, Unlimited format item, CONTAINS may be empty, Additional intrinsic procedures, Additional items in ISO_FORTRAN_ENV.
PGI: first issue with available data.
Changes between August 2010 and December 2010:
Partial support: pointer initialization.
Full support: CONTIGUOUS attribute, simply CONTIGUOUS arrays, implied-shape arrays, EXIT statement, bit sequence comparison, combined shifting, counting bits, masking bits, shifting bits, Bessel functions Euclidean vector norms, parity, execute command line, NULL pointer as a missing dummy argument, ELEMENTAL procedures that are not PURE, ENTRY statement becomes obsolescent.
Changes between April 2010 and August 2010:
Partial support: error and gamma functions.
Full support: coarrays, CONTIGUOUS attribute, simply contiguous arrays, allocating a polymorphic variable,
g0 edit descriptor, unlimited format item, BLOCK construct, stop code, bit sequence comparison, masking bits, selecting a real kind, arc tangent function, location of max or min value in an array, find location in an array, constants, and entry statement becomes obsolescent.
Errata: “null pointer as a missing dummy argument” changed from Y to N.
Partial support: coarrays, allocating polymorphic variables, and constants.
Full support: BLOCK construct, stop code, hyperbolic intrinsic functions, and arc tangent function.
HP: first issue with available data.
IBM: first issue with available data on Fortran 2008 features.
Changes between August 2009 and April 2010:
GFortran added full support for unlimited format items and the error and gamma functions and partial support for the block construct.
Sun added full support for parity.
The information in the above table is from “Compiler Support for the Fortran 2003 and 2008 Standards,” a recurring article in the Fortran Forum by Ian D. Chivers and Jane Sleightholme.