Fortran 通过子程序将一组变量值传递给没有公共块的函数的方法有哪些?

Fortran 通过子程序将一组变量值传递给没有公共块的函数的方法有哪些?,fortran,fortran90,fortran77,Fortran,Fortran90,Fortran77,我不想在我的程序中使用公共块。我的主程序调用一个调用函数的子程序。该函数需要来自子例程的变量 将信息集从子程序传递到函数的方法有哪些 program ... call CONDAT(i,j) end program SUBROUTINE CONDAT(i,j) common /contact/ iab11,iab22,xx2,yy2,zz2 common /ellip/ b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2 call function

我不想在我的程序中使用公共块。我的主程序调用一个调用函数的子程序。该函数需要来自子例程的变量

将信息集从子程序传递到函数的方法有哪些

program
...

call CONDAT(i,j)

end program

SUBROUTINE CONDAT(i,j)

common /contact/ iab11,iab22,xx2,yy2,zz2
common /ellip/ b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2
call function f(x)
RETURN
END

function f(x)
common /contact/ iab11,iab22,xx2,yy2,zz2
common /ellip/ b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2
end

下面是一个如何实现这一目标的示例

该代码已从BFGS方法改编,以显示如何在模块内传递函数和调用其他函数

我在这里使用:

  • 嵌套在其他子例程中的私有函数
  • 将变量从子例程传递到嵌套函数
  • 将函数作为可在模块块外部定义的函数的参数传递
希望这将涵盖你的一切

Module Mod_Example

Private :: private_func

   SUBROUTINE test_routine(res,start,fin,vector,func,dfunc)
      IMPLICIT NONE
      REAL, DIMENSION(:), INTENT(IN) :: res, start, fin
      REAL, DIMENSION(:), INTENT(INOUT) :: vector

      INTERFACE
         FUNCTION func(vector)                                      
            IMPLICIT NONE                                      
            REAL, DIMENSION(:), INTENT(IN) :: vector                
            REAL :: func                                       
         END FUNCTION func                                     

         FUNCTION dfunc(vector)                                     
            IMPLICIT NONE                                      
            REAL, DIMENSION(:), INTENT(IN) :: vector               
            REAL, DIMENSION(size(vector)) :: dfunc                  
         END FUNCTION dfunc                                    
      END INTERFACE

      ! do stuff with p

      private_func(res,start,fin,vector,func,dfunc) 

      ! do stuff
   END SUBROUTINE test_routine

   SUBROUTINE private_func(res,start,fin,vector,func,dfunc)
      IMPLICIT NONE
      REAL, DIMENSION(:), INTENT(IN) :: res, start, fin
      REAL, DIMENSION(:), INTENT(INOUT) :: vector
      INTERFACE
         FUNCTION func(vector)            
            REAL, DIMENSION(:), INTENT(IN) :: vector
            REAL :: func
         END FUNCTION func
         FUNCTION dfunc(vector)
            REAL, DIMENSION(:), INTENT(IN) :: vector
            REAL, DIMENSION(size(vector)) :: dfunc
         END FUNCTION dfunc     
      END INTERFACE   

      ! do stuff             
   END SUBROUTINE private_func

END Mod_Example
  • func
    dfunc
    将在使用
    MODULE\u示例的程序代码中声明,顶部有一个接口块
  • 变量:
    res
    start
    等可以用主程序块中的值声明,并作为参数传递给
    子例程test\u例程
  • 子例程test\u例程
    将调用
    private\u func
    ,调用传递给它的变量
您的主程序将如下所示:

Program Main_Program
   USE Mod_Example
   INTERFACE
      FUNCTION func(vector)            
         REAL, DIMENSION(:), INTENT(IN) :: vector
         REAL :: func
      END FUNCTION func
      FUNCTION dfunc(vector)
         REAL, DIMENSION(:), INTENT(IN) :: vector
         REAL, DIMENSION(size(vector)) :: dfunc
      END FUNCTION dfunc     
   END INTERFACE

   ! do stuff       

   ! calls test_routine form module
   ! uses dfunc and func defined below
   call test_routine(res,start,fin,vector,func,dfunc)

   ! do stuff
END PROGRAM Main_Program

! define dfunc and nfunc for passing into the modular subroutine
FUNCTION func(vector)
   IMPLICIT NONE
   REAL, DIMENSION(:), INTENT(IN) :: vector
   REAL :: func

   nfunc = vector
END FUNCTION func

FUNCTION dfunc(vector)
   IMPLICIT NONE
   REAL, DIMENSION(:), INTENT(IN) :: vector
   REAL, DIMENSION(size(vector)) :: dfunc   

   dfunc = vector
END FUNCTION dfunc

所以,基本上你可以用以下方法来解决这个问题:

SUBROUTINE CONDACT(i,j, iab11,iab22,xx2,yy2,zz2,b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2,res)
  !declaration to all those parameters and res
  res = f(x)
END SUBROUTINE CONDACT

function f(x,iab11,iab22,xx2,yy2,zz2,b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2)
!declaration to all those parameters
end function f

program
  ...

  call CONDAT(i,j,iab11,iab22,xx2,yy2,zz2,b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2,res)

end program
也就是说,只需传递参数即可。 强烈鼓励使用模块,参见Alexander McFarlane的答案,尽管这不是必需的。Alexander McFarlane演示了如何将f作为参数传递给子例程,这样您就可以在子例程中使用不同的函数,但您的代码似乎并不需要这样做

