Vous êtes sur la page 1sur 40

CHBE 303 Fortran 90 Manual

Introduction to Programming in Fortran 90 for Chemical and Biomolecular Engineering Students


by Pradeep P. Bhat, revision/format: Michail Stamatakis Department of Chemical and Biomolecular Engineering Rice University Houston, TX

Copyright 2006 Rice University

Fortran 90
Manual Title page Textooks and References Chapter 1: Introduction to Fortran 90
1.1 A very brief history 1.2 Why Fortran? Page 1 of 40

1.3 Coding in UNIX 1.4 Compiling in UNIX 1.5 Fortran 90 v. FORTRAN 77

Chapter 2: Basic Concepts


2.1 2.2 2.3 2.4 2.5 2.6 2.7

Basic Fortran Program Format Data Types, Declaration, and Parameterization Operations and Logical Expressions Precision Intrinsic Functions Input, Output and Format Descriptors

Chapter 3: Control Structure


3.1 Branches 3.2 Loops 3.3 Pseudocode and Flowcharts

Chapter 4: Subroutines, External Functions, and Modules


4.1 External Functions 4.2 Subroutines

Chapter 5: Arrays
5.1 5.2 5.3 5.4

One Dimensional Arrays Allocatable Arrays Multi-Dimensional Arrays Derived Data Types

APPENDICES A.1: Helpful information A.1.1 A.1.2 A.1.3 A.1.4 Fortran Character Set Operations Random number generator Debugging Guide

TEXTBOOKS:
The following books are recommended:

Fortran 90/95 for Scientists and Engineers Chapman, Steven J. WCB/McGraw-Hill, 1998.

This is the primary reference in developing the notes for this course.

Fortran 90/95 explained Metcalf, M. and Reid, J. Oxford University Press, 1996.

A good reference. Not as comprehensive, nor does it include as many examples as the others, but it is a good reference for questions of syntax and structure. The other options give more examples and better explanations.

Fortran 90 for Engineers and Scientists Nyhoff, L. and Leestma, S. Prentice Hall, 1997.

Page 2 of 40

Basically equivalent to Chapman's book, just arranged differently. Offers many examples of an engineering nature. The pages referenced in the index are not always accurate and explanations are not as clear as Chapman (that's my opinion).

Fortran 90 handbook: complete ANSI/ISO reference Adams J.C. McGraw-Hill, 1992. Fortran 90 programming Ellis T.M.R., Philips I.R., Lahey T.M. Addison-Wesley, 1994.

WEBPAGES:

http://wwwasdoc.web.cern.ch/wwwasdoc/f90.html http://www.ibiblio.org/pub/languages/fortran/ http://www.polyhedron.com/salford/products/other/ftn95_personal.html http://gcc.gnu.org/wiki/GFortran

Michael Metcalf's Fortran 90 CNL Articles A more in depth fortran guide if you want to really get involved! A free fortran compiler running under windows (click DOWNLOAD NOW at the bottom of the page). A free GNU fortran compiler running under windows (click Binaries under "Quick links" and then installer).

1.1

A very brief history

Fortran from its development was intended for translating scientific equations into computer code. It's name is derived from FORmula TRANslation. Developed between 1954 and 1957 by IBM, it was the first program that converted an algorithm into machine language that the computer could read and execute. It was revolutionary and made programming much easier than the generating of machine language by hand. Fortran went through many revisions over the years. FORTRAN II came out in 1958 and FORTRAN IV in 1962 (I am not sure what happened to III). FORTRAN IV was renamed FORTRAN 66 when it became an ANSI standard in 1966. The next major update came in 1977 with FORTRAN 77. This is the version that has been used for the last 20 or so years and is still used by the hard-core, crazy engineers who resist change and enjoy difficult programming. Fortran 90 was developed in 1991 and addresses most of the problems with FORTRAN 77, incorporates most of the new features of languages developed in newer programming languages, attempts to phase out some archaic programming features from previous versions by offering more direct commands, and abandons the tradition of writing Fortran in all upper case. Fortran 90 is a big improvement. Fortran 95 was an update in 1997 that offered a few new features and makes obsolete those awkward options that 90 was attempting to phase out. Although developed early in the 90's, compilers have only recently become available for widespread use of Fortran 90. The resistance of many to the newer version and the simple and versatile (even though less powerful) features of many new computer languages made Fortran/FORTRAN fall out of favor with many during the 90's. Now that Fortan 90/95 compilers are readily available, lucky students like you will be able to have all the advantages of Fortran compilers with much simpler programming syntax.

Page 3 of 40

Also, a newer version of Fortran is in development that will allow more modern features like object oriented programming and will be able to run more efficiently when used for parallel computing.

1.2

Why Fortran?

Probably many of you are wondering why you need to learn Fortran with all the seemingly more simple alternatives, such as MATLAB (in fact, this is hardly an alternative. Fortran is much more powerful than MATLAB. A better argument may be C++ v/s Fortran 90). In fact many universities have dropped Fortran from their Chemical Engineering curriculum. The first reason this occurred was the resitance in the engineering community to moving from FORTRAN 77 to Fortran 90. While many languages were being created and modified for simplicity and for use in specific applications, Fortran lagged behind. However, Fortran remained throughout this time as the superior language for numerical, scientific, and engineering applications. With the improvements in Fortran from version 77 to 90, it remains the language of choice for computational science. Fortran 90 is more powerful than C++ in the areas of numerical robustness, data parallelism, data abstraction, and functional programming. C++ leads only in objectoriented programming, which the next version of Fortran hopes to address.

1.3

Coding in UNIX

When writing code in UNIX you can use any of the text editors (emacs, vi & pico for instance) and write the program. When complete, the program must be saved with a filename and an extension .f90, for instance if you write a program, with name my_code, you have to save that file as my_code.f90. This is important as .f implies fixed format file, while Fortran 90 files (.f90 files) are free format files. An alternative is using Sun Workshop. Those of you who like windows type applications with a nice GUI this is the one for you. I am a novice in using Workshop and prefer the old UNIX way; so, I can offer little advice. It allows you to creat programs, debug them,and build executables. This program is invoked in UNIX by typing workshop &. More information can be found at http://www.ictp.trieste.it/~manuals/programming/sun/. Found there are .html files introducing workshop and also a Fortran handbook (http://www.ictp.trieste.it/~manuals/programming/sun/fortran/user_guide/index.html)

Practice: Open a text editor and write the following simple fortran program. Then save this in a file named code.f90. PROGRAM joke WRITE(*,*) "Hello world!" END

1.4

Compiling in UNIX

Once you have written your code you must compile it before running. Compiling translates the written source code into machine language, or an object program. In order to compile in UNIX, at the prompt type f90 followed by the program name (e.g % f90 progname.f90). This should create an executable file named a.out. You should then be
Page 4 of 40

able to run the program by typing a.out at the UNIX prompt (i.e % a.out, should run the program). Every time you compile a program without the -o option (discussed in the next paragraph) a new a.out file will be created and if a previous a.out file exists it will be overwritten. Many options are available when compiling code and some of these will be discussed later in the notes. One option (-o) allows you to define the name for your executable file. You do not have to use the default executable named a.out. In this way you can compile a program once and have the executable available whenever it is needed. Also, in more advanced cases, two or more executables will need to be linked. In these cases, you must have different names for all executables. For example: % f90 -o progname progname.f90 This command compiles the program progname.f90 and creates an executable file named progname. The typical convention is to name your executable file with the same name as your program, but without an extension. Again, compiling and running in Sun Workshop will be different. Refer to the manuals if interested. Practice: Compile and run the program written previously in 1.3.

1.5

Fortran 90 v/s FORTRAN 77

Although you probably have never seen FORTRAN 77, I will give you a brief summary of some of the changes and obsolete features. Keep in mind that Fortran 90 is upwardly compatible with FORTRAN 77, meaning all features present in FORTRAN 77 are present in Fortran 90. Some FORTRAN 77 features have been designated obsolete and should never be used because of better alternatives. The features deemed obsolete in Fortran 90 are not available in Fortran 95 (they are actually obsolete). The first, and most obvious, change from FORTRAN 77 to Fortran 90 is the conversion from fixed source code to free source. In fixed source form (which dates back to punch cards) statement labels had to appear in the first five columns, column six was used for a continuation indicator, and statements appeared on lines 7-72. In Fortran 90 free source form means you are free to type comments and commands wherever you want. An exclamation point, ! (also known as a "bang"), is used to indicate a comment statement in Fortran 90. Obsolete features include the arithmetic IF statement, ASSIGN and GO TO statements. Avoid use of these features in your code. In fact, don't learn them.

