Fortran 如何在子例程/函数中传递函数名

Fortran 如何在子例程/函数中传递函数名,fortran,Fortran,我的问题是将模块中包含的一系列函数的名称传递给do循环中的子例程 我发布了部分代码。与主模块相比,模块位于两个单独的文件中 %%%文件testKer_mod.f90 module kernel implicit none contains ! POLYNOMIAL function poly(x, ts, ndim, a, param1, param2) integer, intent (in) :: ndim real*8, dimension(ndim

我的问题是将模块中包含的一系列函数的名称传递给do循环中的子例程

我发布了部分代码。与主模块相比,模块位于两个单独的文件中

%%%文件testKer_mod.f90

module kernel
  implicit none
  contains

  ! POLYNOMIAL 
  function poly(x, ts, ndim, a, param1, param2)
     integer, intent (in) :: ndim
     real*8, dimension(ndim), intent(in) :: x
     real*8, dimension(ndim), intent(in) :: ts
     real*8, intent(in) :: a, param1, param2
     real*8 :: r
     real*8 :: poly 

     r = (x(1:ndim) - ts(1:ndim))

     poly = r**(.5*a)

   end function poly

   ! GAUSSIAN
   function gauss(x, ts, ndim, a, gamma, param2)
      integer, intent (in) :: ndim 
      real*8, dimension(ndim), intent(in) :: x
      real*8, dimension(ndim), intent(in) :: ts
      real*8, intent(in) :: a, param2, gamma
      real*8 :: r
      real*8 :: gauss

      r = (x(1:ndim) - ts(1:ndim))

     gauss = exp(-(gamma*r)**a)

  end function gauss

end module kernel
%%%

%%%文件testSRBF_mod.f90

  module srbf
    implicit none
    contains    

  subroutine weigth(nx, x, nts, ts, ndim, s, kernel, StocPar, param, coe, mat)
    integer :: i,j,k,l,m,n
    integer :: info
    integer :: nx, nts, ndim
    integer, dimension(nts) :: ipiv 
    real*8, dimension(nts) :: w
    real*8, dimension(nts) :: s
    real*8, dimension(2) :: param
    real*8, dimension(nx,ndim) :: x
    real*8, dimension(nts,ndim) :: ts
    real*8, dimension(nx,nts) :: phi, mat
    real*8, dimension(nts) :: coe
    real*8 :: stocPar

    interface
     real*8 function kernel(x1, x2, n3, stov, p1, p2)
       integer, intent (in) :: n3
       real*8, dimension(n3), intent(in) :: x1
       real*8, dimension(n3), intent(in) :: x2
       real*8, intent(in) :: stov, p1, p2
     end function kernel
    end interface

    do i = 1, nx
      do j = 1, nts
          phi(i,j) = kernel(x(i,1:ndim), ts(j,1:ndim), ndim, stocPar, param(1), param(2))
      end do
    end do

    w = s       
    mat = phi   
    call DGESV(nts,1,mat,nts,ipiv,w,nts,info) 
    coe = w
  end subroutine weigth 
end module srbf
%%%

%%%主程序测试。f90
程序MKRBF

   use kernel
   use srbf

   implicit none

   !real*8 :: SelKer
   integer :: i,j,k
   integer, parameter :: n = 3
   integer, parameter :: nKer = 2
   real*8, dimension(2,2) :: ParBound, auxpar
   real*8, dimension(2) :: Bound
   real*8, dimension(n) :: Var, func
   real*8, dimension(n,nKer) :: coe
   real*8, dimension(n,n) :: mat

   !external SelKer

   interface
     real*8 function SelKer(ind)
       integer, intent (in) :: ind
     end function SelKer
   end interface

   Bound(1) = 0
   Bound(2) = 5

   ParBound(1,1) = 1 
   ParBound(1,2) = 5
   ParBound(2,1) = 1 
   ParBound(2,2) = 5

   auxpar(1,1) = 0 
   auxpar(1,2) = 0
   auxpar(2,1) = 1 
   auxpar(2,2) = 1

   var(:) = (/ 0., 2.5, 5. /)

   do i = 1, n
       func(i) = cos(3*Var(i)) * exp(-.25*Var(i));
   end do

   do i = 1, nKer
       call weigth(n,Var,n,Var,1,func,SelKer(i),2.0D0,auxpar,coe,mat)
   end do
end program MKRBF

function SelKer(indx)
  integer, intent(in) :: indx
  real*8 :: SelKer

  select case (indx)
  case (1)
    SelKer = poly
  case (2)
    SelKer = gauss
  end select
  return
end function SelKer
%%%

我尝试了界面和外部,但程序给出了相同的错误:

gfortran testKer_mod.f90 testSRBF_mod.f90 test.f90 -llapack -o test
test.f90:46:38:

    call weigth(n,Var,n,Var,1,func,SelKer(i),2.0D0,auxpar,coe,mat)
                                  1
 Error: Expected a procedure for argument 'kernel' at (1)

如何修复它?

查看主程序中的接口块

interface
  real*8 function SelKer(ind)
    integer, intent (in) :: ind
  end function SelKer
end interface
SelKer
是一个具有
real*8
结果的函数。1
SelKer(i)
就是这样一个函数结果。关键的是,
SelKer(i)
不是一个具有
real*8
结果的函数,而是这样一个
real*8
weigth
希望
kernel
的参数是一个函数(这是一个过程)。这是错误消息

谈到如何实现外部函数
SelKer
:我们看到

SelKer = poly
函数
poly
中的函数不是模块内核中的函数
poly
,而是一个本地(默认)实标量变量(具有未定义的值)。请注意函数中缺少

相反,您希望使用过程指针。这是一个广泛的话题,所以我将仅给出一个方法的指示

  • SelKer
    移动到模块
    内核
    中的过程中(从主程序中删除相应的接口块)
  • 将函数结果
    SelKer
    声明为具有类型
    procedure(poly)
  • 对结果使用指针赋值,如
    SelKer=>gauss
  • 还有其他可能更好的方法来构建这样一个计划。特别是,许多人建议不要使用过程指针函数结果



    1
    real*8
    不是标准Fortran。

    查看主程序中的接口块

    interface
      real*8 function SelKer(ind)
        integer, intent (in) :: ind
      end function SelKer
    end interface
    
    SelKer
    是一个具有
    real*8
    结果的函数。1
    SelKer(i)
    就是这样一个函数结果。关键的是,
    SelKer(i)
    不是一个具有
    real*8
    结果的函数,而是这样一个
    real*8
    weigth
    希望
    kernel
    的参数是一个函数(这是一个过程)。这是错误消息

    谈到如何实现外部函数
    SelKer
    :我们看到

    SelKer = poly
    
    函数
    poly
    中的函数不是模块内核中的函数
    poly
    ,而是一个本地(默认)实标量变量(具有未定义的值)。请注意函数中缺少

    相反,您希望使用过程指针。这是一个广泛的话题,所以我将仅给出一个方法的指示

  • SelKer
    移动到模块
    内核
    中的过程中(从主程序中删除相应的接口块)
  • 将函数结果
    SelKer
    声明为具有类型
    procedure(poly)
  • 对结果使用指针赋值,如
    SelKer=>gauss
  • 还有其他可能更好的方法来构建这样一个计划。特别是,许多人建议不要使用过程指针函数结果



    1
    real*8
    不是标准Fortran。

    感谢您的及时回复,但我不知道如何使用过程指针。你能为我的案例提供一个循序渐进的指导方针吗?在我有机会写一个更完整的提纲之前,我看到你问了另一个问题。我将保留这个答案,因为这通常是一个更好的学习方式,从别处寻找并尝试一些东西。然而,即使是急于解决问题,我也没有找到解决办法,因此我打开了一个新的帖子。无论如何,谢谢你给我的答案,因为通过这种方式,我理解了问题所在,然后更好地阐述了问题。谢谢你的及时回复,但我不知道如何使用过程指针。你能为我的案例提供一个循序渐进的指导方针吗?在我有机会写一个更完整的提纲之前,我看到你问了另一个问题。我将保留这个答案,因为这通常是一个更好的学习方式,从别处寻找并尝试一些东西。然而,即使是急于解决问题,我也没有找到解决办法,因此我打开了一个新的帖子。谢谢你给我的答案,因为通过这种方式,我理解了问题所在,然后更好地阐述了问题。