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一样有效。如上所述,我们基本上只有