test

Page 1

Fortran 90 Tutorial

Fortran 90 Tutorial Topics 1. Preface 2. Main Features of Fortran 90 3. How to use Fortran 90 on the Unix computers at Stanford 4. Basic program structure 5. Logical expressions 6. Loops 7. Arrays 8. Subprograms 9. Modules 10. Derived data types 11. Many, many more features of Fortran 90 12. Fortran 90 resources on the Web 13. Extra Stuff for Final Lecture Copyright Š 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 77 Tutorial Home] hargrove@sccm.Stanford.EDU

1. Preface The goal of this Fortran 90 tutorial is to give a quick introduction to the key differences between Fortran 77 and Fortran 90. It is not a complete reference! Many details have been omitted. This tutorial is based on the book "FORTRAN 77 for Engineers and Scientists with an Introduction to Fortran 90" by L. Nyhoff and S. Leestma published by Prentice Hall. This tutorial was designed by Sarah T. Whitlock to be used in the course SCCM-001-F: Introduction to Fortran taught at Stanford University, Winter quarter 1997. It has been modified by Paul H. Hargrove for use in the Fortran class taught Winter quarter 1998, under the course number ME-390. Permission to use this tutorial for educational and other non-commercial purposes is granted provided all author and copyright information is retained. Paul H. Hargrove, Stanford, December 1997. Sarah T. Whitlock, Stanford, January 1997. Copyright Š 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

Fortran 90 Tutorial

1


Fortran 90 Tutorial

2. Main Features of Fortran 90 Fortran 90 is a new programming language intended for use in scientific and engineering applications. It is a language that has developed by the introduction of features that are new to Fortran, but are based on experience of other languages (like C and Matlab for instance). Fortran 90 is very different from earlier versions of Fortran, yet it is completely backwards compatible with Fortran 77. The features of Fortran 90 are far too numerous to mention in entirety here, but some of the key features are outlined below: Free format on source code. In Fortran 90, you can use either the Fortran 77 input format or free format. If you use free format, the file extension .f90 should be used for the file name. Dynamic allocation and pointers. It is now possible to allocate storage dynamically. This enables us to finally get rid of all the "work" arrays! User defined data types. You can now define your own composite data types, similar to struct in C or record in Pascal. Modules. Modules enables you to program in an object oriented style, similar to C++. Modules can also be used to hide global variables, thereby making the Fortran 77 common construct outdated. Recursive functions. Now a part of the language. Built-in array operations. Statements like A=0 and C=A+B are now valid when A and B are arrays. There are also built-in functions for matrix operations, e.g., matmul for performing matrix multiplication. Operator overloading. You can define your own meaning of operators like + and = for your own data types (objects). Copyright Š 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

3. How to use Fortran 90 on the Unix Computers at Stanford Practical Details Unfortunately, the Fortran 90 compiler that resides on the Sun computers in the leland system is unreliable. However, there is no alternative at this time. If you think you're program should compile but it won't, then it might not be your fault. See the instructor if you think the compiler is misbehaving.

Compiling, linking, and executing In virtually the same manner in which we compiled our Fortran 77 routines, we can process our Fortran 90 programs. To compile and link a Fortran 90 source code with the name main.f90, simply type f90 main.f90

2. Main Features of Fortran 90

2


Fortran 90 Tutorial This will create an executable file called a.out. Fortran 90 programs which make use of the free format form (to be explained in the next section) must have an extension .f90. Just as with the Fortran 77 compiler, we are able to specify the name of our executable file with the Fortran90 compiler by specifying the -o option: f90 main.f90 -o main.out

This will create an executable file called main.out. Similarly, we can link to a Fortran 90 compiled library (such as the BLAS/LAPACK library in the class account) by f90 main.f90 -L/usr/class/me390/lib -lmy_lib90

This will link your program main.f90 to the compiled library called libmy_lib90.a which resides on the class account in the directory /usr/class/me390/lib. You may copy this library file to your own account if you wish. However, the file is rather large and may cause you to exceed your disk quota on the leland system. A better approach would be to simply compile your programs requiring the BLAS/LAPACK library using the command given above. Note: the library libmy_lib90.a MUST have been created using the Fortran 90 compiler. Attempts to link a Fortran 90 program to a Fortran 77 library will fail. Copyright © 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

4. Basic program structure Key features • Free-form source code is allowed. Statements may begin in any column. • Lines may extend to 132 characters. • More than one statement may be placed on a line. A semicolon is used as the delimiter to separate statements. • In-line comments are allowed. These comments begin with an exclamation point and extend to the end of the line. • Continuation statements are indicated by the placement of an ampersand (&) as the last non-blank character in the line being continued. Up to 39 continuations are allowed. • Variable names may consist of up to 31 characters. Valid characters include all letters, digits, and the underscore symbol (_). The first character of a variable name must be a letter.

Compiling, linking, and executing

3


Fortran 90 Tutorial

