Is it worth learning Fortran

Thomas Slawig32

Despite its proud age of almost sixty years, Fortran can still be found in all sorts of places. Due to its good performance, the language is still very popular, especially for simulation tasks.

Those who come to computer science students today with the programming language Fortran will reap ignorance and - if they show a typical legacy code example - laughter. Constructs like arithmetic if, a lot of goto-Instructions and obscure loops in do-continue-Form seem out of date and contradict almost all paradigms of good, structured or even object-oriented software development.

On the other hand, anyone who studies the list of codes in the current benchmark collection of the Standard Performance Evaluation Corporation (SPEC) for floating point arithmetic CFP2006 [1] will find half of the Fortran codes there, along with those in C and C ++. At the end of the 1980s, Fortran codes or the corresponding compilers with numerical calculations (i.e. mainly using floating point arithmetic) were considered to be superior to the corresponding C variants in terms of performance. Consequently, anyone who works with more technical or scientific applications such as flow or climate simulations almost inevitably has to do with Fortran legacy code.

Fortran, the "Formula Translator", was the first high-level programming language and was developed by John Backus, also known for the Backus-Naur form of the description of programming languages. The first version appeared as early as 1957. The idea behind the language was to provide programmers who wanted to implement formulas a more comfortable interface than what assembler instructions represent. The driving idea can therefore be compared with that of later numerical linear algebra packages such as LINPACK / LAPACK and Matlab: Complex algorithms and libraries should be able to be used through simple interfaces, above all to simplify programming for users. At a higher level of abstraction, the developers of various Domain Specific Languages ​​(DSL) are still pursuing this concern today. The importance of Fortran becomes clear in the choice of the optimizing Fortran compiler as one of the ten best algorithms of the 20th century by the Society for Industrial and Applied Mathematics [2].

Short history lesson

If you take Fortran's release date into account and immerse yourself in the computer world of that time, you can better understand many of the language elements that seem strange today: It was the time of punch cards. Fixed formatting (the special meaning that the first six columns of each line have in old Fortran dialects and the maximum line length of 72) as well as implicit typing of variables and the aforementioned arithmetic if are motivated by saving lines and characters in code.

However, its spread and the importance of the language for numerical simulations has led to Fortran being continuously developed and repeatedly re-standardized. Today it has almost all the properties of a modern and object-oriented language, plus a few more practical ones.

So there are two ways of looking at Fortran. When it comes to code, it depends largely on when or according to which standard it was created. Because of the compatibility, different dialects of the language often appear mixed in legacy code, which does not exactly contribute to clarity and legibility. One can roughly divide into code up to and including Fortran 77 and from Fortran 90, because this is where the greatest change in the standard took place. Very old code in the standard before Fortran 77, in which there were in some cases no loops, is comparatively rare. If, on the other hand, you want to write a new program or a supplementary, neatly separated module, the history is insignificant. It then only depends on what options Fortran offers in the current standard.

Fortran 77

Looked at more closely

There are many Fortran compilers, most of which offer options for choosing the language standard. The GNU compiler gfortran was used for the article. But also Intel, Portland, NAG, Lahey, Absoft, IBM and others offer corresponding tools. They partly differ in whether they initialize variables with zeros, which has caused surprises in many legacy projects when ported.

The widespread standard Fortran 77 is a compact and clear language that shows its original goal: to be able to easily program numerical operations with brief instructions. Listing 1 shows an example program that performs two simple calculations and uses the essential language constructs for this:

1 program simple_fortran
2 c calculate machine accuracy:
3 x = 1.0
4 do100
5 y = x
6 x = x / 2.0
7 if (1.0 + x .eq.1.0) goto200
8 100continue
9 200print *, 'Machine accuracy =', y
10
11 c calculate sum:
12 write (*, *) 'Please enter n:'
13 read (*, *) n
14 sum = 0.0
15 do300 k = 1, n
16 sum = sum + 1.0 / k
17 300 continue
18 write (*, 10), 'Sum of the reciprocal values ​​of the first',
19 & n, 'natural numbers =', sum
20 10format (a, i3,2x, a, f10.2)
21 end

