Skip to main content

Abstract

In this chapter, we introduce the basic elements of programming using Fortran. After briefly discussing the overall syntax of the language, we address fundamental issues like defining variables (of intrinsic type). Next we introduce input/output (I/O), which provides the primary mechanism for interacting with programs. Afterwards, we describe some of the flow-control constructs supported by modern Fortran (if, case, and do), which are fundamental to most algorithms. We continue with an introduction to the Fortran array-language, which is one of the strongest points of Fortran, of particular significance to scientists and engineers. Finally, the chapter closes with examples of some intrinsic-functions that are often used (for timing programs and generating pseudo-random sequences of numbers).

This is a preview of subscription content, log in via an institution to check access.

Access this chapter

Chapter
USD 29.95
Price excludes VAT (USA)
  • Available as PDF
  • Read on any device
  • Instant download
  • Own it forever
eBook
USD 84.99
Price excludes VAT (USA)
  • Available as EPUB and PDF
  • Read on any device
  • Instant download
  • Own it forever
Softcover Book
USD 109.99
Price excludes VAT (USA)
  • Compact, lightweight edition
  • Dispatched in 3 to 5 business days
  • Free shipping worldwide - see info
Hardcover Book
USD 109.99
Price excludes VAT (USA)
  • Durable hardcover edition
  • Dispatched in 3 to 5 business days
  • Free shipping worldwide - see info

Tax calculation will be finalised at checkout

Purchases are for personal use only

Institutional subscriptions

