Вы находитесь на странице: 1из 32

Numerical Methods in Thermo-Fluid Mechanics

Winter Term 2010/2011

a small F ORTRAN 77+ TUTORIAL


Monday, 2010/11/15

Chair of Fluid Mechanics Technical Faculty Friedrich-Alexander University Erlangen-Nuremberg

Lecture: Prof. Dr.-Ing. A. Delgado, Dipl.-Ing. C. Rauh Exercise: Prof. Dr.-Ing. A. Delgado, Dipl.-Math. T. Horneber Author of Tutorial printout: Dipl.-Math. T. Horneber

Contents Contents

1 Basics 1.1 Program organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Column positions rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 Continuation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5 Blank spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6 Compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.1 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.2 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Variables, types and declarations 2.1 Variable names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Types and declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 The parameter statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Expressions and assignment 3.1 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Type conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Logical expressions 4.1 Logical variables and assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 The if statements 6 Loops 6.1 do loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 while loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 until loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Arrays 7.1 One-dimensional arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 Two-dimensional arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3 Storage format for 2-dimensional arrays . . . . . . . . . . . . . . . . . . . . . . . 7.4 Multi-dimensional arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.5 The dimension statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 4 5 5 5 5 6 6 6 7 7 7 8 9 9 9 10 10 12 12 13 14 14 15 16 17 17 18 18 19 19

Contents 8 Subprograms 8.1 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 Subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3 Call-by-reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Arrays in subprograms 9.1 Variable length arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Passing subsections of arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 File I/O 10.1 Opening and closing a le . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Read and write revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 I/O and format statements 11.1 Simple I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 Read and write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Format statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.2 Common format codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.4 Format strings in read/write statements . . . . . . . . . . . . . . . . . . . 11.2.5 Implicit loops and repeat counts . . . . . . . . . . . . . . . . . . . . . . .

3 20 20 21 22 24 24 25 26 26 27 27 29 29 29 29 30 30 31 31 32 32

1 Basics 1 Basics

A F ORTRAN program is just a sequence of lines of text. Each line has to follow a certain structure. We start with a little example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

program sphvol real radius, volume ! This program reads a real number r and prints the volume of a sphere ! whit radius r. write (*,*) Give radius r: read (*,*) r volume = 4. / 3. * r**3. * 3.14159 write (*,*) Volume = , volume stop end

The lines that begin with a ! are comments. The original F ORTRAN 77 accepted only upper-case letters. Now modern compiler accept also lower-case letters. So, F ORTRAN is not case-sensitive, i.e. A and a are the same variable.

1.1 Program organization A F ORTRAN program consists of a main programm and possibly subprograms (or subroutines). At rst we will talk about the statements in the main program. Later, in a second step, we will treat subroutines. The structure of a main program is:
1 2 3 4 5 6 7 8

program name declarations statements stop end

The words in slanted style are descriptions of what belongs in their place. The stop statement is optional. But it is recommended to always terminate a program with the

1 Basics

stop statement to emphasize that the execution ow stops here. It is not possible to have a variable with the same name as the program.

1.2 Column positions rules Because of the origin of F ORTRAN one must use a very strict column format. F ORTRAN 77 is not a free-format language. Col. 1 Col. 1 - 5 Col. 6 Col. 7 - 72 Col. 73 - 80 : Blank, or a c, * or ! for comments : Statement label (optional) : Continuation of previous line (optional) : Statements : Statement number (optional, not used today)

1.3 Comments A line that begins with letter c, an asterisk * or with an exclamation mark ! is a comment. They could appear everywhere in the program. The c and the asterisk always must be in the rst column, whereas the ! could be in every column.

1.4 Continuation If a statement needs more than the 66 available columns of a single line, one can break the statement into two or more lines and use the continuation mark in position 6.
1 2 3 4 5 6

!23456789 (demonstration of column positions) ! The next statement goes over two physical lines > volume = 4. / 3. * r**3. * 3.14159

!23456789

Any character could be used instead of the > sign as a continuation symbol. One can also use digits (2 for second line, 3 for third line, and so on).