Listing 1: Fortran 77 program

The special features of Fortran 77 are quickly listed: The standard ending for source files is .f and no distinction is made between upper and lower case in the source text. In old code, you can often find keywords in uppercase throughout. The so-called "fixed form" should also be mentioned. It is due to the special meaning of columns 1 (any character marks the line as a comment, see lines 2 and 11 in Listing 1), 2-5 for labels (lines 8,9,17,20) and column 6 for a " Continuation Mark "(which connects the line with the previous one, see line 19).

Every compilable program needs a block program, comparable to the Main-Function in C, C ++ or Java. A further modularization can be achieved through functions with (function) and without return value (subroutine) to reach.

The elementary control structures in Fortran 77 are if-else-Constructs (line 7 in its simplest form) and the do-Loop. On the one hand, it serves as a counting loop, comparable to a for in other languages ​​(lines 15-17 in Listing 1). For another, are with one goto a jump and thus any variants of (do-)while- Loops possible as seen in lines 4 through 8.

Fortran is a language with implicit typing: all variables starting with i to n are whole numbers (data type integer), like the counter variable in the example k and the read upper limit of the loop n. All other variables are single-precision floating-point numbers (Real, in the example x,y and sum). Variables can be declared explicitly, which is recommended in terms of good programming practice.

Only Fortran 90 did it implicit none-Statement that implicit typing is forbidden and should always be used. Double precision floating point numbers are of the type Double Precision or real * 8 respectively real (8)what is all equivalent. The latter notation is used in newer standards.

In line 16 there is an automatic type conversion that Fortran carries out: When dividing the real-Constants 1.0 through an integer value, Fortran converts it to the real type. This corresponds to the procedure in C.

Lines 9, 12, 18 and 19 show the two output options. In the writeStatement, the first argument can be used to specify a file descriptor when writing to a file. Analog enables the readCommand not only to read standard input (as in line 13), but also to read it from a file. The format-The statement from line 20 is also often found in legacy code. The parameter sequence specified there can, in apostrophes and round brackets as a string, also directly for the label 10 as a second parameter of the writeStatement can be used in line 18.

A bizarre example, often cited in a similar form, of an error caused by a typing error and the implicit typing is shown in Listing 2:

1 program test
2
3 do5 K = 1. 3
4 write (*, *) K
5 5 continue
6 write (*, *) do5K, d a t e
7
8 end

Listing 2: Typo

In it stands in the do-Statement instead of the correct comma a period. The beginning of the loop becomes an assignment to the implicitly declared variable do5K. The continue further down, therefore, does nothing at all, but it does not disturb the compiler either. Fortran even ignores spaces, which is aptly commented in a manual from Sun [3]: "Consistently separating words by spaces became a general custom about the tenth century A.D., and lasted until about 1957, when FORTRAN abandoned the practice." (found in [4]).

The output of the program from Listing 2 is therefore a puzzle. Your solution: In line 3, the program assigns the implicitly declared variable do5K the value 1.3 to. In line 4, which is now a simple statement and not part of a loop, the value of the also implicitly declared integer variable k issued. Since it was not initialized, it contains what is currently in the memory, interpreted as an integer value. In line 6 the program now gives the value of do5K off, and off d a t e the variable is created by ignoring the spaces date, implicitly of type Real. It is uninitialized, so the software also outputs the contents of the memory interpreted as floating point numbers at this point. An internet search for "famous Fortran bug" even attributes such an error to the crash of the Mariner 1 space probe, which is denied again elsewhere.

Examples

Examples en masse

Listing 3 contains a function, its call in a main program and the declaration and use of fields. It is possible to save both code parts in one file, but this is not recommended for the sake of a clean structure.