Chapter 2: Basic Concepts


2.1 Basic Fortran

There is some basic information that everyone should know when beginning to use Fortran. First of all, Fortran 90 is case insensitive, meaning A is the same as a, WriTe is
Page 5 of 40

the same as WRITe, etc.. However, when programming it is common (i.e. good) practice to use uppercase when writing Fortran keywords (i.e. WRITE, REAL, PARAMETER, etc.). Also, you should always be consistent when using upper of lowercase. It makes your code more readable and less confusing to others (like the graders) when deciphering your code. The available character set for Fortran 90 is given in A.1.1. Fortran 90 is free source form, unlike FORTRAN 77 which was fixed source. Fixed form, which dates back to the use of punch cards, meant that statement labels had to appear in the first five columns, column six was used for a continuation indicator, and statements appeared on lines 7-72. In Fortran 90 free source form means you are free to type comments and commands wherever you want. An exclamation point, ! (also known as a "bang"), is used to indicate a comment statement. The comment statement follows the bang and continues to the end of the line. Comment statements are ignored by the compiler, but are very important for documenting your program. It is important to use comments frequently to clarify the procedures intended in a program. Comments can be of great assistance to debugging and revising computer programs. A line of Fortran 90 code can have a maximum of 132 characters. An ampersand (&) is placed at the end of a line to indicate that it continues on the next line. At most 39 continuation lines are permitted. If continuing a character string an ampersand must be placed at the end of the first line and the beginning of the next. Only with character strings is the ampersand needed at the start of the next line. Example: PROGRAM test ! This line is a comment ! Comments are ignored by the compiler a = 3.0 + 4.0 + & 13.0 ! After execution variable a will have the value 20.0 PRINT* a END 2.2 Program Format

In general, a Fortran program should have the following form:


heading IMPLICIT NONE specification section execution section internal subprograms END PROGRAM