1.5 Blank spaces Blank spaces are ignored in F ORTRAN 77. So one can remove every blank (but consider the column format) and the code is still acceptable to a compiler but almost unreadable to humans. Only in strings blanks are not ignored, of course.

1 Basics 1.6 Compiling 1.6.1 Linux

In Lunix one can use the gfortran compiler to make out of the F ORTRAN le an executable. One has to save the F ORTRAN le with the extension .f. To compile the F ORTRAN le one has to type gfortran lename. Our example sphvol (it calculates the volume of a sphere with a given radius) we saved it with the name sphvol.f we compile in the following way: gfortran sphvol.f or with a given output name: gfortran sphvol.f -o sphereVolume If one gives no output name then the executable always is named a.out. There are many options for compiling (debugging, optimizations, ...) and to include other les. But we will stay with the simple case.

1.6.2 Windows There are some free F ORTRAN Compiler for Windows. Very easy to install and use is GNUFort9912 . At rst one has to download the le and extract it to some folder, e.g.: C:\FortranCompiler\Fort99\ At second one has to change or set the PATH and LIBRARY_PATH environment variables, in the example case add, if the variables exist, or create the following: PATH = C:\FortranCompiler\Fort99\G77\bin LIBRARY_PATH = C:\FortranCompiler\Fort99\G77\lib To compile a le type in a DOS-shell: g77 filename.f -o filename To execute the le type: filename
1 Download: 2 More

http://www.cse.yorku.ca/~roumani/fortran/gnu99/Fort99.zip informations in the included documents or at: http://www.cse.yorku.ca/~roumani/fortran/ftn.htm

2 Variables, types and declarations 2 Variables, types and declarations 2.1 Variable names

Vaiable names in F ORTRAN consist of 1-6 characters chosen from the letters a-z and the digits 0-9. The rst character must be a letter. F ORTRAN 77 does not distinguish between upper and lower case. The words which make up the F ORTRAN language are called reserved words and cannot be used as names of variable. "program", "real", "stop", "end", "read" and "write" we used already.

2.2 Types and declarations Every variable should be dened in a declaration. This establishes the type of the variable.
1 2 3 4 5

integer real complex character

list of variables list of variables list of variables list of variables

double precision list of variables

The list of variables consists of variable names seperated by commas. If a variable is undeclared, F ORTRAN 77 uses a set of implicit rules to establish the type. All variables starting with the letters i-n are integers and all others are real. One has to be very careful with the implicit rules, because it includes a high potential for errors. One could also manipulate the implicit rules, e.g. with the command implicit double precision (a-h,o-z) Then all variables starting wiht the letters a-h or o-z are of type double precision. But it is not the good style. Instead of the above command one has to use implicit none at the beginning of the program and then declare every single variable correctly. In F ORTRAN 77 exists two types of oating point variables, called real and double precision. Usually a real is a 4 byte variable and a double precision is a 8 byte variable.

2 Variables, types and declarations 2.3 The parameter statement

Some constants appear many times in a program. It is then often desirable to dene them only once, in the beginning of the program. This is what the paramter statement is for. For example, the sphere volume program could be written like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

program sphvol real radius, volume parameter (pi = 3.14159) ! This program reads a real number r and prints the volume of a sphere ! whit radius r. write (*,*) Give radius r: read (*,*) r volume = 4. / 3. * r**3. * pi write (*,*) Volume = , volume stop end

The syntax of the parameter statement is paramter (name = constant, ..., name = constant) One have to follow some rules for the paramter statement: The name dened in the paramter statement is not a variable but a constant. One cannot change its value at a later point in the program. The parameter statement(s) must come before the rst executable statement.

3 Expressions and assignment 3 Expressions and assignment 3.1 Constants

There are 6 types of constants, corresponing to the 6 data types. At rst some integer constants: 1 0 -100 32767 +15

Then we have real constants: 1.0 or 1. -0.25 2.0E6 3.333E-1

The E-notation stand for 10 to the power of 2.0E6 = 2.0 106 . For constants that are larger than the largest real allowed, or that requires high precision, one has to use double precision. These have the same notation except the E is replaced by a D. 2.0D-1 1D99

The fourth type is complex constants: (2, -3) (1., 9.9E-1)

