虚拟过程中的接口不匹配:形状不匹配

时间:2016-05-21 20:24:27

标签: arrays fortran

我正在尝试为微分方程组实现runge-kutta。 我在使用子程序时遇到了一些麻烦。我想把它作为一般代码,通过任何方程组来解决。

该计划的主要代码是:

program main

use ivp_odes

    implicit none

    double precision, allocatable :: t(:), y(:,:)
    double precision :: t0, tf, y0(2), h
    integer :: i

    t0 = 0d0
    tf = 0.5d0
    y0 = [0d0, 0d0]
    h = 0.1d0

    do i=lbound(t,1),ubound(t,1)
        print *, t(i), y(1,i), y(2,i)
    end do

contains

function myfun(t,y) result(dy)

    ! input variables
    double precision, intent(in) :: t, y(2)

    ! output variables
    double precision :: dy(2)

    dy(1) = -4*y(1) + 3*y(2) + 6
    dy(2) = -2.4*y(1) + 1.6*y(2) + 3.6
end function myfun

end program main

myfun是一个示例函数,我有分析解决方案,因此我可以将我的实现与系统的正确响应进行比较。这个myfun函数得到一个变量t和一个包含两个元素y的一维数组,并返回它的派生词,所以我可以用数字方法对它进行整合。

我在一个单独的模块中实现的runge-kutta算法:

module ivp_odes
    implicit none
contains

subroutine rk4(t, y, f, t0, tf, y0, h)
    ! input variables
    double precision, intent(in) :: t0, tf, y0(1:)
    double precision, intent(in) :: h

    interface
        pure function f(t,y) result(dy)
            double precision, intent(in) :: t, y(:)
            double precision :: dy(size(y))
        end function
    end interface

    ! output variables
    double precision, allocatable :: t(:), y(:,:)

    ! auxiliar variables
    integer :: i, m, N
    double precision :: hh
    double precision, allocatable :: k1(:), k2(:), k3(:), k4(:)

    N = ceiling((tf-t0)/h)
    m = size(y0)

    allocate(k1(m),k2(m),k3(m),k4(m))

    if (.not. allocated(y)) then
        allocate(y(m,0:N))
    else
        deallocate(y)
        allocate(y(m,0:N))
    end if

    if (.not. allocated(t)) then
        allocate(t(0:N))
    else
        deallocate(t)
        allocate(t(0:N))
    end if

    t(0) = t0
    y(:,0) = y0

    do i=1,N
        k1(:) = h * f(t(i-1)      , y(:,i-1)        )
        k2(:) = h * f(t(i-1)+h/2 , y(:,i-1)+k1(:)/2)
        k3(:) = h * f(t(i-1)+h/2 , y(:,i-1)+k2(:)/2)
        k4(:) = h * f(t(i-1)+h   , y(:,i-1)+k3(:)  )

        y(:,i) = y(:,i-1) + (k1(:) + 2*k2(:) + 2*k3(:) + k4(:))/6
            t(i) = t(i-1) + h
        end do

        deallocate(k1,k2,k3,k4)

end subroutine rk4

end module ivp_odes

rk子程序的想法是t是时间向量(一维数组)而y是响应向量(二维数组,每行对应一个变量)每列对应于对应时间内变量的值。

我无法找到使其工作的方法,因为我在编译代码时遇到错误,所有这些都与函数myfun在主代码中调用子例程rk时有关。

call rk4(t, y, myfun, t0, tf, y0, h)
                   1
Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of function result

我试图寻找这个问题的答案,并且已经阅读了之前提出的问题:

Interface mismatch - higher order functions

Fortran array cannot be returned in function: not a DUMMY variable

Function in fortran, passing array in, receiving array out

其中一些已帮助我解决了一些错误。但是,我正在尝试做的与第一个问题几乎完全相同,但它根本不起作用。

我正在使用GNU Fortran编译器,并在Code :: Blocks 16.01中编写代码。 无法找到解决问题的方法。

这里有一些我尝试过但没有用的东西:

  • 更改界面中的变量:
interface
    pure function f(t,yy) result(dy)
        double precision, intent(in) :: t, yy(:)
        double precision :: dy(size(y))
    end function
end interface
  • 未在接口
  • 中声明功能结果
interface
    pure function f(t,y)
        double precision, intent(in) :: t, y(:)
    end function
end interface

它产生错误:

    call rk4(t, y, myfun, t0, tf, y0, h)
                   1
Error: Interface mismatch in dummy procedure 'f' at (1): Type mismatch in function result (REAL(4)/REAL(8))
  • 我虽然可以使用过程语句,但我认为要做到这一点,我应该在子例程的同一模块中声明我的函数myfun,对吧?但是有一个通用代码的想法是我不需要在完成后打开这个模块,所以任何时候我想使用我的rk4集成器,我只是调用它,不需要在同一个模块中指定函数。

1 个答案:

答案 0 :(得分:1)

您传递的函数myfun和子例程f所期望的函数rk4的类型不同:

  • fpure,而myfun则不是。
  • f中,y是延迟形状,而在myfun中,它具有明确的形状(对dy有影响)。

这实际上是编译器抱怨的:) 一旦解决了这些问题,代码编译就可以了。