Declarations • The command IMPLICIT NONE is allowed. This feature cancels the default naming convention. When invoked, program variables MUST be specified explicitly. • Modified type specification statements may be used to initialize variables or parameters, e.g., REAL :: Area = 0. INTEGER :: Num_Months = 12 REAL, PARAMETER :: Pi = 3.1415927

declares Area to be a real variable with initial value 0., Num_Months to be an integer variable with the initial value 12, and Pi a real parameter with the value 3.1415927. • The separator :: is required in a type specification statement whenever it is used to initialize a variable or to declare a special attribute (such as PARAMETER). It may be omitted in other cases. For example, to declare the variable Area_circle to be real, we may say REAL Area_circle

or, equivalently REAL :: Area_circle

The latter form is preferred for the purpose of uniform programming style. • The precision of a real, integer, complex, or logical variable may be specified using a kind type parameter. For example, to declare a variable A to be a real number with at least 10 decimal places of precision with a range of at least -10^34 to 10^34, do the following: REAL(KIND = SELECTED_REAL_KIND(10,34)) :: A

If the processor you are using is unable to support a variable with this type specification, a compile-time error will result. To declare a real variable to have the equivalent of Fortran 77 accuracy DOUBLE PRECISION, simply do this: INTEGER, PARAMETER :: DP = SELECTED_REAL_KIND(14) REAL(KIND = DP) :: A

This declares the variable A to be of type real and have at least 14 decimal places of accuracy.

Program composition The basic form of a Fortran 90 program is as follows: PROGRAM name declarations executable statements END PROGRAM

Declarations

4


Fortran 90 Tutorial

5. Logical expressions • Symbolic forms of the relational operators are allowed: Old Operator -----------.LT. .EQ. .LE. <= .GE. .NE.

Symbol -----<

.GT.

>

== >= /=

• IF-ELSE constructs may be named by attaching a label at the beginning of the block: name:

IF ( logical argument) THEN statements logicalELSE argument) IF ( THEN name statements . . . name

END IF

• The CASE construct may be used to execute a set of multi-alternative selection criteria: SELECT CASE (selector) CASE (list #1) statements CASE (list #2) statements . . . CASE DEFAULT statements END SELECT

The selector may be an integer, character, or logical expression. Just like IF_ELSE blocks, CASE constructs may also be named. The list #i is a list of one or more possible values of the selector index. The DEFAULT option in a CASE construct may be omitted, but it is recognized as good programming style to always include it. Consider the following example of the use of the CASE construct: SELECT CASE (Freq_Fly_Points) CASE (:19999) WRITE(*,*) 'Keep flying - no free ticket yet!' CASE(20000:49999) WRITE(*,*) 'Woo-Hoo!! Free ticket in continental U.S.!' CASE(50000:) WRITE(*,*) 'Hawaii here I come!!' CASE DEFAULT WRITE(*,*) 'Sorry - you aren't going anywhere :( ' END SELECT

Here we use the CASE construct to evaluate what sort of reward we might be entitled to on our favorite airline based on the number of accrued frequent flyer points. If we have less than 20,000 5. Logical expressions

5


Fortran 90 Tutorial points, we don't get any reward... yet. If we have between 20,000 and 49,000 points, we can get a free ticket in the continental U.S.. If we have more than 50,000 points, we are on our way to Hawaii!! In this case, the DEFAULT option should never execute, but it is there just in case! Copyright © 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

6. Loops • DO loops may have either of the two forms: DO index variable = start, end, step statements END DO

or, DO n index variable = start, end, step statements n CONTINUE

In both cases, the step variable is optional and is assumed to have the value 1 if omitted. As with IF-ELSE and CASE constructs, DO loops may also have names. • WHILE loops are allowed. They have the general form: DO WHILE (logical argument) statements END DO

• An "infinite" loop may be performed as follows: DO . . . conditional statement EXIT . . . END DO

In this instance, a set of statements are executed repetitively until the conditional statement is satisfied. When this occurs, program control jumps to the next executable statement following the END DO. Copyright © 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home]

6. Loops

6


Fortran 90 Tutorial hargrove@sccm.Stanford.EDU

7. Arrays One-dimensional Arrays • The dimension of an array may be specified by a type specification statement of the form: REAL, DIMENSION(10) :: A, B INTEGER, DIMENSION(0:9) :: C

Here, the three arrays A, B, and C have each been dimensioned with 10 storage slots. The index of the real arrays A and B start at 1 while the index for the integer array C starts at 0. • The value of the individual array elements of the array A may be initialized to the values 1, 2, 3, ..., 10 by either of the two methods: A = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)

or, A = (/ (I, I = 1, 10) /)

• The assignment of the values of one array to another is allowed provided that both arrays in question have the same physical dimension. For example, B = A

assigns the previously determined values of the elements of the A array to the array B. • Operators and functions normally applied to simple expressions may also be applied to arrays having the same number of elements. Such operations are carried out on an element by element basis. For example, A = A + B C = 2*C