HEADING - The heading has the form PROGRAM name, where name is any legal identifier (an identifier includes any of the legal Fortran characters (A1.1) but without blank spaces. Program names must begin with a letter, followed by up to thirty letters, digits, or underscores. This is not mandatory, but it is highly
Page 6 of 40

recommended (meaning points will be taken off if you do not have a program name). Use a name that has some relation to the program task. This way it can assist you or others when looking at your code in the future. A program name will distinguish your code from other codes, modules, and subprograms. IMPLICIT NONE - Although not required for a program to run and compile this statement is required in any program written for this course. Most languages require that all variables be specified; however, Fortran will assign a type to any variable whose type is not declared. IMPLICIT NONE cancels this naming convention. This will help guard against errors associated with variable type that occur due to the default type convention implicit in Fortran. SPECIFICATION SECTION - Following the IMPLICIT NONE declaration it is important to declare the environment of the program. All variables and constants need to be explicitly declared in this portion of the program. The data type must be stated for all constants, variables, parameters, etc. EXECUTION SECTION - This is the section where the program actions are specified. INTERNAL SUBPROGRAMS - If needed subprograms can be contained within the body of the program (internally). END PROGRAM - This is the only required part of the program. It indicates to the compiler the end of the program and also halts execution. This statement can be labeled. Here is a simple example program. PROGRAM introduction IMPLICIT NONE ! heading with name = introduction ! statement that all data types must be declared

! Declare variables and constants in the specification section INTEGER :: age = 26 ! age is integer type data and has the initial value of 26 CHARACTER (4) :: name = "Eric" ! name is character type, length 4, and is Eric ! Now here is the execution section. ! The output is: My name is Eric and I am 26 years old. PRINT *, "My name is ", name, " and I am ", age, "years old." ! There are no internal subprograms in this program ! Here is the END PROGRAM statement. ! It has been labeled with the program name. END PROGRAM introduction

2.3 Data Types, Declaration, and Parameterization


Fortran 90 allows manipulations of various types of data. The data or variable determines the manipulations, operations, or functions allowed to them. Fortran allows five basic data types, plus the ability to define your own types (Section 5.4: Derived Data Types). The available data types are:

Real Integer Complex Character Logical

The type for all constants and variables should be declared in the specification section of the program. Data types are declared in statements like the following: TYPE :: var Where TYPE is the data type (i.e. real, integer, etc) and var is the variable name. Examples: REAL :: temp ! temp is a real variable CHARACTER :: answer, name ! answer and name are variables of the character type INTEGER :: A = 4 ! A is integer type and initialized as the value 4 REAL
Page 7 of 40

Real data can be represented in decimal form as exponents. Real constants written in decimal form must contain a decimal point. A real constant written as "43" is not valid as it is recognized as integer type. "43.", however, is acceptable. Exponential representation in Fortran involves either an integer or decimal number followed by an exponent that is written as an E with an integer following (i.e. 4.56E2). The default precision for real data is typically about seven decimal digits and the range around -10-38 to 1038 (although this is machine dependent). Processors must provide an option to represent the data with more precision than the default. This is termed double precision. Techniques for checking and assuring the precision needed for an application can be seen in another section (2.5 Precision). Example declaration: REAL :: A, B, C A, B and C are of real type. INTEGER Integers are positive or negative whole numbers (including 0) represented by a string of numbers not including commas or decimal points. Integers can be preceded by a negative (-) sign. Ex: INTEGER :: A = 4, B A and B are integer type and A has been given an initial value of 4. B has not been given an initial value. Be careful because some compilers will assign it a value. COMPLEX Fortran allows variables to be declared as complex numbers. Variables such as this are declared with their first value as the real component and the second as the imaginary. The following statements show an example of a complex variable declaration in a portion of a program. Remember that !'s are comment statements explaining the coding logic. ! Declare A as a complex variable COMPLEX :: A ! Set the value of A to 4.2 -3.1i A = (4.2, 3.1) A has been specified as a complex variable and then it's values set as real part = 4.2, imaginary part = 3.1. CHARACTER Character strings are a sequence of Fortran symbols enclosed within quotes or apostrophes (either quotes or apostrophes can be used but it must be the same at beginning and end). The number of characters in a sequence is the length. Blanks are counted as characters. By default, the length of any character string is one. To avoid this, a length should be specified. CHARACTER (LEN = n) :: name CHARACTER (n) :: name In both cases name is of character type with length = n. If an apostrophe or quotes are desired within the string then the alternative should be used to enclose the string. As an alternative the desired symbol can be entered double. As an example: word = "can't" word = 'can''t' Both of these declarations will produce the same character definition, can't. LOGICAL
Page 8 of 40

Logical variables have one of two values: .TRUE. or .FALSE. Logical values can be displayed but are represented by only a T or and F, preceded by a space. the values can also be read but are only assigned according to the first letter represented. For example: LOGICAL :: A, B ! Ask the user for the values of A and B PRINT *, "What are the values of A and B?" READ (*,*) A, B Here A and B have been declared logical variables. The user is prompted for the values of A and B. If the input for those statements are .TRUE, .Turtle both A and B will be assigned the value of .TRUE. Logical expressions can be used for selection and repetition. A list of logical expressions can be seen in the next chapter and A.1.4. PARAMETER DECLARATION Often, a certain constant appears so often in a program it should be declared as a parameter. INTEGER, PARAMETER :: N = 10 REAL, PARAMETER :: pi = 3.141593 This allows one statement to be made at the beginning of the program setting a parameter value to a particular constant. Once a constant is declared a parameter it can no longer be changed. This prevents errors from occurring later where the parameter may be inadvertently changed. Also, using a declared constant throughout a program in lieu of the numerical value allows the parameter to be changed in only one line of code. For example a program may contain statements calculating area throughout the code: area = 3.141593 * r ** 2 If statements using 3.14593 occur frequently in the program it is better to declare a constant (i.e. pi) initially. This way the value is always the same. Repeated typing increases the chance of typographical errors. Also, parameterization creates one area at the beginning of your code where a parameter needs to be changed, rather than searching throughout the program for its many entries.

2.4

Operations and Logical Expressions

OPERATIONS There are various arithmetic operations that can be used with numeric data. They are +, -, *, /, and ** (exponential). The order of priority for these operations are essentially the same as typical mathematical rules: 1. Exponents are performed first, from right to left. 2. Multiplications and divisions are performed next, from left to right. 3. Addition and subtraction are last. They are also directed from left to right. Of course, you can use parentheses to enclose subexpressions. Subexpressions are evaluated first according to the previous priority rules. 4 * 5 * 2 - 3 ** 2 = 40 - 9 = 31 4 * (5 * 2 - 3) ** 2 = 4 * 7 ** 2 = 4 * 49 = 196 A concern with using arithmetic operations is the use of mixed-mode expressions (i.e. combining real and integer quantities). Mixed-mode expressions should typically be avoided as it is considered bad programming. When an integer quantity is combined with a real quantity, the integer is converted to its real equivalent and the expression is then evaluated. For example: 3 + 4.2 = 7.2 5.0 / 10 = 0.5

Page 9 of 40

However, this can lead to problems because the conversion only occurs when the real quantity is encountered in the sequence of operations. the following gives an example of the problems that may occur with mixedmode expressions. 3.2 + 9.0 / 5 = 5.0 3.2 + 9 / 5 = 4.2 The value for 9 / 5 is 1 because it is the division of two integers and the fractional part is truncated. Another problem can occur when using real numbers and exponents. Real exponents should never be used in place of integer exponents. 2.0 ** 3 is evaluated as 2.0 * 2.0 * 2.0 which is 8.0. However, if the exponent is real it is performed using logarithms: 2.0 ** 3.0 = e3.0 ln (2.0) This will not be 8.0 because of roundoff errors. This also causes problems when raising a negative number to a real exponent. A negative logarithm is undefined. (-2.0) ** 2.0 is undefined, while (-2.0) ** 2 is 4.0. Real exponents are ok to use, but only when integer values cannot be used in its place. LOGICAL EXPRESSIONS Logical expressions are expressions that result in either logical constants (.TRUE. or .FALSE.) or logical variables (variables that can take the values of .TRUE. or .FALSE.). Simple logical expressions consist of the following: SYMBOL < or .LT. > or .GT. == or .EQ. <= or .LE. >= or .GE. /= or .NE. A .NE. 6 C * A >= 3 It is important to realize that many real numbers are not stored exactly; so, be cautious when comparing real values using == or /=. These operators may result in a .FALSE. result due to precision errors. It is usually better to use a range of threshold values when analyzing real numbers. Character variables can also be compared logically. Characters are ranked in alphabetic order (with a blank ranked ahead of "a") beginning with the first character. All of the following statements are true: "A" > "B" "better" > "between" "good year" > "goodyear" Compound logical expressions are formed using one of the following operators applied to simple logical expressions:

MEANING Is less than Is greater than Is equal to Is less than or equal to Is greater than or equal to Is not equal to

The following expressions can be evaluated with logical results (.TRUE. or .FALSE.)

.NOT. .AND. .OR. .EQV. .NEQV. .NOT. exp1 returns the opposite result (i.e. if exp1 is .TRUE. then .NOT. exp1 is .FALSE. and vice versa). exp1 .AND. exp2 returns a value of .TRUE. only if both values are .TRUE. If either one, or both arguments are .FALSE. then the compound result is .FALSE. exp1 .OR. exp2 is the opposite. If either value is .TRUE. then the compound result is .TRUE.
Page 10 of 40

If exp1 and exp2 are simple logical expression then

exp1 .EQV. exp2 returns a value of .TRUE. if both arguments are the same and is .FALSE. otherwise. exp1 .NEQV. exp2 is the opposite of .EQV., returning a value of .TRUE. if the two expressions are different.

2.5

Precision

One of the biggest concerns with using real quantities is precision. Often real numbers cannot be stored exactly in the computer's memory, and this can lead to error when looking at real results. The default precision for real data is known as single-precision. Although the exact accuracy is compiler dependent, in general single precision for real data is typically about seven decimal digits and the range around -1038 to 1038. For some applications higher precision is desired. All compilers have at least two kinds of real types, single-precision and double-precision. Single precision is the default for any real number, but double precision can be indicated for values in many ways. Exponentials declared with D rather than E for the exponent are immediately of kind double-precision real by default. For example: 3.0D1 is given double-precision because D is used to indicate the exponent. If an E was used the value would have the default accuracy of single-precision. Real declaration statements can be used to indicate the precision for parameters as follows: REAL(KIND = kind_number) :: vars Numbers that indicate to the compiler what precision of real number is being used are known as kind numbers. Just as the exact accuracy of single and double precision varies from one compiler to the next, so do the kind numbers associated with them. Typically if single will be KIND = 1 and double KIND = 2. Another common option is single-precision KIND = 4 and double-precision KIND = 8. So this brings us naturally to the question of how we can determine the kind numbers for our compiler. Useful for this purpose is the function SELECTED_REAL_KIND. Its general form is: SELECTED REAL KIND (p, r) Where p is the precision desired (number of digits needed to the right of the decimal point) and r is the range (-10r to 10r). p and r are both integer values. This function will return a kind type parameter with at least precision of p and range r. p and r do not have to both be specified. Only one is sufficient for selecting a kind number. Another intrinsic function, KIND (x), can be used to find kind numbers for particular expressions. For example: KIND (4.13) will return the kind number for single-precision, while KIND (1.0D1) will return the kind number for double precision because D implies a double-precision exponent.
Page 11 of 40

Another concern is writing your programs so they can be carried from one compiler to the next without the need for reprogramming compiler dependent statements. In choosing kind numbers there are ways to make your codes "portable" (meaning they can be executed on any Fortran 90 compiler without compiler dependent errors). You can do this by declaring a kind number for single and double-precision in the declaration section of your program. INTEGER, PARAMETER :: double = SELECTED_REAL_KIND (13) REAL (KIND = double) :: A, B In this series of commands the parameter double has been assigned the kind value for double-precision (p = 13 will require double precision). The kind for A and B has been assigned the number for double-precision. Code written with such declarations are portable without corrections. An underscore followed by a kind number appended to a constant is an indicator of the kind of that constant. In general: constant_kindnumber For example: 3.453_2 The number 3.453 is of kind number 2. Again, for portability it is better to use parameters rather than actual numerical values for appending your constants. 3.453_double Now 3.453 has the kind number double. If appropriate statements are made in the declaration section (as previously discussed) then double will be the kind number for double-precision regardless of the compiler used. If double-precision is required for the output of an expression then all variables and constants in that expression should be of double-precision kind. If constants are single-precision and other values double-precision the result will not be as accurate. For example: PROGRAM accuracy IMPLICIT NONE INTEGER, PARAMETER :: double = SELECTED_REAL_KIND (13) REAL (KIND = double) :: A, B, C A = 2.0_double B = 0.1 * A C = 0.1_double * A PRINT *, B PRINT *, C END PROGRAM Depending on your system the output for your program could give the following:
Page 12 of 40

0.2000000029802322 0.2000000000000000 Although the output for B and C should be the same, they are not due to the accuracy of the multiplicative constant (0.1). The precision for C is double-precision because both the constant (as indicated by the underscore (_) followed by double kind number) and the value for A have double precision. However, B has lost precision because the constant used to multiply A has only default single precision. Accuracy has been lost. Note that the value for B will vary for compiler, but will not be as accurate as C. Similarly the commands a = 0.745 b = 0.745D0 may result in a and b having different values because 0.745 is of single precision but a, b and 0.745D0 are of double precision. Thus variable a, could finally have a value like 0.7450000035810196.

2.6

Intrinsic Functions

Fortran 90 has a library of functions available for many common mathematical operations. Including in the available functions are absolute value (ABS(x)), exponential (EXP(x)), logarithm (LOG(x)), and square root (SQRT(x)). A complete list of these functions can be found in the appendices of the reference books (Appendix A of Metcalf, Appendix D of Nyhoff). It is important to pay attention to the types of data that can be used with these functions. For example, the argument (x) in ABS(x) can be real or integer. The result of the function will be of the same data type as the argument. ABS(9.0) = 9.0, but ABS(9) = 9. Some functions require real arguments (EXP(x), COS (x), LOG(x), etc.), while others may have real arguments and integer results (INT(x) is one as it returns the integer portion of a real number, x). Some functions allow definition of the output type. The default value for INT(x) is integer, but this can be changed as follows: INT(x, KIND = kind_number) The output will be the integer portion of x, but it will be of type kind_number. As discussed in 2.5 different data types have compiler-dependent (kind) numbers associated with them. INT can be used to return the integer portion of a number, but the output can have double or single real precision if desired. This is not an option on all functions.

2.7 Input, Output, and Format Descriptors


Obviously, one of the important features of programming is being able to read input (from the keyboard, a data file, etc.) and the output results (to the screen, a data file, etc.). The general commands available for these actions are:

OPEN CLOSE READ WRITE PRINT


Page 13 of 40

All of these commands allow for the input or output to be formatted to the programmers specifications. At the bottom of this chapter is a discussion of format specifiers. OPEN Often it is useful in programs to be able to open files for manipulation and use A unit number must be supplied to a file being opened. the general form of an OPEN statement is as follows: OPEN (open-specifiers)

The first item in the open -specifiers is the unit number. This number will be used in following READ and WRITE statements if these statements are to be applied to the opened file. The next item is the filename, listed as FILE = filename. Also included can be STATUS = status expression. The status expression can be either "OLD", "NEW", or "REPLACE". OLD means the file already exists. NEW means that a new, blank file is being created. REPLACE means that a new blank file is created and will replace an older version if it exists. ACTION = action expression describes the actions allowed to the opened program. It can be either "READ", "WRITE", or "READWRITE". READ means the opened file can only be read and modified. This prohibits any changes fro occurring to a file. WRITE means the file can only be written. This can keep you from inadvertently reading data from a wrong file. READWRITE means that both actions are allowed with this file. IOSTAT = var is a good safety net for assuring that files are opened properly. A number is assigned var that defines the status of the file opened. If the file is opened properly then a 0 is typically assigned to var. If an error occurs then the number assigned to var is associated with an error message. This can be used as a check within the execution of a program to verify a file was opened properly.

Example: OPEN(UNIT = 15, FILE = 'input.dat', STATUS = "OLD", & ACTION = "READWRITE", IOSTAT = Open_Status) IF (Open_Status > 0) STOP "------------Error, File not opened properly------------" The file input.dat is opened and assigned a unit number of 15. If this file is referenced in future READ or WRITE statements then it should be referenced by this unit number. The file is OLD, meaning it already exists, and it is accessible for reading and writing (READWRITE). A number is assigned to the variable Open_Status that reflects the ability of the program to open the file. If it is not opened properly (i.e. Open_Status /= 0) then the next statement halts execution and returns the message "------------Error, File not opened properly------------". It is advisable to use the IOSTAT option whenever opening a file. In this manner you can halt execution at the point where an error occurs and this will assist with debugging. CLOSE Opened files are closed whenever an END of STOP statement is encountered. Alternatively they can be closed at any point of the program by using a CLOSE statement. The general CLOSE statement is: CLOSE (close-list) The close-list must include a unit specifier to indicate what file is to be closed. Other data can be included but are rarely needed. If you are interested in other options check the reference material. Example: CLOSE (13) Closes the file with unit number 13. READ The form of a READ statement is as follows: READ (control -specifiers) input-list
Page 14 of 40

The control-specifiers can contain many items. A unit specifier is used to indicate the input device (the default is the keyboard). If a file is opened (with the OPEN command as discussed further down the page) a unit specifier can be assigned to that file. If data is read from that file then its unit specifier must be indicated. A format specifier can be the next control-list item. Input and output data can be formatted as desired and these commands are discussed at the bottom of the page. Other items that are useful in processing files are available and these can be found in the referenced material. The general form of READ statements: READ (*,*) time, concentration READ *, time, concentration The stars (*) indicate the use of default values. When ()'s are used, the first value is the unit specifier (in this case there is a * so it is the default device, typically the keyboard) and the second value is the format specifier (the * indicates the default, or unformatted data). The variables time and concentration are read from the default input device and are unformatted. The second command is the same as the first, just a type of shorthand. A typical READ statement: READ (15, '(I6, 2F6.2)'), time, conc(1), conc(2) Here, unit number 15 is specified and the second part is a format descriptor. The variables read are time, conc(1), and conc(2). WRITE The WRITE command can be used to output data to various devices. The default (*) for output is the screen. The general form for a WRITE statement is similar to the other input/output options: WRITE (write-specifiers) write-list The options for write-specifiers are essentially the same as the two previous options. The first option is the unit identifier which tells which output source is written (* indicates the default screen). The next option is output format (again, the commands for this will be discussed at the bottom of the page). By default (*), the output is unformatted. ADVANCE = expression is an option that indicates where to place the next output. The expression term can be either "NO" or "YES" If ADVANCE = "NO" then following WRITE statements will begin on the same line as this current output. If ADVANCE = "YES" then the output is advanced one line and any following output begins on that following line. If a value for ADVANCE is not indicated then the value of "YES" is used as default. The write-list consists of the data to be written. Any data type is allowable in the write-list. The expressions can be constants, variables, formulas, etc. The list of expressions are separated by commas. If no write-list is included then a blank is inserted at the indicated WRITE location. Example: WRITE(*,*, ADVANCE = "NO") "The liquid level in the tank is", Level WRITE(*,*) " A level greater than", Level_Max, " indicates a high level alarm." The output for these commands is: The liquid level in the tank is (Level) A level greater than (Level_Max) indicates a high level alarm. Level and Level_Max are variables. ()'s are used here to indicate that we do not know the values of these variables. In truth they will be replaced by numerical values. Notice that the second WRITE statement begins its output on the same line as the first. This occurs because the first statement indicates ADVANCE = "NO". If a third WRITE statement was included then it's output would begin on a new line. PRINT The PRINT statement is less versatile than the WRITE statement. The general PRINT statement is: PRINT format-specifier, print-list PRINT only uses the standard (default) output device. The print-list is the data to printed. Just like the writelist of the WRITE statement the print-list allows use of any data type and the list must be separated by commas. The output can be formatted using the format-specifier. A * indicates unformatted data. A character indicating a format type or a format statement can be used to describe the format. Again, format statements are described below.
Page 15 of 40

Each PRINT statement begins on a new line of output. FORMAT STATEMENTS As previously mentioned input and output can be formatted such that the output is more aesthetically pleasing. Without format statements output will take on a compiler-dependent form that is generally not appealing. The first specification in a format statement is the declaration of the vertical spacing. The following options are available: 1X or " " for normal spacing "0" for double spacing "1" for advancing to the next page before any action "+" for overwriting the last line written integer formatting The letter I is used to describe the format of integer data. The general form is: rIw.m Where r is a repetition indicator. It instructs the number of times this field should be applied. It is a shorthand (i.e. 3I5.2 = I5.2 I5.2 I5.2). w determines the width of the field (or number of spaces) used to display the integer. Blanks are placed in the front of the field (i.e. the output is right justified). If the number is 4353 and w = 5 then the letter will be written (~ indicates a blank space) ~4353 instead of 4353~. m is the minimum number of digits displayed. A declaration for m is not required. For the number 4353, if m = 5 then it will be displayed as 04353. Example: INTEGER :: A = 12, B = 600, C = 12345 PRINT '(1X, 2I5.3, I6)', A, B, C Output (| indicates the edge of the output area, and ~ are spaces): |~~~012~~600~12345 Here the 1X indicates the vertical single spacing. A and B are displayed with a minimum of three characters in a field of width five. Notice that there is always an additional space at the front; so, there are three instead of two spaces in front of A. C is displayed in a field of width 6, with no declaration of the minimum number of characters. If the example were written this way: INTEGER :: A = 12, B = 600, C = 12345 PRINT '(1X, 3I4.3)', A, B, C The output would be as follows: |~~012~600**** If the integer number is larger than the field width then the field is filled with *'s. real formatting

F is one of the descriptors used to format real data. It's general form is: rFw.d

r is the repetition indicator and w the total field width as described before. d indicates the number of digits to the right of the decimal point. Simply: REAL :: A = -12.5, B = 100.678, C = 3.3 WRITE (*, '(1X, 2F7.2, F7.3)') A, B, C Output: |~~-12.50~100.68~~3.300 Obviously, both the negative sign (-) and the decimal point (.) took up a space in the field. Also, notice that the value for C was rounded because d = 2 when three numbers were available outside the decimal point.

E can also be used as a format descriptor. It has the general form: Page 16 of 40

rEw.dEe Most of the form is similar to the F descriptor, but the output is in exponential form. e indicates the number of positions included in the exponent, but is not required. Example: REAL :: A = 112.3E8, B = .078e-7 PRINT '(1X, 2E10.3)', A, B Output: |~~0.112E+11~0.780E-08 The exponent indicator (E) and the neg/pos sign require a space in the field. Also, all exponents are converted so that there is a 0 to the left of the decimal point.

ES can also be used. rESw.dEe

It has the same options as E, but the result is modified so that the value to the left of the decimal point is at least 1 but less than 10. In the same example as used for E: REAL :: A = 112.3E8, B = .078e-7 PRINT '(1X, 2ES10.3)', A, B Output: |~~1.120E+08~7.800E-07 This gives more precision. character formatting Character data can be included in format descriptors. For example: INTEGER :: A = 3 REAL :: B = 0.2 PRINT '(1X, "A =", I5.2, " B =", F5.2)', A, B Output: | A = 03 B = 0.20 rAw r is a repetition indicator and w the field width. Neither are required. Without w the field width is determined by the character size. If w is greater than the character size then the output is right justified. If it less than the character size then the output is the leftmost w characters. The A format desccriptor can be used as a place keeper when producing output. The same PRINT statement from above could be written: PRINT '(1X, A, I5.2, A, F5.2)', "A =", A, " B =", B -or (with ~ as a blank indicator)|~A~=~~~03~B~=~0.20 A can also be used as a format descriptor for character data. In general:

3.1

Branches

Another important technique when writing Fortran code is the ability to select different paths of execution. Your code may need to branch depending on different criteria. The most important of these are:

IF (IF-THEN) IF-ELSE IF-ELSE IF SELECT CASE

IF
Page 17 of 40

The simplest form is the logical IF statement. In general: IF (logical -criteria) execution statement If the logical-criteria is TRUE then the execution is performed. If not the execution statement is bypassed. An example: IF (2.0 < x .AND x < 3.0) PRINT *, x In this case if x is between 2 and 3 then it will be printed. Another IF form used when multiple statements are required for the TRUE case is: IF (logical -criteria) THEN execution statements END IF Notice that all execution statements depending on the IF statement are indented. This is not required, but it makes your code more readable. All the execution statements are performed if the logical statement is TRUE. Otherwise, all information between the IF and END IF statements are ignored. An example: IF (x >= 0) THEN z=x*y PRINT *, "x is a positive number." END IF IF-ELSE The ELSE statement allows specification of execution statements for the case that the logical-criteria of the IF statement is FALSE. IF (logical -criteria) THEN execution statements for true result ELSE execution statements for false result END IF If the logical-criteria is TRUE then the first set of statements are performed and the second are bypassed. If the logical-criteria is FALSE then the first set of statements are bypassed and the second statements performed. As an example: IF (x > 0) THEN PRINT *, "The value is greater than zero." ELSE PRINT *, "The value is not greater than zero." END IF IF-ELSE IF Nested IF statements (IF statements within IF statements )can allow for many selection criteria. For example: IF (x >= 1) THEN PRINT *, "The value is greater than or equal to one." ELSE IF (x > 0) THEN PRINT *, "The value is between zero and one." ELSE PRINT *, "The value is less than or equal to zero." END IF END IF Although nested loops are allowed, they can frequently become very complex if many selection options are desired. The ELSE IF statement allows for multialternative selection in a more simple and easier to read format. In general:

Page 18 of 40

IF (logical -criteria1) THEN execution statements 1 ELSE IF (logical -criteria2) THEN execution statements 2 ELSE IF (logical -criteria3) THEN execution statements 3 ..... ELSE execution statements n END IF The ELSE statement is optional, but it indicates the statements to be performed if none of the IF statements are TRUE. Only one set of execution statements are performed. The expressions are evaluated in order and when a TRUE statement is found, its execution statements will be performed and execution continues with the next statement following the END IF statement. For example: IF (x > 0) THEN PRINT *, "Value is greater than zero." ELSE IF (x < 0) THEN PRINT *, "Value is less than zero." ELSE IF (x == 1) THEN PRINT *, "Value is one." ELSE PRINT *, "Value is zero." END IF Notice if x is equal to one the output of this series of commands will be: Value is greater than zero. It will not be "Value is one." because the first true IF statement is that it is less than zero. That statement was executed and execution proceeded outside of the IF-ELSE IF construct.

SELECT CASE The SELECT CASE construct is not as general as the IF constructs, but it is of use for some specific applications. In general: SELECT CASE (selector) CASE (list1) execution statements 1 CASE (list2) execution statements 2 ... CASE (listn) execution statements n END SELECT The selector is either an integer, character, or logical expression. It cannot be real. List1 to listn are the possible values for the selector. Say you wanted to associate output a letter grade for a known a numerical score. Say the numerical score is associated with the real variable named grade: SELECT CASE (INT(grade)) ! The real value grade is converted to an integer. CASE (90:) ! 90: indicates values of 90 or above. PRINT *, "Your grade is an A." CASE (80:89) ! 80:89 means 80 to 89. PRINT *, "Your grade is a B." CASE (70:79) PRINT *, "Your grade is a C." CASE (60:69) PRINT *, "Your grade is a D." CASE (:59) ! 59: indicates 59 or below.
Page 19 of 40

PRINT *, "Your grade is an F." END SELECT NAMING All of these branching options can be named in order to improve the readability of your code. For the previous example of a nested IF: positive: IF (x >= 1) THEN PRINT *, "The value is greater than or equal to one." ELSE negative: IF (x > 0) THEN PRINT *, "The value is between zero and one." ELSE PRINT *, "The value is less than or equal to zero." END IF negative END IF positive SELECT CASE constructs can be named in much the same way. name: SELECT CASE (selector) CASE (list1) execution statements 1 CASE (list2) execution statements 2 ... CASE (listn) execution statements n END SELECT name

3.2

Loops

Often it is useful to have repeated execution of a particular set of Fortran expressions. This can often be accomplished using the DO command. There are various ways for loops to function, but in general they are either based on counters where loops are continued for a certain number of iterations, or logical expressions where the loop terminates based on the value of a logical expression. Counter Loops Counter loops perform repetitive execution a number of times based on a control-variable. The controlvariable is initialized to a value and incremented a step-size every time a particular list of commands is executed. When the control variable surpasses a specified threshold the execution halts. The general form of the counter controlled DO loop is: DO control-variable = initial value, limit, step-size execution list END DO Initial-value, limit, and step-size are all integer values that indicate the number of loops to be performed. These values can also be variables indicated previous to execution of the loop. Step-size is not required. If not indicated, the default step-size is one. The values for initial-value, limit, and step-size are indicated at the beginning of the loop by either numerical values of variables. These values cannot be changed during execution of the loop. The execution list within a DO loop should be indented. This makes your code more readable, and it is easier to follow the logic. Often you will have DO loops within DO loops (nested DO loops), and in these cases indenting each new loop within the other loops allows you to follow the sequence of loop execution. Here is an example of a counter DO LOOP. INTEGER :: max = 5 DO n=1, max PRINT *, n, n*2 END DO
Page 20 of 40

This output: 1 2 3 4 5 2 4 6 8 10

Step-size was not indicated; so, it is one. The control-variable cannot be modified in the execution section of the loop, but it can be used in the execution statements. The following DO loop shows a loop nested within another loop: DO n = 5, 1, -1 ! From 5 to 1 with a step size of minus 1 DO m = 1,2 PRINT *, n, m END DO END DO Notice how by indenting the loops the order of execution is indicated. The most indented loop is performed in completion first. The output would be: 5 5 4 4 3 3 2 2 1 1 1 2 1 2 1 2 1 2 1 2

Loops can be labeled as another way to organize your nested loops. The previous nested loops could have been written: outer: DO n = 5, 1, -1 ! From 5 to 1 with a step size of minus 1 inner: DO m = 1,2 PRINT *, n, m END DO inner END DO outer If you have many nested loops this could assist in helping you and others follow your code. LOGICAL LOOPS Logical loops are loops that require fulfilling a logical criteria for completion of the loop. These can also be called DO-EXIT loops. The general form is: DO execution statements IF (logical criteria) EXIT execution statements END DO The execution statements can be before and/or after the EXIT statement. When the IF statement is TRUE repetition is halted. Be careful when determining the logical criteria for your IF statement. If it never becomes TRUE you will be left with an infinite loop. The most common use for a logical loop involves halting execution once a calculated value reaches a threshold. For example: n=1 DO IF (n > 10) EXIT n=n+1 END DO
Page 21 of 40

You can also use user input to halt repetition. For example: DO PRINT *, "Enter the radius of your circle." READ *, r PRINT *, "Area is ", pi*r**2 PRINT *, "Do you want to calculate another area?" READ *, response IF (response == "n") EXIT END DO Granted, the parameter pi must have been defined previously and response would need to be defined as a character variable of length = 1 in the specification section of the program, but you see how the user input was used as a decision criteria. A more modern and structured way of realizing a logical loop is with use of the DO WHILE - END DO expression: DO WHILE expression execution statements END DO Here the execution statements are performed as long as expression returns TRUE. When expression becomes FALSE the loop is broken and execution continues with the following statements. The equivalence between DO-EXIT and DO WHILE loops is portrayed below: n=1 DO IF (n > 10) EXIT n=n+1 END DO n=1 DO WHILE (n <= 10) these two command list are equivalent n=n+1 END DO

3.3 Pseudocode and Flowcharts


Good, logical programming is developed through good pre-code planning and organization. This is assisted by the use of pseudocode and program flowcharts. Flowcharts are written with program flow from the top of a page to the bottom. Each command is placed in a box of the appropriate shape, and arrows are used to direct program flow. The following shapes are often used in flowcharts:

Page 22 of 40

Pseudocode is a method of describing computer algorithms using a combination of natural language and programming language. It is essentially an intermittent step towards the development of the actual code. It allows the programmer to formulate their thoughts on the organization and sequence of a computer algorithm without the need for actually following the exact coding syntax. Although pseudocode is frequently used there are no set of rules for its exact implementation. In general, here are some rules that are frequently followed when writing pseudocode:

The usual Fortran symobols are used for arithmetic operations (+, -, *, / , **). Symbolic names are used to indicate the quantities being processed. Certain Fortran keywords can be used, such as PRINT, WRITE, READ, etc. Indentation should be used to indicate branches and loops of instruction.

Here is an example problem, including a flowchart, pseudocode, and the final Fortran 90 program. This problem and solution are from Nyhoff, pg 206: For a given value, Limit, what is the smallest positive integer Number for which the sum Sum = 1 + 2 + ... + Number is greater than Limit. What is the value for this Sum? Pseudocode: Input: An integer Limit Ouput: Two integers: Number and Sum
Page 23 of 40

1. 2. 3. 4.

Enter Limit Set Number = 0. Set Sum = 0. Repeat the following: a. If Sum > Limit, terminate the repitition, otherwise. b. Increment Number by one. c. Add Number to Sum and set equal to Sum. 5. Print Number and Sum. Flowchart:

Page 24 of 40

Fortran 90 code: PROGRAM Summation ! Program to find the smallest positive integer Number ! For which Sum = 1 + 2 + ... + Number ! is greater than a user input value Limit. IMPLICIT NONE ! Declare variable names and types
Page 25 of 40

INTEGER :: Number, Sum, Limit ! Initialize Sum and Number Number = 0 Sum = 0 ! Ask the user to input Limit PRINT *, "Enter the value for which the sum is to exceed:" READ *, Limit ! Create loop that repeats until the smallest value for Number is found. DO IF (Sum > Limit) EXIT ! Terminate repetition once Number is found ! otherwise increment number by one Number = Number + 1 Sum = Sum + 1 END DO ! Print the results PRINT *, "1 + ... + ", Number, "=", Sum, ">", Limit END PROGRAM Chapter 4: Subroutines, External Functions, and Modules 4.1 External Functions

Functions can be defined and accessed outside of the main code structure. Functions are basically similar to subroutines (discussed in 4.2), just simpler. Functions return either a number, array, logical result, or character array. The FUNCTION option exists so you can create mathematical functions that are not explicitly defined (as ABS, SQRT, etc.) in the Fortran 90 library. Once a function is defined it is used in the same way as any of the library functions. Functions can only return one value or one array of values. The basic structure for using and defining a function is as follows: PROGRAM name ... ... variable = functionname (argument_list1) ... ... END PROGRAM FUNCTION function_name(argument_list2) type declarations functionname = expression RETURN END FUNCTION Argument_list1 and argument_list2 do not have to be the same, but they do have to contain the same number and type of variable. If their names are different then argument_list1 is mapped to the values of argument_list2. An example program using a function: PROGRAM testfunc IMPLICIT NONE REAL :: a, b, c, func a = 3.0 b = 4.0
Page 26 of 40

c = func(a,b) END PROGRAM testfunc FUNCTION func(x,y) REAL :: func INTEGER, INTENT (IN) :: x, y func = x ** 2 + 2 * y END FUNCTION func This program will take the values of a and b and input them into the function func(x,y) returning a value for c of 17.0. It is important to define the type for the function, in this case it is real (as seen by the definition "REAL :: func(x,y)"). You can also choose your function to be of type INTEGER, CHARACTER (as needed for the hmwk), or LOGICAL. Tip: Use functions wisely! Innapropriate use may dramatically but unnecessarily increase the computational time. Consider the following example: z = f(x)/(1.0 + f(x)) where f(x) is a REAL valued function that has been defined. Here, to compute z we will need two function evaluations, that is f is evaluated two times. But if we wrote: y = f(x) z = y/(1.0 + y) we now need to evaluate f only once. This means that we decrease the computational time by a factor of two! This can be very significant if the function to be evaluated is "tough"...

4.2

Subroutines

Subroutines are similar to, but more versatile than, external functions. Subroutines can be defined internally (following a CONTAINS statement) or externally (after the END PROGRAM statement). Functions are essentially simplified subroutines. The major differences between functions and subroutines are as follows:

Functions take input and return a single number, character string, logical result, or array to the program that referenced it. Subroutines can return a large amount of output or no data (i.e. they can just perform a task such as printing results or displaying output) to the referencing program. The name of a function is set to the returning value. A subroutine name does not contain a value. Output from a subroutine is returned via the arguments contained in the output list (meaning if you want to return three values you must have one argument in the argument list for each output value). Functions are referenced in the main program structure by using their name in an expression. Subroutines are referenced using a CALL statement.

The basic format of a subroutine description is as follows: SUBROUTINE name(dummy argument-list) specification part execution part END SUBROUTINE The formal argument-list is a list of identifiers for the input and output to the subroutine. These values are called dummy because they are used to pass information between the subroutine and the main program. Subroutines are referenced in main programs using a CALL statement. CALL name(actual argument-list) The actual argument-list contains the variables, constants, or expressions that are to be used by the subroutine. The variables can be returned to the referencing program with values determined by the subroutine, or they can be used as input to the subroutine's execution. The arguments contained in the actual argument-list and the arguments contained in the dummy argument-list do not have to be the same; however, there does have to be the same number of arguments and their types must match.
Page 27 of 40

Here is an example of a program calling a subroutine. The subroutine receives the name of a file, opens it, reads data, and returns that data to the referencing program. MAIN PROGRAM IMPLICIT NONE CHARACTER(20) :: file_name REAL :: vel, dens, conc ! Calling the subroutine. ! The arguments do not need to be the same as ! the dummy arguments in the subroutine. ! values for vel, dens, and conc will be returned. CALL Openfile(file_name, vel, dens, conc) END PROGRAM SUBROUTINE Openfile(name, a, b, c) CHARACTER(20), INTENT(IN) :: name REAL, INTENT (OUT) :: a, b, c INTEGER :: OpenStatus OPEN (UNIT = 10, FILE = name, ACTION = "READ", & IOSTAT = Openstatus) IF (OpenStatus /= 0) STOP "error opening file" READ (10,*) a, b, c END SUBROUTINE

Chapter 5: Arrays
5.1 One Dimensional Arrays

One of the most important features of Fortran 90 is that you can declare data as arrays. Fortran 90 also allows manipulation and operation of intrinsic functions on these arrays (discussed in section 5.3). First we will consider one dimensional arrays. Data is declared as an array in the following manner: type, DIMENSION(min:max) :: array names Type is the data type for all the items in the array. Arrays can be any of the data types described in 2.1. In section 5.4 the possibility of derived data types (where different items in an array are different types) is discussed. Min and max are the minimum and maximum subscripts used by the arrays. If the minimum subscript is one then min can be excluded. Array names is a list of arrays that will have this type with the specified DIMENSION. The names are separated by a comma. Examples: REAL, DIMENSION(1:20) :: A, B REAL, DIMENSION(20) :: A, B INTEGER, DIMENSION(-1:3) :: C All items in the arrays A and B are of type REAL. Space will be allocated for these array during compilation. A and B has space for 20 REAL numbers. C has space for 5 INTEGER numbers, subscripted -1, 0, 1, 2, and 3. Because arrays can require large amounts of memory, sometimes it is useful to be able to allocate (and deallocate) space in memory for the array during execution. This will be discussed in 5.2. For now, we will consider one dimensional, compile-time allocated arrays with items all of the same type. POPULATING ARRAYS Populating arrays (i.e. assigning values to their elements) can be performed in many ways. An easy and compact way is by using explicit DO loops with the subscript changing on each pass through the loop.
Page 28 of 40

REAL, DIMENSION(5) :: A DO I = 1, 5 READ (10, *) A(I) END DO In this case the data comes from UNIT = 10 (which we will assume is a data file). The data must be on separate lines because each READ statement will start on a separate line. Arrays can also be read be using the array name without subscripts. Array A could have been read from UNIT 10: READ (10, *) A Now the READ statement is used only once so the data can be on one line (separated by spaces or commas), on five separate lines, three numbers on one line and then two on the next, or whatever you desire. Finally, arrays can be read using an implied DO loop: READ (10, *) (A(I), I = 1, 5) Again, the READ statement is encountered only once the date does not have to be on separate lines. Practice: Create a text file and type the following data: 1.0 4.9 3.9 7.2 -3.1 4.8 5.9 7.8 9.1 -7.8 2.9 10.3 2.7 1.2 0.0

Save the file and write a program to read the first line. Then write a program that reads the first column. ACCESSING INDIVIDUAL ELEMENTS As implied above, accessing single elements of an array is performed using the array name followed by the subscript contained within parentheses (). You can set add two elements of an array: Sum = A(3) + A(5) here the value for Sum is the third element of array A plus the fifth element. A sum of all the elements in an array could be accessed using a DO loop: Sum = 0 DO I = 1,5 Sum = Sum + A(I) END DO DIRECT ACCESS One advantage of arrays over multiple single variables is direct access to items in an array. For example if you want to read 20 values and store them in the memory, you could store them as 20 separate values: REAL :: input_1, input_2, ... input_20 READ (10, *) input_1, input_2, ... input_20 ! .. are not legal Fortran commands, just an indication of repetition Or you could create an array: REAL, DIMENSION (20) :: input READ (10, *) (input (I), I = 1, 20) In the first case, if you want to access item 20 then it is accessed in the memory sequentially, starting from the beginning. The first 19 must be looked at first before input_20 is encountered. In the case of the array, Input(20) is direct access. The 20 specifies its location and the first 19 are skipped. From this example you can see the space and time saved by using arrays. ARRAY ASSIGNMENT Arrays can be assigned values within your program by containing them within (/ and /). Only values can be contained within these symbols or implied DO loops can be used. For example:
Page 29 of 40

INTEGER, DIMENSION (5) :: A A = (/ 2, 4, 6, 8, 10/) A = (/ (2*I, I = 1,5) /) A = (/ 2, (2*I, I = 2, 4), 10 /) All of these A declarations created the same array A. Arrays can also be assigned using a simple value: A= 0 this assigns the value of 0 to all elements of A. SUBSETS Arrays can be broken down into smaller components, or subsets. This is done as follows: array_name(min:max: step) Where min is the minimum subscript of the array, max is the maximum subscript considered, and step is the step size for the subscripts indicating the subscripts contained within your subarray. For example: REAL, DIMENSION (5) :: A REAL, DIMENSION (3) :: B, C A = (/ 10, 20, 30, 40, 50/) B = A(1:5:2) C = A(2:4) then B contains the first, third, and fifth elements of A (i.e. B = (/ 10, 30, 50/)). C contains the middle three elements of A (i.e. C = (/ 20, 30, 40 /)). INTRINSIC FUNCTIONS Fortran 90 allows various intrinsic functions to be used on arrays. Some of the more common ones are: DOT_PRODUCT(A, B) MAXVAL(A) MINVAL(A) PRODUCT(A) SIZE(A) SUM(A) Returns the dot product of A and B Returns the maximum value in array A Returns the minimum value in array A Returns the product of all the elements in A Returns the number of elements in A Returns the sum of all the elements in A

5.2

Allocatable Arrays

Arrays can be very large and require a lot of memory; therefore, it is often useful to reserve this space only during the times that the array is required. This cannot be done when the array size is declared during compilation. For this reason it is useful to use the programs available run time memory called "free store" to allocate the memory for the array during program execution. This memory can be used and restored using the following commands. An array is declared as ALLOCATABLE by: type, DIMENSION(:), ALLOCATABLE :: array names for example: INTEGER, DIMENSION(:), ALLOCATABLE :: A creates an integer array A that will have memory allocated to it (i.e. have it's size determined) during execution. Allocation occurs using the ALLOCATE command: ALLOCATE (array name(min:max))
Page 30 of 40

Min and max are the limits of the subscripts used. If min is one then it need not be included in the declaration. For example: ALLOCATE (A(20)) now the array A has space for 20 elements. A STAT clause can be used to verify that the allocation has been successful (much like READ or OPEN statements): ALLOCATE (A(20), STAT = allocate_status) IF (allocate_status /= 0) STOP "*** Not enough memory ***" Program execution will stop if the allocation is not successful. This is a good safeguarding tool. Once the array is no longer needed it is important to deallocate the memory so it can be used. this involves the DEALLOCATE command. Again, it is useful to use the STAT option to verify that the deallocation was successful. DEALLOCATE (A)

5.3

Multi-Dimensional Arrays

Although it is useful to have data in one-dimensional arrays, it is sometimes useful to arrange data into rows and columns (two dimensional arrays), rows columns and ranks (three-dimensional), or even higher dimensionality. In this chapter we will consider multidimensional arrays. Multidimensional arrays are declared in much the same way as single arrays. They can be real, integer, logical, complex, or character.. Derived types again can be created but that is discussed in the next chapter. A comma is used to indicate another dimension. Colons are again used to indicate subscript divisions. In general, for n-dimensional arrays: type, DIMENSION(min1:max1, min2:max2, ..., minn:maxn) :: array_names where mini and maxi are a pair of integers determining the subscript ranges for the ith dimension. If the minimum subscript of any dimension is one then mini can be omitted. For example: REAL, DIMENSION(0:4, 3:12, 5) :: A INTEGER, DIMENSION(3, 4) :: B These arrays can also be declared: REAL :: A (0:4, 3:12, 5) INTEGER :: B (3, 4) ! A is a 5 x 10 x 5 array ! B is 3 x 4 ! A is a 5 x 10 x 5 array ! B is 3 x 4

Two dimensional arrays are the most common and the subscripts are just as indicated in most math textbooks. The first subscript represents row number, and the second column number. A(1,1) A(2,1) ...... A(n,1) A(1,2) . . . A(2,2) . . . A(n,2) . . . A(1,m) A(2,m) A(n,m)
Page 31 of 40

INPUT and OUTPUT Just as with one-dimensional arrays, multi-dimensional arrays can be read using explicit DO loops, the array name without subscripts, and implied DO loops. Explicit DO loops of course require a nested DO loop for every additional dimension. In the case of a twodimensional array: DO row = 1, max_rows DO col = 1, max_cols READ (10,*) array (row, col) END DO END DO In this case, if read from a data file the data must be no separate lines. The array will be read "row-wise", meaning the all of the first row is read, then the second row, then third, etc. until completed. The loops could be read "column-wise": DO col = 1, max_cols DO row = 1, max_rows READ (10,*) array (row, col) END DO END DO ! Now col is the outer loop ! and row is the inner

In this case the first column is read (from row 1 to max_rows) then column 2, then 3, until completed. Using DO loops you can control the way in which you array is read. This is much the same for implied DO loops. For "row-wise" input: READ (10,*) ((array(row,col), col = 1, max_cols), row = 1, max_rows) col = 1, max_cols is the nested, or inner, loop. This means row is held constant at 1 and the inner loop is performed, then row is 2 and the inner loop repeated, then row = 3, etc. "Column-wise" input requires only switching the inner and outer loops: READ (10,*) ((array(row,col), row = 1, max_rows), col = 1, max_cols) Finally, the array name without subscripts can be used to input arrays. If another format is not specified it is the Fortran 90 convention to input and output arrays "column-wise"! When data is input it is assigned to the first column until all the rows in that column are filled and then to the next column and so forth. The importance of knowing this can be seen in an example. If you have a data file (assumed to be UNIT=10) with data presented as: 1 5 9 2 3 6 7 10 11 4 8 12

And your program says: INTEGER, DIMENSION(3,4) :: array READ (10,*) array Array will be read like this array(1,1) = 1, array(2,1) = 2, array(3,1) = 3, array(2,1) = 4, etc. Which means that array will truly be:
Page 32 of 40

1 2 3

4 5 6

7 8 9

10 11 12

Fortran reads data sequentially like you read (from left to right, top to bottom), but it will assign values by columns, the first column will be complete before the second column is read. This can be corrected by using an implied DO loop that reads "row-wise". Mistakes can also be seen when you try to print an array. Say the previous array was read properly with an implied DO loop. Then it would actually be contained in memory as: 1 5 9 2 3 6 7 10 11 4 8 12

When you try to print this array formatted as 3 rows and 4 columns of integer data. PRINT '(1x, 4I5/)', array The output will be: 1 5 6 10 11 4 9 3 8 2 7 12

because it prints from left to right, top to bottom, but the order it chooses from the array is "column-wise" just as it reads. Column 1 is printed first, then column 2, then 3, etc. This can be corrected using a combination of DO loops and implied DO loops that is "rowwise" in the print statement: DO row = 1, max_rows PRINT '(1x, 4I5)', (array(row,col), col = 1, max_cols) END DO Since each PRINT statement begins on a new line you are given: 1 5 9 2 3 6 7 10 11 4 8 12

Assigning Values Arrays can be assigned values using one-dimensional array constants, but they must be given the dimensions of the array using the intrinsic RESHAPE command. In general: RESHAPE (one-dimensionalspecifier, shape, pad, order) The one-dimensional specifier gives all the elements of the array. The shape tells the dimensions of the array. Pad are the values to fill parts of the array not given in the onedimensional specifier. These may be repeated if necessary. Order specifies the order in which subscripts should be varied. Pad and order are optional. An example: A = RESHAPE ((/ 1, 2, 3, 4, 5, 6/), (/2,3/)) gives a 2 x 3 array:
Page 33 of 40

1 2

3 4

5 6

By reversing the order: A = RESHAPE ((/ 1, 2, 3, 4, 5, 6/), (/2,3/), ORDER = (/2, 1/)) Subscript to is varied and then one so the 2 x 3 array is: 1 4 2 5 3 6

Pad is used to fill blanks. A = RESHAPE ((/ 1, 2, 3, 4/), (/2,3/), PAD = (/0/), ORDER = (/2, 1/)) The mixing elements are replaced by repeated elements of PAD: 1 4 2 0 3 0

5.4

Derived Data Types

You have seen in previous chapters the six intrinsic data types of Fortran 90: INTEGER, REAL, CHARACTER, COMPLEX, LOGICAL and arrays. Some times it is useful to define new data types, or derived data types. New types are define using the TYPE command: TYPE name declaration_1 declaration_2 ... declaration_n END TYPE name The declarations define the components in this type. It declares both the name and type of each component. For example: TYPE course_list CHARACTER (15) :: Last_name, First_name CHARACTER (1) :: Middle INTEGER :: Student_ID REAL :: average CHARACTER(1) :: grade END TYPE course_list Variables or constants can be defined as a certain type using the following declaration: TYPE(name) :: var Using the type defined above: TYPE(course_list) :: A, B

Page 34 of 40

Now A and B will have 6 components each: Last_name, First_name, Middle, Student_ID, average, grade, and list. You can also define an array so that all its components are of derived type: TYPE(course_list), DIMENSION(10) :: A Now A is a single dimension array with 10 elements all of the derived type course_list. We can assign a value to an element of A as follows: A(1) = couse_list("Smith", "Joe", "J", 11111, 95.5, "A") The first element of A contains all this information. What if you want to access only a portion of A(1)? Then you use the component selector character (%). PRINT *, A(1)%Student_ID will look at element 1 of A and find the component defined in the TYPE declaration as Student_ID; so, it will print: 11111 By the same token, the following statements: PRINT '(1x, A5, F7.2)', A(1)%First_name, A(1)%average will produce: Joe 95.50 Of course you can use the selector with READ statements, assignment statements, executions, etc. The values can be treated like any other variable or constant. APPENDICES

A.1: Helpful information A.1.1 Fortran Character Set


ANSI standard available characters for use with Fortran 90. Note: Fortran is case insensitive. Available Characters: 0,...,9 A,...,Z a,...,z ' " ( ) * + blank : ! & $ ; < > % ? , . = /

Page 35 of 40

ANSI Character Codes

ASCII Character Codes

Page 36 of 40

Page 37 of 40

Page 38 of 40

A.1.2 Operations
Available mathematic operations for Fortran 90 Operator
+ * / **

Description Addition Subtraction Multiplication Division Exponentiation

______________________________________

Order of actions: 1. Exponents are perform first, from right to left. 2. Multiplications and divisions are performed next, from left to right with the order they are encountered. 3. Addition and subtraction are last. They are also performed from left to right with the order they are encountered. Available logical opertations for Fortran 90 Operator
.NOT. .AND. .OR. .EQV. .NEQV.
______________

.NOT.a returns .TRUE. if a is .FALSE. and vice-versa. The values of Logical Expressions that involve two variables are given below: If operands a and b are: Both true One true, one false Both false Then the expressions below evaluate as shown: a .AND. b .TRUE. .FALSE. .FALSE. a .OR. b .TRUE. .TRUE. .FALSE. a .EQV. b .TRUE. .FALSE. .TRUE. a .NEQV. b .FALSE. .TRUE. .FALSE.

Note 1: Operator .NEQV. is sometimes referred as .XOR. Note 2: Remember: .NOT.(a.AND.b) = (.NOT.a) .OR. (.NOT.b) .NOT.(a.OR.b) = (.NOT.a) .AND. (.NOT.b)

A.1.3 Random Number Generator


Often problems arise that require generation of a random number or a series of random numbers. Fortran 90 contains a subprogram for this purpose. The random number generator produces a pseudorandom (it is impossible to have an algorithm that is truly random) number distributed between 0 and 1. The random number generator is initiated by the subprogram RANDOM_SEED. RANDOM_SEED, when called, initializes the random number generator. Three arguments are possible when calling RANDOM_SEED. CALL RANDOM_SEED (SIZE, GET, PUT) If called without an argument then RANDOM_SEED restarts the number generator. If an argument is present it queries the random number generator. SIZE will output the number of integers used to hold the seed. GET
Page 39 of 40

will give the current value of the seed. PUT allows for control of the seed. PUT is the only command that provides input. It indicates the value to be used as the initial seed for the random number generator. PUT must be a one-dimensional array. random seed only needs to be called once in a program. It is used to generate the first random number. Any random numbers generated after the first will use the previous random number as its seed. RANDOM_NUMBER is the actual random number generator. It takes a seed (or more then one if creating an array of random numbers) and generates a pseudorandom number between 0 and 1. The general form is: CALL RANDOM_NUMBER(argument) Argument can be a single variable, an array, or items within an array. It will contain the pseudorandom number based on the seed generated using RANDOM_SEED. If an array is given then the array will be filled with random numbers. Here is an example for generating 5 random numbers using a predetermined seed. INTEGER, DIMENSION (1) :: seed = (/3/) REAL :: num CALL RANDOM_SEED (PUT=seed) DO n = 1, 5 CALL RANDOM_NUMBER(num) PRINT *, num END DO This program will generate and print five random numbers. The first is found using 3 as the seed, and the following ones use the preciously generated number as the seed. num contains the value of the random number generated and is updated for each loop. By controlling the seed the random numbers generated will be the same every time. A compiler will produce the same random number given the same seed.

Page 40 of 40

Vous aimerez peut-être aussi