Computational Biomechanics

Dr. Kewei Li

Functions and Subroutines

As we have discussed about the Fortran functions and subroutines, here is an example in which a Fortran subroutine’s name is passed to another subroutine as an argument.

program main
  ! testing the interface block 
  implicit none
  interface
    subroutine sub1(a,b,y)
      real, intent(in)     :: a, b
      real, intent(inout)  :: y
    end subroutine sub1
  end interface
  real ::  n=1.0, m=2.0, k
  call sub2(n, m, sub1, k)     
  print *, k
end program main
! A simple subroutine for a specific task  
subroutine sub1(a,b,y)
  implicit none
  real, intent(in)      :: a, b
  real, intent(inout)   :: y
  y = a + b
end subroutine sub1
! A subroutine to call the simple subroutine
subroutine sub2(n, m, subfun, k)
  implicit none
  external subfun 
  real, intent(in)    :: n, m
  real, intent(out)   :: k
  real :: z
  call subfun(n,m,z)
  k = z*2.0
end subroutine sub2

As you can see, in this example, the subroutine sub1 is called by sub2 as an argument in the main program. We need to add sub1 to the interface block of the main program in order to pass it to sub2. Another method to deal with this kind of problem is to use the external statement, for example, you can use the following statement to replace the interface block in the example above,

external sub1

With the Intel Fortran compiler 2019, both will be able to handle this kind of problem. According to the documentation of the Intel Fortran compiler,

If you want to describe a routine with greater detail, use the INTERFACE statement. It automatically declares a routine as EXTERNAL, and provides information on result types and argument types.

Thus, the interface block provides more details to the man program than the external statement.

Similarly, we can pass a name of a function to another subroutine,

program main
  ! testing the interface block 
  implicit none
  interface
    real function fun1(a,b)
      real, intent(in)      :: a, b
    end function fun1
  end interface
  real ::  n=1.0, m=2.0, k
  call sub2(n, m, fun1, k)    
  print *, k
end program main
! A simple function 
real function fun1(a,b)
  real, intent(in)      :: a, b
  fun1 = a + b
end function fun1
! A subroutine to call the funciton  
subroutine sub2(n, m, extfun, k)
  real, intent(in)    :: n, m
  real, intent(out)   :: k
  real :: extfun
  k = extfun(n,m)*2.0
end subroutine sub2

Again, you can use the external attribute to replace the interface block in the main problem,

real, external :: fun1 
Go Back