Introduction to coding in Fotran Fortran subprograms Function

Introduction to coding in Fotran
Session 02
Arnau Valladares-Esteban
Universitat Autònoma de Barcelona
Bellaterra, July 22nd 2014
Fortran subprograms
�
�
�
As we discussed yesterday, one of the most powerful ideas
in computer programming is dividing complex task into
simpler pieces
To do so, often, it is useful to divide our program into
subprograms
In Fortran, there are two types of subprograms:
�
�
Functions: read multiple inputs from the outside world
and return one output
Subroutines: read multiple inputs from the outside world
and return no output, one output, or multiple output
Function: Linear grid
�
�
�
Let’s create our first function
We will modify our program for generating linear grids
Now the program will:
�
�
�
�
Read from the keyboard the parameters for our grid: first
value, last value, and number of grid points
Call a function named linspace that computes grid points
Show the grid points in the screen
You can download it here: f_linspace.f90
Function: Linear grid
program f _ l i n s p a c e
i m p l i c i t none ! A l l v a r i a b l e t y p e s w i l l be d e c l a r e d
! Declare v a r i a b l e types
integer :: n
r e a l : : x_first , x_last
real , dimension ( : ) , a l l o c a t a b l e : : output
! Read i n p u t f r o m t h e k e y b o a r d
p r i n t ∗ , " I n t r o d u c e number o f g r i d p o i n t s ( i n t e g e r ) "
read (∗ ,∗) n
a l l o c a t e ( output (n) )
p r i n t ∗ , " Introduce f i r s t point of the g r i d ( r e a l )"
read (∗ ,∗) x _ f i r s t
p r i n t ∗ , " Introduce l a s t point of the g r i d ( r e a l ) "
read (∗ ,∗) x_last
! Call function linspace
output = l i n s p a c e ( x _ f i r s t , x_last , n )
! Print output in the screen
p r i n t ∗ , " Your g r i d i s : "
p r i n t ∗ , output
! Define function
contains ! Contains functions
f u n c t i o n l i n s p a c e ( x_1 , x_n , n ) ! D e f i n e f u n c t i o n
integer :: n, i
r e a l : : x_1 , x_n , l i n s p a c e ( n )
do i = 1 , n ! Loop f r o m i =1 t o i n d=n
l i n s p a c e ( i ) = x_1 + ( ( ( x_n − x_1 ) ∗ ( r e a l ( i −1) ) ) / (
r e a l ( n−1) ) )
en dd o ! c l o s e l o o p
end f u n c t i o n l i n s p a c e
end p r o g r a m f _ l i n s p a c e
Function: Linear grid
Exercise: Exponential utility function
�
�
�
�
�
Write a program that, for any level of consumption (c),
returns the level of utility given by a exponential utility
function
Remember:
1 − e −σc
u (c) =
σ
The risk aversion parameter (σ) must be different than
zero
Use a Fortran function to compute utility
Show the resulting utility (u) on the screen
Exercise: Exponential utility function
Subroutine: find the maximum
�
�
�
Let’s create our first subroutine
We will modify our program for finding the maximum
among random numbers
Now the program will:
�
�
�
�
�
�
Read from the keyboard how many random numbers
between 0 and 1 we want to generate
Create a vector with these numbers
Call the subroutine that finds the maximum and its
position in the vector
Display on screen the results
On top of that, our main program and subroutine will be
in two different .f90 files!
You can download the main program here:
max_rndnum_sub.f90 and the subroutine here:
sub_max.f90
Subroutine: find the maximum
s u b r o u t i n e sub_max ( v e c t o r , n , max , p o s )
i m p l i c i t none
! Declare input / output v a r i a b l e s
integer , intent ( in ) : : n
real , i n t e n t ( in ) , dimension (n) : : vector
i n t e g e r , i n t e n t ( out ) : : pos
r e a l , i n t e n t ( o u t ) : : max
! Declare i n t e r n a l v a r i a b l e s
integer : : ind
! F i n d maximum
max = −1.0
pos = 0
do i n d = 1 , n
i f ( v e c t o r ( i n d ) >= max ) t h e n
max = v e c t o r ( i n d )
pos = i n d
endif
enddo
end s u b r o u t i n e
Subroutine: find the maximum
program max_rndnum_sub
i m p l i c i t none
! Declare v a r i a b l e s
i n t e g e r : : n , res_pos ! s i z e of the v e c t o r
r e a l : : res_max
real , dimension ( : ) , a l l o c a t a b l e : : vector
! Read v e c t o r s i z e
p r i n t ∗ , "How many random numbers ( 0 , 1 ] do you want
to generate ?"
read (∗ ,∗) n
allocate ( vector (n) )
! C a l l random_number
c a l l random_number ( v e c t o r )
! C a l l sub_max
c a l l sub_max ( v e c t o r , n , res_max , r e s _ p o s )
! Display r e s u l t s in the screen
p r i n t ∗ , "Maximum number , i n p o s i t i o n " , r e s _ p o s , " ,
is :"
p r i n t ’ ( f 1 0 . 4 ) ’ , res_max
end program max_rndnum_sub
Subroutine: find the maximum
�
To compile two files into the same executable we just use
the following commands:
gfortran -o name_exe name_file01 . f90 name_file02 . f90
Exercise: Subroutine reads data from .txt
�
�
�
�
Imagine that you are trying to calibrate a labor market
model about the most interesting group of people in the
population: single females
You have a .txt file that contains data on labor market
stocks and transitions
Write a program that reads and stores the data using a
subroutine
Your program should also display the following labor
market statistics on the screen:
U/pop
U/pop+E /pop
�
Unemployment rate:
�
Average unemployment duration:
1
Pr(E |U)
(DMP world)
Exercise: Subroutine reads data from .txt
�
Average monthly CPS data from 2000 to 2005:
77.16
18.29
96.84
1.24
1.92
24.17
54.79
21.04
7.10
4.68
88.22
�
!
!
!
!
!
!
!
!
!
!
!
Single
Single
Single
Single
Single
Single
Single
Single
Single
Single
Single
Women
Women
Women
Women
Women
Women
Women
Women
Women
Women
Women
E / pop
O / pop
E-E
E-U
E-O
U-E
U-U
U-O
O-E
O-U
O-O
You can download the .txt file from here: data.txt
Exercise: Subroutine reads data from .txt
Modules
�
�
�
�
�
�
Some times we need variables and functions to be used in
different programs or subroutines
To do so we can use modules
A module conveniently packages collections of variable
declarations and subprograms so that they may be
imported into other programs
A module does not contains statements to be executed as
in a program
A module can only contain variable declarations and
functions to be used by other modules and programs
A module cannot exist alone; it must be used with other
modules and a main program
A module with all our functions
�
�
�
�
We will create a module that will contain all the functions
we created
We will call it math utils module
It contain valuable tasks that we will need to use in our
future programs
You can download the main program here:
using_modules.f90 and the module here: mathutils.f90
A module with all our functions
m od ul e m a t h u t i l s
i m p l i c i t none
contains
! Linspace
f u n c t i o n l i n s p a c e ( x_1 , x_n , n )
integer :: n, i
r e a l : : x_1 , x_n , l i n s p a c e ( n )
do i = 1 , n ! Loop f r o m i =1 t o i n d=n
l i n s p a c e ( i ) = x_1 + ( ( ( x_n − x_1 ) ∗ ( r e a l ( i −1) ) ) / (
r e a l ( n−1) ) )
en dd o ! c l o s e l o o p
end f u n c t i o n l i n s p a c e
! Exponential u t i l i t y
f u n c t i o n exp_ut ( c , s i g m a )
r e a l : : exp_ut , c , s i g m a
exp_ut = 1 − ( ( e x p (−( s i g m a ∗ c ) ) ) / s i g m a )
end f u n c t i o n exp_ut
! CRRA u t i l i t y
f u n c t i o n crra_ut ( c , sigma )
r e a l : : crra_ut , c , sigma
i f ( s i g m a == 1 . 0 ) t h e n
crra_ut = log ( c )
else
c r r a _ u t = ( c ∗∗(1.0 − s i g m a ) ) /(1.0 − s i g m a )
endif
end f u n c t i o n c r r a _ u t
end m od ul e m a t h u t i l s
A module with all our functions
program using_modules
use m a t h u t i l s
i m p l i c i t none
! Declear v a r i a b l e s
r e a l : : c , sigma , u ! D e c l a r e v a r i a b l e s t y p e s
real , dimension (10) : : useless_grid
! Read c and s i g m a f r o m k e y b o a r d
p r i n t ∗ , " I n t r o d u c e l e v e l o f c o n s u m p t i o n ( >0) "
read (∗ ,∗) c
i f ( c <=0.0 ) t h e n ! Check c i s p o s i t i v e
p r i n t ∗ , "ERROR ! c o n s u m p t i o n must be p o s i t i v e ! "
read (∗ ,∗) c
endif
p r i n t ∗ , " I n t r o d u c e r i s k a v e r s i o n p a r a m e t e r ( >0) "
read (∗ ,∗) sigma
i f ( s i g m a <=0.0 ) t h e n ! Check s i g m a i s p o s i t i v e
p r i n t ∗ , "ERROR ! r i s k a v e r s i o n p a r a m e t e r must be
positive !"
read (∗ ,∗) sigma
endif
! Compute CRRA u t i l i t y
u = crra_ut ( c , sigma )
p r i n t ∗ , " L e v e l o f CRRA u t i l i t y f o r c =" , c , " and s i g m a =" ,
sigma , " i s : " , u
! Compute E x p o n e n t i a l u t i l i t y
u = exp_ut ( c , s i g m a )
p r i n t ∗ , " L e v e l o f E x p o n e n t i a l u t i l i t y f o r c =" , c , " and s i g m a =
" , sigma , " i s : " , u
! Create a ( not v e r y u s e f u l ) g r i d
u s e l e s s _ g r i d = l i n s p a c e ( sigma , c , 10)
p r i n t ∗ , " Your u s e l e s s g r i d i s : "
p r i n t ’ ( f10 .4) ’ , useless_grid
end p r o g r a m u s i n g _ m o d u l e s
A module with all our functions