You are on page 1of 93

Introduction to Fortran

Doug Sondak SCV sondak@bu.edu

Outline
Goals Introduction Emacs Fortran History Basic syntax makefiles Additional syntax

Goals
To be able to write simple Fortran programs To be able to understand and modify existing Fortran code To be able to manage program projects using an editor and makefile

Introduction
Matlab is great! Why do I need to learn a new language?! All codes must be translated to machine language Interpreted language
Matlab, Python, Java Translation is performed incrementally at run time

Compiled language
Fortran, C, C++ Translation is performed once, then executable is run

Introduction (contd)
Compiled languages run faster
I translated a program from Matlab to C for a user, and it ran 7 times as fast Large-scale computing is usually done with compiled language

Some convenient features of interpreted languages (e.g., no need to declare variables) result in performance and/or memory penalties

Emacs
Professional programmers often work within a programming environment
Writing and editing code Running code

On Unix systems, one typically uses an editor to write/modify code Emacs and vi are most popular
We will talk about emacs If you want to use vi, thats fine Arguing about which is better makes the Thirty-Years' War look tame

Emacs (contd)
Emacs is a wonder tool! We will just scratch the surface .emacs file in home directory can be customized Commands can be executed via menus or using the underlying character sequences
I like the latter, so thats what well do This will be our example file for editing

Copy the file junk from /scratch/sondak


cp /scratch/sondak/junk

Emacs Exercise
Type emacs
An emacs window will appear A built-in tutorial is available
Type CTL-h t
Hold CTL while pressing h, release CTL, then press t

We wont do anything with the tutorial here, but its a good resource The META key in the tutorial is Esc

To read a file CTL-x CTL-f


You will be prompted for file name at bottom of window Type junk and hit return If the file doesnt exist, emacs will create it

Emacs Exercise (contd)


You should now see file contents in window To move down CTL-n (next line) To move up CTL-p (previous line) To move forward CTL-f (forward) To move backward CTL-b (backward) You can also navigate by clicking on the desired location
Click on the 0 in 0.282

Emacs Exercise (3)


To delete a character CTL-d
Hit CTL-d 3 times to delete 0.2 Type 1.3 Youve now changed 0.282 to 1.382

Highlight 0.288 with the mouse


Dont include spaces before or after CTL-w will delete the highlighted characters Oh no, we made a mistake! CTL-x u undoes the previous command. Try it; 0.288 should reappear.
another CTL-x u undoes the command previous to that, etc.

Emacs Exercise (4)


The point is the location on the left side of the cursor; i.e., between the character on which the cursor resides and the character to its left. The mark is similar to the point, but its location is set (i.e., doesnt move with cursor). Suppose we want to delete all the characters between (inclusively) 0.288 and 0.407.

Emacs Exercise (5)


Place the cursor on the 0 in 0.288.
can simply click on the 0

To set the mark, CTL-spacebar


The note Mark set will appear at the bottom of the screen.

Move the cursor to the right of 0.407


We place it to the right of the 7 rather than on it because the point is always to the left of the cursor

Emacs Exercise (6)


CTL-w will delete all characters between the mark and the point For now, lets put the characters back in by using CTL-x u Move the cursor to the start of the current line using CTL-a
(CTL-e moves to end of current line)

Delete (kill) the line with CTL-k Another CTL-k deletes the newline character

Emacs Exercise (7)


Meta key is the Esc key We will use M- here to indicate the Meta key The Meta key is hit prior to the subsequent key(s), not simultaneously as with CTL Place the cursor at the top of the file M-> will move the cursor to the bottom of the file M-< will move it back to the top

Emacs Exercise (8)


Suppose we want to swap positions of 14.747 and 14.688 Set the mark at the 1 in 14.747 Place the cursor on the 1 in 14.688 to set the point to the left of the 1 CTL-w will delete 14.747 Place the cursor over the space to the left of the first 1 in 16.155 CTL-y yanks the previously-deleted string

Emacs Exercise (9)


Suppose we want to swap positions of the second and third columns Set the mark after the last 0 in 0.000 in the 1st row of data Set the point to the right of the 8 in 0.758 in column 2, last row CTL-x r k (kill rectangle) deletes the column Place the point after the 8 in 37.578 CTL-x r y (yank rectangle) inserts the column

Emacs Exercise (10)


To save the modified file, CTL-x CTL-s
A note will appear at the bottom of the window saying the file has been saved

To save it under a new name, CTL-x CTL-w


