在Fortran中使用函数名称作为参数时遇到问题 [英] Trouble using function name as argument in Fortran
问题描述
我想让它更容易改变fortran项目中子例程将使用的某个函数。但是我无法让它工作。我已经看到了很多使用 external 的例子,但是我不确定是否必须使用它,因为我把所有的函数和子例程放在模块中。
下面是我正在处理的问题的一个简单示例:
我将程序放在单独的文件中:
程序测试
使用参数
使用circArrayConstructer
使用速度
使用RungeKutta4
implicit none
integer(is):: N,P,nsteps,i,j
real(fd):: D,dt
real(fd),allocatable :: coor(:, :)
integer(is),allocatable :: topo(:, :)
integer(is):: error
read(*,*)D,nsteps,N ,P
dt = 1.0 / nsteps
call circArray(0.5_fd,0.5_fd,0.2_fd,0.2_fd,N,coor,topo,error)
do i = 1,P $ b (mod(P,2)> 0),则$ b $ j调用RK4(dt,coor,D,vel1,coor)
else
调用RK4(dt,coor,D,vel2,coor)
end if
end do
end do
结束程序测试
我将每个子例程和所有函数放在一个单独的模块中,每个模块都有自己的文件:
模块参数
只是定义了常量和变量类型:
模块参数
隐式无
整数,参数:: fs = selected_real_kind(6)
整数,参数:: fd = selected_real_kind(15)
整数,参数:: is = selected_int_kind(9)
integer,parameter :: id = selected_int_kind(18)
real(fd),parameter :: PI = 3.141592653589793
end module参数
模块 circArrayConstructer
包含输出错误的子程序
除以2并自<$ c circArray
, coor
和 topo
,后两个维<
模块 RungeKutta4
在输入中必须分配$ c> N 包含子程序 RK4
,它是第4阶Runge Kutta方法的实现:
module RungeKutta4
use参数
使用速度
隐式无
包含
子程序RK4(dt,coorOld,D,vel,coorNew)
隐式none
real(fd),intent(in):: dt
real(fd),intent(in):: D
real(fd),intent(in):: coorOld( :,:)
real(fd),intent(out):: coorNew(:, :)
real(fd),dimension(size(coorOld,1),size(coorOld,2)) :: k1,k2,k3,k4
real(fd),external :: vel
k1 = vel(coorOld,D)
k2 = vel(coorOld + 0.5 * dt * k1,D)
k3 = vel(coorOld + 0.5 * dt * k2,D)
k4 = vel(coorOld + dt * k3,D)
coorNew = coorOld + dt / 6.0 *(k1 + 2 *(k2 + k3)+ k4)
结束子程序RK4
结束模块RungeKutta4
模块 velocity
包含多个函数:
模块速度
使用参数
隐式无
包含
函数vel1(coor,D)
隐式无
real(fd),intent(in):: D
real(fd),intent(in):: coor(:, :)
real(fd),dimension(size(coor,1 ),size(coor,2)):: vel1
vel1(:,1)= -2.0 * D * coor(:2)* sin(PI * coor(:,1))* cos (2)** 2)
vel1(:2)= D * cos(PI * coor(:,1))* sin(PI * coor(:,2)** 2)
结束函数vel1
函数vel2(coor,D)
隐式无
real(fd),intent(in):: D
real fd),intent(in):: coor(:, :)
real(fd),dimension(size(coor ,1),size(coor,2)):: vel2
vel2(:,1)= 2.0 * D *(1-coor(:,2))* sin(PI * coor(:,1) )* cos(PI *(1-coor(:2))** 2)
vel2(:,2)= D * cos(PI * coor(:,1))* sin(PI * 1 - coor(:,2))** 2)
结束函数vel2
结束模块速度
目前,当我尝试编译程序时,出现如下错误:假过程'vel'中的接口不匹配:函数结果中的类型/等级不匹配。
我尝试了各种各样的东西,例如将 RungeKutta4
中的 vel
的声明更改为 real(fd),external :: vel(:,:)
但是会产生冲突的属性。但是我已经没有想法了解如何使代码工作。
通过模块中的函数,我想要使用 external
。问题是RK4不知道它正在接收的函数的属性。您可以使用接口
块声明该函数:
interface
$函数vel(corr,D)
导入fd
real(fd),intent(in):: D
real(fd),intent(in):: corr(:, :)
real(fd),dimension(size(corr,1),size(corr,2)):: vel
结束函数vel
结束接口
I wanted to make it easier to change a certain function which will be used by a subroutine in a fortran project. However I can not get it to work. I have seen quite a few examples which use the external
, however I am not sure if I have to use it, since I put all my function and subroutines in modules.
Here is a simplified example of the problem I am dealing with:
I have the program in a separate file:
program test
use Parameters
use circArrayConstructer
use velocity
use RungeKutta4
implicit none
integer(is) :: N, P, nsteps, i, j
real(fd) :: D, dt
real(fd), allocatable :: coor(:,:)
integer(is), allocatable :: topo(:,:)
integer(is) :: error
read (*,*) D, nsteps, N, P
dt = 1.0 / nsteps
call circArray ( 0.5_fd, 0.5_fd, 0.2_fd, 0.2_fd, N, coor, topo, error )
do i = 1, P
do j = 1, nsteps
if ( mod(P,2) > 0 ) then
call RK4 ( dt, coor, D, vel1, coor )
else
call RK4 ( dt, coor, D, vel2, coor )
end if
end do
end do
end program test
I put each subroutine and all the functions in a separate module and each module has its own file:
The module Parameters
just defines constants and variable types:
module Parameters
implicit none
integer, parameter :: fs = selected_real_kind(6)
integer, parameter :: fd = selected_real_kind(15)
integer, parameter :: is = selected_int_kind(9)
integer, parameter :: id = selected_int_kind(18)
real(fd), parameter :: PI = 3.141592653589793
end module Parameters
Module circArrayConstructer
contains the subroutine circArray
which has the output error
, coor
and topo
, the last two have dimensions N
by 2 and since N
in an input they have to be allocated.
Module RungeKutta4
contains the subroutine RK4
which is an implementation of the 4th order Runge Kutta method:
module RungeKutta4
use Parameters
use velocity
implicit none
contains
subroutine RK4 ( dt, coorOld, D, vel, coorNew )
implicit none
real(fd), intent(in ) :: dt
real(fd), intent(in ) :: D
real(fd), intent(in ) :: coorOld(:,:)
real(fd), intent(out) :: coorNew(:,:)
real(fd), dimension(size(coorOld,1), size(coorOld,2)) :: k1, k2, k3, k4
real(fd), external :: vel
k1 = vel ( coorOld , D )
k2 = vel ( coorOld + 0.5 * dt * k1, D )
k3 = vel ( coorOld + 0.5 * dt * k2, D )
k4 = vel ( coorOld + dt * k3, D )
coorNew = coorOld + dt / 6.0 * (k1 + 2 * (k2 + k3) + k4)
end subroutine RK4
end module RungeKutta4
And module velocity
contains multiple functions:
module velocity
use Parameters
implicit none
contains
function vel1 ( coor, D )
implicit none
real(fd), intent(in) :: D
real(fd), intent(in) :: coor(:,:)
real(fd), dimension(size(coor,1), size(coor,2)) :: vel1
vel1(:,1) = -2.0 * D * coor(:,2) * sin(PI * coor(:,1)) * cos(PI * coor(:,2) ** 2)
vel1(:,2) = D * cos(PI * coor(:,1)) * sin(PI * coor(:,2) ** 2)
end function vel1
function vel2 ( coor, D )
implicit none
real(fd), intent(in) :: D
real(fd), intent(in) :: coor(:,:)
real(fd), dimension(size(coor,1), size(coor,2)) :: vel2
vel2(:,1) = 2.0 * D * (1 - coor(:,2)) * sin(PI * coor(:,1)) * cos(PI * (1 - coor(:,2)) ** 2)
vel2(:,2) = D * cos(PI * coor(:,1)) * sin(PI * (1 - coor(:,2)) ** 2)
end function vel2
end module velocity
Currently when I try to compile the program I get the error: Interface mismatch in dummy procedure 'vel': Type/rank mismatch in function result.
I have tried all kinds of things, such as changing the declaration of vel
in RungeKutta4
to real(fd), external :: vel(:,:)
but that gives conflicting attributes. But I have run out of ideas on how to make the code work.
With the function in a module, you don't want to use external
. The problem is that RK4 doesn't know the properties of the function that it is receiving. You can declare the function with an interface
block:
interface
function vel ( corr, D )
import fd
real (fd), intent (in) :: D
real (fd), intent (in) :: corr (:,:)
real(fd), dimension(size(corr,1), size(corr,2)) :: vel
end function vel
end interface
这篇关于在Fortran中使用函数名称作为参数时遇到问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!