1 program function_example
2 double precision x (10), y (10)
3 integer k
4 double precision scalar_product
5 do100 k = 1.10
6 x (k) = k ** 2
7 y (k) = sin (x (k))
8 write (*, *), x (k), y (k)
9 100continue
10 write (*, *) scalar_product (x, y, 10)
11 end
12
13 double precision function scalar_product (x, y, n)
14 double precision x (n), y (n)
15 integer n, k
16 scalar_product = 0.0d0
17 do100 k = 1, n
18 scalar_product = scalar_product + x (k) * y (k)
19 100continue
20 end

Listing 3: Function with a call

All variables are explicitly declared in the listing and double precision is used for the floating point numbers. In the main program, the function is also declared with the type of its return value (line 4), which is necessary because otherwise it is implicitly a type real would be viewed, which would lead to a type mismatch. In the signature of the function in line 13, the type of the return value is the keyword function prefixed. Alternatively, the name of the function can also be declared in it like a variable with the corresponding type. Lines 5 and 6 show two examples of the mathematical functions available in Fortran (** denotes the power function).

Listing 4 shows a subroutine for swapping the values ​​of two variables and their use in a main program:

1 program subroutine_example
2 integer i, j
3 i = 1
4 j = 2
5 write (*, *) "before: i =", i, "j =", j
6 call swap (i, j)
7 write (*, *) "afterwards: i =", i, "j =", j
8 end
9
10 subroutine swap (i, j)
11 integer i, j, k
12 k = i
13 i = j
14 j = k
15 end

Listing 4: Exchange of values

It shows that Fortran works with references of the parameters (call by reference). This ensures that the values ​​of the variables i and j are swapped. In comparable C code, this would not be the case without the use of references or pointers.

Another characteristic and widely used element in Fortran-77 programs are the so-called Common-Blocks that combine global variables. However, each block only designates a common memory area. It is up to them how developers distribute it to variables in individual subroutines and functions. Listing 5 shows an example (not recommended):

1 program common_blocks
2 common / cb / x, y
3 real x, y
4 x = 1.0
5 y = 2.0
6 write (*, *) 'in the main program:', x, y
7 call sub ()
8 end
9
10 subroutine sub ()
11 common / cb / z
12 double precision e.g.
13 write (*, *) 'in the subroutine:', e.g.
14 end

Listing 5: common block

The same thing happens in the main program and in the subroutine CommonBlock with the name cb is used, but the main program interprets it with two floating point numbers x, y easier and the subroutine with only one (z) of double precision. Both times the same shared memory is accessed, but it is assigned to variables of different types. It is clear that mistakes happen particularly often in this context.

In the pre-Fortran 90 world there are neither dynamic fields nor self-defined, structured data types. Pointers are also not part of the standard. However, many compiler manufacturers are familiar with cray pointers: integer variables that are comparable and compatible with C pointers. With a includeInstruction can be used to include files, often with the ending .inc are provided. In legacy code, global variables are often integrated in common blocks in this way.

Very old code (before the Fortran IV standard, well before Fortran 77) does not yet have the do-Loop. This leads to adventurous constructs: Listing 6 contains the real code structure of an old function in a climate model:

1 IF (A.LE.1.0E-08) GO TO10
2 B = ATAN (C / D)
3 IF (D) 11,10,12
4 11 B = B + E
5 GO TO13
6 12IF (C) 14,13,13
7 14 B = B + 2.0 * E
8 GO TO 13
9 10 IF (C) 15,16,17
10 15 B = 1.5 * E
11 GO TO 13
12 16 B = 0.0
13 GO TO13
14 17 B = E / 2.0
15 13 F = B / G

Listing 6: Climate model

In it comes the aforementioned arithmetic if for use (lines 3, 9). Depending on whether the value in brackets behind the if is less than, equal to or greater than zero, the program jumps to the corresponding one of the three labels specified after it. Such code contradicts pretty much everything that is nowadays understood to be good, structured programming practice and is hardly readable.

All the details of Fortran 77 will not be discussed here. If you want to immerse yourself in the world before Fortran 90 or have to do with old code or parts of code, you can rummage through old editions of corresponding books (e.g. [5]). Many of them are antiquarian available for cents.

