26.09.2013 Views

Chapter 11. More Fortran Elements: Functions and Subroutines 11.1 ...

Chapter 11. More Fortran Elements: Functions and Subroutines 11.1 ...

Chapter 11. More Fortran Elements: Functions and Subroutines 11.1 ...

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Chapter</strong> <strong>11.</strong> <strong>More</strong> <strong>Fortran</strong> <strong>Elements</strong>: <strong>Functions</strong> <strong>and</strong> <strong>Subroutines</strong><br />

<strong>11.</strong>1 Overview<br />

In many situations, it is useful to write portable <strong>Fortran</strong> code so that a particular algorithm<br />

may be used in more than one program. It also is helpful when programming a complex problem<br />

to break it up into smaller sections. <strong>Fortran</strong> functions <strong>and</strong> subroutines are small subprograms that<br />

allow for portability <strong>and</strong> division of tasks.<br />

<strong>11.</strong> 2 <strong>Functions</strong><br />

A function in <strong>Fortran</strong> is a subprogram that takes some arguments, performs some<br />

calculations, <strong>and</strong> returns a single result. Intrinsic functions such as SIN(), COS(), ABS(), <strong>and</strong><br />

EXP() are special built-in cases of <strong>Fortran</strong> functions; however, an external function subprogram<br />

may be written to perform any desired computation.<br />

<strong>11.</strong>2.1 Function Subprogram Layout<br />

The layout of an external function subprogram is very similar to any other program layout<br />

in <strong>Fortran</strong>. A function has four main sections as shown in Figure <strong>11.</strong>1: the function type <strong>and</strong> name<br />

with specified arguments, variable declarations, the main body of the subprogram, <strong>and</strong> the end of the<br />

subprogram.<br />

type function name(arg1, arg2, …) start of function<br />

implicit none<br />

variable declarations<br />

real arg1, arg2, x, y<br />

integer i, j, k<br />

.<br />

.<br />

.<br />

calculations are carried<br />

out here<br />

.<br />

.<br />

.<br />

return<br />

end<br />

main body of function subprogram<br />

end of function<br />

Figure <strong>11.</strong>1. Layout of a typical <strong>Fortran</strong> function subprogram.<br />

The FUNCTION statement is placed at the beginning of the function subprogram <strong>and</strong><br />

identifies the function name. The function must be declared as a specific type, INTEGER or<br />

REAL, prior to the function name. The arguments passed to the function from the main program<br />

are enclosed in parentheses after the function name. Any number of arguments may be passed <strong>and</strong><br />

the arguments may correspond to any variable type <strong>and</strong> also may be arrays.<br />

The Variable Declaration section of the subprogram has the same format as it does in a<br />

regular <strong>Fortran</strong> program. Note that the arguments passed to the function from a main program<br />

must be declared in the Variable Declaration section.<br />

67


The Main Body of the subprogram has the same format as in a regular <strong>Fortran</strong> program.<br />

The main computational task of the function is carried out in this section.<br />

The End of the Function is indicated by the statement RETURN, which passes execution<br />

back to the main program, <strong>and</strong> END, which signifies the end of the function subprogram.<br />

<strong>11.</strong>2.2 Using an External Function in a <strong>Fortran</strong> Program<br />

An external function is used in a <strong>Fortran</strong> program in much the same way as an intrinsic<br />

function. When an intrinsic function is used, it is included as part of an assignment statement. For<br />

example, to evaluate the expression x = 3sin( 24t),<br />

an assignment statement including the intrinsic<br />

function SIN() is used, as illustrated below.<br />

X = 3.0*SIN(24.0*T)<br />

€<br />

An external function may be called in a similar fashion as part of an assignment statement. A<br />

typical assignment statement employing an external function is shown below.<br />

Z = FUNCTION(ARG1, ARG2, …)<br />

The function may be passed one or more arguments by the main program. However, the result of<br />

function evaluation is a single numerical value, just as the result of evaluating sin 1.5<br />

numerical value.<br />

In order to use an external function as part of an assignment statement, the name of the<br />

function must be declared in the Variable Declaration section of the main program. The function<br />

may be declared as real or integer depending on the type of result it<br />

€<br />

returns.<br />

68<br />

( ) yields a single<br />

<strong>11.</strong>2.3 Function Subprogram Example<br />

The use of an external function in <strong>Fortran</strong> will be illustrated with the example of numerical<br />