assigns the ith element of A the value of the sum of the ith elements of arrays A and B. Similarly, the ith element of C is assigned the value equal to the ith element of itself multiplied by 2. • A WHERE construct may be used to assign values to the individual elements of an array with WHERE (logical argument) sequence of array assignments ELSEWHERE sequence of array assignments END WHERE

For example, if A is assigned the values A = (/ (I, I = 1,10) /)

then, we may consider assigning the elements of the array B as WHERE (A > 5) B = 1. ELSEWHERE

7. Arrays

7


Fortran 90 Tutorial B = 0. END WHERE

This assigns to B the values 0, 0, 0, 0, 0, 1, 1, 1, 1, 1. • Several intrinsic array-type functions are available for processing arrays. Some of these include DOT_PRODUCT(A, B): MAXVAL(A): MAXLOC(A):

PRODUCT(A): SUM(A):

returns the dot product of A and B returns the maximum value in array A returns a one-element 1D array whose value is the location of the first occurrence of the maximum value in A returns the product of the elements of A returns the sum of the elements of A

• An array may be allocatable, i.e., it may be assigned memory storage during execution. To declare a real allocatable array A, do REAL, DIMENSION(:), ALLOCATABLE :: A

At run time, the actual bounds for the array A may be determined by the statement ALLOCATE ( A(N) )

where N is an integer variable that has been previously assigned. To ensure that enough memory is available to allocate space for your array, make use of the STAT option of the ALLOCATE command: ALLOCATE ( A(N), STAT = AllocateStatus) IF (AllocateStatus /= 0) STOP "*** Not enough memory ***"

Here, AllocateStatus is an integer variable. AllocateStatus takes the value 0 if allocation is successful or some other machine dependent value of there is insufficient memory. An array can be released from memory by using the DEALLOCATE command DEALLOCATE (A, STAT = DeAllocateStatus)

Again, DeAllocateStatus is an integer variable whose value is 0 if the deallocation was successful.

Multi-dimensional arrays • Multi-dimensional arrays can be dimensioned with statements like REAL, DIMENSION(2,3) :: A REAL, DIMENSION(0:1,0:2) :: B INTEGER, DIMENSION(10,20,3) :: I

The maximum limit on the rank (the number of dimensions) of an array is 7. • The values of the elements of a multi-dimensional array may be assigned in a manner similar to that for the one-dimensional variety. For instance, the values 1, 2, 3, 4, 5, 6 may be assigned to the two-dimensional array A by A = (/ 1, 2, 3, 4, 5, 6 /)

This assigns the values of the A array in column order similar to the rules of Fortran 77. One-dimensional Arrays

8


Fortran 90 Tutorial • The assignment of the values of one array to another is allowed provided that both arrays in question have the same physical dimension. For example, B = A

assigns the previously determined values of the elements of the A array to the array B. • Just like with one-dimensional arrays, operators and functions normally applied to simple expressions may also be applied to multi-dimensional arrays having the same number of elements. Such operations are carried out on an element by element basis. • A WHERE construct may be used to assign values to the individual elements of an array with WHERE (logical argument) sequence of array assignments ELSEWHERE sequence of array assignments END WHERE

• Several intrinsic array-type functions are available for processing multi-dimensional arrays. Some of the more useful ones are MAXVAL(A, D):

MAXLOC(A):

SUM(A, D):

MATMUL(A, B): TRANSPOSE(A):

returns an array of one less dimension than A containing the maximum values of A along dimension D (if D is omitted, returns the maximum value in the entire array) returns a one-element 1D array whose value is the location of the first occurrence of the maximum value in A returns an array of one less dimension than A containing the sums of the elements of A along dimension D (if D is omitted, returns sum of the elements in the entire array) returns the matrix product of A and B returns the transpose of the 2D array A

• An array may be allocatable, i.e., it may be assigned memory storage during execution. To declare a real allocatable array A, do REAL, DIMENSION(:, :), ALLOCATABLE :: A

At run time, the actual bounds for the array A may be determined by the statements ALLOCATE ( A(N, N), STAT = AllocateStatus) IF (AllocateStatus /= 0) STOP "*** Not enough memory ***"

Here, N and AllocateStatus are integer variables. AllocateStatus takes the value 0 if allocation is successful or some other machine dependent value of there is insufficient memory. An array can be released from memory by using the DEALLOCATE command DEALLOCATE (A, STAT = DeAllocateStatus)

Again, DeAllocateStatus is an integer variable whose value is 0 if the deallocation was successful. Copyright © 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home]

Multi-dimensional arrays

9


Fortran 90 Tutorial hargrove@sccm.Stanford.EDU

