15
Fortran/Fortran examples Part of the Fortran WikiBook The following Fortran code examples or sample programs show different situations depending on the compiler. The first set of examples are for the Fortran II, IV, and 77 compilers. The remaining examples can be compiled and run with any newer standard Fortran compiler (see the end of the main Fortran article for lists of compilers). Most modern Fortran compilers expect a file with a .f or .for extension (for FORTRAN 66 or FORTRAN 77 source, although the FORTRAN 66 dialect may have to be selected specifically with a commandline option) or .f90/.f95 extension (for Fortran 90/95 source, respectively). Contents 1 FORTRAN II, IV, and 77 compilers 1.1 Area Of a Triangle program 1.1.1 Simple Fortran II program 1.1.2 Simple Fortran IV program 1.1.3 Simple Fortran 77 program 2 "Retro" FORTRAN IV 2.1 Hello, World program 2.1.1 FORTRAN 66 (also FORTRAN IV) 2.1.2 FORTRAN 77 2.1.3 Fortran 90 3 Fortran 77 examples 3.1 Greatest common divisor 3.2 Complex numbers 4 Fortran 90/95 examples 4.1 Summations with a DO loop 4.2 Calculating cylinder area 4.3 Dynamic memory allocation and arrays 4.4 Writing functions 4.5 Writing subroutines 4.6 Internal and Elemental Procedures 4.7 Pointers and targets methods 4.8 Module programming FORTRAN II, IV, and 77 compilers NOTE: Before FORTRAN 90, most FORTRAN compilers enforced fixedformat source code,a carryover from IBM punch cards (http://en.wikipedia.org/wiki/Punch_card) comments must begin with a * or C or ! in column 1 statement labels must occur in columns 15 continuation lines must have a nonblank character in column 6 statements must start in column 7 the linelength may be limited to 72 characters (derived from the 80byte width of a punchcard,

Fortran_Fortran examples - Wikibooks, open books for an open world.pdf

Embed Size (px)

Citation preview

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 1/15

Fortran/Fortran examplesPart of the Fortran WikiBook

The following Fortran code examples or sample programs show different situations depending on thecompiler. The first set of examples are for the Fortran II, IV, and 77 compilers. The remaining examplescan be compiled and run with any newer standard Fortran compiler (see the end of the main Fortranarticle for lists of compilers). Most modern Fortran compilers expect a file with a .f or .for extension(for FORTRAN 66 or FORTRAN 77 source, although the FORTRAN 66 dialect may have to beselected specifically with a command­line option) or .f90/.f95 extension (for Fortran 90/95 source,respectively).

Contents

1 FORTRAN II, IV, and 77 compilers1.1 Area Of a Triangle program

1.1.1 Simple Fortran II program1.1.2 Simple Fortran IV program1.1.3 Simple Fortran 77 program

2 "Retro" FORTRAN IV2.1 Hello, World program

2.1.1 FORTRAN 66 (also FORTRAN IV)2.1.2 FORTRAN 772.1.3 Fortran 90

3 Fortran 77 examples3.1 Greatest common divisor3.2 Complex numbers

4 Fortran 90/95 examples4.1 Summations with a DO loop4.2 Calculating cylinder area4.3 Dynamic memory allocation and arrays4.4 Writing functions4.5 Writing subroutines4.6 Internal and Elemental Procedures4.7 Pointers and targets methods4.8 Module programming

FORTRAN II, IV, and 77 compilers

NOTE: Before FORTRAN 90, most FORTRAN compilers enforced fixed­format source code, acarryover from IBM punch cards (http://en.wikipedia.org/wiki/Punch_card)

comments must begin with a * or C or ! in column 1statement labels must occur in columns 1­5continuation lines must have a non­blank character in column 6statements must start in column 7the line­length may be limited to 72 characters (derived from the 80­byte width of a punch­card,

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 2/15

with last 8 characters reserved for (optional) sequence numbers)

If errors are produced when you compile your FORTRAN code, first check the column alignment. Somecompilers also offer free form source by using a compiler flag

Area Of a Triangle program

Simple Fortran II program

One data card input

If one of the input values is zero, then the program will end with an error code of "1" in the job controlcard listing following the execution of the program. Normal output will be one line printed with A, B, C,and AREA. No specific units are stated.

C AREA OF A TRIANGLE ‐ HERON'S FORMULAC INPUT ‐ CARD READER UNIT 5, INTEGER INPUTC OUTPUT ‐ LINE PRINTER UNIT 6, REAL OUTPUTC INPUT ERROR DISPAY ERROR OUTPUT CODE 1 IN JOB CONTROL LISTING INTEGER A,B,C READ(5,501) A,B,C 501 FORMAT(3I5) IF(A.EQ.0 .OR. B.EQ.0 .OR. C.EQ.0) STOP 1 S = (A + B + C) / 2.0 AREA = SQRT( S * (S ‐ A) * (S ‐ B) * (S ‐ C)) WRITE(6,601) A,B,C,AREA 601 FORMAT(4H A= ,I5,5H B= ,I5,5H C= ,I5,8H AREA= ,F10.2,12HSQUARE UNITS) STOP END

Simple Fortran IV program

Multiple data card input

This program has two input checks: one for a blank card to indicate end­of­data, and the other for a zerovalue within the input data. Either condition causes a message to be printed.

C AREA OF A TRIANGLE ‐ HERON'S FORMULAC INPUT ‐ CARD READER UNIT 5, INTEGER INPUT, ONE BLANK CARD FOR END‐OF‐DATAC OUTPUT ‐ LINE PRINTER UNIT 6, REAL OUTPUTC INPUT ERROR DISPAY ERROR MESSAGE ON OUTPUT 501 FORMAT(3I5) 601 FORMAT(4H A= ,I5,5H B= ,I5,5H C= ,I5,8H AREA= ,F10.2,12HSQUARE UNITS) 602 FORMAT(10HNORMAL END) 603 FORMAT(23HINPUT ERROR, ZERO VALUE) INTEGER A,B,C 10 READ(5,501) A,B,C IF(A.EQ.0 .AND. B.EQ.0 .AND. C.EQ.0) GO TO 50 IF(A.EQ.0 .OR. B.EQ.0 .OR. C.EQ.0) GO TO 90 S = (A + B + C) / 2.0 AREA = SQRT( S * (S ‐ A) * (S ‐ B) * (S ‐ C)) WRITE(6,601) A,B,C,AREA GO TO 10 50 WRITE(6,602) STOP 90 WRITE(6,603) STOP END

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 3/15

Simple Fortran 77 program

Multiple data card input

This program has two input checks in the READ statement with the END and ERR parameters, one for ablank card to indicate end­of­data; and the other for zero value along with valid data. In either condition,a message will be printed.

C AREA OF A TRIANGLE ‐ HERON'S FORMULAC INPUT ‐ CARD READER UNIT 5, INTEGER INPUT, NO BLANK CARD FOR END OF DATAC OUTPUT ‐ LINE PRINTER UNIT 6, REAL OUTPUTC INPUT ERROR DISPAYS ERROR MESSAGE ON OUTPUT 501 FORMAT(3I5) 601 FORMAT(" A= ",I5," B= ",I5," C= ",I5," AREA= ",F10.2,"SQUARE UNITS") 602 FORMAT("NORMAL END") 603 FORMAT("INPUT ERROR OR ZERO VALUE ERROR") INTEGER A,B,C 10 READ(5,501,END=50,ERR=90) A,B,C IF(A=0 .OR. B=0 .OR. C=0) GO TO 90 S = (A + B + C) / 2.0 AREA = SQRT( S * (S ‐ A) * (S ‐ B) * (S ‐ C)) WRITE(6,601) A,B,C,AREA GO TO 10 50 WRITE(6,602) STOP 90 WRITE(6,603) STOP END

"Retro" FORTRAN IV

A retro example of a FORTRAN IV (later evolved into FORTRAN 66) program deck is available on theIBM 1130 page, including the IBM 1130 DM2 JCL required for compilation and execution. An IBM1130 emulator is available at IBM 1130.org (http://ibm1130.org/) that will allow the FORTRAN IVprogram to be compiled and run on a PC.

Hello, World program

In keeping with computing tradition, the first example presented is a simple program to display thewords "Hello, world" on the screen (or printer).

FORTRAN 66 (also FORTRAN IV)

C FORTRAN IV WAS ONE OF THE FIRST PROGRAMMING C LANGUAGES TO SUPPORT SOURCE COMMENTS WRITE (6,7) 7 FORMAT(13H HELLO, WORLD) STOP END

This program prints "HELLO, WORLD" to Fortran unit number 6, which on most machines was the lineprinter or terminal. (The card reader or keyboard was usually connected as unit 5). The number 7 in theWRITE statement refers to the statement number of the corresponding FORMAT statement. FORMAT statementsmay be placed anywhere in the same program or function/subroutine block as the WRITE statements

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 4/15

which reference them. Typically a FORMAT statement is placed immediately following the WRITE statementwhich invokes it; alternatively, FORMAT statements are grouped together at the end of the program orsubprogram block. If execution flows into a FORMAT statement, it is a no­op; thus, the example above hasonly two executable statements, WRITE and STOP.

The initial 13H in the FORMAT statement in the above example defines a Hollerith constant, here meaningthat the 13 characters immediately following are to be taken as a character constant (note that theHollerith constant is not surrounded by delimiters). (Some compilers also supported character literalsenclosed in single quotes, a practice that came to be standard with FORTRAN 77.)

The space immediately following the 13H is a carriage control character, telling the I/O system toadvance to a new line on the output. A zero in this position advances two lines (double space), a 1advances to the top of a new page and + character will not advance to a new line, allowing overprinting.

FORTRAN 77

As of FORTRAN 77, single quotes are used to delimit character literals, and inline character strings maybe used instead of references to FORMAT statements. Comment lines may be indicated with either a C or anasterisk (*) in column 1.

PROGRAM HELLO* The PRINT statement is like WRITE,* but prints to the standard output unit PRINT '(A)', 'Hello, world' STOP END

Fortran 90

As of Fortran 90, double quotes are allowed in addition to single quotes. An updated version of theHello, world example (which here makes use of list­directed I/O, supported as of FORTRAN 77) couldbe written in Fortran 90 as follows:

program HelloWorld write (*,*) 'Hello, world!' ! This is an inline comment end program HelloWorld

Fortran 77 examples

Greatest common divisor

The following introductory example in FORTRAN 77 finds the greatest common divisor for twonumbers and using a verbatim implementation of Euclid's algorithm.

* euclid.f (FORTRAN 77)* Find greatest common divisor using the Euclidean algorithm

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 5/15

PROGRAM EUCLID PRINT *, 'A?' READ *, NA IF (NA.LE.0) THEN PRINT *, 'A must be a positive integer.' STOP END IF PRINT *, 'B?' READ *, NB IF (NB.LE.0) THEN PRINT *, 'B must be a positive integer.' STOP END IF PRINT *, 'The GCD of', NA, ' and', NB, ' is', NGCD(NA, NB), '.' STOP END FUNCTION NGCD(NA, NB) IA = NA IB = NB 1 IF (IB.NE.0) THEN ITEMP = IA IA = IB IB = MOD(ITEMP, IB) GOTO 1 END IF NGCD = IA RETURN END

The above example is intended to illustrate the following:

The PRINT and READ statements in the above use '*' as a format, specifying list­directed formatting.List­directed formatting instructs the compiler to make an educated guess about the required inputor output format based on the following arguments.As the earliest machines running Fortran had restricted character sets, FORTRAN 77 usesabbreviations such as .EQ., .NE., .LT., .GT., .LE., and .GE. to represent the relational operators =,≠, <, >, ≤, and ≥, respectively.This example relies on the implicit typing mechanism to specify the INTEGER types of NA, NB, IA,IB, and ITEMP.In the function NGCD(NA, NB), the values of the function arguments NA and NB are copied into thelocal variables IA and IB respectively. This is necessary as the values of IA and IB are alteredwithin the function. Because argument passing in Fortran functions and subroutines utilize call byreference by default (rather than call by value, as is the default in languages such as C), modifyingNA and NB from within the function would effectively have modified the corresponding actualarguments in the main PROGRAM unit which called the function.

The following shows the results of compiling and running the program.

$ g77 ‐o euclid euclid.f$ euclid A?24 B?36 The GCD of 24 and 36 is 12.

Complex numbers

The following FORTRAN 77 example prints out the values of (where ) for values of .

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 6/15

* cmplxd.f (FORTRAN 77)* Demonstration of COMPLEX numbers** Prints the values of e ** (j * i * pi / 4) for i = 0, 1, 2, ..., 7* where j is the imaginary number sqrt(‐1) PROGRAM CMPLXD IMPLICIT COMPLEX(X) PARAMETER (PI = 3.141592653589793, XJ = (0, 1)) DO 1, I = 0, 7 X = EXP(XJ * I * PI / 4) IF (AIMAG(X).LT.0) THEN PRINT 2, 'e**(j*', I, '*pi/4) = ', REAL(X), ' ‐ j',‐AIMAG(X) ELSE PRINT 2, 'e**(j*', I, '*pi/4) = ', REAL(X), ' + j', AIMAG(X) END IF 2 FORMAT (A, I1, A, F10.7, A, F9.7) 1 CONTINUE STOP END

The above example is intended to illustrate the following:

The IMPLICIT statement can be used to specify the implicit type of variables based on their initialletter if different from the default implicit typing scheme described above. In this example, thisstatement specifies that the implicit type of variables beginning with the letter X shall be COMPLEX.The PARAMETER statement may be used to specify constants. The second constant in this example(XJ) is given the complex­valued value , where is the imaginary unit .The first number in the DO statement specifies the number of the last statement considered to bewithin the body of the DO loop. In this example, as neither the END IF nor the FORMAT is a singleexecutable statement, the CONTINUE statement (which does nothing) is used simply in order forthere to be some statement to denote as the final statement of the loop.EXP() corresponds to the exponential function . In FORTRAN 77, this is a generic function,meaning that it accepts arguments of multiple types (such as REAL and, in this example, COMPLEX).In FORTRAN 66, a specific function would have to be called by name depending on the type ofthe function arguments (for this example, CEXP() for a COMPLEX­valued argument).When applied to a COMPLEX­valued argument, REAL() and AIMAG() return the values of theargument's real and imaginary components, respectively.

Incidentally, the output of the above program is as follows (see the article on Euler's formula for thegeometric interpretation of these values as eight points spaced evenly about a unit circle in the complexplane).

$ cmplxde**(j*0*pi/4) = 1.0000000 + j0.0000000e**(j*1*pi/4) = 0.7071068 + j0.7071068e**(j*2*pi/4) = 0.0000000 + j1.0000000e**(j*3*pi/4) = ‐0.7071068 + j0.7071068e**(j*4*pi/4) = ‐1.0000000 ‐ j0.0000001e**(j*5*pi/4) = ‐0.7071066 ‐ j0.7071069e**(j*6*pi/4) = 0.0000000 ‐ j1.0000000e**(j*7*pi/4) = 0.7071070 ‐ j0.7071065

Error can be seen occurring in the last decimal place in some of the numbers above, a result of theCOMPLEX data type representing its real and imaginary components in single precision. Incidentally,Fortran 90 also made standard a double­precision complex­number data type (although severalcompilers provided such a type even earlier).

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 7/15

Fortran 90/95 examples

Summations with a DO loop

In this example of Fortran 90 code, the programmer has written the bulk of the code inside of a DO loop.Upon execution, instructions are printed to the screen and a SUM variable is initialized to zero outsidethe loop. Once the loop begins, it asks the user to input any number. This number is added to thevariable SUM every time the loop repeats. If the user inputs 0, the EXIT statement terminates the loop,and the value of SUM is displayed on screen.

Also apparent in this program is a data file. Before the loop begins, the program creates (or opens, if ithas already been run before) a text file called "SumData.DAT". During the loop, the WRITE statementstores any user­inputted number in this file, and upon termination of the loop, also saves the answer.

! sum.f90! Performs summations using in a loop using EXIT statement! Saves input information and the summation in a data file program summationimplicit noneinteger :: sum, a print*, "This program performs summations. Enter 0 to stop."open(unit=10, file="SumData.DAT") sum = 0 do print*, "Add:" read*, a if (a == 0) then exit else sum = sum + a end if write(10,*) aend do print*, "Summation =", sumwrite(10,*) "Summation =", sumclose(10) end

When executed, the console would display the following:

This program performs summations. Enter 0 to stop. Add:1 Add:2 Add: 3 Add:0 Summation = 6

And the file SumData.DAT would contain:

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 8/15

123Summation = 6

Calculating cylinder area

The following program, which calculates the surface area of a cylinder, illustrates free­form source inputand other features introduced by Fortran 90.

program cylinder ! Calculate the surface area of a cylinder.!! Declare variables and constants.! constants=pi! variables=radius squared and height implicit none ! Require all variables to be explicitly declared integer :: ierr character(1) :: yn real :: radius, height, area real, parameter :: pi = 3.141592653589793 interactive_loop: do ! Prompt the user for radius and height! and read them. write (*,*) 'Enter radius and height.' read (*,*,iostat=ierr) radius,height ! If radius and height could not be read from input,! then cycle through the loop. if (ierr /= 0) then write(*,*) 'Error, invalid input.' cycle interactive_loop end if ! Compute area. The ** means "raise to a power." area = 2 * pi * (radius**2 + radius*height) ! Write the input variables (radius, height)! and output (area) to the screen. write (*,'(1x,a7,f6.2,5x,a7,f6.2,5x,a5,f6.2)') & 'radius=',radius,'height=',height,'area=',area yn = ' ' yn_loop: do write(*,*) 'Perform another calculation? y[n]' read(*,'(a1)') yn if (yn=='y' .or. yn=='Y') exit yn_loop if (yn=='n' .or. yn=='N' .or. yn==' ') exit interactive_loop end do yn_loop end do interactive_loop end program cylinder

Dynamic memory allocation and arrays

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 9/15

The following program illustrates dynamic memory allocation and array­based operations, two featuresintroduced with Fortran 90. Particularly noteworthy is the absence of DO loops and IF/THEN statements inmanipulating the array; mathematical operations are applied to the array as a whole. Also apparent is theuse of descriptive variable names and general code formatting that comport with contemporaryprogramming style. This example computes an average over data entered interactively.

program average ! Read in some numbers and take the average! As written, if there are no data points, an average of zero is returned! While this may not be desired behavior, it keeps this example simple implicit none integer :: number_of_points real, dimension(:), allocatable :: points real :: average_points=0., positive_average=0., negative_average=0. write (*,*) "Input number of points to average:" read (*,*) number_of_points allocate (points(number_of_points)) write (*,*) "Enter the points to average:" read (*,*) points ! Take the average by summing points and dividing by number_of_points if (number_of_points > 0) average_points = sum(points)/number_of_points ! Now form average over positive and negative points only if (count(points > 0.) > 0) positive_average = sum(points, points > 0.) & /count(points > 0.) if (count(points < 0.) > 0) negative_average = sum(points, points < 0.) & /count(points < 0.) deallocate (points) ! Print result to terminal write (*,'(''Average = '', 1g12.4)') average_points write (*,'(''Average of positive points = '', 1g12.4)') positive_average write (*,'(''Average of negative points = '', 1g12.4)') negative_average end program average

Writing functions

Modern Fortran features available for use with procedures, including deferred­shape, protected, andoptional arguments, are illustrated in the following example, a function to solve a system of linearequations.

function gauss_sparse(num_iter, tol, b, A, x, actual_iter) result(tol_max) ! This function solves a system of equations (Ax = b) by using the Gauss‐Seidel Method implicit none real :: tol_max ! Input: its value cannot be modified from within the function integer, intent(in) :: num_iter real, intent(in) :: tol real, intent(in), dimension(:) :: b, A(:,:) ! Input/Output: its input value is used within the function, and can be modified real, intent(inout) :: x(:) ! Output: its value is modified from within the function, only if the argument is required

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 10/15

integer, optional, intent(out) :: actual_iter ! Locals integer :: i, n, iter real :: xk ! Initialize values n = size(b) ! Size of array, obtained using size intrinsic function tol_max = 2. * tol iter = 0 ! Compute solution until convergence convergence_loop: do while (tol_max >= tol .and. iter < num_iter); iter = iter + 1 tol_max = ‐1. ! Reset the tolerance value ! Compute solution for the k‐th iteration iteration_loop: do i = 1, n ! Compute the current x‐value xk = (b(i) ‐ dot_product(A(i,:i‐1),x(:i‐1)) ‐ dot_product(A(i,i+1:n),x(i+1:n))) / A(i, i) ! Compute the error of the solution! dot_product(a,v)=a'b tol_max = max((abs(x(i) ‐ xk)/(1. + abs(xk))) ** 2, abs(A(i, i) * (x(i) ‐ xk)), tol_max) x(i) = xk enddo iteration_loop enddo convergence_loop if (present(actual_iter)) actual_iter = iter end function gauss_sparse

Note that an explicit interface to this routine must be available to its caller so that the type signature isknown. This is preferably done by placing the function in a MODULE and then USEing the module in thecalling routine. An alternative is to use an INTERFACE block, as shown by the following example:

program test_gauss_sparse implicit none ! explicit interface to the gauss_sparse function interface function gauss_sparse(num_iter, tol, b, A, x, actual_iter) result(tol_max) real :: tol_max integer, intent(in) :: num_iter real, intent(in) :: tol real, intent(in), dimension(:) :: b, A(:,:) real, intent(inout) :: x(:) integer, optional, intent(out) :: actual_iter end function end interface ! declare variables integer :: i, N = 3, actual_iter real :: residue real, allocatable :: A(:,:), x(:), b(:) ! allocate arrays allocate (A(N, N), b(N), x(N)) ! Initialize matrix A = reshape([(real(i), i = 1, size(A))], shape(A)) ! Make matrix diagonally dominant do i = 1, size(A, 1) A(i,i) = sum(A(i,:)) + 1 enddo ! Initialize b b = [(i, i = 1, size(b))] ! Initial (guess) solution x = b

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 11/15

! invoke the gauss_sparse function residue = gauss_sparse(num_iter = 100, & tol = 1E‐5, & b = b, & A = a, & x = x, & actual_iter = actual_iter) ! Output print '(/ "A = ")' do i = 1, size(A, 1) print '(100f6.1)', A(i,:) enddo print '(/ "b = " / (f6.1))', b print '(/ "residue = ", g10.3 / "iterations = ", i0 / "solution = "/ (11x, g10.3))', & residue, actual_iter, x end program test_gauss_sparse

Writing subroutines

In those cases where it is desired to return values via a procedure's arguments, a subroutine is preferredover a function; this is illustrated by the following subroutine to swap the contents of two arrays:

subroutine swap_real(a1, a2) implicit none ! Input/Output real, intent(inout) :: a1(:), a2(:) ! Locals integer :: i real :: a ! Swap do i = 1, min(size(a1), size(a2)) a = a1(i) a1(i) = a2(i) a2(i) = a enddo end subroutine swap_real

As in the previous example, an explicit interface to this routine must be available to its caller so that thetype signature is known. As before, this is preferably done by placing the function in a MODULE and thenUSEing the module in the calling routine. An alternative is to use a INTERFACE block.

Internal and Elemental Procedures

An alternative way to write the swap_real subroutine from the previous example, is:

subroutine swap_real(a1, a2) implicit none ! Input/Output real, intent(inout) :: a1(:), a2(:) ! Locals integer :: N

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 12/15

! Swap, using the internal subroutine N = min(size(a1), size(a2)) call swap_e(a1(:N), a2(:N)) contains elemental subroutine swap_e(a1, a2) real, intent(inout) :: a1, a2 real :: a a = a1 a1 = a2 a2 = a end subroutine swap_eend subroutine swap_real

In the example, the swap_e subroutine is elemental, i.e., it acts upon its array arguments, on an element­by­element basis. Elemental procedures must be pure (i.e., they must have no side effects and can invokeonly pure procedures), and all the arguments must be scalar. Since swap_e is internal to the swap_realsubroutine, no other program unit can invoke it.

The following program serves as a test for any of the two swap_real subroutines presented:

program test_swap_real implicit none ! explicit interface to the swap_real subroutine interface subroutine swap_real(a1, a2) real, intent(inout) :: a1(:), a2(:) end subroutine swap_real end interface ! Declare variables integer :: i real :: a(10), b(10) ! Initialize a, b a = [(real(i), i = 1, 20, 2)] b = a + 1 ! Output before swap print '(/"before swap:")' print '("a = [", 10f6.1, "]")', a print '("b = [", 10f6.1, "]")', b ! Call the swap_real subroutine call swap_real(a, b) ! Output after swap print '(// "after swap:")' print '("a = [", 10f6.1, "]")', a print '("b = [", 10f6.1, "]")', b end program test_swap_real

Pointers and targets methods

In Fortran, the concept of pointers differs from that in C­like languages. A Fortran 90 pointer does notmerely store the memory address of a target variable; it also contains additional descriptive informationsuch as the target's rank, the upper and lower bounds of each dimension, and even strides throughmemory. This allows a Fortran 90 pointer to point at submatrices.

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 13/15

Fortran 90 pointers are "associated" with well­defined "target" variables, via either the pointerassignment operator (=>) or an ALLOCATE statement. When appearing in expressions, pointers are alwaysdereferenced; no "pointer arithmetic" is possible.

The following example illustrates the concept:

module SomeModule implicit none contains elemental function A(x) result(res) integer :: res integer, intent(IN) :: x res = x + 1 end functionend module SomeModule program Test use SomeModule, DoSomething => A implicit none !Declare variables integer, parameter :: m = 3, n = 3 integer, pointer :: p(:)=>null(), q(:,:)=>null() integer, allocatable, target :: A(:,:) integer :: istat = 0, i, j character(80) :: fmt ! Write format string for matrices! (/ A / A, " = [", 3( "[",3(i2, 1x), "]" / 5x), "]" ) write (fmt, '("(/ A / A, "" = ["", ", i0, "( ""["",", i0, "(i2, 1x), ""]"" / 5x), ""]"" )")') m, n allocate(A(m, n), q(m, n), stat = istat) if (istat /= 0) stop 'Error during allocation of A and q' ! Matrix A is:! A = [[ 1 4 7 ]! [ 2 5 8 ]! [ 3 6 9 ]! ] A = reshape([(i, i = 1, size(A))], shape(A)) q = A write(*, fmt) "Matrix A is:", "A", ((A(i, j), j = 1, size(A, 2)), i = 1, size(A, 1)) ! p will be associated with the first column of A p => A(:, 1) ! This operation on p has a direct effect on matrix A p = p ** 2 ! This will end the association between p and the first column of A nullify(p) ! Matrix A becomes:! A = [[ 1 4 7 ]! [ 4 5 8 ]! [ 9 6 9 ]! ] write(*, fmt) "Matrix A becomes:", "A", ((A(i, j), j = 1, size(A, 2)), i = 1, size(A, 1)) ! Perform some array operation q = q + A ! Matrix q becomes:! q = [[ 2 8 14 ]! [ 6 10 16 ]! [12 12 18 ]! ] write(*, fmt) "Matrix q becomes:", "q", ((q(i, j), j = 1, size(A, 2)), i = 1, size(A, 1)) ! Use p as an ordinary array allocate (p(1:m*n), stat = istat) if (istat /= 0) stop 'Error during allocation of p' ! Perform some array operation

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 14/15

p = reshape(DoSomething(A + A ** 2), shape(p)) ! Array operation:! p(1) = 3! p(2) = 21! p(3) = 91! p(4) = 21! p(5) = 31! p(6) = 43! p(7) = 57! p(8) = 73! p(9) = 91 write(*, '("Array operation:" / (4x,"p(",i0,") = ",i0))') (i, p(i), i = 1, size(p)) deallocate(A, p, q, stat = istat) if (istat /= 0) stop 'Error during deallocation' end program Test

Module programming

A module is a program unit which contains data definitions, global data, and CONTAINed procedures.Unlike a simple INCLUDE file, a module is an independent program unit that can be compiled separatelyand linked in its binary form. Once compiled, a module's public contents can be made visible to a callingroutine via the USE statement.

The module mechanism makes the explicit interface of procedures easily available to calling routines. Infact, modern Fortran encourages every SUBROUTINE and FUNCTION to be CONTAINed in a MODULE. This allowsthe programmer to use the newer argument passing options and allows the compiler to perform full typechecking on the interface.

The following example also illustrates derived types, overloading of operators and generic procedures.

module GlobalModule ! Reference to a pair of procedures included in a previously compiled! module named PortabilityLibrary use PortabilityLibrary, only: GetLastError, & ! Generic procedure Date ! Specific procedure! Constants integer, parameter :: dp_k = kind (1.0d0) ! Double precision kind real, parameter :: zero = (0.) real(dp_k), parameter :: pi = 3.141592653589793_dp_k ! Variables integer :: n, m, retint logical :: status, retlog character(50) :: AppName ! Arrays real, allocatable, dimension(:,:,:) :: a, b, c, d complex(dp_k), allocatable, dimension(:) :: z ! Derived type definitions type ijk integer :: i integer :: j integer :: k end type ijk type matrix integer m, n real, allocatable :: a(:,:) ! Fortran 2003 feature. For Fortran 95, use the pointer attribute instead end type matrix ! All the variables and procedures from this module can be accessed! by other program units, except for AppName public

3/23/2015 Fortran/Fortran examples ­ Wikibooks, open books for an open world

http://en.wikibooks.org/wiki/Fortran/Fortran_examples 15/15

private :: AppName ! Generic procedure swap interface swap module procedure swap_integer, swap_real end interface swap interface GetLastError ! This adds a new, additional procedure to the ! generic procedure GetLastError module procedure GetLastError_GlobalModule end interface GetLastError ! Operator overloading interface operator(+) module procedure add_ijk end interface ! Prototype for external procedure interface function gauss_sparse(num_iter, tol, b, A, x, actual_iter) result(tol_max) real :: tol_max integer, intent(in) :: num_iter real, intent(in) :: tol real, intent(in), dimension(:) :: b, A(:,:) real, intent(inout) :: x(:) integer, optional, intent(out) :: actual_iter end function gauss_sparse end interface ! Procedures included in the module contains ! Internal function function add_ijk(ijk_1, ijk_2) type(ijk) add_ijk, ijk_1, ijk_2 intent(in) :: ijk_1, ijk_2 add_ijk = ijk(ijk_1%i + ijk_2%i, ijk_1%j + ijk_2%j, ijk_1%k + ijk_2%k) end function add_ijk ! Include external files include 'swap_integer.f90' ! Comments SHOULDN'T be added on include lines include 'swap_real.f90'end module GlobalModule

Retrieved from "http://en.wikibooks.org/w/index.php?title=Fortran/Fortran_examples&oldid=2585181"

This page was last modified on 26 November 2013, at 19:18.Text is available under the Creative Commons Attribution­ShareAlike License.; additional termsmay apply. By using this site, you agree to the Terms of Use and Privacy Policy.