Sie sind auf Seite 1von 30

A Quick Fortran 77 Course

Hans Petter Langtangen

Simula Research Laboratory


&
Dept. of Informatics, Univ. of Oslo

February 2004

A Quick Fortran 77 Course – p. 1


Advantages of Fortran 77
F77 is a very simple language
F77 is easy to learn
F77 was made for computing mathematical formulas
and operating efficiently on plain arrays
F77 is still (and will forever be?) the dominating
language for numerical computing
Lots of well tested and efficient F77 libraries exist
Compilers have 50 years of experience with optimizing
F77 loops over arrays
Result: F77 is hard to beat when it comes to array
operations

A Quick Fortran 77 Course – p. 2


Disadvantages of Fortran 77
The basic variables types are primitive
No struct or class construct in F77
No dynamic memory allocation
Very primitive language for text processing, lists and
more complicated data structures
F77 codes are difficult to extend, maintain and re-use
F90/F95: extension of F77 with classes
(but not virtual functions, templates etc.)
The efficiency of F90/F95 is still problematic, and F77
programmers move very slowly to F90/F95

A Quick Fortran 77 Course – p. 3


My opinion
F77 is attractive for time-critical loops (array operations)
Make the rest of the program in a higher-level language:
Python, C++, Java or F95
Python and F77 is an easy-to-use pair!
Note: integration of F77 with C++ or Java is not
straightforward

A Quick Fortran 77 Course – p. 4


Formatting rules
Lines starting with a character in column 1 are
comment lines
Program statements must begin in column 7 or later
A character in column 6 indicates continuation of the
previous line
Labels (for “go to”) appear as numbers in column 2-5
Only one statement per line
No use of semicolon after a statement
White space has no meaning (can be omitted)

A Quick Fortran 77 Course – p. 5


Example on source code file format
C lines starting with a char in column 1 are comments
C program statements start in column 7
C lines can be continued with a char in column 6:
REAL R, S1,
& S2, S3
GO TO 100
C label numbers (can be avoided) appear in column 2-5
10 CONTINUE
100 CONTINUE
C only one statement can appear at each line
C Traditional F77 used upper-case chars and up to 6 chars
C in variable names - most modern compilers allow much longer
C variable names
C F77 is not case sensitive

A Quick Fortran 77 Course – p. 6


Basic variable types
INTEGER N
REAL R
C array A of length N, indices from 1 to N:
REAL A(N)
C other arrays:
DOUBLE PRECISION B(N,N), Q(-1:N), P(0:N,3,2)
C array sizes: NxN N+2 (N+1)x3x2
C array indices start at 1 unless explicitly specified
C boolean variables:
LOGICAL ON, CONVGD
C Fortran has full support for complex numbers:
COMPLEX Z, Y
C alternative floating-point types:
REAL*4 VAR1, VAR2
REAL*8 VAR2, BARR(N)

A Quick Fortran 77 Course – p. 7


Subroutines
Subroutine (no return value):
SUBROUTINE MYFUNC2(F1, F2, N, M)
C first declare the variable types of the arguments:
INTEGER N, M
REAL*4 F1(N), F2(M,N)
C declare local variables in the routine:
REAL*4 A, B, C
C computing statements:
...
RETURN
END

Example on call:
INTEGER P, Q
REAL*8 A(P), A0(Q,P)
...
CALL MYFUNC(A, A0, Q, P)
...

A Quick Fortran 77 Course – p. 8