现在,这是一个非常长的参数列表,您可能不想一直随身携带这些参数。 通常的处理方法是将这些参数放入一个函数中,然后将其传递。 像这样:

!> A module implementing ellip related stuff.
module ellip_module

  implicit none

  type ellip_type
    !whatever datatypes these need to be...
    integer :: b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2
  end type
end module ellip_module


!> A module implementing condact related stuff.
module condact_module
  use ellip_module ! Make use of the ellip module to have the type available

  implicit none

  type condact_type
    !whatever datatypes these need to be...
    integer :: iab11,iab22,xx2,yy2,zz2
  end type

  contains

  subroutine condact(i,j, con, ellip, res)
     integer :: i,j
     type(condact_type) :: con
     type(ellip_type) :: ellip
     real :: res

     real :: x
     res = f(x, con, ellip)
  end subroutine condact

  function f(x, con, ellip) result(res)
    real :: x
    real :: res
    type(condact_type) :: con
    type(ellip_type) :: ellip

    res = !whatever this should do
  end function f
end module condact_module


!> A program using the condact functionality.
program test_condact
  use ellip_module
  use condact_module

  implicit none

  type(condact_type) :: mycon
  type(ellip_type) :: myellip
  integer :: i,j
  real :: res

  call condact(i,j, mycon, myellip, res)
end program test_condact

这只是一个粗略的草图,但我得到的印象是这就是您要寻找的。

这里您关心的是关联:您希望能够将函数
f
中的实体与子例程
condat
中的实体关联起来。存储关联是实现这一点的一种方法,这就是公共块所做的

还有其他形式的联系可能是有用的。这些是

  • 使用关联
  • 东道主协会
  • 论元关联
参数关联如中所述

使用关联通过如下模块实现

module global_variables
  implicit none     ! I'm guessing on declarations, but that's not important
  public   ! Which is the default
  real b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2,xx2,yy2,zz2
  integer iab11,iab22
end module

subroutine condat(i,j)
  use global_variables   ! Those public things are use associated
  ...
end subroutine

function f(x)
  use global_variables   ! And the same entities are accessible here
  ...
end function
主机关联正在访问主机可访问的实体。这里的主机可以是模块或程序

module everything
  integer iab11,...
  real ...
 contains
  subroutine condat(i,j)
    ! iab11 available from the host module
  end subroutine

  function f(x)
    ! iab11 available from the host module
  end function
end module
甚至是子程序本身

subroutine condat(i,j)
  integer iab11,...
  real ...
 contains
  function f(x)
    ! Host condat's iab11 is accessible here
  end function
 end subroutine

程序接受参数。将数据作为参数传递,并在调用其他参数时使用它们。您能否提供一些特定的代码,以显示您实际上不了解的内容?正如casey所说,将参数传递给子程序或过程基本上没有区别,所以我有点不清楚您的问题的目的。谢谢casey和Haraldkl。我用例子编辑了我的问题。我的问题是,如何在不使用公共块的情况下,将公共块“contact and ellip”中的变量从子程序“CONDAT”传递到函数f(x)。@SadiaF我将使用模块以更简洁的格式实现这一点。。。请参阅下面的说明如果您真的需要f77方法,唯一的替代方法是将所有内容作为函数参数传递。(如果你不是故意的,你应该删除那个标签)谢谢亚历山大。我一定会尝试使用该模块,并让您知道它是否有效。因此,没有公共块或模块就无法传递信息?@SadiaF模块不是严格要求的。我也不确定,你是否真的想要函数作为参数。从你的代码来看,它看起来只是一个普通的调用。严格来说,你是对的,它只是一个普通的调用,但我在中添加了函数来演示如何实现这一点。此外,我还发现模块使大型项目更容易处理。当然,应该使用模块!我只是在她的评论中提到萨迪亚夫的问题,这是否可以在没有模块的情况下完成:是的,可以,但我强烈建议不要这样做。我甚至应该更新我下面的例子来使用两个模块。谢谢@Alexander McFarlane!非常感谢你!我会使用“使用协会”并让你知道它是否有效。@SadiaF没问题,我希望你把你的公地整理好。据我所知,OpenMP并行化的最佳选择是在ford例程中定义ellip和condact类型的局部变量,并将它们传递下去。由于OpenMP循环在外部,因此无需进一步ado,这些将是完全私有的。本地化变量不起作用。As子例程覆盖并共享变量。我的旧代码是用FORTRAN77编写的。模块在77上不工作!我不知道下一步该怎么办@萨迪亚夫我不太清楚你说的覆盖是什么意思。通过重写,我了解到这些例程只是在使用相同的内存来处理一些独立的事情,这样一个例程的结果就被另一个例程忽略了。如果不是这样,您需要一些非局部变量,您仍然可以通过上述方法实现,尽管并行化策略将取决于数据如何流经例程。类型和模块都不能在F77中工作,但这不是问题,因为现在所有的编译器都是F90。@SadiaF也许您可以在上用Fortran标记发布一个更完整、更有效的代码示例。代码审查致力于代码改进。注意,即使代码的其他部分是F77,也不需要坚持使用F77。出于实际目的,F77是F90的子集,这意味着您的代码库可能与F77一样有效。如上所述,我们基本上只有