The rst number denotes the real part and the second number the imaginary part. The parts are seperated by a comma and enclosed in parentheses. The fth type is logical constants. These can only have one of two values: .true. .false.

The enclosing dots are required. The last type is character constants. These are often used as an array of characters, called a string. The content of a string is enclosed in apostrophes (single quotes): ABC Keep smiling! Have a nice day.

Strings and character constants are case-sensitive. Be aware of the problem if you want to have an apostrophe inside a string, then you have to double it: Its a nice day

3.2 Expressions The simples non-constant expressions are of the form

3 Expressions and assignment operand operator operand and an example is x + y or x + 2 * y

10

This raises the question of precedence. The precedence of arithmetic operators in F ORTRAN 77 are (from highest to lowest):

, / +,

{exponential} {multiplication, division} {addition, subtraction}

All these operators are calculated left-to-right, except the exponentiation operator **. To change the default order one can use parentheses. Extreme caution must be taken when using the division operator, which has different meanings for integers and reals. If one of the operands is integer, then an integer division is performed. If both operands are real, a real division is performed. 3/2 = 1 but 3./2.= 1.5 (Note the decimal points!!!)

3.3 Assignment The assignment has the form varible_name = expression The interpretation is as follows: Evaluate the right hand side and assign the result to the variable on the left. volume = 4./3.* r**3.* pi The variables of the right hand side are not changed here.

3.4 Type conversion When different data types occur in the same expressioin, type conversion has to take place. Some conversions are done by F ORTRAN implictly: real x x = x + 1 Here, the integer number one is converted into the real number one. For numbers the following explicit functions are available:

3 Expressions and assignment int real dble ichar char

11

The rst three have the obvious meaning. ichar takes a character and converts it to an integer, char does the opposite. To multiply two real values x and y using double precision and store the results in the double precision variable w do the following: w = dble(x) * dble(y) Note that this is different from w = dble(x*y)

4 Logical expressions 4 Logical expressions

12

Logical expressions can only have the value .true. or .false.. A logical expression can be formed by comparing arithmetic expressions using the following relational operators: operator .LT. .LE. .GT. .GE. .EQ. .NE. meaning

< > = =

4.1 Logical variables and assignment Truth values can be stored in logical variables. The assignment is analogous to the arithmetic assignment. logical a, b a = .TRUE. b = a .AND. 3 .LT. 5/2 The order of precedence is important, as the last example shows. Thr rule is that arithmetic expressioins are evaluated rst, then relational operators, and nally logical operators. Hence b will be assigned .FALSE. in the example above. Among the logical operatorts the precedence (in the absence of parenthesis) is that .NOT. is done rst, then .AND., then .OR. is done last.

5 The if statements 5 The if statements The if statement is a conditional statement. The simplest one is the logical if statement: if (logical expression) executable statement This has to be written in one line, e.g.: if (x .LT. 0) x = -x

13

If more than one statement should be executed inside the if, then the following syntax should be used:
1 2 3

if (logical expression) then statements endif

The most general form of the if statement has the following form:
1 2 3 4 5 6 7 8 9

if (logical expression) then statements elseif (logical expression) then statements : : else statements endif

Of course the if statements could be nested in several limits.

6 Loops 6 Loops

14

In the original F ORTRAN 77 there exists only one loop: the do loop (for loop in other languages). Other loops has to be constructed by a combination of do, if and goto.

6.1 do loops This simple example prints the numbers from one to twenty:
1 2 3 4 5 6 7 8 9 10

program count integer i, n n = 20 do 10 i = 1, n write(*,*) i =, i 10 continue stop end

The number 10 is a statement label. Every loop require such a label. The programmer is responsible for assigning a unique number to each label in each program (or subprogram). The statement label must be in column 1-5. The numerical value has no signicance, so any integer could be used. The next example prints the even numbers between one and 20 in decreasing order:
1 2 3 4 5 6 7 8 9 10

program countdowneven integer i, n = 20 do 10 i = n, 1, -2 write(*,*) i =, i 10 continue stop end n

The general form of do loops is as follows:


1 2 3

do label var = expr1, expr2, expr3 statements label continue

6 Loops

15