integration. The trapezoidal approximation to the integral of a function is given by the expression<br />

b<br />

∫ f ( x)<br />

dx ≈ h<br />

2 f x [ ( 1)<br />

+ f ( xn ) ] + h∑ f ( xi) . (<strong>11.</strong>1)<br />

a<br />

In Equation (<strong>11.</strong>1), the function has been sampled on the interval a ≤ x ≤ b by n points separated<br />

by step size h. An external function written to implement the trapezoidal approximation to the<br />

integral is given<br />

€<br />

below.<br />

€<br />

n−1<br />

i=2


REAL*8 FUNCTION TRAP(NPTS, H, F)<br />

IMPLICIT NONE<br />

INTEGER NPTS, I<br />

REAL*8 H, F(NPTS)<br />

TRAP = 0.5 * H * ( F(1) + F(NPTS) )<br />

DO 100 I = 2, NPTS–1<br />

TRAP = TRAP + H * F(I)<br />

100 CONTINUE<br />

RETURN<br />

END<br />

The arguments that must be passed to the function from the main program include the<br />

number of integration points, the step size h, <strong>and</strong> the array containing the sampled function. These<br />

variables <strong>and</strong> any others used within the function subprogram must be defined in the variable<br />

declaration statement. The variable names used in the function argument list are dummy variables.<br />

The same names do not have to be used in the main program but their types must match.<br />

The main body of the function subprogram calculates the value of the integral using the<br />

trapezoidal approximation, Equation (<strong>11.</strong>1). At the end of the subprogram, the value of the integral<br />

is stored in the variable TRAP. The RETURN statement then sends the program control back to<br />

the main program.<br />

An example of a <strong>Fortran</strong> program that uses the TRAP function to determine the value of the<br />

integral<br />

e x<br />

1<br />

∫ dx with the trapezoidal approximation is given below. A step size of Δx = 0.01 is<br />

0<br />

employed so that the number of integration points is 101. The main program must define as<br />

REAL*8 the variable TRAP, which corresponds to the value returned by the function subprogram.<br />

€<br />

€<br />

PROGRAM INTEGRATE<br />

IMPLICIT NONE<br />

INTEGER N, I<br />

REAL*8 DELTAX, X, F(101), INTEGRAL, TRAP<br />

DELTAX = 0.01<br />

N = 101<br />

DO 100 I = 1, N<br />

X = DELTAX * (I–1)<br />

F(I) = EXP(X)<br />

100 CONTINUE<br />

INTEGRAL = TRAP(N, DELTAX, F)<br />

WRITE(*,*) 'The value of the integral is ', INTEGRAL<br />

69


STOP<br />

END<br />

In the main program, the variable denoting the number of points is N but in the function the<br />

same variable is defined as NPTS. The variable names do not have to match. The first argument in<br />

the argument list of the function will be stored as the integer variable NPTS in the function no<br />

matter what it is called in the main program. Similarly, in the main program, the step size is called<br />

DELTAX, but in the function the same variable is called H. In both the main program <strong>and</strong> the<br />

function subprogram, the array containing the function to be integrated is called F; however, in<br />

general the two array names do not have to match.<br />

<strong>11.</strong>2.4 Compiling Source Code Containing External <strong>Functions</strong><br />

To compile a <strong>Fortran</strong> program that uses an external function, the source code may be saved<br />

in a single file or in multiple files. If the source code for the main program <strong>and</strong> the external<br />

function is stored in a single file, the source code for the function must be listed after the main<br />

program. The compilation with g77 is then no different than that of a single <strong>Fortran</strong> program:<br />

g77 –o pgm.exe file.f<br />

If the source code of the main program is stored in one file <strong>and</strong> the source code of the external<br />

function is stored in a second file, then the compilation statement must include both files:<br />

g77 –o pgm.exe file1.f file2.f<br />

Here, file1.f <strong>and</strong> file2.f are the two files containing the main program <strong>and</strong> external function source<br />

code, <strong>and</strong> pgm.exe is the single executable program created by compilation. Note that any number<br />

of external functions may be employed in a main program.<br />

<strong>11.</strong>3 <strong>Subroutines</strong><br />

A subroutine in <strong>Fortran</strong> also is a subprogram <strong>and</strong> is similar to an external function. The<br />

difference is that a function may return only one numerical result <strong>and</strong> a subroutine may return<br />

multiple numerical results.<br />

<strong>11.</strong>3.1 Subroutine Layout<br />