8. Subprograms General information Just like Fortran 77, the language Fortran 90 allows for two types of subprograms: (1) Functions, and (2) Subroutines. In general, there are two forms of subprograms: (1) Internal, and (2) External. Internal subprograms are those routines that may appear within the main program by making use of the CONTAINS statement. We will not discuss these types of subprograms. External subprograms are those which appear in a separate program section after the main program END statement. This is simiilar to the practices we have already encountered in Fortran 77. We will discuss this type of subprogram. Also, just like Fortran 77, function subprograms in Fortran 90 have an explicit type and are intended to return one value. Subroutine subprograms, on the other hand, have no explicit type and return multiple or no values through a parameter call list. Because we will be focusing on external subprograms, it is essential that we make use of a feature of Fortran 90 known as the INTERFACE block. This block is safety feature which allows main programs and external subprograms to interface appropriately. An interface block ensures that the calling program and the subprogram have the correct number and type of arguments. This helps the compiler to detect incorrect usage of a subprogram at compile time. An interface block consists of: 1. The number of arguments 2. The type of each argument 3. The type of the value(s) returned by the subprogram

We will address the various aspects of subprograms by a few examples.

Function subprograms As an example of a program that makes use of a function subprogram, consider the following PROGRAM Area !--------------------------------------------------------------------! ! This program computes the area of a circle given the input radius ! ! Uses: FUNCTION Area_Circle (r) ! !--------------------------------------------------------------------IMPLICIT NONE INTERFACE FUNCTION Area_Circle (r) REAL, Area_Circle REAL, INTENT(IN) :: r END FUNCTION Area_Circle END INTERFACE ! Declare local variables REAL :: radius !

Prompt user for radius of circle

8. Subprograms

10


Fortran 90 Tutorial write(*, '(A)', ADVANCE = "NO") "Enter the radius of the circle: read(*,*) radius

"

! Write out area of circle using function call write(*,100) "Area of circle with radius", radius, " is", & Area_Circle(radius) 100 format (A, 2x, F6.2, A, 2x, F11.2) END PROGRAM Area !-----Area_Circle---------------------------------------------------! ! Function to compute the area of a circle of given radius ! !--------------------------------------------------------------------FUNCTION Area_Circle(r) IMPLICIT NONE REAL :: Area_Circle REAL, INTENT(IN) :: r ! Declare local constant Pi REAL, PARAMETER :: Pi = 3.1415927 Area_Circle = Pi * r * r END FUNCTION Area_Circle

This program makes use of the function Area_Circle to compute the area of a circle of radius r. The function appears after the END PROGRAM of the main program Area, so it is classified as an external subprogram. Because it is an external routine, the main program makes use of an interface block to define all of the parameters required by the function Area_Circle. The Fortran 90 version of the function subprogram operates in much the same manner as the function subprogram in Fortran 77. Note that the only substantive difference here is the ability to explicitly declare the arguments of the function itself. Take special note of the type descriptor INTENT(IN). This attribute of the variable r in the function subprogram identifies the variable r as a strictly input variable. As such it cannot be modified by the subprogram and its modified value unintentionally returned to the main program. Note also the use of the I/O specifier ADVANCE = "NO" in the write statement prompting the user for the radius of the circle. This option allows the line not to advance after the prompting statement is given. The line will advance on the screen after the user inputs the value of the radius.

Subroutine subprograms An example of a Fortran 90 subroutine subprogram in action is given here PROGRAM Area !--------------------------------------------------------------------! ! This program computes the area of a circle given the input radius ! ! Uses: SUBROUTINE Compute_Area(r, Area) ! !--------------------------------------------------------------------IMPLICIT NONE

Function subprograms

11


Fortran 90 Tutorial INTERFACE SUBROUTINE Compute_Area(r, Area) REAL, INTENT(IN) :: r REAL, INTENT(OUT) :: Area END SUBROUTINE Compute_Area END INTERFACE ! Declare local variables REAL :: radius, Area_Circle ! Prompt user for radius of circle write(*, '(A)', ADVANCE = "NO") "Enter the radius of the circle: read(*,*) radius

"

! Call subroutine to compute area of circle CALL Compute_Area(radius, Area_Circle) ! Write out area of circle write(*,100) "Area of circle with radius", radius, " is", & Area_Circle 100 format (A, 2x, F6.2, A, 2x, F11.2) END PROGRAM Area !-----Compute_Area--------------------------------------------------! ! Subroutine to compute the area of a circle of given radius ! !--------------------------------------------------------------------SUBROUTINE Compute_Area(r, Area) IMPLICIT NONE REAL, INTENT(IN) :: r REAL, INTENT(OUT) :: Area ! Declare local constant Pi REAL, PARAMETER :: Pi = 3.1415927 Area = Pi * r * r END SUBROUTINE Compute_Area

This program makes use of the subroutine Compute_Area to compute the area of a circle of radius r. Again, the functionality here is much the same as that of subroutines in Fortran 77. Note the use of the interface block to define the parameters in the external subroutine as well as the use of the attribute INTENT(OUT) for the return variable Area.

Recursive subprograms Fortran 90 also allows the use of recursive subprograms. As an example of the utility of such a feature, look at this program which calculates the value of n! using a recirsive function subprogram: PROGRAM Compute_Factorial !--------------------------------------------------------------------! ! This program computes n! using a recursive function ! ! Uses: FUNCTION Factorial(n)