var is the loop variable (loop index) which must be an integer. expr1 species the initial value of var, expr2 is the terminationg bound, and expr3 is the increment step (if the increment step is +1, then it is optional). Note: The do loop variable must never be changed by other statements within the loop!!! Many today F ORTRAN 77 compiler allow do loops to be closed by the enddo statement. Here one needs no statement label. F ORTRAN only evaluates the start, end and step expressions once, before the rst pass through the body of the loop. So, the following do loop will multiply a non-negative j by two, rather than running forever as the equivalent loop might in another language.
1 2 3 4 5 6 7 8

integer i, j read (*,*) j do 20 i = 1, j j = j + 1 20 continue write (*,*) j

6.2 while loops The most intuitive way to write a while loop is
1 2 3

while (logical expression) do statements enddo

or alternatively,
1 2 3

do while (logical expression) statements enddo

The program will alternate testing the condition and executing the statements in the body as long as the condition in the while statement is true.

6 Loops

16

Even though this syntax is accepted by many compilers, it is not F ORTRAN 77. The correct way is to use if and goto:
1 2 3 4 5 6 7 8

integer n n = 1 10 if (n .le. 100) then write (*,*) n n = 2 * n goto 10 endif

6.3 until loops If the termination criterion is at the end instead of the beginning, it is often called an until loop. The pseudocode looks like this:
1 2 3

do statements until (logical expression)

Again, this should be implemented in F ORTRAN 77 by using if and goto:


1 2 3

label

continue statements if (logical expression) goto label

7 Arrays 7 Arrays

17

Many scientic computations use vectors and matrices. The data type F ORTRAN uses for representing such objects is the array. A one-dimensional array corresponds to a vector, while a two-dimensional array corresponds to a matrix. To fully understand how this works in F ORTRAN 77, you will have to know not only the syntax for usage, but also how these objects are stored in memory in F ORTRAN 77.

7.1 One-dimensional arrays The simplest array is the one-dimensional array, which is just a sequence of elements stored consecutively in memory. For example, the declaration real a(20) declares a as a real array of length 20. That is, a consists of 20 real numbers stored contiguously in memory. By convention, F ORTRAN arrays are indexed from 1 and up. Thus the rst number in the array is denoted by a(1) and the last by a(20). However, one may dene an arbitrary index range for your arrays using the following syntax: real b(0:19), c(-162:237) Here, b is exactly similar to a from the previous example, except the index runs from 0 through 19. c is an array of length 237-(-162)+1 = 400. The type of an array element can be any of the basic data types. Examples: integer i(10) logical aa(0:1) double precision x(100) Each element of an array can be thought of as a separate variable. You reference the ith element of array a by a(i). Here is a code segment storing the 10 rst square numbers in the array sq:
1 2 3 4 5

integer i, sq(10) do 100 i = 1, 10 sq(i) = i**2 100 continue

A common bug in F ORTRAN is that the program tries to access array elements that are out of bounds or undened. This is the responsibility of the programmer, and the F ORTRAN compiler will not detect any such bugs!

7 Arrays 7.2 Two-dimensional arrays Matrices are very important in linear algebra. dimensional arrays. For example, the declaration real A(3,5)

18

Matrices are usually represented by two-

denes a two-dimensional array of 3*5=15 real numbers. It is useful to think of the rst index as the row index, and the second as the column index. Hence we get the graphical picture: (1,1) (2,1) (3,1) (1,2) (2,2) (3,2) (1,3) (2,3) (3,3) (1,4) (2,4) (3,4) (1,5) (2,5) (3,5)

Two-dimensional arrays may also have indices in an arbitrary dened range. The general syntax for declarations is: name (low_index1 : hi_index1, low_index2 : hi_index2)

The total size of the array is then size = (hi_index1-low_index1+1)*(hi_index2-low_index2+1) It is quite common in F ORTRAN to declare arrays that are larger than the matrix we want to store. (This is because F ORTRAN does not have dynamic storage allocation.) This is perfectly legal. Example:
1 2 3 4 5 6 7 8 9

real A(3,5) integer i,j ! We will only use the upper 3 by 3 part of this array. do 20 j = 1, 3 do 20 i = 1, 3 a(i,j) = real(i)/real(j) 10 continue