Functions
Functions return a single value:
REAL*8 FUNCTION PTCOOR(COOR, PT, DIR, N)
INTEGER N, PT, DIR
REAL*8 COOR(N,2)
PTCOOR = COOR(PT,DIR)
RETURN
C the PTCOOR variable (equals the name of the function
C is returned from this function

Example on call:
INTEGER N
REAL*8 C
...
C = PTCOOR(COOR, 8, 1, N)

All arguments to subroutines and functions are


transferred as “pointers” (call by reference) so any
change to COOR, PT, DIR or N above is visible in the
calling code
A Quick Fortran 77 Course – p. 9
No dynamic memory allocation
Arrays must be allocated with a length fixed at compile
time
INTEGER LENGTH
PARAMETER (LENGTH=10000)
C array with fixed size at compile time:
REAL*8 ARR(LENGTH)
CALL MYFUNC(ARR, LENGTH)
...
C in a subroutine,
C the array can have "variable" size:
SUBROUTINE MYFUNC(A, N)
INTEGER N
REAL*8 A(N)
...

Ugly techniques exist for simulating dynamic memory


allocation

A Quick Fortran 77 Course – p. 10


Scratch arrays
If you need scratch arrays inside a routine, these must
be allocated outside (with fixed length) and provided as
arguments:
INTEGER N
PARAMETER (N=390000)
REAL*8 WORK1(N)
...
CALL MYFUNC3(Q1, Q2, N, WORK1)
...
SUBROUTINE MYFUNC3(Q1, Q2, N, SCRATCH)
INTEGER N
REAL*8 Q1, Q2, SCRATCH(N)
...

A Quick Fortran 77 Course – p. 11


Main program
The main program starts with PROGRAM:
PROGRAM MYPROG
INTEGER SIZE
PARAMETER (SIZE=100000)
REAL*8 COOR(SIZE,2), WORK1(SIZE), WORK2(SIZE)
...
CALL COMPUTE(COOR, WORK1, WORK2, N)
...
END

The rest of the code is subroutines or functions

A Quick Fortran 77 Course – p. 12


Loops over arrays
For-loops are called do-loops in F77:
C i=1,3,5,7,...,N and j=1,2,3,...,N:
DO J = 1, N
DO I = 1,N,2
A(I,J) = SIN(I*DX + J*DY)
END DO
END DO

Arrays are stored column-wise in Fortran 77 (row-wise


in C), so the first index should have the fastest variation
in a loop!

A Quick Fortran 77 Course – p. 13


If-tests
C comparison operators:
C .LT. .LE. .GT. .GE. .EQ.
C < <= > >= ==
IF (A .GE. MAX) THEN
MAX = A
END IF
IF (Q2 .LT. Q1) THEN
Q2 = Q1
ELSE IF (Q2 .EQ. Q1) THEN
Q2 = 0.0
ELSE
Q1 = 0.0
END IF

A Quick Fortran 77 Course – p. 14


Strings
C declare strings with fixed length:
CHARACTER BUFFER*200
CHARACTER FILENAME*30
CALL FILEREAD(FILENAME)
...
SUBROUTINE FILEREAD(NAME)
C strings in a subroutine (unknown length):
CHARACTER NAME*(*)
..

A Quick Fortran 77 Course – p. 15


I/O, standard input/output
WRITE(*,*) ’computed A(’,I,’)=’,A(I,J)
WRITE(*,*) ’Give two numbers:’
READ(*,*) R1, R2

A Quick Fortran 77 Course – p. 16


I/O, files (1)
INFILE=20
OPEN(INFILE, FILE=NAME, STATUS=’UNKNOWN’, IOSTAT=IERR,
& FORM=’FORMATTED’)
IF (IERR .GT. 0) THEN
C unsuccessful opening of the file
WRITE(*,*) ’Could not open file’, NAME
END IF
READ(INFILE,*) N
DO I = 1,N
READ(INFILE,*) A(I)
END DO
C try to read more...
DO I = 1, 1.0E+20
READ(INFILE, *, IOSTAT=IERR) A(N+I)
IF (IERR .LT. 0) THEN
C end of file
AL = N+I
GO TO 100
ELSE IF (IERR .GT. 0) THEN
WRITE(*,*) ’Read error...’
END IF
END DO
CLOSE(INFILE)
A Quick Fortran 77 Course – p. 17
I/O, files (2)
100 CONTINUE
OPEN(21, FILE=’sim.dat’, STATUS=’UNKNOWN’,
& FORM=’FORMATTED’)
WRITE(21,*) N
DO I = 1,N
WRITE(21,*) A(I)
END DO
CLOSE(21)

A Quick Fortran 77 Course – p. 18


Global variables
Global variables in F77 are stored in (named) common
blocks:
INTEGER J1, M
REAL*8 A(M)
COMMON /DATA1/ J1, M, A

To use a global variable in a routine, the complete


common block must be declared
Most F77 compilers allow a keyword "include" for
including a file with the definition of a common block
(otherwise all declarations of a common block must be
consistent throughtout a program)

A Quick Fortran 77 Course – p. 19


Scientific Hello World
program helloworld
real*8 r, s
write(*,*) ’Give a number:’
read(*,*) r
s = sin(r)
write(*,*) ’Hello, World! sin(’,r,’)=’,s
C with format string (A is text, F is float):
write(*,1000) ’Hello, World! sin(’,r,’)=’,s
1000 format(A, F6.3, A, F11.8)
end

A Quick Fortran 77 Course – p. 20


Compiling and using the code
Compiling and linking:
g77 -O3 -c hw.f # produces hw.o object file
g77 -o tmp.app hw.o # links to executable tmp.app

Running the program:


unix> ./tmp.app
Give a number:
0.0001
Hello, World! sin( 0.0001)= 9.99999998E-05
Hello, World! sin( 0.000)= 0.00010000

A Quick Fortran 77 Course – p. 21


A complete application
We shall show the complete F77 code for a program
solving the differential equation

d2 y dy
m 2 + b + cf (y) = A cos ωt
dt dt
numerically
Initial conditions:

dy
y(0) = y0 , =0
dt t=0

Most solution methods require the equation to be


rewritten as a system of first-order differential
equations:
dy1 A Quick Fortran 77 Course – p. 22
Initialize parameters
subroutine scan2(m_, b_, c_, A_, w_, y0_, tstop_, dt_, func_)
C Initialize the data needed in the solver, and store in a
C common block /data/, from the arguments to this subroutine.
real*8 m_, b_, c_, A_, w_, y0_, tstop_, dt_
character func_*(*)
real*8 m, b, c, A, w, y0, tstop, dt
character func*20
common /data/ m, b, c, A, w, y0, tstop, dt, func
m = m_
b = b_
c = c_
A = A_
w = w_
y0 = y0_
tstop = tstop_
dt = dt_
func = func_
return
end

A Quick Fortran 77 Course – p. 23


Initialize parameters from stdin
subroutine scan1()
C Read input data (physical and numerical parameters)
C from standard input. The data are stored in a common block.
real*8 m_, b_, c_, A_, w_, y0_, tstop_, dt_
character func_*20
read(*,*) m_, b_, c_, func_, A_, w_, y0_, tstop_, dt_
call scan2(m_, b_, c_, A_, w_, y0_, tstop_, dt_, func_)
return
end

A Quick Fortran 77 Course – p. 24


Step in forward Euler method
subroutine adv_fe(y, n, t, dt, scratch)
C Advance the solution one time step using the
C Forward Euler method.
integer n, i
real*8 y(n), t, dt, scratch(n)
call rhs(scratch, y, n, t)
C Forward Euler scheme:
do 10 i = 1,n
y(i) = y(i) + dt*scratch(i)
10 continue
return
end

A Quick Fortran 77 Course – p. 25


Step in 2nd-order Runge-Kutta method
subroutine adv_rk2(y, n, t, dt, scratch1, scratch2)
C Advance the solution one time step using a
C 2nd order Runge-Kutta method.
integer n, i
real*8 y(n), t, dt, scratch1(n), scratch2(n), t2
call rhs(scratch1, y, n, t)
do 10 i = 1,n
scratch2(i) = y(i) + dt*scratch1(i)
10 continue
t2 = t + dt
call rhs(scratch2, scratch2, n, t2)
do 20 i = 1,n
y(i) = y(i) + 0.5*dt*(scratch1(i) + scratch2(i))
20 continue
return
end

A Quick Fortran 77 Course – p. 26


Define equations to be solved
The numerical algorithm subroutines call a subroutine
that evaluates the right-hand side of the first-order
differential equation system
Code on next slide

A Quick Fortran 77 Course – p. 27


Define equations to be solved
subroutine rhs(f, y, n, t)
C Define the right-hand side of the ODE system.
integer n
real*8 f(n), y(n), t
real*8 cterm
real*8 m, b, c, A, w, y0, tstop, dt
character func*20
common /data/ m, b, c, A, w, y0, tstop, dt, func
if (func .eq. ’y’) then
cterm = y(1)
else if (func .eq. ’siny’) then
cterm = sin(y(1))
else if (func .eq. ’y3’) then
cterm = y(1) + (y(1)**3)/6.0
else
write(*,*) ’Error: spring-term ’,func,’ illegal’
cterm = 0.0
endif
f(1) = y(2)
f(2) = ( -b*y(2) - c*cterm + A*cos(w*t) )/m
return
end A Quick Fortran 77 Course – p. 28
Putting it all together
subroutine timeloop()
C Integrate the ODEs in time by calling adv_fe or
C adv_rk2 at every time step.
integer n, nmax
parameter (nmax=2)
real*8 time, y(nmax), scratch1(nmax), scratch2(nmax)
real*8 m, b, c, A, w, y0, tstop, dt
character func*20
common /data/ m, b, c, A, w, y0, tstop, dt, func
n = 2
C initial conditions:
y(1) = y0
y(2) = 0.0
open(21, file=’sim.dat’, status=’unknown’, form=’formatted’)
do 10 time = dt, tstop, dt
C call adv_fe (y, n, time, dt, scratch1)
call adv_rk2 (y, n, time, dt, scratch1, scratch2)
write(21,1000) time, y(1)
10 continue
close(21)
return
1000 format(F12.4, F12.4)
end A Quick Fortran 77 Course – p. 29
A main program
program oscillator
call scan1()
call timeloop()
end

A Quick Fortran 77 Course – p. 30

Das könnte Ihnen auch gefallen