Subroutine subprograms

12


Fortran 90 Tutorial ! !--------------------------------------------------------------------IMPLICIT NONE INTERFACE FUNCTION Factorial(n) INTEGER :: Factorial INTEGER, INTENT(IN) :: n END FUNCTION Factorial END INTERFACE ! Declare local variables INTEGER :: n ! Prompt user for radius of circle write(*, '(A)', ADVANCE = "NO") "Enter n for computing n!: read(*,*) n

"

! Write out value of factorial using function call write(*,100) n, "factorial is ", Factorial(n) 100 format (I3, 2x, A, 2x, I12) END PROGRAM Compute_Factorial !-----Factorial-----------------------------------------------------! ! Function to calculate factorials resursively ! !--------------------------------------------------------------------RECURSIVE FUNCTION Factorial(n) RESULT(Fact) IMPLICIT NONE INTEGER :: Fact INTEGER, INTENT(IN) :: n IF (n == 0) THEN Fact = 1 ELSE Fact = n * Factorial(n-1) END IF END FUNCTION Factorial

Note the attribute RECURSIVE applied to the function Factorial. Also note the RESULT value in the function. This syntax is needed so that the subprogram knows when (and what) to return to the main program when the recursive loop is finished. Copyright Š 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

9. Modules In typical engineering programming applications, it often the case that there are parameters, variables, and subprograms that must be shared by several program units. Fortran 90 provides a special program unit known as a MODULE that conveniently packages collections of declarations and subprograms so that they may be Recursive subprograms

13


Fortran 90 Tutorial imported into other program units. The functionality of the module unit is similar to that of the C header file.

Simple modules A form of a module is as follows MODULE name specifications END MODULE name

Note that this is the simplest form of the module unit. More general forms exist which allow the inclusion of subprograms and procedures. We will only address the simplest form of the module unit here. A program module is made accessible to the various program units by way of the USE statement. Consider the following program which makes use of a module in the computation of the area of a circle: MODULE Circle !--------------------------------------------------------------------! ! Module containing definitions of variables needed to ! compute the area of a circle of radius r ! !--------------------------------------------------------------------REAL, PARAMETER :: Pi = 3.1415927 REAL :: radius END MODULE Circle PROGRAM Area !--------------------------------------------------------------------! ! This program computes the area of a circle given the input radius ! ! Uses: MODULE Circle ! FUNCTION Area_Circle (r) ! !--------------------------------------------------------------------USE Circle, ONLY : radius IMPLICIT NONE INTERFACE FUNCTION Area_Circle (r) REAL, INTENT(IN) :: r END FUNCTION Area_Circle END INTERFACE

! Prompt user for radius of circle write(*, '(A)', ADVANCE = "NO") "Enter the radius of the circle: read(*,*) radius

"

! Write out area of circle using function call write(*,100) "Area of circle with radius", radius, " is", & Area_Circle(radius) 100 format (A, 2x, F6.2, A, 2x, F11.2) END PROGRAM Area !-----Area_Circle---------------------------------------------------!

9. Modules

14


Fortran 90 Tutorial ! Function to compute the area of a circle of given radius ! !--------------------------------------------------------------------FUNCTION Area_Circle(r) USE Circle, ONLY : Pi IMPLICIT NONE REAL :: Area_Circle REAL, INTENT(IN) :: r Area_Circle = Pi * r * r END FUNCTION Area_Circle

In this example, we define a module which declares the type of the two real variables Pi and radius. In addition, in this module, we declare the value of the parameter Pi. To make use of the module in the main program, we employ the USE statement. We use a special form of the USE statement that specifies that we are only interested in the value radius in the main program, namely, USE Circle, ONLY : radius. Similarly, we make use of only the parameter Pi in the function subprogram Area_Circle by way of the USE statement appearing in that routine. The USE statement *** MUST *** appear at the beginning of the declaration part of the program unit making use of the module!! It must appear EVEN BEFORE the statement IMPLICIT NONE!

Modules for dynamic array allocation There are times when you may wish to declare an array to be allocatable. However, you may wish to allocate its memory storage in a subprogram rather than in the main program. Unfortunately, allocatable arrays are not allowed to be passed as formal arguments to subprograms. The module construct provides a way for you to pass dynamically allocatable arrays to several program units. Consider the following example: MODULE Dyn_Array !--------------------------------------------------------------------! ! Module containing definitions needed to dynamically allocate ! the values of an array ! !--------------------------------------------------------------------INTEGER :: n REAL, DIMENSION(:), ALLOCATABLE :: A END MODULE Dyn_Array PROGRAM Play_with_Array !--------------------------------------------------------------------! ! This program calls a subroutine to read in the values of ! a dynamically allocated array A and calls several 1D intrinsic ! array functions ! ! Uses: MODULE Dyn_Array ! SUBROUTINE Get_Data ! SUBROUTINE Dealloc_Array ! !--------------------------------------------------------------------USE Dyn_Array IMPLICIT NONE INTERFACE

Simple modules