All in all, Fortran 77 has a number of options that tempt you to program unclean and therefore error-prone code. On the other hand, a consistently explicit typing and the avoidance of adventurous constructs can result in faster, easily readable code.

One advantage of Fortran 77 is that it is slightly similar to C code. Since the data types have mutual equivalents (C: float - Fortran: real, doubledouble precision or real (8), intintegrity) there are no problems at this point. However, you should check the correspondence carefully with the respective compilers. Fields can also be passed from one language to another, for example when calling a function, since the C pointers are compatible with the references of the Fortran fields. Note the reverse storage method for multi-dimensional fields: C stores them line by line, Fortran by column. Listing 7 shows an example of a call to the Fortran subroutine from Listing 4 from a C program:

1 #include
2
3 extern int swap_ (int *, int *);
4
5 int main () {
6 int i = 1, j = 2;
7 printf ("before: i =% i, j =% i \ n", i, j);
8 swap _ (& i, & j);
9 printf ("after: i =% i, j =% i \ n", i, j);
10 return 0;
11 }

Listing 7: Calling Fortran from C

Note the address operators for the integrity-Variables in C, because Fortran only knows "Call by reference". The GNU compiler used first translated with gfortran -c swap.f the Fortran subroutine, which is on its own in a file swap.f and thus created the object file swap.o. The analogous step for the C main program from Listing 7 was then carried out with gcc. Then left with gfortran listing7.o swap.o Generate an executable program from both object files. Depending on the compiler, the underscore must be appended to the name of the Fortran subroutine (lines 3 and 8 in the C program).

Fortran 90

Next generation Fortran

Version 90 marks the beginning of the second epoch of the Fortran language. With it, many of the weaknesses and shortcomings mentioned were eliminated. Most compilers identify Fortran-90 programs by the extension .f90. In order to be able to better delimit the code, corresponding programs are often written in lower case throughout, although the language still makes no difference between upper and lower case. Often one can also make the suggestion not to indent the bodies of subroutines and functions. Apple's Xcode development environment, which has Fortran syntax highlighting, for example automatically formats Fortran code in this way, although this does not necessarily improve readability. There is no strict rule, so developers should be prepared for all kinds of more or less wild formatting with legacy code.

With the introduction of the new version, most compilers also made it possible to run the C preprocessor upstream, mostly using the file extension .F. The old Fortran-include- Statements often through #include- Replaced preprocessor directives. However, preprocessor instructions are often accompanied by their #if-Used conditional compiling directives, which can make code extremely difficult to read. In some program codes there are subroutines that start directly with a #if begin and the associated #endif end up. The compiler therefore only translates the entire code if the value in the variable named in the directive is appropriate. Unfortunately, it is not always possible to use option files that set parameters with which the corresponding functions can be called at runtime.

What is essential in Fortran 90 is the introduction of the so-called Free Format, in which the old regulation of column meanings has been repealed. The continuation mark is now an & at the end of the line to be connected to the following. A more modern structuring of loops enables the more legible ones doInstructions with a enddo instead of the combination of label and continue in the end as well as the do-while-Variant. There are also one break-Instruction to prematurely exit loops and a case/switch-Construct. They offer Fortran 90 the options that are available in other languages ​​such as C.

Listing 8 shows the Fortran 90 version of the program from Listing 1 in free format:

1 program fortran90
2 implicit none
3 real x, y, sum
4 integer n, k
5! calculate machine accuracy:
6 x = 1.0
7 do while (1.0 + x> 1.0)
8 y = x
9 x = x / 2.0
10 end do
11 print *, 'machine accuracy =', y
12
13! calculate sum:
14 write (*, *) 'Please enter n:'
15 read (*, *) n
16 sum = 0.0
17 do k = 1, n
18 sum = sum + 1.0 / k
19 end of Thursday
20 write (*, '(a, i3,2x, a, f10.2)'), ↲
'Sum of the reciprocal values ​​of the first', ↲
n, 'natural numbers =', sum
21 end program

Listing 8: Fortran 90 program