The elements in the submatrix A(1:3,4:5) are undened. Do not assume these elements are initialized to zero by the compiler (some compilers will do this, but not all).

7.3 Storage format for 2-dimensional arrays F ORTRAN stores higher dimensional arrays as a contiguous sequence of elements. It is important to know that 2-dimensional arrays are stored by column. So in the above example, array element

7 Arrays

19

(1,2) will follow element (3,1). Then follows the rest of the second column, thereafter the third column, and so on. Consider again the example where we only use the upper 3 by 3 submatrix of the 3 by 5 array A(3,5). The 9 interesting elements will then be stored in the rst nine memory locations, while the last six are not used. This works out neatly because the leading dimension is the same for both the array and the matrix we store in the array. However, frequently the leading dimension of the array will be larger than the rst dimension of the matrix. Then the matrix will not be stored contiguously in memory, even if the array is contiguous. For example, suppose the declaration was A(5,3) instead. Then there would be two "unused" memory cells between the end of one column and the beginning of the next column (again we are assuming the matrix is 3 by 3). This may seem complicated, but actually it is quite simple when you get used to it. If you are in doubt, it can be useful to look at how the address of an array element is computed. Each array will have some memory address assigned to the beginning of the array, that is element (1,1). The address of element (i,j) is then given by addr[A(i,j)] = addr[A(1,1)] + (j-1)*lda + (i-1) where lda is the leading (i.e. row) dimension of A. Note that lda is in general different from the actual matrix dimension. Many F ORTRAN errors are caused by this, so it is very important you understand the distinction!

7.4 Multi-dimensional arrays F ORTRAN 77 allows arrays of up to seven dimensions. The syntax and storage format are analogous to the two-dimensional case, so we will not spend time on this.

7.5 The dimension statement There is an alternate way to declare arrays in F ORTRAN 77. The statements real A, x dimension x(50) dimension A(10,20) are equivalent to real A(10,20), x(50) This dimension statement is considered old-fashioned style today.

8 Subprograms 8 Subprograms

20

F ORTRAN knows about the modular approach and so one can split the program into smaller units called subprograms. F ORTRAN has two different types of subprograms, called functions and subroutines.

8.1 Functions In F ORTRAN one can write own functions, called user dened functions. There are also has some intrinsic functions. Here is a simple example how to use a function: x = cos(pi/3.0) Here cos is the cosine function (one has to dene pi manually, F ORTRAN 77 has no intrinsic constants). Some examples of intrinsic F ORTRAN 77 functions: abs min max sqrt sin cos tan atan exp log absolute value minimum value maximum value square root sine cosine tangent arctangent exponential (natural) logarith (natural)

A function has always a type. Most of the intrinsic functions are generic, so the compiler would check the types and use the correct version of e.g. cos (real or double precision). But one has to be careful, because sometimes the compiler decides not the correct way. Now we turn to the user dened functions. Let us go to the rst example of calculating the volume of a sphere. There we need no user dened functions but we could use one. The line with the calculation of the volume could be dened as a function.
1 2 3 4 5 6 7 8

program sphvol implicit none double precision pi, r, volume, vol parameter (pi = 4.0d0 * atan(1.0d0)) ! This program reads a number r and prints the volume of a sphere ! with radius r.

8 Subprograms
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

21

write (*,*) Give radius r: read (*,*) r vol = volume(r,pi) write (*,*) Volume = , vol stop end ! ---------------------------------------------------------------------double precision function volume(r,pi) implicit none double precision r, pi volume = 4. / 3. * r**3. * pi return end

The structure of a function is almost equal to the structure of the main program. The differences are: Functions have a type. This type msut also be declared in the calling program. The return value shoud be stored in a variable with the same name as the function. Functions are terminated by the return statement instead of stop. General structure of a function:
1 2 3 4 5

type function name (list of variables) declarations statements return end

8.2 Subroutines Compared to a function a subroutine can not only return one value. The syntax of a subroutine is as follows:
1 2 3 4 5

subroutine name (list of arguments) declarations statements return end

8 Subprograms

22

Subroutines have no type and consequently cannot be declared in the calling program unit. To invoke a subroutine one has to use the word call before their name. A small example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

