Académique Documents
Professionnel Documents
Culture Documents
• Why Fortran?
- A lot of legacy software written in it (well, often in Fortran 77).
- High-level abstraction (as compared to C); e.g. handling of arrays.
- Large number of numerical libraries built for Fortran.
• Often a question of personal taste and the fact which language you learned first.
1. FORTRAN66
2. FORTRAN77 These two must not be used anymore!
- From now on I call the language simply Fortran or F90+ (meaning all other version except FORTRAN77)
- If there is need to distinguish between 90, 95, 2003, and 2008 versions will tell it explicitly.
- A good source of compiler support of the latest Fortran features can be found at
http://www.fortranplus.co.uk/resources/fortran_2003_2008_compiler_support.pdf
1. For more info on history of programming languages see e.g. http://www.levenez.com/lang/
Introduction to Fortran
• Material
- Fortran 95/2003 Explained by Michael Metcalf, John Reid and Malcolm Cohen, Oxford University Press
- A newer version Modern Fortran Explained by the same authors and publisher
- CSC has published a free Fortran 95/2003 guide in Finnish (see http://www.csc.fi/csc/julkaisut/oppaat)
- Small example programs presented in these lecture notes can be downloaded from
http://www.physics.helsinki.fi/courses/s/stltk/progs/
Introduction to Fortran
• Structure of a Fortran procedure definition
- Integer
parameter qualifier tells that this
integer,parameter :: ik=selected_int_kind(9) object is a constant; its value can
integer(kind=ik) :: i not be changed.
- Example
program intkind progs> gfortran intkind.f90 Change p from 2 to 4 in the code
implicit none progs> ./a.out progs> a.out
integer,parameter :: ik=selected_int_kind(2) 1 2 1 2
integer(kind=ik) :: i 2 4 2 4
integer :: j 3 8 3 8
4 16 4 16
i=1 5 32 5 32
do j=1,20 6 64 6 64
i=i*2 7 -128 7 128
write(0,*) j,i 8 0 8 256
end do 9 0 9 512
10 0 10 1024
stop 11 0 11 2048
end program intkind 12 0 12 4096
13 0 13 8192
14 0 14 16384
15 0 15 -32768
- Default integer (i.e. if you say only integer :: i) is in most environments of size 32 bits (corresponding to p = 9 ).
Introduction to Fortran
- Real
integer,parameter :: rk=selected_real_kind(6,15)
real(kind=rk) :: x (or more simply real(rk) :: x)
- Parameters of the function selected_real_kind(p,r) tell the minimum decimal precision (p) and range of the
exponent (r) of the real type.
- Example
program realkind progs> gfortran realkind.f90 Use (10,40) instead of (6,15)
implicit none progs> a.out progs> ./a.out
integer,parameter :: rk=selected_real_kind(6,15) 1 100.0000 1 100.000000000000
real(kind=rk) :: x 2 10000.00 2 10000.0000000000
integer :: j 3 1000000. 3 1000000.00000000
4 1.0000000E+08 4 100000000.000000
x=1.0 5 1.0000000E+10 ...
do j=1,64 ... 153 9.999999999999997E+305
x=x*100.0 18 1.0000001E+36 154 9.999999999999996E+307
write(0,*) j,x 19 1.0000001E+38 155 +Infinity
end do 20 +Infinity 156 +Infinity
21 +Infinity ...
stop 22 +Infinity
end program realkind ...
- Default real (using only real :: x) is in most systems 32 bit long (i.e. corresponds to float in C).
- But not always!
- This kind-qualifier is exactly the feature that should prevent problems with different word lengths.
- By using it your code is easier to port to other systems. (Well, in practice, most machines today use IEEE floating
point numbers)
integer,parameter :: rk=selected_real_kind(10,40)
complex(kind=rk) :: z
z=(1.0,1.0)
- Boolean
logical :: firsttime=.true.
...
if (firsttime) then
...
firsttime=.false.
end if
- Strings
Assigning and concatenation
character(len=80) :: c,d,e
character(len=80) :: c c=”first”
c=’No, joo!’ d=”last”
write(0,*) c e=trim(c)//” and “//trim(d) Function trim strips the trailing
write(0,*) e
spaces from the string.
- Substring: c(5:10), c(:4), c(11:) Comparison
character(len=80) :: c,d
c=”first”
- Note that string handling in F90 is ...
d=”last”
much easier than in C, methinks: if (c==d) then
write(0,*) “equal!”
endif
Introduction to Fortran
- Own type definitions (structs)
program typedeftest
implicit none
type person
character(len=20) :: first,last
integer :: age
end type person progs> gfortran typedef.f90
progs> a.out
Matti Meikäläinen 75
type(person) :: student
student%first=’Matti’
student%last=’Meikäläinen’
student%age=75
stop
end program typedeftest
Introduction to Fortran
• Comparison operators
- In FORTRAN77 the comparison operators had the dotted forms given below in the last column:
• Logical operators
- These only have the dotted forms.
Examples:
Operator Fortran
.not.(a<b.and.b>c)
Negation .not.
Logical and .and. a>=b .or. b>=c
Logical or .or.
Logical equivalence .eqv.
Logical inequivalence .neqv.
[name:] do iter_var=first,last[,step]
executable statements
end do [name]
- Inside the do loop you can use the statement exit to stop the iteration (jump out of the loop) or cycle to stop the cur-
rent iteration and continue the next one.
- Examples:
- In F77 real iteration variables were allowed. This is no more the case in F90+.
- Naming the loops is helpful if you have many loops within each other and want e.g. jump out from the outermost one.
- It also makes the code more readable.
Introduction to Fortran
• Arrays
integer,dimension(10) :: k real(kind=rk),dimension(:),allocatable :: x
real,dimension(10,10) :: x real(kind=rk),dimension(:,:),allocatable :: y
real,dimension(100) :: x1 integer :: n,err
real(kind=rk),dimension(4,4,4) :: y ...
print *,’Give array size.’
Or more tersely read *,n
allocate(x(n),y(0:n,0:n),stat=err)
integer :: k(10) if (err/=0) then
real :: x(10,10),x1(100) print *,"Could not allocate."
real(kind=rk) :: y(4,4,4) stop
end if
...
x=1.0
y=2.0
...
deallocate(x,y)
1. equivalence(x,y)--> variables x and y can now be used interchangibly. In F77, however, this is a static definition. A good tool for making obfuscated
code.
Introduction to Fortran
• Reading and writing files
- Open a file: unit number identifies an open file (cf. C file pointer)
integer :: st
character(len=40) :: fname
real :: x
...
fname=’in.dat’
open(unit=10,file=fname,status=’old’,iostat=st) status=’old’ file should exist
if (st/=0) then status=’new’ file should not exist
print *,’Error in opening file.’ status=’replace’ if the files exists it
is deleted and a new
stop one is created
end if
- It is usual in open, close, read, and write statements to leave out the keywords unit and fmt
open(unit=10,file=fname) open(10,file=fname)
close(unit=10) close(10)
write(unit=10,fmt=*) write(10,*)
read(unit=10,fmt=’(a)’) read(10,’(a)’)
- The format string defined by keyword fmt determines in which form data is read in and printed out (cf. format string in
sprintf in C; see next slide)
- Probably the easiest way (in the beginning at least) is to use so called list-directed formatting; i.e. using ‘*’ as the for-
mat string.
- In this case the system decides what format to use based on what is being printed or read; e.g.
write(6,*) ‘Time step ‘,dt
read(5,*) x
- Predetermined units:
0 = stderr
5 = stdin
6 = stdout
- These units need not be explicitly opened.
- Units 5 and 6 can be replaced by ‘*’ in reading and writing, respectively.
- Output to stdout can also be done using the print statement:
print format_specifier,io_list
- E.g. print *,’X is now ‘,x
Introduction to Fortran
- The most important format specifiers:
Writing
Specifier Meaning
Reading
Specifier Meaning
- You can use these for detailed formatting of io but the easiest way is to use the list-directed io (fmt=*)
Tools for High Performance Computing 2013: 2. Introduction to Fortran 16
Introduction to Fortran
- A simple example of reading from stdin and writing to stdout:
program readtest
implicit none
real :: x
integer :: i,s
character(len=20) :: c
do
len_trim(c) is an intrinsic
print *,’Give x,i,c.’ function returning the length of the
read(*,*,iostat=s) x,i,c string without the trailing spaces
if (s/=0) exit
print *,2*x,10*i,len_trim(c)
end do
print *,’Bye!’
stop
end program readtest
Introduction to Fortran
• Procedures
- With intent(in), intent(out), intent(inout) you can specify whether the function or subroutine parameters
are only input, only output or both input and output parameters, respectively. For example:
x=2.0*x
y=2.0*y
return
end subroutine sub
- And call
call sub(x,y,n)
Introduction to Fortran
- An array of a character string as a parameter of a procedure can be of assumed length or shape.
- In this case the procedure interface has to be written out explicitly.
x=1.0
y=2.0
call sub(x,y)
print *,x
print *,y Personal opinion: The clearest way to pass arrays to subroutines is
to pass also the sizes; for example:
stop
end program assumedtest call sub(x,y,3)
...
subroutine sub(x,y)
implicit none subroutine sub(x,y,n)
real :: x(:),y(:,:) implicit none
print *,size(x),size(y) integer :: n
x=2.0*x real :: x(n),y(n,n)
y=3.0*y print *,size(x),size(y)
return x=2.0*x
end subroutine sub y=3.0*y
return
end subroutine sub
subroutine sub(x,y,n)
...
logical,save :: firsttime=.true.
...
if (firsttime) then
! Initialization
...
firsttime=.false.
endif
! Normal execution
...
- Same as static in C.
Introduction to Fortran
- Argument association may be positional (normal way) or by keywords:
program argassoc
implicit none
integer :: i,j
progs> gfortran argassoc.f90
i=1;j=2 progs> a.out
call sub(i,j) ! Positional 2 -2
write(0,*) i,j 2 -2
-2 2
i=1;j=2
call sub(arg1=i,arg2=j) ! By keyword
write(0,*) i,j
i=1;j=2
call sub(arg1=j,arg2=i) ! By keyword
write(0,*) i,j
stop
subroutine sub(arg1,arg2)
implicit none
integer,intent(inout) :: arg1,arg2
arg1=arg1*arg2
arg2=-arg1
return
end subroutine sub
module stuff
program moduleexample
implicit none use stuff
integer,parameter ::& implicit none
& rk=selected_real_kind(p=15,r=100) real(kind=rk) :: r
real(kind=rk) :: pi=3.14159265358979 call readr(r)
contains print *,"Radius : " , r
function area(r)
print *,"Circumference : " ,2.0*pi*r
real(kind=rk),intent(in) :: r
print *,"Area : " , area(r)
real(kind=rk) :: area end program moduleexample
area=pi*r**2
end function area
subroutine readr(r)
real(kind=rk),intent(out) :: r
print *,"Give r"
read *,r
end subroutine readr
end module stuff
- You can only use a part of the module by giving the only qualifier:
use stuff, only : rk
- The name of the object in the module can also be changed:
use stuff, only : rk => real_type
Introduction to Fortran
• Main differences between Fortran and C
Fortran C
- It is possible to use both Fortran and C in the same program but the Fortran-C interface is not (yet) standardized.
- Math functions
- Generic and specific names; e.g. sqrt(), dsqrt(), csqrt()
- Generic names: type of result depends on the argument:
stop
Underscore notation for giving the
end program genericfunctionname
kind parameter of a literal constant.
Introduction to Fortran
- What’s going on here?
program pi_accuracy
integer,parameter :: rk0=selected_real_kind(5,10)
integer,parameter :: rk1=selected_real_kind(10,40)
integer,parameter :: rk2=selected_real_kind(30,200)
real(rk2) :: pi0
real(rk2) :: pi1 progs> ifort pi_accuracy.f90
real(rk2) :: pi2 progs> ./a.out
3.14159274101257324218750000000000
pi0=4.0*atan2(1.0_rk0,1.0_rk0)
3.14159265358979311599796346854419
pi1=4.0*atan2(1.0_rk1,1.0_rk1)
pi2=4.0*atan2(1.0_rk2,1.0_rk2) 3.14159265358979323846264338327950
print *,pi0
print *,pi1
print *,pi2
stop
end program pi_accuracy
CEILING(a[,kind]) E The smallest integer greater than or equal to the argument value
CHAR(i[,kind]) E The character in the specified position of the processor character set
CONJG(z) E The conjugate of a complex number
COS(x) E The cosine of the argument, which is in radians
COSH(x) E The hyperbolic cosine of the argument
COUNT(mask[,dim][,kind]) T The number of .TRUE. elements in the argument array
CSHIFT(array,shift[,dim]) T An array that has the elements of the argument array circularly shifted
DBLE(a) E The corresponding double precision value of the argument integer argu-
ment
DIGITS(x) I The number of significant digits in the model for the argument
DIM(x,y) E The positive difference between the two arguments
DOT_PRODUCT(vector_a,vector_b) T The dot product of two rank-one arrays(also called a vector multiply func-
tion)
EOSHIFT(array,shift[,boundary][,dim]) T An array that has the elements of the argument array end-off shifted
EPSILON(x) I The number that is almost negligible when compared to one
EXP(x) E The exponential ex for the argument x
EXPONENT(x) E The value of the exponent part of a real argument
FLOOR(a[,kind]) E The largest integer less than or equal to the argument value
FRACTION(x) E The fractional part of a real argument
HUGE(x) I The largest number in the model for the argument
IACHAR(c) E The position of the specified character in the ASCII character set
IAND(i,j) E The logical AND of the two arguments
IBCLR(i,pos) E The specified position of argument I cleared(set to zero)
- Below is a list of the standard intrinsic subroutines (from Intel Fortran compiler Language Reference Manual, /opt/intel_fc_80/doc/for_lang.pdf):
Introduction to Fortran
- Functions for array handling (one of the greatest features of F90+):
program anyexample
implicit none progs> ifort anyexample.f90
integer :: i,j,a(10) progs> ./a.out
do i=1,10 1 2 3 4 5 6 7 8 9 10
a(i)=i yes
end do
print '(10(i0,x))',a
if (any(a(5:10)>9)) print '(a)','yes'
if (all(a(5:10)>9)) print '(a)','yes'
print '(10l1)',a(5:10)>9
stop
end program anyexample
stop
end program dotproductexample
stop
end program matmulexample
Introduction to Fortran
- Examples of string handling functions:
stop
end program stringhandling
program cputime
implicit none
integer,parameter ::&
& rk=selected_real_kind(10,40),NMAX=100000000
real(kind=rk) :: x,t1,t2
integer :: n progs> ifort cputime.f90
progs> a.out
x=0.0 Result 18.9978964138534
call cpu_time(t1) CPU time in seconds 1.63975200000000
do n=NMAX,1,-1
x=x+1.0_rk/real(n,rk)
end do
call cpu_time(t2)
print *,’Result ’,x
print *,’CPU time in seconds ’,t2-t1
stop
end program cputime
Introduction to Fortran
• F90+ has two constructs that helps the handling of arrays.
- With the where construct you can modify arrays without using explicit do-loops:
program whereexample
implicit none
integer,parameter ::&
& rk=selected_real_kind(10,40),i1=1,i2=10
real(kind=rk),dimension(i1:i2) :: x,y
integer :: n
do n=i1,i2
x(n)=n-i2/2
end do mask expression
where (x<0.0)
y=-10.0
elsewhere
y=0.0
end where progs> ifort whereexample.f90
print ’(10f6.1)’,x progs> ./a.out
print ’(10f6.1)’,y -4.0 -3.0 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 5.0
-10.0 -10.0 -10.0 -10.0 0.0 0.0 0.0 0.0 0.0 0.0
stop
end program whereexample
program whereexample1
implicit none
integer,parameter :: &
& rk=selected_real_kind(10,40),i1=1,i2=10
real(kind=rk),dimension(i1:i2) :: x
logical :: mask(i1:i2)
integer :: n
x=1.0
mask=.false.
mask(i1:i2:2)=.true.
where (mask)
x=-1.0
end where
progs> ifort whereexample1.f90
print ’(50l6)’,mask progs> ./a.out
print ’(50f6.1)’,x T F T F T F T F T F
-1.0 1.0 -1.0 1.0 -1.0 1.0 -1.0 1.0 -1.0 1.0
stop
end program whereexample1
Introduction to Fortran
- Fortran95 added the forall construct to the language.
- In a way it is a do-loop or an array construct where the order of iteration does not matter; i.e. it can be parallellized:
program forallexample
implicit none progs> ifort forallexample.f90
integer,parameter :: & progs> a.out
& rk=selected_real_kind(10,40) 0 0 0 0 0 0 0 0 0 0
integer :: a(10,10) 0 0 0 0 0 0 0 0 0 0
integer :: i,j 0 0 0 0 0 0 0 0 6 0
0 0 0 0 0 0 0 0 0 0
a=0 0 0 0 0 0 0 6 0 7 0
forall (i=1:10:2,j=1:10:2,i+j>10) 0 0 0 0 0 0 0 0 0 0
a(i,j)=(i+j)/2 0 0 0 0 6 0 7 0 8 0
end forall 0 0 0 0 0 0 0 0 0 0
0 0 6 0 7 0 8 0 9 0
print ’(10i4)’,a 0 0 0 0 0 0 0 0 0 0
stop
end program forallexample