There is now one do-whileLoop (lines 7-10) that continue is through a enddo replaced and the labels are superfluous. A ! introduces comments: The compiler ignores everything that follows in the line. The old comparison operators remain valid, but are supplemented by the more common form (> alternative to .gt. for "greater than" in the example, see that .eq. For equal in Listing 1). In addition, the implicit none-Instruction for use, it forces the declaration of all variables and must appear directly at the beginning of every program and every function or subroutine to which it applies.

The introduction of dynamic fields (arrays) is another major innovation in Fortran 90. An example can be seen in Listing 9:

1 program arrays
2 implicit none
3 integer :: n = 3
4 real (8), allocatable :: x (:)
5! real (8), allocatable, dimension (:) :: x
6 real (8), allocatable :: A (:, :)
7 real (8), allocatable, target :: y (:)
8 real (8), pointer :: p (:)
9 real (8) d
10 allocate (x (n))
11 allocate (y (n))
12 allocate (A (n, n))
13 x = 1.0d0
14 y = 2.0d0 * x - 3.0d0
15 p => y
16 A = 3.0d0
17 d = dot_product (x, y)
18 A = matmul (A, A)
19 write (*, *) d
20 write (*, *) x
21 write (*, *) y
22 write (*, *) p
23 write (*, *) A
24 deallocate (x, y, A)
25 end program

Listing 9: Dynamic fields

The program creates a dynamic field in line 4, gives it memory space in line 9 and releases the latter again in line 23. The double colons in the declaration are now necessary because the keyword allocatable must be specified. The above-mentioned modern notation can be found in the listing real (8) use for double precision floating point numbers. The commented out line 5 shows an equivalent notation. Line 6 shows the creation of a two-dimensional field and line 8 shows a pointer that should point to a one-dimensional field, which it does in line 15. Variables to which a pointer should point must target-Attribute received. The Fortran 90 pointers are not comparable or compatible with those from C. The implementation of dynamic arrays is generally less error-prone than in C, because no pointers are required for it. In addition, operations on entire fields were made possible (lines 13, 14 and 16) and various functions were introduced on fields (in the listing in lines 17, 18 for the scalar and matrix product), which ensures significantly shorter and more readable code and Matlab -Syntax is similar. The ending d0 for the constants in lines 13, 14 and 16, the correct spelling is in scientific format for double-precision constants (hence d), with mantissa (before the d) and exponent (after the d). That would not be necessary at this point, since otherwise, as in C, an automatic conversion from single precision to the type of the variable (i.e. double precision) would take place.

Derived types and modules

An important addition to Fortran 90 are self-defined, structured data types, so-called "Derived Types", which will be described later. In addition, the standardization committee introduced the concept of modules, which among other things is a replacement for CommonBlocks are. As in the latter, global variables can be summarized there. After that it is possible to use the instruction on it from any function or subroutine use to access. With use , only: use is also possible to a limited extent. Listings 10 and 11 show the alternative to the Common-Blocks from Listing 5 when using the modules: The module in Listing 10 contains the declaration of the two variables, in Listing 11 the module is integrated and global variables can be accessed.

1 module xy_module
2 real x, y
3 end modules

Listing 10: Definition of a module

1 program modules
2 use xy_module
3 x = 1.0
4 y = 2.0
5 write (*, *) 'in the main program:', x, y
6 call sub ()
7 end program
8
9 subroutine sub ()
10 use xy_module
11 write (*, *) 'in the subroutine:', x, y
12 end subroutine

Listing 11: Using the module

Please note that the module has to be compiled first. The emerging .mod- The file is then required to compile the code parts using the module.

The name corresponds to the .mod-File that of the module, not that of the module's source file. Generating Makefiles with correct dependencies is therefore not entirely trivial. The .modFiles are also not necessarily compatible between compilers, which can be a problem when compiling across platforms.

