对于Fortran90/95而言,fortran子程序包括:function,external function and subroutine. function,就是严格意义上的fortran内部函数(sum, sqrt, sin, etc),在主函数及其他子程序中直接调用。

! sqrt就是一个常见内部函数
a = sqrt(b^2+c^2)

以下主要介绍自定义函数和子程序及其传递的函数变量,自定义函数本质上就是数学上的函数,一般要传递自变量给自定义函数,返回函数值。子程序不一定是这样,可以没有返值,最重要的是子程序的输入输出都在形参列表中。

传递参数

(1)传递参数可以是常量,但只有跟函数定义的参数类型对应才会到想要的结果。如call fx(1.0)就必须用1.0而不是1。

(2)传递数组参数,在声明时可以用变量赋值它的大小,也可以不指定大小(但是不建议如此,因为编译器不能判断数据的赋值空间会降低编译效率)。

subroutine fx(num,size)
implicit none
integer :: size
integer, dimension(:) :: num(size)
……
return
end sobroutine fx

subroutine

子程序使用比较常见,就是把一段常用代码独立出来方便重复调用。子程序可以传递参数,也可以不传递参数(形参列表就空着),可以返回参数,也可以不返回参数。

subroutine name (parameter1, parameter2)  
implicit none       
integer, intent(in)  :: parameter1
integer, intent(out) :: parameter2   
 ……                               
return
end subroutine name

子程序可以直接调用,不管是主函数还是其他子代码,只需要 call subroutine_name(para1,para2)。这里所谓直接调用就是为了强调其与自定义函数不同,不需要在主函数中声明。

external function

前面已经说,相对于子程序而言,自定义函数一般需要返回值,返回形参也就是函数名,所以在函数本身内部需要定义返回值类型,或者直接在函数名前添加,或者在形参后添加result形参,如:

! 函数内部定义返回值类型
function besselj(a,b)
implicit none
integer, intent(in) :: a, b
real*8 :: besselj
...
besselj = ....
return
end function besselj
! 函数名前添加函数类型
real*8 function besselj(a,b)
implicit none
integer, intent(in) :: a, b
...
besselj = ....
return
end function besselj
!函数名后添加result形参
function besselj(a,b) result(c)
implicit none
integer, intent(in) :: a, b
real*8 :: c
...
c = ....
return
end function besselj

因此,在主程序和子代码中都调用自定义函数都需要定义函数类型real*8, external :: besselj。除非在模块中定义了自定义函数,则其调用不需要提前声明其函数类型。

程序接口

interface,就是function、subroutine及其相关变量的声明。以下情况必需使用接口:

  • 函数返回值为数组
  • 指定参数位置来传递参数
  • 调用参数个数不固定(optional
  • 输入指针参数
  • 函数返回值为指针

其使用也相对简单,可以放在主程序声明部分,也可以放在module中。

interface
      subroutine fx( a,b,c )
         integer, intent(in) :: a
         real(4), intent(out) :: c
         integer, optional    :: c
      end subroutine fx   
end interface

模块

Module不是函数,它用于封装子代码模块,一般是把具有相关功能的函数及变量封装在一起。

  • moudle中定义的变量在moudule内部的函数可以直接使用
  • moudle中定义的全局变量,在主程序仲可以直接使用
  • module中函数必需写在contains命令之后,函数(包括,自定义函数)之间直接调用
  • moudle中可以使用include插入其他文件(moudule, subroutine, etc)

主程序或者子代码中调用时,需要在声明之前添加use module_name