Вы находитесь на странице: 1из 12

School of Engineering University of Warwick ES440/911 Computational Fluid Dynamics Lab session Week 15: Fortran I Novak Elliott

(N.S.J.Elliott@warwick.ac.uk) A. Introduction The goal of this lab session is to give a quick introduction to the most useful features of the Fortran 90 programming language for scientific applications. Fortran, an acronym for Formula Translation, is a general-purpose, procedural, programming language that is especially suited to numeric computation and scientific computing. Originally developed by IBM in the 1950s, Fortran came to dominate this area of programming early on and has been in continual use in computationally intensive areas such as climate modelling, computational chemistry and computational fluid dynamics (CFD) for half a century. There have been many revisions of the Fortran language, each being designated by the year the ANSI standard was proposed. Thus we have Fortran 66, Fortran 77, Fortran 90, Fortran 95, Fortran 2003, and the latest revision in progress is tentatively entitled Fortran 2008. The most common Fortran version today is still Fortran 90, although Fortran 77 is still used in legacy code. There are also several versions of Fortran aimed at parallel computers. The most important one is High Performance Fortran (HPF), which is a de-facto standard and indeed many features have made there way into official ANSI revisions. Users should be aware that most Fortran 90 compilers allow a superset of Fortran 90, i.e. they allow non-standard extensions. In this lab session we will emphasize standard ANSI Fortran 90 which will give your programs greater portability to other platforms (such as linux, for example). Finally, given that Fortran is half a century old and many other languages have been developed since its creation, one may reasonably ask: Why bother learning Fortran? or Shouldnt I learn C++ instead? There are many arguments for and against one language over another but what should always be remembered is that every programming language was designed with a specific purpose in mind. Fortran was designed to be very good at number crunching but is not very good for generating graphics. Similarly, Javas strength is web applications, C is great for direct access to hardware and C++ is good for object-oriented tasks. Admittedly, with a deep understanding of the subtleties of the C++ language one can write a C++ program with the same computational efficiency as a Fortran program and arguably with prettier syntax. However, writing a fast number crunching program in Fortran is much simpler and achieves the same result. Moreover, some of the leading commercial CFD packages on the market (e.g., Star CCM+, CFX) allow users to write their own code in Fortran to extend the capabilities of the software to solve highly customised problems, a service often offered by CFD consultant engineers.

B. Fortran Programming Tutorial 1. Fortran Basics 1.1 Getting up and running A Fortran program is simply a sequence of computer instructions written as lines of text. The text has to follow certain syntax to be a valid program. We will start by looking at a simple example: program circle implicit none ! This program simply calculates the area of a circle ! Declarations (variables and constants) real(8) :: radius, area ! Statements (where the work is done) radius = 10.0D0 area = 3.141592D0 * radius * radius write (*,*) 'The area = ', area end program circle Open the program Notepad (start->Run->type notepad and hit enter), copy and paste the above text and then save the file as circle.f90 in your home directory (File>Save as->choose All Files and type circle.f90). Next open a command prompt (start->Run>type cmd then press enter), change to your home directory (type i:\), and type the following command: g95 o circle circle.f90 You should now have a program called circle.exe. Run this program. You should see the following output: The area = 314.1592

Congratulations, you have just written your first Fortran program! Now lets have a look at what weve just done. 1.2 Compiler and linker We began with a text file and ended up with a computer program how did we do it? The answer is by using the compiler and linker, g95.exe, which is a program for reading source code (circle.f90) and compiling it into object code and then linking all of the object code together into a single executable program (circle.exe). Sometimes the compiling and linking is done in separate stages but in our case its done all in one go so from here on we will simply refer to the process as compiling and g95 as the compiler. Note that g95 is actually a Fortran 95 compiler but is backwards compatible with Fortran 90.