program sphvol implicit none double precision pi, r, vol parameter (pi = 4.0d0 * atan(1.0d0)) ! This program reads a number r and prints the volume of a sphere ! with radius r. write (*,*) Give radius r: read (*,*) r call volume(r,pi,vol) write (*,*) Volume = , vol stop end ! ---------------------------------------------------------------------subroutine volume(r,pi,vol) implicit none double precision r, pi, vol vol = 4. / 3. * r**3. * pi return end

Note that we have to declare the input/output parameters, i.e. the variables that are commonn to both the caller and the callee. Additionaly in a new line one can dene local varibles, that can only be used within the subroutine. One can use the same variable names in different subroutines and the compiler will know that they are different variables that just have the same names.

8.3 Call-by-reference F ORTRAN 77 uses the so-called call-by-reference paradigm. That means that the memory address of the arguments (pointers) and not the values of the arguments (call-by-value) are passed. A small example:
1 2

program callex integer m, n

8 Subprograms
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

23

m = 1 n = 2 call iswap(m, n) write(*,*) m, n stop end ! ---------------------------------------------------------------------subroutine iswap (a, b) integer a, b ! Local variables integer tmp tmp = a a = b b = tmp return end

The output is 2 1. If F ORTRAN 77 would use call-by-value then the output have been 1 2, the variables m and n were unchanged. So be careful with that. It is easy to introduce undesired side effects. For example, sometimes it is tempting to use an input parameter in a subprogram as a local variable and change its value. Since the new value will then propagate back to the calling program with an unexpected value, you should never do this unless (like our iswap subroutine) the change is part of the purpose of the subroutine.

9 Arrays in subprograms 9 Arrays in subprograms

24

Fortran subprogram calls are based on call by reference. This means that the calling parameters are not copied to the called subprogram, but rather that the addresses of the parameters (variables) are passed. This saves a lot of memory space when dealing with arrays. No extra storage is needed as the subroutine operates on the same memory locations as the calling (sub-)program. However, you as a programmer have to know about this and take it into account. It is possible to declare local arrays in Fortran subprograms, but this feature is rarely used. Typically, all arrays are declared (and dimensioned) in the main program and then passed on to the subprograms as needed.

9.1 Variable length arrays A basic operation is the saxpy operation: y := alpha * x + y where alpha is a scalar but x and y are vectors. One could write a subroutine for this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

subroutine saxpy(n, alpha, x, y) integer n real alpha, x(*), y(*) ! Saxpy: Compute y := alpha * x + y ! where x and y are vectors of lenght n (at least). ! Local variables integer i do 10 i = 1, n y(i) = alpha * x(i) + y(i) 10 continue return end

The asterisk declaration x(*) and y(*) says that x and y are arrays of arbitrary length. Because of call-by-reference no additional space is required, the subroutine works directly on the space of the array elements. The programmer has the responsibility to make sure, that somewhere else the arrays have been declared to have lenght n or more. A very common error in F ORTRAN 77 occurs when you try to access out-of-bounds array elements.

9 Arrays in subprograms One can also declare the arrays like this: real x(n), y(n)

25

9.2 Passing subsections of arrays The next subroutine is about matrix-vector multiplication. There are two basic ways to do this, either by using innner products or the above saxpy operation. See here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

subroutine matvec (m, n, A, lda, x, y) integer m, n, lda real x(*), y(*), A(lda,*) ! Compute y = A*x, where A is m by n and stored in an array ! with leading dimension lda. ! Local variables integer i, j ! Initialize y do 10 i = 1, m y(i) = 0.0 10 continue ! Matrix-vector product by saxpy on columns in A. ! Notice that the length of each column of A is m, not n! do 20 j = 1, n call saxpy (m, x(j), A(1,j), y) 20 continue return end

The code is very general to allow for arbitrary dimensions m and n, but one still needs to specify the leading dimension of matrix A. The asterisk declaration can only be used for the last dimension of an array! Because of the way F ORTRAN 77 stores multidimensional arrays. To compute y = A*x by saxpy, one needs access to the columns of A. The jth column of A is A(1:m,j). However, in F ORTRAN 77 we cannot use such subarray syntax (but it is encouraged in Fortran 90!). So instead we provide a pointer to the rst element in the column, which is A(1,j) (it is not really a pointer, but it may be helpful to think of it as if it were). We know that the next memory locations will contain the succeeding array elements in this column. The saxpy subroutine will treat A(1,j) as the rst element of a vector, and does not know that this vector happens to be a column of a matrix.