15


Fortran 90 Tutorial SUBROUTINE Get_Data END SUBROUTINE Get_Data END INTERFACE INTERFACE SUBROUTINE Dealloc_Array END SUBROUTINE Dealloc_Array END INTERFACE ! Declare local variables REAL :: Prod_A, Sum_A ! Call subroutine to read in data for array A CALL Get_Data ! Use intrinsic functions to generate data Prod_A = PRODUCT(A) ! Write out product of elements of array A write(*,100) "The product of the elements of array A area", & Prod_A ! Use intrinsic function to generate more data Sum_A = SUM(A) ! Write out sum of elements of array A write(*,100) "The sum of the elements of array A are", & Sum_A ! Now, deallocate memory containing array A CALL Dealloc_Array ! Place for format statement to live 100 format (A, 2x, F11.2) END PROGRAM Play_with_Array !-----Get_Data-------------------------------------------------------! ! Subroutine to read in the number of values to fill A array, ! allocate space, and to assign the values to A ! ! Uses: MODULE Dyn_Array ! !--------------------------------------------------------------------SUBROUTINE Get_Data USE Dyn_Array IMPLICIT NONE ! Declare local variables INTEGER :: AllocateStatus ! Read in number of array elements from user write(*,'(A)', ADVANCE = "NO") "Input the number of elements desired: read(*,*) n

"

! Allocate storage for array A accordingly ALLOCATE( A(n), STAT = AllocateStatus) IF (AllocateStatus /= 0) STOP "*** Not enough memory ***" ! Read in values for A

Modules for dynamic array allocation

16


Fortran 90 Tutorial write(*, '(A)', ADVANCE = "NO") "Input array values: read(*,*) A

"

END SUBROUTINE Get_Data !-----Dealloc_Array--------------------------------------------------! ! Subroutine to deallocate array space ! ! Uses: MODULE Dyn_Array ! !--------------------------------------------------------------------SUBROUTINE Dealloc_Array USE Dyn_Array IMPLICIT NONE ! Declare local variables INTEGER :: DeAllocateStatus ! Deallocate storage for array A DEALLOCATE( A, STAT = DeAllocateStatus) IF (DeAllocateStatus /= 0) STOP "*** Trouble deallocating ***" END SUBROUTINE Dealloc_Array

Here we make use of the module Dyn_Array to declare the array A an allocatable real array. The integer n will be the size of the array when its value is input by the user in subroutine Get_Data. Note how the subroutines used to allocate and deallocate memory use no formal arguments. This is because all of the arguments needed are passed via the module Dyn_Array. Copyright Š 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

10. Derived data types A useful feature in Fortran 90 is the ability to define derived data types. This feature is similar to the structure feature of the C programming language. The manner in which one defines and uses a derived data type is best illustrated through example: TYPE Point REAL :: X, Y END TYPE Point TYPE Circle TYPE (Point) :: Center REAL :: Radius END TYPE Circle TYPE (Circle) :: C

This declares the variable C to be of type Circle. C formally has two components. The first component, Circle, is itself a derived data type consisting of two real components called X and Y. The second component of C is 10. Derived data types

17


Fortran 90 Tutorial a variable named Radius of type real. The variable C may be assigned a value in either of these ways: C = Circle(Point(0., 0.), 1.)

or, equivalently C%Center%X = 0. C%Center%Y = 0. C%Radius = 1.

In both cases, the "circle" C was assigned the center point (0., 0.) and given the radius 1. (the unit circle). There are many practical uses for derived data types. And, these data types function just like any other variable in a program unit, namely, they may be initialized, modified, and even passed to subprograms as parameters. Copyright © 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

11. Many, many more features of Fortran 90 There are several very important features of Fortran 90 that we are unable to cover due to time constraints. Fortran 90 is a powerful language worthy of far more than the 3 measly hours we have spent on it in class. I hope that you will continue to investigate the capabilities of this language. As a place to start, here a couple of Fortran 90 books I have found useful: Fortran 90 for Engineers and scientists, by L. R. Nyhoff and S. C. Leestma, Prentice Hall, 1997. This is a fairly complete reference with lots of useful examples. Fortran 90/95 explained, M. Metcalf, and J. Reid, Oxford, 1996. This is a fairly inexpensive book that gives a reasonable coverage of Fortran 90 and a good introduction to Fortran 95. Copyright © 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

12. Fortran 90 resources on the Web • Fortran books • Fortran 90 Information • Tutorial: Fortran 90 for the Fortran 77 Programmer.

11. Many, many more features of Fortran 90

18


Fortran 90 Tutorial Copyright Š 1996-7 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

13. Extra Stuff This lesson just contains some extra material(s) to be discussed in the final lecture. The discriptions here are quite brief.