1.3 Comments The lines that begin with with a "!" are comments and while they are ignored by the computer they make the program more readable for humans. Well-written comments are crucial to program readibility. Commercial Fortran codes often contain about 50% comments. 1.4 Program Organisation The structure of a Fortran program is: program name implicit none declarations executable statements end program name Note: Courier Font is used for Fortran commands, Italic Roman Font is used for generic descriptons and Arial Font is used for input and output from the command line. The implicit none statement ensures that all variables are explicitly declared and makes programs easier to debug and understand do NOT omit this statement! 1.6 Continuation A line may be up to 132 characters long and occasionally a statement will not fit into a single line. One can then break the statement into two or more lines, and use the continuation mark & at the end and at the beginning of the continuation. Example: ! The next statement goes over two physical lines area = 3.14159265358979D0 & & * radius * radius 1.7 Blank spaces Blank spaces are ignored in Fortran 90 with one exception: within numeric constants. Therefore, million = 1 000 000 is invalid. That exception aside, if you remove all blanks in a Fortran 90 program, the program is still syntactically correct but almost unreadable for humans. 1.8 Exercises 1(a) Identify 3 errors in the following Fortran 90 program:

program test implicit none ! integer :: int int = 12 write(*,*) 'The value of int is ', & int end test 1(b) Correct these errors, compile the program as test.exe and run it. The output should be: The value of int is 12 Hint: if the compiler generates error messages then these will help identify the problems in the code dont be afraid of these, this is what debugging is all about and accounts for the majority of program development time! 2. Variables, declarations and types 2.1. Variable names Variable names in Fortran 90 may be up to 31 characters in length and chosen from the letters a-z, the digits 0-9, and the underscore _ character. The first character must be a letter! Fortran 90 does not distinguish between upper and lower case, in fact, it assumes all input is upper case. 2.2 Types and declarations Every variable must be defined in a declaration. This establishes the type of the variable. The most common declarations are: integer :: real :: real(8) :: complex :: logical :: character :: list of variables list of variables list of variables list of variables list of variables list of variables

The list of variables should consist of variable names separated by commas. We will be using the integer type for general counting and indexing operations, the real(8) type for high accuracy (28 = 64 bit) numerical computations and the character type for reporting. Note: the real type has the same accuracy as the machine architecture, which may only be 32 bit (24) on some machines. 2.3 The parameter statement Some constants appear many times in a program. It is then often desirable to define them only once, in the beginning of the program. This is what the parameter statement is for. It also makes programs more readable. For example, the test area program should have been written like this:

real(8), parameter :: pi = 3.141592D0 real(8) :: radius, area area = pi * radius * radius The syntax of the parameter statement is variable type, parameter :: name = constant Note the following: Once a variable is assigned a value in a parameter statement it becomes a constant whose value cannot change for the rest of the program A variable can appear in at most one parameter statement The parameter statement(s) must come before the first executable statement Common uses of the parameter statement in CFD programs are to define fluid properties (e.g. density), geometry dimensions (pipe diameter), initial conditions (ambient temperature) and boundary conditions (inlet velocity). 2.4 Exercises 2(a) Which of the following variable names are invalid, and why? A5, 5a, variable, XY3Z4Q, AT&T, number1, NO1, NO 1, NO_1, stop 2(b) Write a program to check your answer to part (a). 3. Expressions and assignment 3.1 Constants The simplest form of an expression is a constant. Here are some examples for the integer type: 1 0 -100 32767 +15 and the real(8) type: 1.0D0 -0.25D0 2.0D6 3.333D-1 The D-notation means that you should multiply the constant by 10 raised to the power following the "D". Hence, 2.0D6 is two million, while 3.333D-1 is approximately one third.

Note: do not leave off the D! 1.0 is implicitly a real constant whereas 1.0D0 is a real(8) constant. In the circle program try changing the value of pi from a real(8) constant to a real constant and see what happens to the area! The reasoning behind this is found below in section 3.3. The last type we will deal with are character constants. These are most often used as an array of characters, called a string. These consist of an arbitrary sequence of characters enclosed in apostrophes (single quotes): 'ABC' 'Anything goes!' 'It is a nice day' Strings and character constants are case sensitive. A problem arises if you want to have an apostrophe in the string itself. In this case, you should double the apostrophe: 'It''s a nice day' 3.2 Expressions The simplest expressions are of the form operand operator operand and an example is x + y The result of an expression is itself an operand, hence we can nest expressions together like x + 2 * y This raises the question of precedence: Does the last expression mean x + (2*y) or (x+2)*y? The precedence of arithmetic operators in Fortran 90 are (from highest to lowest): () ** *,/ +,{Brackets} {Indicial exponentiation} {Multiplication, Division} {Addition, Subtraction}