Youll be prompted for the name at the bottom of the screen Note that when you get these kinds of prompts, you can edit them using emacs commands
Type a file name and then move back and forth with CTL-b and CTL-f

CTL-x CTL-c to quit Previous version will appear with ~ suffix in working directory

Fortran History
Before Fortran, programs were written in assembly language Fortran was the first widely-used high-level computer language
1957 Developed by IBM for scientific applications

Fortran History
Fortran 66 (1966) Fortran 77 (1978) Fortran 90 (1991)
fairly modern (structures, etc.) Current workhorse Fortran

Fortran 95 (minor tweaks to Fortran 90) Fortran 2003


Gradually being implemented by compiler companies Object-oriented support Interoperability with C is in the standard
yay!

What Language Should I Use?


I usually suggest using the language you know best Matlab is great, but is not a good choice for major number crunching
Researchers often write codes in Matlab, and they grow and grow (the codes, not the researchers) until they are much too slow
Then a painful translation is often required

What Language? (contd)


Fortran is hard to beat for performance C has the potential to be as fast as Fortran if you avoid aliasing issues and promise the optimizer your code wont screw up aliasing
Fortran doesnt have this issue due to the different nature of its pointers

I have not written large C++ codes, but its to my understanding that object-oriented constructs tend to be slow Suggestion write computationally-intensive codes in Fortran or C
Can parallelize using MPI and/or OpenMP

Fortran Syntax
Source lines are not ended with semicolons (as in C or Matlab) Ampersand at end of line tells compiler that statement is continued on next source line Not case-sensitive Spaces dont matter except within literal character strings
I use them liberally to make code easy to read

Comment character is !

Fortran Syntax (contd)


Declarations should declare each variable as being integer, real (floating point), character, etc. Integers and reals are stored differently Integer arithmetic will truncate result
If i=3 and k=2, i/k=1, k/i=0

Fortran Syntax (3)


There are sometimes several ways to do the same thing
For backward compatibility We will only use modern constructs

Source file suffix is compiler dependent


Usually .f90

Fortran Syntax (4)


First statement in code is program statement
Followed by program name I like to give the source file the same name as the program
myprog.f90 program myprog (name of source file) (first line in source code)

Fortran Syntax (5)


implicit none
Due to older versions of Fortran
Had implicit typing
Variables did not have to be declared If names started with i-n, were automatically integers If a-h,o-z, were automatically single-precision reals

Implicit typing is considered bad programming practice


Always use implicit none often next line after program

Implicit none says that all variables must be declared If you use implicit none and dont declare all variables, compiler will yell at you

Fortran Syntax (6)


A character string is enclosed by single quotes
Characters within the quotes will be taken literally This is my character string.

print*
list-directed output Lazy way to produce output
No format required

Follow by comma, then stuff to print print*, This is my character string.

Fortran Syntax (7)


At the end of the code is an end program statement, followed by program name
Paired with program statement that starts the code end program myprog

Exercise 1
Write a hello world program in an editor
Program should print a string 4 lines of code Save it to a file name with a .f90 suffix

solution

Compilation
A compiler is a program that reads source code and converts it to a form usable by the computer Code compiled for a given processor will not generally run on other processors
AMD and Intel are compatible

On katana we have Portland Group compilers (pgf90) and GNU compilers (gfortran) Well use pgf90, since its usually faster

Compilation (contd)
Compilers have huge numbers of options
See PGI compiler documentation at http://www.pgroup.com/doc/pgiug.pdf PGI Fortran reference is at http://www.pgroup.com/doc/pgifortref.pdf

For now, we will simply use the o option, which allows you to specify the name of the resulting executable

Compilation (3)
Can create a Unix window within emacs:
CTL-x 2 will split the window horizontally CTL-x o toggles between windows
o stands for other

M-x will prompt for a command at the bottom of the window


Type shell (no quotes) for the command Half of emacs window will now be a Unix shell, so you can do your compilation there In a normal Unix tcshell you can retrieve previous Unix commands with the up arrow; here its CTL up arrow

In a Unix window (in emacs or separate window):


pgf90 o hello_world hello_world.f90

Compilation (4)
Compile your code If it simply returns a Unix prompt it worked If you get error messages, read them carefully and see if you can fix the source code and recompile Once it compiles correctly, type the executable name at a Unix prompt, and it will print your string

Declarations
Lists of variables with their associated types Placed in source code directly after implicit none Basic types:
Integer Real Character logical

Declarations (contd)
Examples:
integer :: i, j, k real :: xval, time character(20) :: name, date logical :: isit

