在Fortran中使用函数名称作为参数时遇到问题 [英] Trouble using function name as argument in Fortran

查看:319
本文介绍了在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 包含输出错误的子程序 circArray coor topo ,后两个维< N 除以2并自<$ c

模块 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