i.e. the old BIMDAS rule from primary school. All these operators are calculated left-to-right, except the exponentiation operator **, which has right-to-left precedence. Its best to use brackets to ensure that each expression is evaluated in the order intended. Note: Extreme caution must be taken when using the division operator, which has a quite different meaning for integers and higher precision types (real(8)). If the

operands are both integers, an integer division is performed, otherwise a floating point arithmetic division is performed. E.g., 3/2 equals 1, while 3.0/2.0 equals 1.5. 3.3 Assignment The assignment has the form variable_name = expression The interpretation is as follows: Evaluate the right hand side and assign the resulting value to the variable on the left. The expression on the right may contain other variables, but these never change value! For example, area = pi * radius**2 does not change the value of pi or radius, only area. 3.4 Exercises 3(a) Calculate the value of the following Fortran 90 expressions (by hand): 2+1-10/3/4 2**3/3*2-5 -(3*4-2)**(3-2**1+1)/-2 3(b) Write a Fortran 90 program that prints these constant expressions using the write(*,*) statement (as used in circle program in section 1.1) and check your hand calculations. 3(c) Use spaces and brackets to make the order of evaluation more clear. 4. Conditional statements and decision making 4.1 Logical expressions Logical expressions can only have the value .TRUE. or .FALSE. A logical expression can be formed by comparing arithmetic expressions using the following relational operators: < less than <= less than or equal to > greater than >= greater than or equal to == equal to /= not equal to Logical expressions can be combined by the logical operators .AND. .OR. .NOT. which have the expected meaning. 4.2 If statements The ability to make decisions is what makes a program useful and the simplest way to do this is with the logical if statement: if (logical expression) executable statement

This has to be written on one line. This example finds the absolute value of x: if (x < 0) x = -x If more than one statement should be executed inside the if, then the following syntax should be used: if (logical expression) then statements endif The most general form of the if statement has the following form: if (logical expression) then statements elseif (logical expression) then statements : : else statements endif The execution flow is from top to bottom. The conditional expressions are evaluated in sequence until one is found to be true. Then the associated code is executed and the control jumps to the next statement after the endif. if statements can be nested in several levels. To ensure readability, it is important to use proper indentation. Here is an example: if (x > 0) then if (x >= y) then write(*,*) 'x else write(*,*) 'x endif elseif (x < 0) then write(*,*) 'x is else write(*,*) 'x is endif

is positive and x >= y' is positive but x < y' negative' zero'

You should avoid nesting too many levels of if statements as the logic becomes difficult to follow.. 4.3 Exercises 4(a) Calculate the value of these logical expressions (by hand): (.true. .and. .false.) .or. .true. (2 < 2) .or. (5 == 11/2)

and then write a Fortran program to check your answers. What happens if you remove the brackets? 4(b) Write a Fortran 90 program that reads in two integers from the user and then assigns the integer variable t the following value: x+y x-y y 0 if x and y are both positive if x is positive and y negative if x is negative if x or y is zero

Print the value of t at the end of the program. Hint: to read in a number from the user the read(*,*) function can be used: write(*,*)'Input first number and press enter: ' read(*,*) x 5. Loops and arrays 5.1 Loops For performing repeated tasks, such as calculating the pressure in every cell of a CFD model, for example, loops are used. Fortran has the do-loop which corresponds to what is known as a for-loop in other languages. Here is a simple example that prints the cumulative sums of the integers from 1 through n (assume n has been assigned a value elsewhere): integer :: i, n, sum sum = 0 do i = 1, n sum = sum + i write(*,*) 'i = ', i write(*,*) 'sum = ', sum end do The variable defined in the do-statement is incremented by 1 by default. However, you can define any other integer to be the step. This program segment prints the even numbers between 1 and 10 in decreasing order: integer :: i do i = 10, 1, -2 write(*,*) 'i =', i end do The general form of the do loop is as follows: do var = expr1, expr2, expr3 statements