The simple use of modules as a replacement for Common-Blocks and thus as the place of declaration of global variables are often found in legacy code. Modules become confusing when they come back use-Contain statements and include other modules, which causes nesting. Detective work is often necessary in order to really find the dependencies of global variables defined in modules and integrated with them in complex code. It is not without reason that every good programming training warns against the use of the latter. But modules can do more, because with them the age of object orientation in Fortran begins. Only with it do they really make sense.

Object orientation

Fortran is evolving

Starting with the Fortran 90 standard up to the current one (Fortran 2008), elements of object-oriented programming gradually found their way into the language. To show what is currently possible with them, the description of the implementation and use of a class follows. In object orientation, a class combines data (attributes) and operations (methods). In Fortran, this can be implemented using a so-called Derived Type in a module with functions and subroutines that follow a contains-Instruction stand.

Developers can implement further object-oriented concepts if access modifiers for data encapsulation and overloading of functions and operators are added. Listing 12 shows an example of a module with the basic structure of a class with which fractions, i.e. rational numbers with an integer numerator and denominator, can be represented and calculated:

1 module RationalClass2 implicit none
3
4 type, public :: Rational
5 private
6 integer num, den
7 end type Rational
8
9 interface Rational
10 module procedure construct
11 module procedure constructInteger
12 end interface
13
14 interface assignment (=)
15 module procedure assign Integer
16 end interface
17
18 interface operator (*)
19 module procedure times
20 module procedure timesRational
21 module procedure timesInteger
22 end interface
21
22 interface abs
23 module procedure absRational
24 end interface
25
26 writeRational interface
27 module procedure writeRationalScalar
28 end interface
29
30 contains
31
32! constructors:
33 elemental type (Rational) function construct (num, den)
34 integer, intent (in) :: num
35 integer, intent (in) :: den
36 construct% num = num
37 construct% den = den
38 end function
39
40 elemental type (Rational) function constructInteger (num)
41 integer, intent (in) :: num
42 constructInteger = construct (num, 1)
43 end function
44
45! getters:
46 elemental real (8) function getnum (r)
47 type (Rational), intent (in) :: r
48 getnum = r% num
49 end function
50
51 elemental real (8) function getden (r)
52 type (Rational), intent (in) :: r
53 getden = r% den
54 end function
55
56! setters:
57 elemental subroutine setnum (r, num)
58 type (Rational), intent (inout) :: r
59 integer, intent (in) :: num
60 r% num = num
61 end subroutine
62
63 set elemental subroutine (r, den)
64 type (Rational), intent (inout) :: r
65 integer, intent (in) :: den
66 r% den = den
67 end subroutine
68
69! assignment operator:
70 elemental subroutine assignInteger (r, num)
71 type (Rational), intent (inout) :: r
72 integer, intent (in) :: num
73 r% num = num
74 r% den = 1
75 end subroutine
76
77! multiplication operators:
78 elemental type (Rational) function times (r1, r2)
79 type (Rational), intent (in) :: r1, r2
80 times% num = r1% num * r2% num
81 times% den = r1% den * r2% den
82 end function
83
84 elemental type (Rational) function timesRational (r, i)
85 type (Rational), intent (in) :: r
86 integer, intent (in) :: i
87 timesRational = times (r, Rational (i))
88 end function
89
90 elemental type (Rational) function timesInteger (i, r)
91 type (Rational), intent (in) :: r
92 integer, intent (in) :: i
93 timesInteger = times (Rational (i), r)
94 end function
95
96! abs function:
97 type (Rational) function absRational (r)
98 type (Rational), intent (in) :: r
99 absRational = Rational (abs (r% num), abs (r% den))
100 end function
101
102! output:
103 subroutine writeRationalScalar (r)
104 type (Rational), intent (in) :: r
105 write (*, *) 'Rational object:', r% num, '/', r% den
106 end subroutine
107
108 end module RationalClass

Listing 12: Definition of a class

Listing 13 contains a simple main program for this. In Listing 12 you can see the declaration of a self-defined data type in lines 4-7. This is where the access modifiers come public for the guy himself and private for the two attributes num (for numerator, counter) and the (for denominator, denominator) of the fraction is used. The definition of the type Rational Now allows you to create variables of this type in the main program (Listing 13, Line 5):