10 File I/O 10 File I/O

26

So far we have assumed that the input/output has been to the standard input or the standard output. It is also possible to read from or write to les which are stored on some external storage device, typically a disk (hard disk, oppy) or a tape. In F ORTRAN each le is associated with a unit number, an integer between 1 and 99. Some unit numbers are reserved: 5 is standard input, 6 is standard output.

10.1 Opening and closing a le Before you can use a le you have to open it. The command is open (list-of-specifiers) where the most speciers are: [UNIT =] IOSTAT = ERR = FILE = STATUS = ACCESS = FORM = RECL = u ios err fname sta acc frm rl

The unit number u is a number in the range 1-99 that denotes this le (the programmer may chose any number but he/she has to make sure it is unique). ios is the I/O status identier and should be an integer variable. Upon return, ios is zero if the statement was successful and returns a non-zero value otherwise. err is a label which the program will jump to if there is an error. fname is a character string denoting the le name. sta is a character string that has to be either NEW, OLD or SCRATCH. It shows the prior status of the le. A scratch le is a le that is created when opened and deleted when closed (or the program ends). acc must be either SEQUENTIAL or DIRECT. The default is SEQUENTIAL. frm must be either FORMATTED or UNFORMATTED. The default is UNFORMATTED. rl species the length of each record in a direct-access le.

10 File I/O For more details on these speciers, see a good F ORTRAN 77 book3 .

27

After a le has been opened, you can access it by read and write statements. When you are done with the le, it should be closed by the statement: close ([UNIT = ]u[, IOSTAT = ios, ERR = err, STATUS = sta]) where, as usual, the parameters in brackets are optional. In this case sta is a character string which can be KEEP (the default) or DELETE.

10.2 Read and write revisited The only necessary change from our previous simplied read/write statements, is that the unit number must be specied. But frequently one wants to add more speciers. Here is how: read ([UNIT = ]u, FMT = ]fmt, IOSTAT = ios, ERR = err, END = s) read ([UNIT = ]u, FMT = ]fmt, IOSTAT = ios, ERR = err, END = s) where most of the speciers have been described above. The END = s speciers denes which statement label the proram jumps to if it reaches end-of-le.

10.3 Example You are given a data le with xyz coordinates for a bunch of points. The number of points is given on the rst line. The le name of the data le is points.dat. The format for each coordinate is known to be F10.4 (Well learn about FORMAT statements in a later lesson). Here is a short program that reads the data into 3 arrays x,y,z:
1 2 3 4 5 6 7 8 9 10 11 12 13 14

program inpdat ! ! ! integer nmax, u parameter (nmax=1000, u=20) real x(nmax), y(nmax), z(nmax) ! Open the data file open (UNIT > > FILE = u, = points.dat, This program reads n points from a data file and stores them in 3 arrays x, y, z.

STATUS = OLD)

3 F ORTRAN

77 Programming 2nd: With an Introduction to the F ORTRAN 90 Standard

T. M. R. Ellis

10 File I/O
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

28

Read the number of points

read(u,*) n if (n.GT.nmax) then write(*,*) Error: n = , n, is larger than nmax =, nmax goto 9999 endif ! Loop over the data points do 10 i= 1, n read(u,100) x(i), y(i), z(i) 10 100 enddo format (3(F10.4)) ! Close the file close (u) 9999 stop end

11 I/O and format statements 11 I/O and format statements 11.1 Simple I/O

29

An important part of any computer program is to handle input and output. In our examples so far, we have already used the two most common Fortran constructs for this: read and write. Fortran I/O can be quite complicated, so we will only describe some simpler cases in this tutorial.