The layout of a subroutine is very similar to that of a function. A subroutine has four main<br />

sections as shown in Figure <strong>11.</strong>2: the subroutine name with specified arguments, variable<br />

declarations, the main body of the subroutine, <strong>and</strong> the end of the subroutine.<br />

70


subroutine name(arg1, arg2, …) start of subroutine<br />

implicit none<br />

variable declarations<br />

real arg1, arg2, x, y<br />

integer i, j, k<br />

.<br />

.<br />

.<br />

calculations are carried<br />

out here<br />

.<br />

.<br />

.<br />

return<br />

end<br />

main body of subroutine<br />

end of subroutine<br />

Figure <strong>11.</strong>2. Layout of a typical <strong>Fortran</strong> subroutine.<br />

The SUBROUTINE statement is placed at the beginning of the subroutine <strong>and</strong> identifies<br />

the subroutine name. The arguments passed to <strong>and</strong> from the subroutine are enclosed in parentheses<br />

after the subroutine name. Any number of arguments may be passed back <strong>and</strong> forth <strong>and</strong> the<br />

arguments may correspond to any variable type <strong>and</strong> also may be arrays.<br />

The Variable Declaration section of the subroutine has the same format as it does in a<br />

regular <strong>Fortran</strong> program. Note that the arguments passed between the subroutine <strong>and</strong> the main<br />

program must be declared in the Variable Declaration section.<br />

The Main Body of the subroutine has the same format as in a regular <strong>Fortran</strong> program.<br />

The main computational tasks of the subroutine are carried out in this section.<br />

The End of the Subroutine is indicated by the statement RETURN, which passes<br />

execution back to the main program, <strong>and</strong> END, which signifies the end of the subroutine.<br />

<strong>11.</strong>3.2 Using a Subroutine in a <strong>Fortran</strong> Program<br />

A subroutine is employed in a <strong>Fortran</strong> program in a slightly different way than an external<br />

function. Because the subroutine may pass back to the main program multiple numerical results,<br />

the subroutine is not included as part of an assignment statement. Rather, a CALL statement is<br />

employed. The format of a typical CALL statement is shown below.<br />

CALL NAME(ARG1, ARG2, …)<br />

In the CALL statement, NAME refers to the name of the subroutine. Note that the subroutine name<br />

should not be the same as any other variable name <strong>and</strong> unlike an external function, it should not be<br />

declared as a real or integer variable. This is because a subroutine may pass back to the main<br />

program the values of many variables, both real <strong>and</strong> integer, while a function only returns a single<br />

value.<br />

71


<strong>11.</strong>3.3 Subroutine Example<br />

The use of a subroutine in <strong>Fortran</strong> will be illustrated with the example of the Verlet<br />

algorithm. Recall from <strong>Chapter</strong> 5 <strong>and</strong> Assignment 1 that the velocity Verlet algorithm for<br />

numerically approximating solutions to Newton’s equations of motion is<br />

€<br />

x n+1 = x n + v n Δt + 1<br />

2 a n Δt<br />

( )2 . (<strong>11.</strong>2)<br />

vn+1 = vn + 1<br />

2 an + a ( n+1)Δt<br />

. (<strong>11.</strong>3)<br />

A subroutine written to carry out N steps of the Verlet algorithm for the harmonic oscillator is given<br />

below. The number of points, time step size, harmonic oscillator force constant, mass, <strong>and</strong> initial<br />

position <strong>and</strong> initial velocity<br />

€<br />

are the variables passed to the subroutine. The subroutine returns two<br />

arrays, the position <strong>and</strong> velocity as functions of time.<br />

SUBROUTINE VERLET(N, DT, K, M, X0, V0, X, V)<br />

IMPLICIT NONE<br />

INTEGER N, I<br />

REAL*8 DT, K, M, X0, V0, A1, A2, X(N), V(N)<br />

X(1) = X0<br />

V(1) = V0<br />

DO 100 I = 2, N<br />

A1 = –K*X(I–1)/M<br />

X(I) = X(I–1) + V(I–1)*DT + 0.5*A1*DT**2<br />

A2 = –K*X(I)/M<br />

V(I) = V(I–1) + 0.5*(A1+A2)*DT<br />

100 CONTINUE<br />

RETURN<br />

END<br />

All the variables passed from the main program to the subroutine as well as any others used<br />

within the subroutine must be defined in the variable declaration statement. As was the case for<br />