Generic subprograms In Fortran 77 many of the intrinsic functions (sin, cos, abs) return the same type as they receive as an argument. These are known as generic functions. There was no way in Fortran 77 to do the same for user routines. Here is an example of Fortran 90 generic subroutines from Fortran 90 for the Fortran 77 Programmer. This example defines a subroutine, SWAP, which works for reals, integers and characters. Note that while this example only defines a genereic subroutine, generic functions are written in the same way. MODULE SWAPPER INTERFACE SWAP MODULE PROCEDURE SWAP_R, SWAP_I, SWAP_C END INTERFACE CONTAINS SUBROUTINE SWAP_R(A, B) IMPLICIT NONE REAL, INTENT (INOUT) :: A, B REAL :: TEMP TEMP = A ; A = B ; B = TEMP END SUBROUTINE SWAP_R SUBROUTINE SWAP_I(A, B) IMPLICIT NONE INTEGER, INTENT (INOUT) :: A, B INTEGER :: TEMP TEMP = A ; A = B ; B = TEMP END SUBROUTINE SWAP_I SUBROUTINE SWAP_C(A, B) IMPLICIT NONE CHARACTER, INTENT (INOUT) :: A, B CHARACTER :: TEMP TEMP = A ; A = B ; B = TEMP END SUBROUTINE SWAP_C END MODULE SWAPPER

Here is a simple program to use the SWAP subroutine: PROGRAM SWAP_MAIN USE SWAPPER IMPLICIT NONE INTEGER REAL CHARACTER

12. Fortran 90 resources on the Web

:: I, J, K, L :: A, B, X, Y :: C, D, E, F

19


Fortran 90 Tutorial I = 1 ; A = 7.1 ; C = 'a' ; WRITE CALL CALL CALL WRITE

J = 2 B = 10.9 d = 'b'

(*,*) I, SWAP (I, SWAP (A, SWAP (C, (*,*) I,

; ; ;

J, K, L, A, J) ; CALL B) ; CALL D) ; CALL J, K, L, A,

K = 100 ; L = 200 X = 11.1; Y = 17.0 E = '1' ; F = '"' B, X, Y, SWAP (K, SWAP (X, SWAP (E, B, X, Y,

C, D, E, F L) Y) F) C, D, E, F

END

Module procedures and operator overloading Here is (long) an example which shows both modules procedures and operator overloading. The purpose of this example is to define a matrix type so that the following things work as they would in Matlab: type(matrix), dimension(n,n) :: A, B, C type(matrix), dimension(n) :: x, b A = B * C b = A * x x = b / A

A normal array of reals in Fortran 90 would do addition, subtraction and assignment correctly. However, it would do multiplication and division element-wise as explained in class. The module below defines the matrix type and the =, +, -, * and / operators for it. Note that the operators are defined in the same manner as other generic subprograms. ! matrix.f90 ! ! Module for matrix type and operations ! by Paul H. Hargrove ! May 13, 1996 ! module operator type matrix real elem end type matrix interface assignment(=) module procedure matrix_from_real, matrix_from_matrix, & vector_from_real, vector_from_vector end interface interface operator(+) module procedure matrix_add, vector_add end interface interface operator(-) module procedure matrix_sub, vector_sub end interface interface operator(*) module procedure matrix_mul, vector_mul, matrix_vector_mul end interface interface operator(/) module procedure matrix_div, matrix_vector_div

Generic subprograms

20


Fortran 90 Tutorial end interface contains ! ! ASSIGNMENT OPERATORS: X = Y ! subroutine matrix_from_real(X, Y) ! copy a 2D array of reals to a 2D array of type matrix real, intent(in), dimension(:,:) :: Y type(matrix), intent(out), dimension(size(Y,1),size(Y,2)) :: X X(:,:)%elem = Y(:,:) end subroutine matrix_from_real subroutine matrix_from_matrix(X, Y) ! copy a 2D array of type matrix type(matrix), intent(in), dimension(:,:) :: Y type(matrix), intent(out), dimension(size(Y,1),size(Y,2)) :: X X(:,:)%elem = Y(:,:)%elem end subroutine matrix_from_matrix subroutine vector_from_real(X, Y) ! copy a 1D array of reals to a 1D array of type matrix real, intent(in), dimension(:) :: Y type(matrix), intent(out), dimension(size(Y,1)) :: X X(:)%elem = Y(:) end subroutine vector_from_real subroutine vector_from_vector(X, Y) ! copy a 1D array of type matrix type(matrix), intent(in), dimension(:) :: Y type(matrix), intent(out), dimension(size(Y,1)) :: X X(:)%elem = Y(:)%elem end subroutine vector_from_vector ! ! ADDITION OPERATORS: X = Y + Z ! function matrix_add(Y, Z) result(X) ! add 2D arrays of type matrix type(matrix), intent(in), dimension(:,:) :: Y type(matrix), intent(in), dimension(size(Y,1),size(Y,2)) :: Z type(matrix), dimension(size(Y,1),size(Y,2)) :: X X(:,:)%elem = Y(:,:)%elem + Z(:,:)%elem end function matrix_add function vector_add(Y, Z) result(X) ! add 1D arrays of type matrix type(matrix), intent(in), dimension(:) :: Y type(matrix), intent(in), dimension(size(Y,1)) :: Z type(matrix), dimension(size(Y,1)) :: X X(:)%elem = Y(:)%elem + Z(:)%elem end function vector_add