end do var is the loop variable (often called the loop index) which must be integer. expr1 specifies the initial value of var, expr2 is the terminating bound, and expr3 is the increment (step). Note: The do-loop variable must never be changed by other statements within the loop! This will cause great confusion. 5.2 Arrays Many scientific computations use vectors and matrices. The data construct Fortran uses for representing such objects is the array. A one-dimensional array corresponds to a vector, while a two-dimensional array corresponds to a matrix. Arrays are usually manipulated using do-loops. One-dimensional arrays The simplest array is the one-dimensional array, which is just a linear sequence of elements stored consecutively in memory. For example, the declaration real(8) :: a(20) declares a as a real(8) array of length 20. That is, a consists of 20 real(8) numbers stored contiguously in memory. By convention, Fortran arrays are indexed from 1 and up. Thus the first number in the array is denoted by a(1) and the last by a(20) The type of an array element can be any of the basic data types. Examples: integer :: i(10) real(8) :: x(100) Each element of an array can be thought of as a separate variable. You reference the i'th element of array a by a(i). Here is a code segment that stores the 10 first square numbers in the array sq: integer :: i, sq(10) do i = 1, 10 sq(i) = i**2 end do Note: A common bug in Fortran is that the program tries to access array elements that are out of bounds or undefined. This is the responsibility of the programmer, and the Fortran compiler will not detect any such bugs! Two-dimensional arrays Matrices are very important in linear algebra. Matrices are usually represented by two-dimensional arrays. For example, the declaration real(8) :: A(3,5)

defines a two-dimensional array of 3*5=15 real(8) numbers. It is useful to think of the first index as the row index, and the second as the column index. Hence we get the graphical picture: (1,1) (1,2) (1,3) (1,4) (1,5) (2,1) (2,2) (2,3) (2,4) (2,5) (3,1) (3,2) (3,3) (3,4) (3,5) In the old days of Fortran 77 it was standard practice to declare arrays that were larger than the matrix we wanted to store since Fortran 77 did not have dynamic memory allocation; thus it was usual to make the array big enough to handle the worst case scenario. A typical example of this might be: real(8) :: A(3,5) integer :: r,c ! We will only use the upper 3 by 3 ! part of this array. ! Loop through each column c do c = 1, 3 ! Loop through each row r do r = 1, 3 a(r,c) = dble(r)/dble(c) end do end do The elements in the submatrix A(1:3,4:5) are undefined. Do not assume these elements are initialized to zero by the compiler (some compilers will do this, but not all). Fortran 90 does have dynamic memory allocation so that one can allocate just the right amount of memory, which can be figured out in the program itself. However, we will leave this topic for the week after next so for the time being simply declare fixed sized arrays as above. 5.3 Exercises 5(a) Write a program that calculates and prints out the first 100 Fibonacci numbers. The first few Fibonacci numbers are: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 5(b) Write a program that prints out a 10 x 10 checker board using 1s and 0s. 5(c) Write a program that solves the following three simultaneous equations: x + 2y + 3z = 6 4x + 5y + 6z = 15 7x + 8y = 15 Hint: recall from linear algebra AX = B, X = A-1 B

C. Useful resources The g95 compiler is free and can be downloaded from http://ftp.g95.org. e.g., for a windows machine choose Self-extracting Windows x86. D. Compiling Fortran 90 in F211 under UNIX If g95 is unavailable on your computer then as a workaround you may use the f90 compiler available on primrose, a general purpose unix machine. i. ii. Make sure that Hummingbird Exceed is installed on your computer. If it is not then reboot your computer. Double click on the desktop icon labelled primrose and enter your user name and password (Ignore the error message about not being able to create a log file). To create a fortran file named circle.f90 type: nedit circle.f90 & <enter> To compile this file type: f90 o circle circle.f90 <enter> To run this program type: ./circle <enter> Some useful UNIX commands: ls list the contents of current directory rm myfile delete file called filename mkdir myfolder create a folder called myfolder cd myfolder change to folder called myfolder cd .. change out of folder called myfolder

iii. iv. v. vi.

Вам также может понравиться