Category Archives: Undergrad posts

Fortran lessons

Fortran: Install

To download and install GNU Fortran into Windows, download into your c:\ directory the four files

g77exe.zip g77doc.zip
g77lib.zip unzip.zip .

Get a command prompt and go to the root directory on your c drive by entering

cd c:\

Change the name of unzip.zip to unzip.exe by entering

ren unzip.zip unzip.exe

Next unzip the three zipped files by entering in succession

									unzip g77exe.zip
									unzip g77lib.zip
									unzip g77doc.zip

The three files will unzip into a g77 directory, divided into three subdirectories named g77\bin, g77\lib, and g77\doc.

Fortran is run from the g77\bin directory. It is simplest to save all your Fortran programs to this same directory. To get into this directory from a DOS prompt, enter

									cd c:\g77\bin

Then, to compile for example the file hello.f, enter

g77 hello.f
Fortran creates a compiled file that it names a.exe. To run this file from the g77\bin directory just enter

a

If you want to give the compiled file a name of your own choosing, say such as hello.exe, then compile it with the command

g77 hello.f -o hello.exe

(Any name you give a compiled file must end with the extension .exe.)

On your home computer probably the easiest editor for creating Fortran source files is the DOS editor. Open a DOS window, go to the g77\bin directory (as above), and enter "edit". The DOS editor will open and you can type your source file. When you save the file, just name it whatever.f and it will automatically be saved to the g77\bin directory (by default, since that is the directory from which you opened the DOS editor). You do not have to enclose the name in quotes, as you do in saving with Notepad.

Perhaps the most efficient way of writing and testing a Fortran program on your home computer is to open two DOS windows, one for editing your source file with the DOS editor, and the second for compiling and running your program. In each window you will be working from the g77\bin directory, and you can jump from one window to the other with the click of your mouse.

Remark: This distribution of Fortran was obtained from the now defunct website http://www.geocities.com/Athens/Olympus/5564/g77.htm but the instructions should work (last checked on January 7, 2012).

Fortran: More

Topics


Following is further Fortran information not covered in the lessons.

More Intrinsic Functions

This table lists additional functions intrinsic to Fortran, not already listed in Lesson 1.

Function Description
aint(x) truncates the decimal part of x
(without changing the type of x)
anint(x) rounds x to the nearest integer
(without changing the type of x)
int(x) converts x to integer type, giving it
the value of the integer closest to x
but no larger than x in absolute value
log10(x) common logarithm of x (base 10)
max(x1,x2,...,xn) maximum of x1, x2, ..., xn
min(x1,x2,...,xn) minimum of x1, x2, ..., xn
nint(x) converts x to integer type,
rounding x to the nearest integer

Save

This command, used in a subprogram, preserves the values of local variables (i.e., variables used in the subprogram but not listed in the title statement) from one call of the subprogram to the next. For instance, the statement

save m, z

in a subroutine ensures that in calls after the first run the subroutine remembers the final values of m and z from the previous run. A save statement by itself,
save    ,