Arithmetic
+, -, *, / ** indicates power
2.41.5

2.4**1.5

Built-in functions such as sin, acos, exp, etc. Exponential notation indicated by letter e
4.2 103

4.2e5

More List-Directed i/o


read* is list-directed read, analogous to print* Follow with comma, then comma-delimited list of variables you want to read
read*, x, j

Often use list-directed read and write together


print*, Enter a float and an integer: read*, x, j print*, float = , x, integer = , j

Exercise 2
Write program to prompt for a Celcius temperature, convert it to Fahrenheit, and print the result.
make sure you declare all variables its a good habit to use decimal points with all reals, even if theyre whole numbers, e.g., 3.0

F = (9/5)C + 32

solution

Arrays
Specify static dimensions in declaration:
real, dimension(10,3,5) :: x

Can also specify ranges of values


integer, dimension(3:11, -15:-2) :: ival, jval

Arrays (contd)
Dynamic allocation
Need to specify no. dimensions in declaration Need to specify that its an allocatable array real, dimension(:,:,:), allocatable :: x, y allocate function performs allocation allocate( x(ni,nj,nk), y(ldim,mdim,ndim) ) When youre done with the variables, deallocate deallocate(x, y)
not necessary at very end of code; Fortran will clean them up for you

Parameters
If variable has known, fixed value, declare as parameter and initialize in declaration
integer, parameter :: idim = 100, jdim = 200 Compiler substitutes values wherever variables appear in code Efficient, since there are no memory accesses Often used for declaring arrays integer, parameter :: idim = 100, jdim = 200 real, dimension(idim, jdim) :: x integer, dimension(idim) :: iarray

Exercise 3
Write program to prompt for 2 floating-point vectors of length 3, calculate the dot product, and print the result Dont name the code dot_product or dot
Fortran has a dot_product intrinsic function there is a unix command called dot

If x is an array, can use array name in list-directed read, and it will expect the appropriate number of values (dimension) separated by spaces 3

c ai bi
i 1

solution

Control
Do loop repeats calculation over range of indices
do i = 1, 10 a(i) = sqrt( b(i)**2 + c(i)**2 ) enddo

Can use increment that is not equal to 1


Goes at end of do statement, unlike Matlab do i = 10, -10, -2

Exercise 4
Modify dot product program to use a do loop solution

If-Then-Else
Conditional execution of block of source code Based on relational operators
< > == <= >= /= .and. .or. less than greater than equal to less than or equal to greater than or equal to not equal to

If-Then-Else (contd)
if( x > 0.0 .and. y > 0.0 ) then z = 1.0/(x+y) elseif ( x < 0.0 .and. y < 0.0) then z = -2.0/(x+y) else print*, Error condition endif

Exercise 5
In dot product code, check if the magnitude of the dot product is less than 106 using the absolute value function abs. If it is, print a message. If not, calculate the reciprocal of the dot product and print the result. solution

Array Syntax
Fortran will perform operations on entire arrays
Like Matlab, unlike C

To add two arrays, simply use


c=a+b

Can also specify array sections


c(-5:10) = a(0:15) + b(0:30:2) Here we use b(0), b(2), b(4),

Array Syntax (contd)


There are intrinsic functions to perform some operations on entire arrays
sum sum(x) is the same as x(1) + x(2) + x(3) + product minval maxval

Exercise 6
Modify dot product code to use array syntax instead of do loop
use sum intrinsic to sum comnponents

solution

Subprograms
Subroutines and functions
Function returns a single object (number, array, etc.), and usually does not alter the arguments
Altering arguments in a function, called side effects, is sometimes considered bad programming practice

Subroutine transfers calculated values (if any) through arguments

Functions
Definition starts with a return type End with end function analogous to end program Example: distance between two vectors
real function distfunc(a, b) real, dimension(3) :: a, b distfunc = sqrt( sum((b-a)**2) ) end function distfunc

Use:
z = distfunc(x, y) Names of dummy arguments dont have to match actual names distfunc must be declared in calling routine real :: distfunc

Subroutines
End with end subroutine analogous to end program Distance subroutine
subroutine distsub(a, b, dist) real :: dist real, dimension(3) :: a, b dist = sqrt( sum((b-a)**2) ) end subroutine distfunc

Use:
call distsub (x, y, d) As with function, names of dummy arguments dont have to match actual names

Exercise 7
Modify dot-product program to use a subroutine to compute the dot product
The subroutine definition may go before or after the main program in source code Dont forget to declare arguments

solution