Notes

  1. 1.

    For example, extended Backus-Naur form (EBNF).

  2. 2.

    EBNF is also useful for defining consistent data formats and even simple domain-specific languages (DSLs).

  3. 3.

    This is related to a legacy feature, which could lead to insidious bugs. The take-home message for new programmers is to always use . The flag can be used, in principle, in gfortran, but this is also discouraged because it introduces an unnecessary dependency on compiler behavior.

  4. 4.

    The special characters are (framed by boxes): , , , , , , , , , , , , (blank), , , , , , , , , , , , , , , , , , and . Certain combinations of these are reserved for operators and separators.

  5. 5.

    A maximum of \(31\) characters were allowed in Fortran 95.

  6. 6.

    A good guideline is to make the code indicate clearly what is being done (through choice of meaningful variable and function names), and then to use the comments to describe the motivations (why it has been done like that, and what other problem-specific aspects are relevant).

  7. 7.

    Exceptions to this rule are compiler directives (“pragmas”), which are specially-formatted comments that communicate additional information to the compiler; examples will be shown in Sect. 5.3, when we will discuss how to specify, using the Open MultiProcessing (OpenMP) extensions, which portions of the code should be attempted to be run in parallel.

  8. 8.

    The previous limit (according to the Fortran 95 standard) was of up to 39 continuation lines.

  9. 9.

    Note that some text editors feature automatic indentation, which makes this easier.

  10. 10.

    Other languages, such as Matrix Laboratory \(^{\circledR }\) (MATLAB) or The R Project for Statistical Computing (R), support dynamic typing, so the type of a variable can change during the execution of the program.

  11. 11.

    It is also possible to define custom types, enabling data-encapsulation techniques similar to C++ (this will be discussed in Sect. 3.3.2).

  12. 12.

    \(1.27e2 \equiv 1.27\times 10^{2}\).

  13. 13.

    This is not a “hard” rule, however, because many factors enter the performance equation—e.g. specialized hardware units within the central processing unit (CPU), the memory hierarchy, vectorization, etc.

  14. 14.

    An intuitive approach would be to reserve one bit for the sign, and use the rest for the modulus. However, to reduce hardware complexity most systems use another convention (“two’s complement”).

  15. 15.

    Note that enabling such options will most probably make the program slower too, so they are not meant for “production” runs.

  16. 16.

    Not to be confused with an equivalence in the mathematical sense. In Fortran, that is represented by the operator, which we discuss shortly, in relation to the type.

  17. 17.

    This is not to be seen as a “silver bullet”, since numerical noise will still corrupt the results, if the algorithm is inherently unstable.

  18. 18.

    Compilers are required to provide a default for each of the 5 intrinsic types, but they may (and most do) support additional kinds.

  19. 19.

    In practice, it is more convenient to use shorter denominators for the -parameters.

  20. 20.

    The situation is more complex for this type, because some values which are exactly representable using the decimal floating-point notation can only be approximated in the binary floating-point notation.

  21. 21.

    We encountered this mechanism in the Fortran distribution of the popular Numerical Recipes book, see Press et al. [12].

  22. 22.

    This approach is more convenient, in the sense that the user does not have to re-compile the program every time the filename changes. For real-world software, we prefer to minimize interaction with users, and allow specification of filenames (e.g. model input) at the invocation command line instead (Sect. 5.5.1), which facilitates unattended runs.

  23. 23.

    If you try this example, you may notice that an additional space is printed at the beginning of every line. This is the default behavior, related to some legacy output devices. We will discuss how to avoid this in Sect. 2.4.

  24. 24.

    The complete network of tasks for obtaining the final data products can become quite complex. In such cases, it often pays off to automatize the entire process, using shell scripts (see Sect. 5.6.1 for a brief overview of the options available, and some suggestions for further reading).

  25. 25.

    See, for example, Java Application Programming Interface (JAPI) for an open-source solution; a commercial alternative is Winteracter.

  26. 26.

    A model which provides a GUI is the Planet Simulator (see Fraedrich et al. [3], Kirk et al. [7]).

  27. 27.

    A lack of graphical interfaces does not imply obsolete software practices: textual, command line interfaces can be readily used to automate complete workflows. This paradigm is suitable for ESS models, which usually need a long time to run. However, GUI-based systems are often suitable for steering operations which complete very fast, such as low-resolution models or tools in exploratory data analysis.

  28. 28.

    In Fortran, formatted I/O means ASCII-text form; conversely, un-formatted I/O means binary form. We do not cover binary I/O in this text, even if it is more space-efficient, due to possible portability issues (we highlight an alternative form of efficient I/O in Sect. 5.2.2).

  29. 29.

    This is discussed later, in Sect. 2.4.2; the process is controlled via an edit descriptor, which is embedded in a format specification.

  30. 30.

    For C/C++ programmers: this is the Fortran equivalent to the , and streams.

  31. 31.

    It is possible, and sometimes useful, to have less edit descriptors than elements in the I/O list. In such situations, the edit descriptors are reused, while switching to a new record (for examples, see Sect. 2.6.5).

  32. 32.

    Special facilities also exist for arrays and derived types. We discuss the former in Sect. 2.6.5, after introducing the corresponding language elements. For the latter, see Metcalf et al. [10].

  33. 33.

    This form is highly recommended, as it relieves the programmer from bugs associated with manually selecting the field width (corrupted, asterisks-filled fields can occur if the number of digits in the number exceeds the expected field width). However, this makes the formatting of values variable, and may not be appropriate for applications where precise control of alignment is important (like compatibility with other programs, or for improving the clarity of the output). Also, note that this approach does not work for input (where would cause any input value to be set to zero).

  34. 34.

    However, unlike , the value of d remains important even in this case, since truncation is usually inevitable when converting floating-point binary numbers to the decimal base.

  35. 35.

    Note that, if the current record is not empty, the number of empty records inserted by such an edit descriptor is \(n-1\).

  36. 36.

    In C, the equivalent statement would be:

  37. 37.

    There is also the option to use -statements, as we mentioned previously. However, their usefulness is limited to the first issue, which is why we chose not to describe them—see Metcalf et al. [10] for details.

  38. 38.

    The general input statement has the same name as the simplified form, but observe the other differences.

  39. 39.

    In Fortran, every statement can be given a label, which is simply a positive integer (of at most 5 digits), written before the statement. These provide “bookmarks” within the code, allowing the program to “jump” to that statement when necessary—either transparently to the user (when the jump results from error handling), or explicitly (using the controversial statement). Please note that explicit jumps with go to are strongly discouraged, as they can quickly make programs difficult to understand!

  40. 40.

    Creating “binary” files is also possible, but we avoid discussing this, in favor of another format which is more appropriate in ESS, i.e., netCDF (see Sect. 5.2.2).

  41. 41.

    Note that there might be some system-dependent restrictions on what constitutes a valid filename.

  42. 42.

    The standard specifies that a negative value (but different from , which signals an error) will be chosen for , to avoid clashes with any existing code that uses the previous method of assigning -numbers, where positive numbers had to be used.

  43. 43.

    Such data loss can occur when writing to files, since most platforms use buffering mechanisms for temporarily storing output data, to compensate for the slow speed of the permanent storage devices (e.g. disks).

  44. 44.

    Strictly speaking, these do not form true I/O operations (the buffers are still memory areas associated with the program, so no external system is involved), but it is convenient to treat them as such (as done for the equivalent class in C++).

  45. 45.

    Here, we imply there is one output file for each time step, to illustrate the idea. Note, however, that this may not always be a good approach. In particular, when the number of time steps is large, it is more convenient to write several time steps in each file (this is supported by the netCDF-format, which we will describe in Sect. 5.2.2).

  46. 46.

    Various technicalities (such as platform dependence of the internal, bit-level representation of the same data) can make the data transfer nontrivial for binary data.

  47. 47.

    Note that the keywords and do not appear in the compact form.

  48. 48.

    The process is called nesting. When used, nesting has to be complete, in the sense that the “parent”-construct must include the “child”-construct entirely (it is not allowed to have only partial overlap between the two).

  49. 49.

    This is a common convention in ESS, where = winter, = spring, = summer, and = autumn (for the northern hemisphere). The acronyms are obtained by joining the first letters of the months in each season.

  50. 50.

    These are, in a sense, the discrete equivalents of \(\pm \infty \).

  51. 51.

    “Non-deterministic” means, in this context, not (easily) determined at compilation time.

  52. 52.

    At least, until the program is terminated forcibly.

  53. 53.

    is an optional name, which allows to clarify to which loop the -command should be applied, in case of multiple nested -loops.

  54. 54.

    Because the merits of a data structure can only be proven in the context of the algorithms applied on them, most references unify these two aspects (e.g. Mehlhorn and Sanders [9] or Cormen et al. [2]).

  55. 55.

    At the risk of stating the obvious: this should not be confused with dimensionality of the physical space (if we store the components of a \(3D\)-vector in an array, that array will have ).

  56. 56.

    So an entity with a more irregular shape, such as the set of non-zero elements of a lower-triangular matrix, needs to be stored indirectly when arrays are used.

  57. 57.

    This is achieved with the -attribute.

  58. 58.

    Here, we refer to the Virtual Memory subsystem, which includes mainly the random-access memory (RAM) and, less used nowadays, portions on secondary storage (e.g. hard-drives) which extend the apparent amount of memory available.

  59. 59.

    This relates to the memory-hierarchy within modern systems. There are usually several layers of cache-memory (very fast, but with small capacity) between the CPU and RAM, to hide the relatively high latency for fetching data from RAM. Most caches implement a pre-fetching policy, and higher performance is achieved when the order in which array elements are processed is close to the array element order. Note that more details need to be considered, for performance-critical (sub)programs (for more information, see Hager and Wellein [5]).

  60. 60.

    The list of indices can also be provided as a \(1D\)-array of size \(n\).

  61. 61.

    Such ranges are very similar to what we illustrated previously for the program-flow construct, except that in this case commas () need to be replaced by colons ().

  62. 62.

    This notation was introduced in Fortran 2003. Note that there is also an older (equivalent) notation, using the tokens and .

  63. 63.

    For array constants this is, naturally, required.

  64. 64.

    This assumes the lower bound for the index is odd, and that the upper one is even.

  65. 65.

    Or surrounded by the pre-Fortran 2003 tokens and .

  66. 66.

    Additional arguments are supported, although not discussed here—see, e.g. Metcalf et al. [10].

  67. 67.

    Strictly speaking, it is still possible to deduce the coordinates of a specific element in the output list, by counting its position, and then comparing this with the expected array element order; however, this can hardly be called productive use of the programmer’s time.

  68. 68.

    Programmers familiar with C++ can think of this as a restricted form of function overloading.

  69. 69.

    is an intrinsic subroutine, described in Sect. 2.7.2.

  70. 70.

    In our examples above, this would mean changing elements of .

  71. 71.

    In many ways, forall is a more restricted version of , which is why we prefer to describe only the latter. The syntax is very similar for both constructs. See, e.g. Metcalf et al. [10] for more details on forall.

  72. 72.

    That being said, we found that both gfortran (version 4.7.2) and ifort (version 13.0.0) support this construct, with the exception of the type specification. Check the documentation of your compiler, for any flags that may need to be added to enable this feature (e.g. , with being the number of parallel threads (for gfortran), or (for ifort)

  73. 73.

    Therefore, the program may successfully compile, but still contain bugs, if some of these implied guarantees do not actually hold!

  74. 74.

    Strictly speaking, those which reference a labelled statement are allowed, as long as that statement is still within the -construct.

  75. 75.

    Pointers are still useful in many contexts, like for constructing more advanced data structures. They too are supported in Fortran, via the -attribute (but Fortran pointers carry more information and restrictions than their C/C++ counterparts). We do not discuss this issue in this text—see, e.g. Metcalf et al. [10] or Chapman [1].

  76. 76.

    This is fundamentally different from randomness in the physical sense, which is driven by the quantum-probabilistic processes at the atomic scale. These effects are then amplified at the mesoscopic scales, due to the large number of degrees of freedom of the system (e.g. climate system, see Hasselmann [6]).

  77. 77.

    In situations where perfect reproducibility of results is necessary, the seeding step could be skipped. However, a more scientifically-robust method to achieve this is to use a sequence of random numbers large enough that the reproducibility is achieved algorithmically.

  78. 78.

    You can check how large the array needs to be for your platform, by calling the seed function like , where is an scalar, inside which the result of the inquiry will be placed.

  79. 79.

    A better solution for seeding may be to use the entropy pool of the OS. In Linux, you can read data from the file (see, e.g. Exercise 10).

References

  1. Chapman, S.J.: Fortran 95/2003 for Scientists and Engineers. McGraw-Hill Science/Engineering/Math, New York (2007)

    Google Scholar 

  2. Cormen, T.H., Leiserson, C.E., Rivest, R.L., Stein, C.: Introduction to Algorithms. MIT Press, Cambridge (2009)

    Google Scholar 

  3. Fraedrich, K., Jansen, H., Kirk, E., Luksch, U., Lunkeit, F.: The planet simulator: towards a user friendly model. Meteorol. Z. 14(3), 299–304 (2005)

    Article  Google Scholar 

  4. Goldberg, D.: What every computer scientist should know about floating-point arithmetic. ACM Comput. Surv. 23(1), 5–48 (1991)

    Article  Google Scholar 

  5. Hager, G., Wellein, G.: Introduction to High Performance Computing for Scientists and Engineers. CRC Press, Boca Raton (2010)

    Book  Google Scholar 

  6. Hasselmann, K.: Stochastic climate models Part I. Theory Tellus 28A(6), 473–485 (1976)

    Article  Google Scholar 

  7. Kirk, E., Fraedrich, K., Lunkeit, F., Ulmen, C.: The planet simulator: a coupled system of climate modules with real time visualization. Technical Report 45(7), Linköping University (2009)

    Google Scholar 

  8. Marshall, J., Plumb, R.A.: Atmosphere, Ocean and Climate Dynamics: An Introductory Text, 1st edn. Academic Press, Boston (2007)

    Google Scholar 

  9. Mehlhorn, K., Sanders, P.: Algorithms and Data Structures: The Basic Toolbox. Springer, Berlin (2010)

    Google Scholar 

  10. Metcalf, M., Reid, J., Cohen, M.: Modern Fortran Explained. Oxford University Press, Oxford (2011)

    Google Scholar 

  11. Overton, M.L.: Numerical Computing with IEEE Floating Point Arithmetic. Society for Industrial and Applied Mathematics, Philadelphia (2001)

    Book  Google Scholar 

  12. Press, W.H., Teukolsky, S.A., Vetterling, W.T., Flannery, B.P.: The art of parallel scientific computing. Numerical Recipes in Fortran 90, vol. 2, 2nd edn. Cambridge University Press, Cambridge (1996). also available as http://apps.nrbook.com/fortran/index.html

  13. Reid, J.: The new features of Fortran 2003. ACM SIGPLAN Fortran Forum 26(1), 10–33 (2007)

    Article  Google Scholar 

Download references

Author information

Authors and Affiliations

Authors

Corresponding author

Correspondence to Dragos B. Chirila .

Rights and permissions

Reprints and permissions

Copyright information

© 2015 Springer-Verlag Berlin Heidelberg

About this chapter

Cite this chapter

Chirila, D.B., Lohmann, G. (2015). Fortran Basics. In: Introduction to Modern Fortran for the Earth System Sciences. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-642-37009-0_2

Download citation

Publish with us

Policies and ethics