我想更容易更改某个函数,该函数将由fortran项目中的子例程使用。但是我无法让它发挥作用。我看过很多使用external
的例子,但我不确定是否必须使用它,因为我把所有的函数和子程序放在模块中。
以下是我正在处理的问题的简化示例:
我将程序放在一个单独的文件中:
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
我将每个子程序和所有函数放在一个单独的模块中,每个模块都有自己的文件:
模块Parameters
只定义常量和变量类型:
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
模块circArrayConstructer
包含子例程circArray
,其输出为error
,coor
和topo
,后两个维度为N
2,因为输入中需要N
,所以必须分配它们。
模块RungeKutta4
包含子程序RK4
,它是4阶Runge Kutta方法的实现:
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
模块velocity
包含多个功能:
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
目前,当我尝试编译程序时,我收到错误:虚拟程序中的接口不匹配' vel':函数结果中的类型/等级不匹配。
我尝试了各种各样的事情,例如将vel
中RungeKutta4
的声明更改为real(fd), external :: vel(:,:)
,但这会产生相互矛盾的属性。但是我已经没有关于如何使代码工作的想法。
答案 0 :(得分:4)
使用模块中的功能,您不想使用external
。问题是RK4不知道它正在接收的函数的属性。您可以使用interface
块声明该函数:
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