external function, the variable names used in the subroutine argument list are dummy variables. The<br />

same names do not have to be used in the main program but their types must match.<br />

The main body of the subroutine carries out multiple iterations of the Verlet equations<br />

(<strong>11.</strong>2) <strong>and</strong> (<strong>11.</strong>3). At the end of the subroutine, the array X contains the position as a function of<br />

time <strong>and</strong> the array V contains the velocity as a function of time. These arrays are passed back to the<br />

main program. The RETURN statement then sends the program control back to the main program.<br />

An example of a main program that calls the VERLET subroutine is given below. The<br />

values of the step size, number of time steps, force constant, mass, <strong>and</strong> initial position <strong>and</strong> velocity<br />

are all input from the screen. The main program then calls the VERLET subroutine to advance the<br />

72


position <strong>and</strong> velocity solutions in time. Once the subroutine has completed its calculations, the<br />

results are written to a file by the main program along with the time.<br />

PROGRAM HARMOSC<br />

IMPLICIT NONE<br />

INTEGER NTIME, I<br />

REAL*8 DELTAT, K, M, T, X0, V0, X(5000), V(5000)<br />

OPEN(UNIT=25, FILE='verlet.out', STATUS='unknown')<br />

WRITE(*,*)'Enter force constant:'<br />

READ(*,*) K<br />

WRITE (*,*)'Enter mass:'<br />

READ(*,*) M<br />

WRITE (*,*)'Enter deltat:'<br />

READ(*,*) DELTAT<br />

WRITE (*,*)'Enter no. of time steps:'<br />

READ(*,*) NTIME<br />

WRITE (*,*)'Enter initial position:'<br />

READ(*,*) X0<br />

WRITE (*,*)'Enter initial velocity:'<br />

READ(*,*) V0<br />

CALL VERLET(NTIME, DELTAT, K, M, X0, V0, X, V)<br />

T = 0.<br />

DO 100 I = 1, NTIME<br />

T = T + DELTAT<br />

WRITE(25,*) T, X(I), V(I)<br />

100 CONTINUE<br />

CLOSE(UNIT=25)<br />

STOP<br />

END<br />

In the main program, the variable denoting the number of time steps is NTIME but in the<br />

subroutine the same variable is defined as N. As was the case for external functions, the variable<br />

names do not have to match in the subroutine <strong>and</strong> main program. The first argument in the<br />

argument list of the subroutine will be stored as the integer variable N in the function no matter<br />

what it is called in the main program. Similarly, in the main program, the time step size is called<br />

DELTAT, but in the subroutine the same variable is called DT.<br />

<strong>11.</strong>3.4 Compiling Source Code Containing <strong>Subroutines</strong><br />

To compile a <strong>Fortran</strong> program that uses a subroutine, the source code may be saved in a<br />

single file or in multiple files. If the source code for the main program <strong>and</strong> the subroutine is stored<br />

in a single file, the source code for the subroutine must be listed after the main program. The<br />

compilation with g77 is then no different than that of a single <strong>Fortran</strong> program:<br />

73


g77 –o pgm.exe file.f<br />

If the source code of the main program is stored in one file <strong>and</strong> the source code of the subroutine is<br />

stored in a second file, then the compilation statement must include both files:<br />

g77 –o pgm.exe file1.f file2.f<br />

Here, file1.f <strong>and</strong> file2.f are the two files containing the main program <strong>and</strong> subroutine source code,<br />

<strong>and</strong> pgm.exe is the single executable program created by compilation. Note that any number of<br />

subroutines may be employed in a main program.<br />

74


<strong>Chapter</strong> 11 Review Problems<br />

1. Construct an external function in <strong>Fortran</strong> to convert degrees Fahrenheit to Celsius. The<br />

function is passed the temperature in degrees Fahrenheit <strong>and</strong> returns the temperature in Celsius.<br />

Write a main program to input the temperature in degrees Fahrenheit <strong>and</strong> use the external<br />

function to convert to Celsius. The main program should then write out the temperature in<br />

degrees Fahrenheit <strong>and</strong> Celsius to the screen.<br />

2. Write an external function in <strong>Fortran</strong> to calculate the factorial n!<br />

3. Construct a subroutine to calculate the average <strong>and</strong> st<strong>and</strong>ard deviation of a data set. The<br />

subroutine should be passed the number of data points <strong>and</strong> a one-dimensional array containing<br />

the data.<br />

75

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!