Basics of Code Management


Large codes usually consist of multiple files I usually create a separate file for each subprogram
Easier to edit Can recompile one subprogram at a time

Files can be compiled, but not linked, using c option; then object files can be linked
pgf90 c mycode.f90 pgf90 c myfunc.f90 pgf90 o mycode mycode.o myfunc.o

Exercise 8
Put dot-product subroutine and main program in separate files Give main program same name you have been using for code, e.g., program dotprod and dotprod.f90 Give subroutine same name you used for subroutine, e.g., subroutine dp and dp.f90 Compile, link, and run solution

Makefiles
Make is a Unix utility to help manage codes When you make changes to files, it will
Automatically deduce which files need to be compiled and compile them Link latest object files

Makefile is a file that tells the make utility what to do Default name of file is makefile or Makefile
Can use other names if youd like

Makefiles (contd)
Makefile contains different sections with different functions
The sections are not executed in order!

Comment character is # There are defaults for some values, but I like to define everything explicitly

Makefiles (3)
example makefile:
### suffix rule .SUFFIXES: .SUFFIXES: .f90 .o .f90.o: $(F90) $(COMPFLAGS) $*.f90 ### compiler F90 = pgf90 COMMONFLAGS = -O3 COMPFLAGS = -c $(COMMONFLAGS) LINKFLAGS = $(COMMONFLAGS) ### objects OBJ = mymain.o sub1.o sub2.o fun1.o ### compile and link myexe: $(OBJ) $(F90) o $@ $(LINKFLAGS) $(OBJ)

Makefiles (4)
variables
Some character strings appear repeatedly in makefiles Its convenient to give them names so if they are changed, you only have to do it in one place To define variable: name = string No quotes are required for the string String may contain spaces name is any name you want Variable names are usually all capitals To continue line, use \ character

Makefiles (5)
Variables (contd)
To use variable, either of these work:
$(name) ${name}

Example:
Define compiler
F90 = pgf90

To use elsewhere in makefile:


$(F90)

Makefiles (6)
Good practice to define compiler info in variables
F90 = pgf90 COMMONFLAGS = -O3 COMPFLAGS = -c $(COMMONFLAGS) LINKFLAGS = $(COMMONFLAGS)

Makefiles (7)
Have to define all file suffixes that may be encountered
.SUFFIXES: .o .f90

Just to be safe, delete any default suffixes first with a null .SUFFIXES: command
.SUFFIXES: .SUFFIXES: .o .f90

Makefiles (8)
Have to tell how to create one file suffix from another with a suffix rule
.f90.o: $(F90) $(COMPFLAGS) $*.f90

The first line indicates that the rule tells how to create a .o file from a .f90 file The second line tells how to create the .o file The big space before $(F90) is a tab, and you must use it! *$ is automatically the root of the first file

Makefiles (9)
Usually define variable with all object file names
OBJ = mymain.o sub1.o anothersub.o \ firstfunc.o func2.o

Makefiles (10)
Finally, everything falls together with the definition of a rule
target: prerequisites recipe

The target is any name you choose


Often use name of executable

Prerequisites are files that are required by target


e.g., executable requires object files

Recipe tells what you want the makefile to do

Makefiles (11)
### suffix rule .SUFFIXES: .SUFFIXES: .f90 .o .f90.o: $(F90) $(COMPFLAGS) $*.f90 ### compiler F90 = pgf90 COMMONFLAGS = -O3 COMPFLAGS = -c $(COMMONFLAGS) LINKFLAGS = $(COMMONFLAGS) ### objects OBJ = mymain.o sub1.o sub2.o fun1.o

### compile and link myexe: $(OBJ) $(F90) o $@ $(LINKFLAGS) $(OBJ)

Automatic variable for target

Makefiles (12)
When you type make, it will look for a file called makefile or Makefile It then searches for the first target in the file In our example (and the usual case) the object files are prerequisites It checks the suffix rule to see how to create an object file In our case, it sees that .o files depend on .f90 files It checks the time stamps on the associated .o and .f90 files to see if the .f90 is newer If the .f90 file is newer it performs the suffix rule
In our case, compiles the routine

Makefiles (13)
Once all the prerequisites are updated as required, it performs the recipe In our case it links the object files and creates our executable Many makefiles have an additional target, clean, that removes .o and other files
clean: rm f *.o

When there are multiple targets, specify desired target as argument to make command
make clean

Exercise 9
Create a makefile for your dot product code Include two targets
executable clean

Delete your old object files using make clean Build your code using the makefile solution