1 RationalTest program
2 use RationalClass
3 implicit none
4
5 type (Rational) :: r1, r2
6 type (Rational), allocatable :: r3 (:)
7 integer :: i, n = 3
8
9 r1 = Rational (1, 2)
10 r2 = Rational (3)
11 call writeRational (r1)
12 call writeRational (r2)
13 r2 = r1 * r2
14 call writeRational (r2)
15
16 allocate (r3 (n))
17 r3 = Rational (0)
18 r3 = r3 * r3
19 do i = 1, n
20 call writeRational (r3 (i))
21 enddo
22 deallocate (r3)
23
24 end program

Listing 13: Using the class

After the type definition, various interface blocks now follow in the module. The first (lines 9-12) contains the definition of the interface Rational takes place with two procedures defined in the module. The term procedure stands for Fortran functions or subroutines.

Calls the main program (Listing 13, lines 9, 10) Rational the module procedures listed in the interface block are searched for that match their parameters. In the present case, line 9 of the main program is called via the interface Rational the function construct from line 35 of the module, which receives two integer parameters. Line 10 of the main program, on the other hand, calls the one with only one parameter (line 42 in the module). Functions and operators, such as the multiplication operator here, can now be overloaded in a completely identical manner. For the procedures in the module, the respective parameters were also saved as intent (in) respectively out and inout marked. The compiler checks this specification introduced in Fortran 90, which represents an additional protection mechanism.

In the main program it can be seen that there is a direct field (variable r3) of the new data type could generate, initialize and calculate with it. This can work if the corresponding procedures as in the module as elemental Marked are. This enables your own data types and classes to have a convenient syntax that corresponds to that for fields of primitive data types.

Inheritance is also possible in Fortran. Since such modern constructs are not likely to be found in legacy code and the meaning of inheritance in numerical simulation codes is also controversial, they will not be discussed in detail here.

A very compact, but nevertheless comprehensive presentation of modern Fortran can be found in [4] - not only with regard to climate models, as the title might suggest. In addition, we recommend the book "Modern Fortran Explained" [6], which is not so much a textbook as a reference work for the current language standard. The authors are involved in its creation. In "Computing for Scientists" [7] an interesting comparison is made between Fortran 90 and C ++ with regard to object orientation, which was not fully realized when the book was published in Fortran.

Conclusion

By their very nature, modern object-oriented constructs are rare in legacy code. What you can find at least in climate models is the often confusing use of modules and preprocessor instructions. However, this is precisely the typical challenge of complex legacy projects: you cannot simply replace the entire program with a new implementation, and parts of it cannot easily be rewritten because clean interfaces are often missing. With tools for software development, however, it looks good: The current Eclipse in the version for parallel applications has good and convenient built-in Fortran support. Nothing stands in the way of trying it out. (jul)

Thomas Slawig
is Professor for Algorithmic Optimal Control at the Institute for Computer Science at the University of Kiel and mainly deals with climate models. He has been working with the Fortran language for around 20 years.

literature

  1. Floating Point Component of SPEC CPU2006; www.spec.org/cpu2006/CFP2006
  2. B.A. Ciapra; The Best of the 20th Century: Editors Name Top Ten Algorithms; Society for Industrial and Applied Mathematics (SIAM) News Vol. 33 No. 4, 2000
  3. FORTRAN 77 4.0 Reference Manual, SunSoft, Mountain View 1995.
  4. D. B. Chirila, G. Lohmann; Introduction to Modern Fortran for the Earth System Sciences, Springer 2015.
  5. H. Wehnes; FORTRAN 77. Structured programming with FORTRAN 77; Hanser Verlag, 5th edition 1989.
  6. M. Metcalf, J. Reid, M. Cohen; Modern Fortran Explained; Oxford University Press 2011.
  7. Barlow, R. J., Barnett, A. R.; Computing for Scientists, Principles of Programming with Fortran 90 and C ++; Wiley 1998.

32 comments