我有兴趣编写一个函数,该函数将要使用的模块名称作为其输入之一。例如,我编写了一个用于求解 ODE 系统的 Runge Kutta 4 阶积分器。我更愿意编写实际的 Runge Kutta 积分函数,以便为定义 ODE 系统的函数提供输入。
这是一个示例模块,其中包含定义 ODE 系统的函数
MODULE DIFF_EQ
! Description: This module contains the function that defines the
! system of ODEs to be solved.
CONTAINS
FUNCTION YDOT(t, y, PP) RESULT(yd)
! Description: This function defines the system of ODEs to be
! solved.
!
! Inputs: t - current independent variable value (real, scalar)
! y - current dependent variable value (real, array)
! PP - passed parameters/constants (real, array)
!
! Outputs: yd - current value of ODE (real, array)
IMPLICIT NONE
REAL*8, INTENT(IN) :: t
REAL*8, DIMENSION(2), INTENT(IN) :: y
REAL*8, DIMENSION(3), INTENT(IN) :: PP
REAL*8, DIMENSION(2) :: yd
yd = [y(2), &
-PP(1)*SIN(y(1)) + SIN(PP(2)*t) + PP(3)]
END FUNCTION YDOT
END MODULE DIFF_EQ
这是 Runge Kutta 集成模块
MODULE RUNGE_KUTTA
! Description: This module contains the function that implements the Runge Kutta 4th
! order integration scheme.
CONTAINS
FUNCTION RK4(Neq, tspan, y0, dt, DEQ, PP) RESULT(t_y)
! Description: This function implements the Runge Kutta 4th order integration scheme.
!
! Inputs: Neq - number of equations in system of ODEs (integer, scalar)
! tspan - [t0, tF] where t0 is start time and tF is end time (real, array - 2)
! y0 - [y1, y2, ..., yNeq] @ t0 (real, array - Neq)
! dt - time step size such that t1 = t0 + dt (real, scalar)
! PP - passed parameters/constants (real, array - variable)
!
! Outputs: t_y - time and solution (real, matrix - n x Neq + 1)
USE DIFF_EQ
IMPLICIT NONE
INTEGER, INTENT(IN) :: Neq
REAL*8, DIMENSION(2), INTENT(IN) :: tspan
REAL*8, DIMENSION(Neq), INTENT(IN) :: y0
REAL*8 :: dt
REAL*8, EXTERNAL :: DEQ
REAL*8, DIMENSION(:), INTENT(IN) :: PP
INTEGER :: n, i
REAL*8, DIMENSION(:,:), ALLOCATABLE :: t_y
REAL*8, DIMENSION(Neq) :: k1, k2, k3, k4
n = CEILING((tspan(2) - tspan(1))/dt + 1.0D0)
ALLOCATE(t_y(n, Neq+1))
IF (MOD(tspan(2) - tspan(1), dt) .LT. 0.000000000000001D0) THEN
t_y(1:n, 1) = [(tspan(1) + dt*(i-1), i = 1, n)]
ELSE
t_y(1:n, 1) = [(tspan(1) + dt*(i-1), i = 1, n-1), tspan(2)]
ENDIF
t_y(1, 2:Neq+1) = y0
PRINT *, t_y(1, 1:Neq+1)
DO i = 2, n
dt = t_y(i, 1) - t_y(i-1, 1)
k1 = DEQ(t_y(i-1, 1), t_y(i-1, 2:Neq+1), PP)
k2 = DEQ(t_y(i-1, 1) + 0.5D0*dt, t_y(i-1, 2:Neq+1) + 0.5D0*dt*k1, PP)
k3 = DEQ(t_y(i-1, 1) + 0.5D0*dt, t_y(i-1, 2:Neq+1) + 0.5D0*dt*k2, PP)
k4 = DEQ(t_y(i-1, 1) + dt, t_y(i-1, 2:Neq+1) + dt*k3, PP)
t_y(i, 2:Neq+1) = t_y(i-1, 2:Neq+1) + 0.16666666666666667D0*dt*(k1 + 2.0D0*k2 + 2.0D0*k3 + k4)
PRINT *, t_y(i, 1:Neq+1)
ENDDO
END FUNCTION RK4
END MODULE RUNGE_KUTTA
以及接受输入并调用函数的主程序
PROGRAM RK4_TEST
USE DIFF_EQ
USE RUNGE_KUTTA
IMPLICIT NONE
INTEGER :: Neq
REAL*8, DIMENSION(2) :: tspan
REAL*8, DIMENSION(2) :: y0
REAL*8 :: dt
REAL*8, DIMENSION(3) :: PP
INTEGER :: n
REAL*8, DIMENSION(:,:), ALLOCATABLE :: t_y
Neq = 2
tspan = [0.0D0, 1.0D0]
y0 = [1.0D0, 0.0D0]
dt = 0.1D0
PP = [1.0D0, 5.0D0, 0.0D0]
n = CEILING((tspan(2) - tspan(1))/dt + 1.0D0)
ALLOCATE(t_y(n, Neq+1))
t_y = RK4(Neq, tspan, y0, dt, YDOT, PP)
END PROGRAM RK4_TEST
使用 gfortran,这是由
gfortran DIFF_EQ.f90 RUNGE_KUTTA.f90 RK4_TEST.f90 -o MAIN.exe
Segmentation fault (core dumped)
它编译没有错误,但是当我尝试运行它时收到一条消息。
感谢您提供的任何帮助。