11.1.1 Read and write textttRead is used for input, while write is used for output. A simple form is read (unit no, format no) list-of-variables write (unit no, format no) list-of-variables The unit number can refer to either standard input, standard output, or a le. The format number refers to a label for a format statement, which will be described in the next section. It is possible to simplify these statements further by using asterisks (*) for some arguments, like we have done in most of our examples so far. This is sometimes called list directed read/write. read (*,*) list-of-variables write (*,*) list-of-variables 11.1.2 Examples Here is a code segment from a Fortran program:
1 2 3 4 5 6

integer m, n real x, y, z(10) read(*,*) m, n read(*,*) x, y read(*,*) z

We give the input through standard input (possibly through a data le directed to standard input). A data le consists of records according to traditional F ORTRAN terminology. Each record here contains a number (either integer or real). Records are separated by either blanks or commas. Here are three identical inputs: -1 100 -1.0 1e+2 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

11 I/O and format statements or -1, 100 -1.0, 1e+2 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., or -1 100 -1.0 1e+2 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.,

30

In the folowing example the rst line has to much inputs. So the last two inputs of the rst line are discarded, x and y are assigned to the rst two inputs of the second line (1. and 2.) and the rest of the line is discarded. Therefore all elements of z are unlled. -1, 100, -1.0, 1e+2 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.,

11.2 Format statements Until now we have used free format input/output. If the programmer wants to specify the format, he can use the F ORTRAN 77 format statement. The same format statements are used for input and output.

11.2.1 Syntax
1 2

label

write(*, label) list of variables format formatcode

If you want to print an integer i in a eld 4 characters wide and a real number x in xed point notation with 3 decimal places:
1 2

900

write(*, 900) i, x format (I4,F*.3)

The format label 900 is chosen arbitrarily, but it is common to use higher numbers than the control ow labels. After the keyword format is in parenthesis the format code. I4 stands for in integer with wide 4, F8.3 stands for a number in xed point notation with eld width 8 and 3 decimal places.

11 I/O and format statements

31

The programmer is free in the location of the format statement, but there are two common styles: Either the format statement follows directly after the read/write statement, or all the format statements are grouped together at the end of the (sub-)program.

11.2.2 Common format codes A - text string D - double precision numbers, exponent notation E - real numbers, exponent notation F - real numbers, fixed point notation I - integer X - horizontal skip (space) / - vertical skip (newline) The format code F (and similarly D, E) has the general form Fw.d where w is an integer constant denoting the eld width and d is an integer constant denoting the number of signicant digits. For integers only the eld width is specied, so the syntax is Iw. Similarly, character strings can be specied as Aw but the eld width is often dropped. If the eld the programmer allocates is to large it will be usually lled with spaces and the text will be adjusted to the right. For horizontal spacing one can use nx. So one has n horizontal spaces. Without n one space is assumed. For vertical spacing use /. But note that each read or write statement by default ends with a newline.

11.2.3 Examples
1 2 3 4 5 6 7 8 9 10 11 12 13

x = 0.025 write(*,100) x=, x format (A,F) write(*,110) x=, x format (A,F5.3) write(*,120) x=, x format (A,E) write(*,130) x=, x format (A,E8.1)

100

110

120

130

11 I/O and format statements Output: x= x=0.025 x= 0.2500000E-01 x= 0.3E-01 0.0250000

32

Note that F ORTRAN 77 follows the rounding rule that digits 0-4 are rounded downwards while 5-9 are rounded upwards. In the opposite to this example one can use one format statement for as much read/write statements as one wants. That is very practical for tables.

11.2.4 Format strings in read/write statements One can give the format code in the read/write statement directly. The next statement
1

write (*, (A, F8.3)) x = , x

is equivalent to
1 2

write (*, 990) x = , x 990 format (A, F8.3)

One also can give strings in the format statement:


1 2

write (*, 990) x 990 format (x = , F8.3)

11.2.5 Implicit loops and repeat counts If one has a two dimensional array and wants to print the upper left 5 by 10 submatrix with 10 values each on 5 rows, then one can write:
1 2 3 4

do 10 i = 1, 5 write(*,1000) (a(i,j), j=1,10) 10 1000 continue format (I6)

Here one has to loops, an explicit over the rows and an implicit loop over the column index j. One can use repetition in format statements or shorthand notations for repetitions: 950 format (2X, I3, 2X, I3, 2X, I3, 2X, I3) 950 format (4(2X, I3))

Вам также может понравиться