A BRIEF INTRODUCTION TO FORTRAN 95 -- AUGUST 2003 An expansion and modification by John Monahan of notes from Steve Ellner. This brief introduction to Fortran 95 is an expansion, modification, and update of some notes by Steve Ellner. The reader should note that while the author has been programming in Fortran for over 30 years, this new version is still unfamiliar, and there may be some small errors in this document. 0. Invoking compiler Fortran is a compiled language, not interpreted. So the code is written in a file -- say smpl1.f for the first example -- and the compiler reads the code and produces executable (machine language) code -- and let's put it somewhere -- smpl1.ex is a good name. The compiler to use at present (August 2003) is the NAg Fortran 95 compiler. To access it, you first need to add its locker via add nagf95 and then issue the compilation command f95 smpl1.f -o smpl1.ex where f95 says Fortran 95 compiler smpl1.f file name of Fortran code -o says put the executable in the file to follow smpl1.ex where to put the executable Then to run the program, just give the name of the executable: smpl1.ex If your output is not directed to a file, but to the screen, as in smpl1.f, you can write it in a file using smpl1.ex > smpl1.out If you have stuff in the file and want the program to append to this file, then use smpl1.ex >> smpl1.out 1. File format For many years, Fortran stuck to a strict format for the language: statement numbers in columns 1-6, code in columns 7-72, only one way to do comments, and limited length of variable names. While many of these has been liberalized in this new version, most of the code you will see will follow the old standard, with rather strict adherance to a personal coding style. 2. Program structure Most FORTRAN programs for follow a simple pattern of program 'parts': PROGRAM name "Setup" (non-executable) statements - implicit none - type declarations - dimensioning of arrays - variable initializations - format (for output) statements Executed statements - input data from a file or the keyboard - carry out the calculations you want - output results to file or screen STOP ( stops execution ) END name ( ends program or subprogram ) Subroutines & function subprograms A program may not need all of the parts listed above: everything but the END statement is optional. 3. *** Comments *** Comments are a very important part of the program, because undocumented programs have very limited value -- only the simplest ones can be understood, and often simple ones are impossible for the author to read after a span of a few months. The old way of putting in comments was a 'c' or 'C' in the FIRST column of a line making the whole line a comment. Now the symbol '!' (exclamation point) makes the remainder of the line a comment. 4. Examples Here's a minimal example, which does some calculations and writes the result to the screen: program smpl1 implicit none ! forces all variables to be declared ! a very simple program and here's a comment line real x,y 21 format('smpl1 output',2f12.6) x = 23. + exp(-2.2) ! and I can put a comment at y = x - 9 ! the end of a line ! write has two arguments -- unit and format write(*,21) x,y ! use default output unit stop end program smpl1 An example with more parts: program smpl2 implicit none ! forces all variables to be declared ! a very simple program and here's a comment line real a,b,c,d,e 20 format(3f8.4) open( unit=11, file='smpl2.in') ! input file smpl2.in open( unit=12, file='smpl2.out') ! output file smpl2.out read(11,20) a,b,c write(12,20) a,b,c ! write what you read close(11) ! done with reading ! do some calculations d = a*b + c e = d*d write(12,*) 'some output',d,e close(12) stop end program smpl2 To read in data from a file, you have to 'open' the file and assign it a unit number (in this case, I chose 11), read in the data, and close the file. Each of those is a separate statement open( unit=11, file='smpl2.in') read(11,20) a,b,c close(11) ! done with reading (NOTE: the file smpl2.in must already exist before this program is run). Then we do some arithmetic: d = a*b + c e = d*d (The format for this kind of FORTRAN statement is RESULT = OPERATION That is, on the right-hand side of the =, there's a list of computations that you want done. On the left-hand side is a variable name, and that variable is assigned as its value the result of the computations). To write the data to a file, we must open the file, write the output to it, and close the file (tedious, but unavoidable): open( unit=12, file='smpl2.out') write(12,20) a,b,c ! write what you read write(12,*) 'some output',d,e close(12) (NOTE: you can write to a file that doesn't exist yet). The end of the main program (last line of code) (and of any sub-programs -- we'll get to those later) must be indicated by an 'end' statement (D) Initialization If you do not assign a value to a variable, then you cannot be sure what value is stored there -- it could be something from the last program that ran. As a result, it is important to initialize variables. There are a couple of ways to do this. First, variable can be initialized with a simple instruction: sum = 0. Two other ways initialize when the program is compiled. One way is to add it to a variable declaration: real :: x = 0. If this variable should never change its value, add the 'parameter' tag: integer, parameter :: p = 3 A third way, also done at compile time, is the use of a 'DATA' statement: data x/ 0./, z/ 21.5/ 5. Formats Formats tell the computer how to convert from human writing conventions to computer writing conventions. On input, it tells how to convert the text '2.78' into a number. On output, it tells how to convert a long string of zeros and ones into characters or base 10 numbers to be read by a human. You have seen examples that work both ways: 20 format(3f8.4) On input, it says that there will be three numbers, each taking eight spaces to write, and there will be a decimal point five places from the end. This means the numbers to be read will look like 23.1234-13.1212 0.0101 In this way, you can place numbers right next to each other. The most common formats are format examples looks like rFw.d 3f8.4, f5.0 23.1234, -1234 Ew.d 2e16.9, e8.2 -0.231234567e-12 Iw i4, 4i10 1234 rX 9x (r spaces) Gw.d g12.4 (chooses best form) rAw 3a8 abcdefgh (characters) Although not always shown, most of these formats can be repeated (rIw). If the data file looks like this -2.116 92.443 1234567890123456just count columns then the code 21 format(2f7.3) read(12,21) x,y will have x=-2.116 and y=92.443. However, using a different format and read statement as below, the same line 22 format(f5.1,2i2,f3.1,i2) read(77,22) z,k1,k2,w,k3 will give z=-2.1, k1=16, k2=9, w=2.4 and k3=43. 6. Arithmetic Operations + Addition c=a+b - Subtraction c=1.0-b * Multiplication c=5.0*b / Division c=3.0/b ** Exponentiation c=y**2 Unless you use parentheses to indicate otherwise, these are done in the order Exponentiation Multiplication & division Addition and Subtraction Examples: b = 12-4/2**3 gives b = 12 - 4/8 = 12 - 0.5 = 11.5 b=(12-4)/2**3 gives b= 8/8 =1 b=((12-4)/2)**3 gives b= (8/2)**3 = 4**3 = 64 -1**2 gives -(1**2) = -1 (-1)**2 gives 1 *** Since you will never remember *** always use parentheses *** 7. Variables (A) Naming restrictions Fortran USED to have restrictions on the names you can give to variables. The restrictions vary among implementations of FORTRAN (e.g., SUN vs. DOS) so it's a good idea to stick to the strictest restrictions: - no more than 6 characters in length ** relaxed ** - consists only of letters and numbers (no blanks, punctuation, or other special characters) ** can include underscore _ ** - must start with a letter OK NAMES NOT OK NAMES num4 thenumber4 (** ok, but long **) prodab proda*b v123 123v myfile my file FORTRAN does not pay attention to upper vs. lower case, so if you have a variable named var1 and another named VAR1, they will be treated as being the same object. ADVICE: use ONLY lower-case in variable names. (NOTE: subroutines and function subprogram names follow the same rules). (B) Integer vs. real, variables & contants FORTRAN distinguishes between integer-valued and real-valued (aka floating point) constants. Integers look like usual mathematical integers (... -3, -2, -1, 0, 1, 2, 3 ... ) , anything else is floating point (real-valued), such as 3.14, 2.5, 0.3333, etc. All variables must be declared what their type is -- integer or real -- as a consequence of the statement implicit none This style of programming avoids problems with misspellings, and forces the author to keep track of all variables -- a good discipline. Real variables come in two flavors: single precision and double precision. Single precision keeps track of only 7-8 digits, and double precision keeps track of twice as many digits. For the first part of this class we will only use single precision; for root-finding, maximum likelihoood and nonlinear regression, we will use only double precision. real x ! x is single precision (default) real(kind=2) y ! y is double precision Note that different compilers use different values of KIND for double precision: kind=2 for NAg and kind=4 for Lahey/Fujita. (C) Arithmetic and variable types It is VERY risky to carry out operations involving two different types of variables. Mixing integers and reals in an operation, or single versus double precision reals, often leads to answers you don't expect. After declarations real var1,var2,var3,xmax integer max OK statements Not OK statments var1=var2 + var3 var1 = max + var2 xmax=15.5 - 3.2 max= 15.5 - 3.2 Problems also occur if type-mixing results from an operation: program smpl3 ! compare integer & floating point divides implicit none integer j,k real x,y ! divide integer 3 by integer 4 j = 3 k = j / 4 ! divide floating point 3 by floating point 4 x = 3.0 y = x / 4.0 write(*,*) 'integer ',k,' floating point ',y stop end program smpl3 If you run this program, you find that j/k=0, x/y=0.75. WHY? Because j and k are integers (by default), so when you divide them the result is an integer (that's how FORTRAN works, and we're stuck with it), whose value is determined by FORTRAN's rules for truncation and rounding. Note that the operation j/k appears to be safe because j and k are both integers, but the result (in ordinary arithmetic) is a real (0.75) and we have inadvertently mixed types. (D) Type conversion But suppose that you DID want to add max + var2 -- what can you do then? Use functions built into FORTRAN for type conversion program smpl4 implicit none integer max real var1,var2,xmax max = 3 var2 = 15.6 xmax = real(max) var1 = xmax + var2 write(*,*) var1 stop end program smpl4 The function 'real' converts an integer to a floating point (real). To go the other way use INT or NINT. INT truncates, NINT rounds to the nearest integer. program smpl5 implicit none integer j,k real x,y x = 7.0 y = 4.0 j = int(x/y) k = nint(x/y) open(11,file='smpl5.out') write(11,*) 'truncating with int: ', j write(11,*) 'rounding with nint: ', k close(11) stop end program smpl5 Since x/y=1.75, int(x/y) will be 1 and nint(x/y) will be 2. Note how easy it is to add text to output. (E) Initialization If you do not assign a value to a variable, then you cannot be sure what value is stored there -- it could be something from the last program that ran. As a result, it is important to initialize variables. There are a couple of ways to do this. First, variable can be initialized with a simple instruction: sum = 0. Two other ways initialize when the program is compiled. One way is to add it to a variable declaration: real :: x = 0. If we do not want this variable's value to change, we can add the 'parameter' designation: integer, parameter :: p = 3 A third way, also done at compile time, is the use of a 'DATA' statement: data x/ 0./, z/ 21.5/ 8. Other library functions FORTRAN comes with many other built-in functions besides those for type conversion: abs(real) absolute value of real iabs(int) absolute value of integer log(real>0) natural log (log base e) log10(real>0) log base 10 sin,cos,tan(real) trig functions of real (in RADIANS) exp(real) e**real sqrt(real) square root and many others (see your FORTRAN manual). Functions that take real arguments are usually 'generic' for single vs. double precision: they take either as an input, and give an output of the same type. 9. Conditional execution using IF/THEN/ELSE IF statements allow statements, or blocks of statements, to be skipped if certain conditions are not met. For example program smpl6 implicit none real a1, a2, amin, amax read(*,*) a1,a2 if(a1.lt.a2) then amin = a1 amax = a2 else amin = a2 amax = a1 endif write(*,*) amin,amax stop end program smpl6 This program reads two numbers from keyboard input, and writes out to the screen the smaller of them, and then the larger of them. The 'else' part is optional; for example your program could include a block like if (xlight.gt.xlmin) then size = size + sgrow(xlight) height = height + hgrow(xlight) endif which does what it looks like: if xlight>xlmin, the lines size = size + grow(xlight) height = height + hgrow(xlight) are executed, and otherwise they aren't executed. There are several built-in relation operators that can be used in IF statements: .lt. less than .gt. greater than .le. less than or equal to .ge. greater than or equal to .eq. exactly equal to These can be combined using .and. .or. as in the following if( (a.gt.b) .or. (c.lt.d) ) then a = a-1.0 endif The "if" statement means exactly what it should: if a>b, or c