preserves the values of all local variables in the subprogram. You cannot save a listed variable of the subprogram - the compiler will give an error message. (EG: If a subroutine's first line is "subroutine area(r)", then you cannot save r.)

Common (Blank)

Ordinarily the only information shared between the main program and subprograms are the values of variables appearing in variable lists. The common statement can be used to share additional information.
The simplest form of the common statement is the blank common statement. Let us suppose for illustration that the main program has real variables x and y as well as an integer variable n which are to be shared with one or more subroutines. Then at the beginning of the main program, before any executable statements, you first declare the types of x, y, and n and next insert the "blank common" statement
common x, y, n    .

This instructs Fortran to preserve three "common" memory locations for x, y, and n, designated as triangles below:
x → Δ
y → Δ
n → Δ

These memory locations are then accessible by all subroutines of the program containing a similar common statement (but with possibly different variables). For example, suppose a subroutine declares real variables u and v and an integer variable m. If the subroutine contains also the common statement
common u, v, m    ,

then u, v, and m will share memory locations with x, y, and n, respectively :
x → Δ ← u
y → Δ ← v
n → Δ ← m

When the values of u, v, and m change in the subroutine, then the values of x, y, and n in the main program change accordingly; and vice-versa - changes in x, y, or n in the main program produce changes in u, v, and m in the subroutine. Obviously, because of the sharing of memory locations, the types of x, y, and n must match those of u, v, and m, respectively (and also dimensions must match in the case of arrays.)
It is possible for a third or even more subroutines to share the same three memory locations. If a third subroutine has real variables a and b and an integer variable k, as well as the statement

common a, b, k    ,

then x, u, a share one memory location, y, v, b another, and n, m, k a third. A change in one of these variables in the main program or a subroutine produces the same change in whatever variables share the same memory location.
A common statement cannot list variables that are listed also in the title statement of the subprogram in which the common statement appears. (EG: If a subroutine's first line is "subroutine area(r)", then you cannot list r in the subroutine's common statement.)

Common (Named)

In programs with more than one subroutine it is sometimes desirable to share different sets of variables among different sets of program units. In such situations the named common statement is useful. The general form of this statement is

common / name1 / list1 / name2 / list2 / name3 / list3 / … / nameN / listN    .

The "names" are names for the different sets of variables, and the "lists" contain the names of variables in these sets.
Suppose, for example, that the main program uses variables A, B, C, D, E, F, G, while subroutine "demo1" uses variables A, B, C, D, and subroutine "demo2" uses variables C, D, E, F, G. If we want all program units using the same variable to share the value of that variable, then in the main program we insert the named common statement
common / first / A, B / second / C, D / third / E, F G     ,

in subroutine "demo 1" we insert
common / first / A, B / second / C, D    ,

and in "demo 2" we insert
common / second / C, D / third / E, F, G    .

Then the variable set "first" consists of A and B, and is shared by the main program and demo1. Variable set "second" consists of C and D and is shared by all three units. Variable set "third" consists of E, F, and G and is shared by the main program and "demo2". It is not necessary that different units use the same variable names for shared data. For example, subroutine "demo2" could name its five variables V, W, X, Y, Z; then its common statement would change to
common / second / V, W / third / X, Y, Z     ,

and consequently V and C would share a memory location, as would W and D, X and E, Y and F, and Z and G.

Data

A data statement is used to initialize (i.e., assign initial values to) variables before the program begins. All data statements must appear after parameter and type declarations; it is common practice to include them immediately following these statements.
The general form of a data statement is
data list1 / data1 / list2 / data2 / list3 / data 3 / ... / listN / dataN /     .

Each list is a list of variables separated by commas, and each data is a list of values of the variables in the preceding list. Following is a table of examples with the corresponding resulting assignments:
data x, y, z / 2.1, 3.3, -4.4 / x = 2.1, y = 3.3, z = - 4.4
data k, m, n, p / 3 * 0, 1 / k = m = n = 0, p = 1
data first, last / "Jane", "Smith" / first = "Jane", last = "Smith"
data A / 5.2 / B, C / 2.8, 3.9 / A = 5.2, B = 2.8, C = 3.9
data x, y / 2*1. / m,n / 2*0 / pi / 3.14 / x = y = 1., m = n = 0, pi = 3.14

Note that in a data list the notation "n * x" means that the value x is to be assigned to n successive variables in the preceding variable list.
Data statements were necessary in earlier versions of Fortran, when the compiler did not automatically initialize variables; in more modern versions of Fortran they can usually be omitted without repercussions.

Arithmetic If

The arithmetic if statement has the form

if (expression) k, m, n     ,

where expression is some numeric expression that Fortran can evaluate, and k, m, n are integers representing labels of executable statements. If expression is negative, zero, or positive, then the program jumps to the statement labeled k, m, or n, respectively. As illustration, a program solving a quadratic equation
ax2 + bx + c = 0

might have the arithmetic if statement
if (b * b - 4 * a * c) 10, 20, 30    .

Then if the discriminant b2 - 4ac is negative, the program jumps to the statement labeled 10, if it is zero the jump is to label 20, and if positive to label 30.

Computed Go To

The computed go to statement has the form
go to (n1 , n2 , ..., nm) integer expression    ,

where n1, n2, ..., nm are integers representing labels of executable statements, and integer expression is some integer - valued expression that Fortran can evaluate. If the value of this expression is 1, the program jumps to the statement labeled n1, if the value is 2 the program jumps to the statement labeled n2, etc. For example, suppose a program contains the sequence
print *, "Enter the number of the task you want to perform:"
read *, n
go to (10,12,14,16,18,20) n

If the user enters 1, the program jumps to the statement labeled 10, if the user enters 2 it jumps to statement 12, if the user enters 3 it jumps to 14, etc. If the user errs and enters an integer different from 1, 2, 3, 4, 5, 6, Fortran defaults to the first statement listed, in this case statement 10.

Fortran: Lesson 7

Lesson topics


View Demos
#1 #2 #3
Download Demos
#1 #2 #3

Sometimes it is convenient in a Fortran program to use files for accessing or storing data - especially when large amounts of data are involved. Too much keyboard input during the run of a program leads to mistakes and tedium, while too much screen output has similar consequences. Putting data into files - both for input and output - is a more leisurely and less error-prone approach.

Open

The open command is used to open files - that is, it makes files available so that Fortran can read or write to them. The simplest form of the command is
open (unit = number, file = "name")    .

In place of number you insert a positive integer (but not 6) to be used to refer to the file, and instead of name you insert the name of the file. Here are examples of open commands:
									open (unit = 2, file = "scores")
									open (unit = 7, file = "a:scores.txt")
									open (unit = 5, file = "h:\\results\\primes")
									open (unit = 24, file = "c:\\fortran\\data\\divisors.dat")

Fortran uses the unit number to access the file with later read and write statements. Several files can be open at once, but each must have a different number. There is one thing to remember about numbering a file - you cannot use the number 6, as GNU Fortran reserves that number to refer to the screen.
Note that quotes enclose the filename. Also, in specifying a directory path for a file, you must use double backslashes instead of single ones. Do not put a space on either side of the colon after the drive letter. If you do not specify a drive or directory path for a file, or if you specify the same drive upon which GNU Fortran is installed but without a path, GNU Fortran will by default assume the file is located on the same drive and in the same directory from where Fortran is running.
If the named file does not already exist, Fortran will create it; if it does exist, Fortran will replace it. (So don't mistakenly give the file the same name as another important file!)

Close

The close command is used to close one or more files - examples are
									close (5)
									close (1, 3, 8)
The first of these commands closes the file numbered 5, while the second closes the three files numbered 1, 3, and 8. It is not necessary to close files; all files will automatically be closed when an end or stop statement is executed. However, in programs handling large amounts of data it can be prudent to close files before the end of the program in order to avoid possible memory problems and to increase efficiency.

Write (to Files)

The write command is used to write data to a file. For example, the command
									write (7,*)
works like a print * command, except that data is written to the file numbered 7 instead of to the screen. The two statements
									print *, "The solutions to the equation are : ", x1, x2
									write (7,*) "The solutions to the equation are : ", x1, x2

produce exactly the same output, except that the first writes to the screen and the second to file number 7. The command "write (7,*)" on a line by itself serves as a line feed, skipping a line in the file numbered 7 before the next writing to that file.
You can also use write statements in conjunction with format statements to write to a file; this gives you better control of formatting. In the following, the first number in "write (7,5)" refers to the file number and the second to the label of the format statement:
									 	write (7,5) "The solutions are ", x1, " and ", x2
									5	format (a,f16.10,a,f16.10)

The "write (7,5)" command works exactly like the similar command "write (*,5)", except that in the former output is directed to file number 7, and in the latter to the screen.
Each execution of a write command writes to a single line in a file. The next write command will write to a new line.
Here is a program that finds and prints to a file the divisors of an integer n :
									program divisors
								c	This program finds the divisors of an integer input by the user.
								c	The divisors are printed to a file.
									integer n, k, d(10)
									open (unit = 1, file = "divisors")
									print *, "Enter a positive integer :"
									read *, n
									write (1,*) "Here are the divisors of ", n, " :"
									k = 0
									do i = 1, n
										if (mod(n,i) .eq. 0) then
											k = k + 1
											d(k) = i
										end if
										if (k .eq. 10) then
											write (1,5) (d(j), j = 1, 10)
											k = 0
										end if
									end do
									write (1,5) (d(j), j = 1, k)
								5	format (10i7)
									close (1)
									print *, "The divisors are listed in the file 'divisors'. Bye."
									end

Note that the program counts the divisors, storing them in an array d, until 10 are accumulated; then it prints these 10 on a single line, reserving 7 places for each divisor. It then begins a new count and repeats the procedure until all divisors are found. The last write statement prints whatever divisors are left over after the last full line of 10. The close statement, included here for demonstration only, is unnecessary, as the program is all but finished at that point and the end statement will automatically close the file anyway.

Read (from Files)

The read statement is used to read data from a file. Generally data is read from a file in the standard way, line-by-line and from left to right. But you must remember that each read statement begins reading a new line, whether or not the preceding read statement used all the data in the preceding line.
Suppose for example that a file is numbered 7, and that the first two lines of the file contain the data (separated by commas)
1.23 , 4.56 , 7.89
11, 13 , "Sally"

If the first two read statements in the program are
									read (7,*) x, y, z
									read (7,*) m, n, first
then the program assigns x = 1.23, y = 4.56, z = 7.89, m = 11, n = 13, first = "Sally". The variables will have to be declared in the program to correspond with the data assigned them by the read statements. For instance, in the above situation x, y, and z will have been declared real variables, m and n integers, and "first" a character variable. Failure to match variable types with data types will most likely lead to error messages.
It is possible that a program does not know beforehand the length of a file. If data is being read from a loop, there is a way to exit the loop when all data in the file has been read, thereby avoiding a program hang-up. One simply modifies the read statement to something like
									read (7,*,end=10)
This command instructs Fortran to read the next line in the file numbered 7, but to jump to the statement labelled 10 in the program in the event that the last line in that file has already been read.
You can also use format specifiers in read statements, but this can be somewhat tedious and we will not go into the details. As but one example, suppose you want to make the assignments
n = 77     ,     x = 123.45     ,     y = 67.8   ,

where n is an integer and x and y are real variables. Then you may use the read and format statements
										read (7,5) n, x, y
									5	format (i2,f5.2,f3.1)

and in file number 7 place the corresponding line of data
7712345678    .

Fortran will read and separate the data, insert appropriate decimal points, and assign it to the variables. But as you can see the method is confusing and perhaps not worth the effort.