Kind
Declarations of variables can be modified using kind parameter Often used for precision of reals Intrinsic function selected_real_kind(n) returns kind that will have at least n significant digits
n = 6 will give you single precision n = 12 will give you double precision

Kind (contd)
integer, parameter :: rk = selected_real_kind(12) real(rk) :: x, y, z real(rk), dimension(101,101,101) :: a If you want to change precision, can easily be done by changing one line of code

Exercise 10
Modify dot-product code to use kinds to declare double-precision reals
Dont forget to modify all files make will automatically compile and link

solution

Modules
Program units that group variables and subprograms Good for global variables Checking of subprogram arguments
If type or number is wrong, linker will yell at you

Can be convenient to package variables and/or subprograms of a given type

Modules (contd)
module module-name
implicit none variable declarations contains subprogram definitions

end module module-name

Modules (3)
Only need contains if module contains subprograms I usually name my modules (and associated files) with _mod in the name, e.g., solvers_mod, solvers_mod.f90 In program unit that needs to access components of module use module-name use statement must be before implicit none

Modules (4)
use statement may specify specific components to access by using only qualifier:
use solvers_mod, only: nvals, x

A Fortran style suggestion:


Group global variables in modules based on function Employ use only for all variables required in program unit All variables then appear at top of program unit in declarations or use statements

Modules (5)
When linking object files, modules must come first in the list
In my makefiles I create a MODS variable analogous to OBJS Link command then contains $(MODS) $(OBJS)

Exercise 11
Create module prec_mod
Separate file called prec_mod.f90 Parameter rk Real kind for double

Use this module in dot-product program units Modify makefile to compile module
add module list to dependencies and link recipe

solution

Derived Types
Analogous to structures in C Can package a number of variables under one name
type grid integer :: nvals real, dimension(100,100) :: x, y, jacobian end type grid

Derived Types (contd)


To declare a variable
type(grid) :: grid1

Components are accessed using %


grid1%nvals = 20 grid1%x = 0.0

Handy way to transfer lots of data to a subprogram


call calc_jacobian(grid1)

Exercise 12
Create module with definition of rvec3 type
Size of vector nvals=3
not a paremeter cant have parameter in derived type

Real 3-component vector Use prec_mod

Modify code to use rvec3 Modify makefile to include new module solution

i/o
List-directed output gives little control write statement allows formatted output
write(unit, format) variables

Unit is a number indicating where you want to write data


The number 6 is std out (write to screen)

i/o (contd)
im
For integers m is total number of characters in field
i3 125

am
For character strings m is number of characters
a5 hello

Left-justifies If m isnt specified, writes number of characters in variable declaration

i/o (3)
fm.n
For floating-point (real) numbers m is total number of characters in field n is number of decimal places
f5.3 f5.2 1.234 -1.23

If m is larger than required, right-justifies

em.n
Exponential notation
e9.2 -0.23e-01

Always zero left of decimal

i/o (4)
esm.n
scientific notation
es9.2 -2.30e-02

In format statement, put formats within () Example write statement


write(6, (a, f6.2, i5, es15.3)) answers are , x, j, y

i/o (5)
Suppose you want to write to a file?
open statement open(11, file=mydata.d) 11 is unit number
Dont use 5 or 6
Reserved for std in, std out

Use this unit in your write statement When youre finished writing, close the file close(11)

i/o (6)
Can also read from file
read rather than write Can use * instead of format specifier read(11,*) j, x

Exercise 13
Write your dot-product result to a file solution

Unformatted i/o
Binary data take much less disk space than ascii (formatted) data Data can be written in binary representation
Not directly human-readable open(199, file=unf.d, form=unformatted) write(199) x(1:100000), j1, j2 read(199) x(1:100000), j1, j2 Note that there is no format specification

Fortran unformatted slightly different format than C binary


Fortran unformatted contains record delimiters

Exercise 14
Modify dot-product program to:
Write result to unformatted file
dont write character string, just number

After file is closed, open it back up and read result Print result to make sure it wrote/read correctly

solution

References
Lots of books available
I have an older edition of Fortran 95/2003 Explained by Metcalf, Reid, and Cohen that I like

PGI
Compiler
http://www.pgroup.com/doc/pgiug.pdf

Fortran language reference


http://www.pgroup.com/doc/pgifortref.pdf

gfortran
http://gcc.gnu.org/wiki/GFortran

Survey
Please fill out the course survey at
http://scv.bu.edu/survey/fall10tut_survey.html

You might also like