Module procedures and operator overloading

21


Fortran 90 Tutorial ! ! SUBTRACTION OPERATORS: X = Y - Z ! function matrix_sub(Y, Z) result(X) ! subtract 2D arrays of type matrix type(matrix), intent(in), dimension(:,:) :: Y type(matrix), intent(in), dimension(size(Y,1),size(Y,2)) :: Z type(matrix), dimension(size(Y,1),size(Y,2)) :: X X(:,:)%elem = Y(:,:)%elem - Z(:,:)%elem end function matrix_sub function vector_sub(Y, Z) result(X) ! subtract 1D arrays of type matrix type(matrix), intent(in), dimension(:) :: Y type(matrix), intent(in), dimension(size(Y,1)) :: Z type(matrix), dimension(size(Y,1)) :: X X(:)%elem = Y(:)%elem - Z(:)%elem end function vector_sub ! ! MULTIPLICATION OPERATORS: X = Y * Z ! function matrix_mul(Y, Z) result(X) ! multiply 2D arrays of type matrix ! NOTE: NAG's F90 demo won't deal w/ "half constrained" dimensions type(matrix), intent(in), dimension(:,:) :: Y type(matrix), intent(in), dimension(:,:) :: Z type(matrix), dimension(size(Y,1),size(Z,2)) :: X X(:,:)%elem = MATMUL(Y(:,:)%elem, Z(:,:)%elem) end function matrix_mul function vector_mul(Y, Z) result(X) ! multiply 1D arrays of type matrix type(matrix), intent(in), dimension(:) :: Y type(matrix), intent(in), dimension(size(Y,1)) :: Z real X X = DOTPRODUCT(Y(:)%elem, Z(:)%elem) end function vector_mul function matrix_vector_mul(Y, Z) result(X) ! multiply 2D array times 1D array of type matrix type(matrix), intent(in), dimension(:,:) :: Y type(matrix), intent(in), dimension(size(Y,2)) :: Z type(matrix), dimension(size(Y,1)) :: X X(:)%elem = MATMUL(Y(:,:)%elem, Z(:)%elem) end function matrix_vector_mul ! ! DIVISION OPERATORS: X = Y/Z = INV(Z) * Y ! function matrix_div(Y, Z) result(X) ! "divide" 2D arrays of type matrix type(matrix), intent(in), dimension(:,:) :: Y type(matrix), intent(in), dimension(:,:) :: Z

Module procedures and operator overloading

22


Fortran 90 Tutorial type(matrix), dimension(size(Y,1),size(Y,2)) :: X real, dimension(size(Z,1),size(Z,2)) :: W integer i, j, k, n ! copy arguments so they aren't modified W(:,:) = Z(:,:)%elem X(:,:)%elem = Y(:,:)%elem ! perform Gauss elimination on augmented matrix (W|X) n = size(Z,2) do k = 1,n-1 do i=k+1,n W(i,k) = W(i,k)/W(k,k) X(i,:)%elem = X(i,:)%elem - W(i,k) * X(k,:)%elem end do do j=k+1,n do i=k+1,n W(i,j) = W(i,j) - W(i,k) * W(k,j) end do end do end do ! perform back substitution on X do k = n,1,-1 X(k,:)%elem = X(k,:)%elem / W(k,k) do i=1,k-1 X(i,:)%elem = X(i,:)%elem - W(i,k) * X(k,:)%elem end do end do end function matrix_div function matrix_vector_div(Y, Z) result(X) ! "divide" 1D array by 2D array of type matrix type(matrix), intent(in), dimension(:) :: Y type(matrix), intent(in), dimension(:,:) :: Z type(matrix), dimension(size(Y,1)) :: X real, dimension(size(Z,1),size(Z,2)) :: W integer i, j, k, n ! copy arguments so they aren't modified W(:,:) = Z(:,:)%elem X(:)%elem = Y(:)%elem ! perform Gauss elimination on augmented matrix (W|X) n = size(Z,2) do k = 1,n-1 do i=k+1,n W(i,k) = W(i,k)/W(k,k) X(i)%elem = X(i)%elem - W(i,k) * X(k)%elem end do do j=k+1,n do i=k+1,n W(i,j) = W(i,j) - W(i,k) * W(k,j) end do end do end do ! perform back substitution on X do k = n,1,-1 X(k)%elem = X(k)%elem / W(k,k) do i=1,k-1 X(i)%elem = X(i)%elem - W(i,k) * X(k)%elem

Module procedures and operator overloading

23


Fortran 90 Tutorial end do end do end function matrix_vector_div end module operator

Copyright Š 1998 by Stanford University. All rights reserved. [ME-390 Home Page] [Fortran 90 Tutorial Home] hargrove@sccm.Stanford.EDU

Module procedures and operator overloading

24


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.