Functions and Subroutines

Optional Arguments

•     some dummy arguments of subprograms can be declared to be optional

•     allows using default values for arguments

subroutine swap(x, y, condition)

integer, intent(inout) :: x,y

integer, intent(in), optional :: condition

integer :: temp

! condition = 1 performs a swap only if x < y

! condition = 2 performs a swap only if x > y

! if condition is not specified always perform a swap

Optional Arguments

if present(condition) then

if ( (condition == 1) .and. (x < y)) then

temp = x; x = y ;  y = temp

elseif ((condition == 2) .and. (x > y)) then

temp = x; x = y ;  y = temp

endif

else

temp = x; x = y ;  y = temp

endif

end subroutine swap

Using Optional Arguments

•     compulsory arguments should come before optional arguments

•     if some optional arguments are missing, keyword arguments used in calling program

•     keywords specify the dummy arguments which are to be assigned values

•     keywords are names of dummy arguments and allow changing order of arguments

•     keywords must be used for optional arguments

Keyword Arguments

•     arguments specified by naming the dummy argument and assigning an expression to it

call swap(x,y,1)

call swap(x,y)

call swap(condition = 2, x = x, y = y)

•     if a keyword argument is used, all later arguments must be keyword arguments

•     initial arguments correspond by position

•     keywords override positional correspondence

Array Arguments

•     whole array can be an argument for a subprogram

•     corresponding dummy argument must be an array of the same rank

•     shape of dummy argument is not declared

•     assumed to be same as that of corresponding actual argument

•     may be different for different calls

•     intrinsic functions used to determine shape

Array Arguments

subroutine inverse(a,b)

integer, intent(in), dimension(:,:) :: a

integer, intent(out), dimension(:,:) :: b

! declares a and b to be rank 2 arrays

! actual shape of a and b will depend on actual argument

integer, dimension(size(a,dim=1), size(a,dim=2)) :: c

! c is a local variable

! shape of local arrays must be declared

! it can depend on the shape of actual arguments

! c is also called an automatic array

Array Arguments

function sort(a)  result(b)

integer, intent(in), dimension(:) :: a

integer, dimension(size(a)) :: b

integer :: i, j

do i = 1, n

j = count(b(1:i-1) <= a(i))

b(j+2:i) = b(j+1:i-1)

b(j+1) = a(i)

end do

end function sort

 

 

Allocatable Arrays

•     allocatable arrays must be allocated before being passed to a subprogram

•     allocatable arrays used in subprograms must be deallocated in the subprogram

•     “memory leak” can occur

–   each execution of subprogram creates a new copy of the array which becomes inaccessible after it terminates

•     use automatic arrays instead

External Subprograms

•     subprograms not contained in any program

•     such subprograms can be compiled separately

•     can be used ( “called”) by any program

•     same structure as internal subprograms, except that they may contain other internal subprograms

•     allows sharing of code between programs

•     old style of Fortran programming

–   not recommended for Fortran 90

–   alternatives available ( modules, see later)

External Subprograms

subroutine swap(x,y)

implicit none

! required here as not contained in any program

real, intent(inout) :: x, y

real :: temp

temp = x

x = y

y = temp

end subroutine swap

! only variables declared in subprogram and arguments

! can be used

Using External Subprograms

•     similar to internal subprograms

•     call statement used for subroutines and function names for functions

•     arguments and declarations of external subprograms not known in calling program

•     an explicit interface to external subprograms must be provided

•     all declarations of arguments in subprogram must be included in calling program

Calling External Subprograms

program test_call

implicit none

real :: x, y

interface

subroutine swap(x,y)

real, intent(inout) :: x, y

end subroutine swap

end interface

read *, x, y

if (x < y) then call swap(x,y)

print *, x, y

end program test_call

Interface Statement

•     all definitions of subprograms used in a (sub)program contained in interface block

•     comes after all declarations of variables

•     contains first line of each subprogram used and declarations of all dummy arguments

interface

subroutine a(list_of_dummy arguments of a)

! declarations of dummy arguments in subroutine a

end subroutine a

function b(list_of_dummy arguments of b)

! declarations of arguments of b

end function b

end interface

 

Using External Subprograms

•     file containing several external subprograms may be compiled separately

•     -c option should be used when compiling

•     subprograms cannot be executed by themselves, must be called by a program

•     produces “object code” ( .o files)

•     use this file when compiling a program using any of these subprograms

•     executable code is produced (called linking)

 

Libraries

•     a precompiled collection of external subprograms can be built, can be used whenever required

•     library of subprograms

•     many commercial libraries available especially for numerical computation

•     source code is not available

•     cannot make modifications

•     build your own library

•     interface to subprograms must be known

General Integration Program

•     trapezoidal rule can be applied to integrate any function

•     function to be integrated is “external”

•     main program can be compiled (with –c option) without  the function to be integrated

•     produces a .o file

•     compile the external function with this

•     program needs to be compiled only once

General Integration Program

program integrate

implicit none

real :: a, b, h, integral

integer :: n, i

interface

function f(x)

real, intent(in) :: x

real :: f

end function f

end interface

print *, “enter endpoints and number of intervals”

read *, a, b, n

h = (b-a)/real(n)

integral = (f(a)+f(b))/2.0

! uses external function f

do i = 1, n-1

integral = integral + f(a+i*h)

end do

integral = integral*h

print *, “integral is”, integral

end program integrate

Function Arguments

•     names of functions can be arguments

•     general subprogram for integration

•     name of function to be integrated can be passed as a parameter

•     same subprogram used for integrating many different functions

•     name of function specified when subprogram is called

•     name is not a character string

Example

subroutine trapezoid(f,a,b,n,integral)

implicit none

real, intent(in) :: a, b

real, intent(out) :: integral

real, external :: f  ! declares f  an external real function

integer, intent(in)  :: n

real :: h

integer :: i

h = (b-a)/real(n)

integral = (f(a)+f(b))/2.0

do i = 1, n-1

integral = integral + f(a+i*h)

end do

integral = integral * h

end subroutine  trapezoid

 

program integrate

implicit none

real :: a, b, integral

integer :: n

real, external :: func1, func2, func3, func4

character(len=5) :: name

interface

    subroutine trapezoid(f,a,b,n,integral)

    real, intent(in) :: a,b

    integer, intent(in) :: n

    real, intent(out) :: integral

    real, external :: f

    end subroutine trapezoid

end interface

print *, "enter function to be integrated"

read *, name

print *, "give end points of interval"

read *, a, b

print *, "enter number of intervals"

read *, n

select case(name)

case("f1")

call trapezoid(func1,a,b,n,integral)

case("f2")

call trapezoid(func2,a,b,n,integral)

case("f3")

call trapezoid(func3,a,b,n,integral)

case("f4“)

call trapezoid(func4,a,b,n,integral)

case default

print *, "unknown function“

stop

end select

print *, "integral is", integral

end program integrate

 

function func1(x)

implicit none

real, intent(in) :: x

real :: func1

func1 = x*sin(x)

end function func1

 

function func2(x)

! statements in function func2

end function func2

Compilation

•     all subprograms maybe in separate files

•     f90 –c integrate.f90  trapezoid.f90

•     will produce files integrate.o and trapezoid.o

•     f90 –c func1.f90 func2.f90 func3.f90 func4.f90

•     link all files together to form executable code

•     f90 integrate.o trapezoid.o func1.o func2.o ….

•     all required functions must be available before executable code can be generated