650 likes | 690 Views
An Introduction to Fortran. Lecture 1 Mar 19 2009 Kevin Keay. Outline. Lecture 1: 10-12 PM (Thu) Lecture 2: 10-12 AM (Fri) Lab session 1: 2-3:30 PM (Thu) Lab session 2: At your leisure.
E N D
An Introduction to Fortran Lecture 1 Mar 19 2009 Kevin Keay
Outline • Lecture 1: 10-12 PM (Thu) • Lecture 2: 10-12 AM (Fri) • Lab session 1: 2-3:30 PM (Thu) • Lab session 2: At your leisure
Fortran (Formula translator) is a scientific programming language which began life in the late 1950s. The language was designed to help scientists and engineers perform complex computational tasks. Basically it was a way of getting a computer to operate on mathematical formulae and equations in various fields, like meteorology, and produce ‘answers’ to practical problems. It has evolved over the ensuing decades to become the leading scientific language. Much of the world’s library of scientific programs is in Fortran although this will change with the increasing popularity of C, which is suitable for any programming task, not just for science. Introduction
Many scientific organisations, like the Australian Bureau of Meteorology, continue to use their older Fortran code since it is too expensive and inefficient to rewrite the existing code in C, especially if it is working correctly. Of course, many new routines are being written in C and the two languages may be interfaced too. Hence Fortran programs will still be compiled and used in the future.
Today there are two common versions of Fortran which are widely used: Fortran 77 and Fortran 90 (the numbers are supposed to reflect the years in which they appeared). The former is available for all platforms (PC, Sun, iMac) while the latter is traditionally associated with supercomputers (Cray, NEC), which have more than one CPU, since it features parallel and vector processing (ways to make a program run faster). • Only Fortran 77 is covered in this course. However there will be a simple illustration of Fortran 90.
There is not a lot of experience with Fortran 90 in our group. However there are Fortran 90 compilers on atlas (Sun) f90 and Linux machines pgf90. Kevin Keay has limited experience with Fortran 90 but should be approached initially with any queries. He has compiled a few Fortran 90 programs written elsewhere. Fortran 90 allows the user to operate on arrays and vectors in a simpler way than Fortran 77 – the code looks quite different! Most of you probably won’t need to use it but there is a possibility that you might obtain code from outside the group written in this way Fortran 90
Other programming languages • For your research you are most welcome to use other languages such as C. We recommend Fortran due to the wealth of experience within our group and it is not too difficult to learn. For your information the free C compiler gcc is available on all operating systems. The Suns also have the compiler cc. Kevin Keay has written some programs in C but is not an expert!
References • There are electronic documents at: http://www.earthsci.unimelb.edu.au/~kevin/fortran_course_notes/ • It is recommended that you read the following documents in this order: A Simple Fortran Primer – Rosemary Mardling, Monash University (1997) (used with permission of the author). See: primer.pdf Supplementary Notes for An Introduction to Fortran Programming – Kevin Keay (2006). See: suppnotes_2007.pdf Further information • You may obtain further information from the following sources. Professional Programmer’s Guide to Fortran 77 - Clive Page, University of Leicester (1995) (public domain). See: reference.pdf Interactive Fortran 77: A Hands on Approach (2nd Ed) - Ian D Chivers and Jane Sleightholme (1990). See: f77book.pdf • See: man g77, info g77 and g77 –-help on the Linux PCs and Suns. Some of these help pages may not be on other operating systems. On the Suns see: man f77 for help on the Sun f77 compiler (not the same as g77).
A simple example • We will consider a simple Fortran program to illustrate the basic concepts involved.
Basic structure of the program • Here is a very simple Fortran program. It consists of a set of statements that start with the program statement and finish with the end statement. This set of statements, or the Fortran source code, is saved in a text file e.g. first.f . To avoid compilation ‘hassles’ it is a good idea to use the extension .f for your source code files. Also, save as ‘text-only’, not as a Word document.
Each statement begins in column 7 and ends no greater than column 72 (the ruler just before the example is to make this clear – this ruler does not appear in the source code file). There are a couple of exceptions to this. • Firstly, if you have a long statement you place a character in column 6 of the next line (often a + or *) and continue the rest of the statement. • Secondly, you may need to use statement numbers associated with the goto and format statements. These numbers may go anywhere in columns 1-5. They are actually labels of your choice and have not connection with the line number in the source code file. Thirdly, you may put comments anywhere in your program. These have the character c in column 1 followed by any text. You may also use an exclamation mark (!) after a statement – an in-line comment.
111---------------------------------------------------------777111---------------------------------------------------------777 123456789012---------------------------------------------------------012 program first c c * Declaration section implicit none ! Need to declare all variables real x,y c c * Executable section write(*,*)'My first program' write(*,*)'Enter a number: ' read(*,*)x y= x**2 +4*x -12 c * Free format output c In Mardling, print is used instead of write c i.e. write(*,*) == print *, write(*,*)'x=',x,' y= ',y c * User-specified formatted output write(*,10)x,y 10 format('x=',F8.4,2X,'y=',F9.5) end
The program comprises two sections: declaration and executable. • The declaration section consists of statements that define variables and parameters used in your program. These immediately follow the program statement (this just has the name of your program) and come before all executable statements. • The executable section consists of statements that actually dosomething e.g. the read statement reads in data from the keyboard or a data file. The executable statement: y= x**2 +4*x -12 computes the variable y from the value of x. • Finally, we have the end statement.
We may also regard the executable section as comprising three generic blocks: input, processing and output. • The inputblock is the read statement – this allows us to input data into the program. • The statement: y= x**2 +4*x -12 is the processing block. Here we perform operations on (process) x to get y. • Finally, the write statements constitute the output block – we need to view our results, in this case the value of y.
What does this example program do? • Well, it prints a couple of informative messages on the computer screen (write) and waits for you to enter a real (floating point) number (read) e.g. 2.5 (note that if you enter 2 it is interpreted as 2.0). The statement: read(*,*) x means read from the keyboard and the number will be interpreted from its declaration i.e. real. This number is assigned to the variable x • Then the statement: y= x**2 +4*x -12 computes the variable y – in this case, y would be 4.25. Finally, the values of x and y are written on the screen (write). • For illustration, this is done in free format and then by a user-definedformat. The first approach involving write(*,*) is convenient - this means write to the screen in a default way - while the second approach using the two statements write(*,10)x,y and 10 format allows greater control over the written output. Note that the connecting statement number or label (10) for the second approach.
Compiling the program • To compile this program we need a Fortran compiler. This is a piece of software which reads the Fortran source code file (first.f) and turns it into an executable program (software) which runs on your computer. The executable program is often called an executable or a binary. On most of the computers systems in the School of Earth Sciences there is a public domain Fortran 77 compiler called g77. Traditionally, the compiler is called f77 but on some machines (especially the Suns) there is a proprietary Fortran compiler (f77) as well as the ‘free’ one (g77). In general, f77 may have some different options to g77.Note: On the Linux PCs and Windows XP, g77 is usually aliased to f77 so the names actually refer to the same compiler.
Hence to compile our example on any computer system: g77 –o first first.f • The option –o allows us to specify the output name of the executable. By default i.e. without the –o option, it is called a.out (or a.exe on Windows PCs).
The compiler produces one or more binary objects with the extension .o corresponding to your source code In our case, there is one called first.o but it is not retained unless the –c option of the g77 compiler is used. When the program is compiled some pre-packaged routines which are stored as librariesare linkedwith the compiler binary output (objects) from your source code to create an executable. • To show the creation of the object, the above compilation could be performed in two steps: g77 –c first.f (this creates the binary object first.o) g77 –o first first.o (this links the object to the system libraries to create the executable)
An extension of this approach is used in makefiles involving the make command. (This will be touched on in the Lab Session). Some simple examples of these are intrinsic (inbuilt) functions e.g. sin(x). Depending on the complexity of your program, a host of libraries may be required. For instance, to incorporate NCAR Graphics into your Fortran program (like conmap7) the NCAR Graphics libraries need to be available to the compiler so that the graphics routines are linked with your code.
The executable will only run on your current operating system e.g. an executable compiled on a Linux PC will not run on a Windows XP PC or an iMac. However, in principle you can transfer the source code (first.f) to other machines and compile it there – and it should work! This is the real power of programming.
Running the program • To run the executable, just type in the name: first . On the screen you will see the messages: My first program Enter a number: followed by a prompt. Enter a number from the keyboard e.g. 2.5. Then some more output text is written to the screen: x= 2.5 y= 4.25 x= 2.5000 y= 4.25000 • The above is the screen output on a PC running Windows 2000. The program was compiled with g77 under the Cygwin Linux emulation software. (This software is available on the PCs running Windows XP in the PC Lab.)
The first line uses free format and is chosen by the compiler. The second line is specified by the user in the format statement. Firstly, we write the text: x= on the screen. The value of the variable x is written in a field of 8 columns with 4 decimal places (F8.4), followed by a white space of 2 columns (2X). Finally, we write the text: y= and the value of the variable y in a field of 9 columns with 5 decimal places (F9.5). In both fields F denotes floating point (real) numbers corresponding to the declaration of x and y as real variables.
Some remarks on the example • Although the above program is quite simple it nevertheless illustrates the basics of Fortran programming (in fact, any programming language). Extensions of the example might include reading from a data file, doing some processing e.g. computing the mean or a Fourier transform, and outputting to another data file. • The input and output files may have a special format, perhaps even binary i.e. not viewable as text. Much of our weather data is in binary formats – usually they result in smaller files and are read more quickly than text files if there is a lot of data.
Fortran 90 • Most of the programs written by our group are in Fortran 77. • In the past couple of years there has been some exposure to Fortran 90, which is used at the BoM and CSIRO • Our Fortran 90 compilers (Linux: pgf90 Solaris: f90) will process Fortran 77 code too (Fortran 77 is a subset of Fortran 90) • A good reference book is: Introduction to programming with Fortran : with coverage of Fortran 90, 95, 2003, and 77 / Ian D. Chivers and Jane Sleightholme (2006) (Earth Sciences Library: 005.262 CHIV)
Fortran 90 (2) • For Fortran 90 on the Linux machines see: man pgf90 for use on pgf90. There is also an introductory document on Fortran 90 at: http://www.dur.ac.uk/resources/its/info/guides/138fortran90.pdf • This is also saved on the Honours website site as: 138fortran90.pdf • On the Solaris machines see: man f90 for use on f90
Fortran 90 (3) • Fortran 90 is designed for high performance scientific computing • It can treat arrays (vectors and matrices) by their symbolic form e.g. Y = A * B rather than by a set of do loops to operate on the individual elements e.g. y(i) = a(i,j) * b(j) • A lot of concepts from C are implemented • It is free format – you don’t need to start in column 7!
Fortran 90 (4) • Example ! EXAMPLE 1 ! real,dimension(10)::a=(/(i,i=1,10)/) real,dimension(10)::b,c integer i b=a +1. ! Vector addition c=a*sin(b) ! Vector operation print *, c ! Same as write(*,*)c do i=1,10 write(*,*)i,a(i),b(i),c(i) enddo end
Fortran 90 (5) • On the Linux machines you may compile this program with pgf90 e.g. pgf90 –o example example.f90 • On the Solaris machines use f90 e.g. f90 –o example example.f90
1. Program source file (.f file) For historical reasons dating back to the days of punched cards the standard Fortran statement record or line is 72 columns (characters) wide: ------------------…-------- 1 567 72 ↑ ← Statement (code) in columns. 7-72 → Column Long statements (exceeding column 72) can be continued on the next line by putting a character in column 6 (often a *). Statement labels e.g. on format statements are from 1-99999 in columns 1-5 (any justification). Comments have a c in column 1. You can also use ! at the end of a statement e.g. 100□□□format(‘x= ‘,F8.2)□□!A comment (□ is a blank space)
Code from other source files can be incorporated with the include statement e.g. include ‘extracode.f’ When the f77 or g77 command is used then the code in the file extracode.f will be ‘pasted’ into the current file at the include statement. We use this approach in Lab Session notes example 11 (c) (corr3.f).
2. Assignment of variables As a general rule you will have the statement: implicit none as the second line of your program. This means that you must explicitly declare all variables in the same way as the C programming language. Without this statement it is assumed that variables beginning with I-N are integer e.g. icount and A-H and O-Z are real e.g. radius.
The = sign is interpreted as ‘assigned to’. Each variable or array element e.g. x, p(3) has a memory location allocated to it. Assuming that x is declared as real then the statement x = 2 stores the real number 2.0 in the memory location allocated (or reserved for) the variable x. If we have the two statements: x = 2 x = x + 5.7 then the second statement takes the current value of x (2.0), adds 5.7 to x to get 7.7 and then overwrites the memory location for x with the new value i.e. after the second statement x is now 7.7.
3. Format descriptors In the ‘old days’ numbers had to be right-justified for read. This doesn’t seem to apply anymore. In the following the field width w includes the decimal point and +/– . d is the number of decimal places. Note that for write numbers are output as right-justified and text as left-justified. Real or floating point numbers → d ← Fw.d----•--e.g.F7.2 ← w → e.g. a = 104.5627 will be output as □104.56 (note rounding to fit format; □ represents a space) Exponential representation of floating point numbers ← d → Ew.d ±0•------E±xy e.g. E13.6 ← w → This always begins with a decimal part less than one. e.g. a = 104.5627 will be output as □0.104563E+03 (note rounding to fit format)
Integers Iw ------ e.g. I6 ← w → e.g. j = 4 will be output as □□□□□4 Character or text variables Aw ------ e.g. A6 ← w → Character variables are written left-justified e.g. label= ‘date‘ With the above format (A6) this will appear as: date□□ (□ is a blank space)
4. Input Read a real number from the keyboard and assign to real variable x. real x read(*,*)x keyboard ↑ ↑ free format Note: read(*,*) == read(5,*) i.e. unit 5 is reserved for the keyboard. Read an integer from the keyboard into variable i. integer i read(*,*)i Read in 5 real numbers from the keyboard into array a. integer i real a(5) read(*,*)(a(i),i=1,5) ← implied DO loop The last line is equivalent to: read(*,*)a(1),a(2),a(3),a(4),a(5)
Input/output from a file To access a disk file for reading (input) or writing (output) we use the open statement e.g. open (1,file=‘test.dat’,format=‘formatted’) open (1,file=‘test.dat’) For a text (readable) file omit the format keyword. To read from the file use something like: read(1,*)x To write to the file use something like: write(1,*)x Note: The number 1 refers to a unit number in the range 1-99. However there are two special (reserved) unit numbers: 5,6. read(*,*) == read(5,*) i.e. unit 5 is reserved for the keyboard. write(*,*) == write(6,*) i.e. unit 6 is reserved for the screen. To avoid portability issues do not use these special units to open files.
In many cases we read data from a file and we’re not sure how many numbers there will be in the file. We make use of the read end keyword. For simplicity we will assume that the file press.dat contains a column of numbers e.g. 1021.1 1000.3 1001.7 … integer i,n real p(100) open (1,file=’press.dat’)← Unit 1 is assigned to the file press.dat (a kind of short name or handle) do i=1,100 read(1,*,end=9)p(i) enddo 9 continue← Go to here if we encounter the end of the file (end=9) n= i –1← Last value of i corresponds to the end of the file (one greater) write(*,*)’n=’,n We can now process the array of numbers p(i) i=1 … n .
In the last example it was assumed that we were reading in a single column of numbers. Imagine that the file press.dat contains the following: Data□□□□□Pressure ← □ denotes a blank space 850601□□□1021.1 850602□□□1000.3 850603□□□1001.7 ↑ Column 1 To read in the second column of numbers into array p: character line*80 ← A variable to hold 80 characters integer i,n real p(100) open (1,file=’press.dat’) read(1,*)line or read(1,’(A)’)line do i=1,100 read(1,’(9x,F6.1)’,end=9)p(i) ← Formatted read statement enddo 9 continue n= i –1 write(*,*)’n=’,n
We can also use a format statement: read(1,200,end=9)p(i) ← Use the format statement with label 200 200 format(9x,F6.1) which is equivalent to: read(1,’(9x,F6.1)’,end=9)p(i) To read in the line of text as two column labels and both columns of data: character label1*4, label2*8← Variables to hold column labels of 4 and 8 characters integer i,n real p(100) integer date(100) ← Array to hold integer date open (1,file=’press.dat’) read(1,210)label1,label2 210 format(A4,5x,A8) ← Format for labels do i=1,100 read(1,’(I6,3x,F6.1)’,end=9)date(i),p(i) ← Formatted read statement to read date(i) and p(i) enddo 9 continue n= i –1 write(*,*)’n=’,n If we are only reading numerical values e.g. three columns of numbers, then usually the simplest approach would be something like: read(1,*)x(i),y(i),z(i)
5. Output Generally write is just the opposite of read. Write a real number x to the screen. real x write(*,*)x screen ↑ ↑ free format Note: write(*,*) == write(6,*) i.e. unit 6 is reserved for the screen. In the primer: write(*,*)x is equivalent to print *,x You can use a format statement and include some output text: write(*,100)x 100 format(’The answer is ’,F8.2) is equivalent to write(*,’(’’The answer is ’’,F8.2)’)x ← Note repeated quotes
6. Internal read and write This involves reading from or writing to a character variable that is treated as a ‘pretend’ file. For instance: integer n character*80 optarg← orcharacter optarg*80 read(optarg,*)n The integer variable n is read from the character variable optarg as if it were a line of text in a file. Similarly for a real variable we can have: read(optarg,*)x We can also use a format e.g. read(optarg,’(2x,F6.1)’)x Similarly we can write to a character variable: write(optarg,*)x write(optarg,’(2x,F6.1)’)x
7. Logical variables See the primer and reference. These are declared as logical type e.g. logical lexist A logical variable is either true (1) or false (0). Usually we use an if statement with a logical expression involving our variables e.g. if (x.eq.5) then ← Is x=5? If so then go to the then section otherwise go to the else section y = 2 ← If x=5 then go here and set y=2 else y = -4 ← If x is not 5 then go here and set y=-4 endif write(*,*)’x= ’,x,’ y= ’,y If the expression in (…) is true the then section is executed otherwise we jump to the else section.
Sometimes we code the above as: logical istrue istrue= (x.eq.5)← This will be either true (1) or false (0) if(istrue)then ← If x is 5 then istrue will be 1 and we go to the then section … endif write(*,*)’istrue=’,istrue,’ x= ’,x,’ y= ’,y Note: If you write out a logical variable you will see T for true (1) and F for false (0) on most systems. You can also set a logical variable to true or false e.g. exists= .true.
8. Mixed mode arithmetic An expression that involves a combination of real and integer variables will give a real value, as long as the output variable is real. real x,y integer i,j y= x/i ← y is real j= x/i ← j is an integer i.e. integer truncation of x/i Hence if i= 4 and x= 11. then y= 2.75 and j= 2 i.e. 2.75 is truncated to 2. An expression involving integers only will be the integer truncation. integer i,j,k real y k= i/j ← k is an integer i.e. integer truncation of i/j y= i/j ← y is the real conversion of the integer truncation Hence if i= 7 and j= 2 then k= 3 (integer truncation 7/2= 3). Note that y= 3. i.e. the integer 3 is converted to real (3.0).
9. do loops These are covered in the primer and reference but a few comments will be made. do loops are convenient for summations used to compute the mean and other statistics. Consider the mean of the sample x1, x2, …, xn : The summation is x1+ x2+ …+ xn . If we identify an array x of size n with the sample then the summation is x(1) + x(2) + …+x(n). Alternatively the summation can be expressed as a set of successive accumulations: s1 = x(1) s2 = x(1) + x(2) = s1 + x(2) s3 = x(1) + x(2) + x(3) = s2 + x(3) …
We can use a do loop to represent these accumulations: xbar = 0. ← Initialise xbar i.e. start with a sum of zero do i=1,n xbar = xbar + x(i) ← Add x(i) to previous sum to get current sum enddo xbar = xbar / n ← Get the mean by dividing the sum by n In older code the form: do 200 i=1,n … 200 continue is often seen. Note: do loops are often indented for clarity.
A useful variation is the do while loop. In this case the logical condition that must be true for the loop to be processed is given as part of the do while statement e.g. n= 10 i= 1 y= 2. do while (i.le.n.and.y.gt.0)← Logical condition y= y +sin(x(i))← sin is a Fortran intrinsic (built-in) function i= i +1 ← i is modified enddo Note that both aspects of this particular condition must be true for the operations within the loop to be processed.
A pair of ‘nested’ DO loops is useful for processing 2D array elements: do j=1,nlat do i=1,nlon y(i,j)= z(i,j)* a + b enddo enddo Here i might correspond to longitude and j to latitude. Note: the array element y(i,j) may be treated as a simple variable in computations.
There is a special form of the do loop which is used only with the read and write statements – it is called an implied do loop e.g. n= 3 read(1,*)(x(i),i=1,n) The list in () is expanded i.e. it is equivalent to listing the array elements x(i) explicitly i.e. read(1,*)x(1),x(2),x(3) For large n e.g. n=10000, the implied do loop form is obviously very useful.