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