Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran语言中的龙格库塔_Fortran_Fortran90_Runge Kutta - Fatal编程技术网

Fortran语言中的龙格库塔

Fortran语言中的龙格库塔,fortran,fortran90,runge-kutta,Fortran,Fortran90,Runge Kutta,我试图在Fortran中实现Runge-Kutta方法,并且面临收敛问题。我不知道我应该展示多少代码,所以我将详细描述这个问题,并请指导我应该在文章中添加/删除哪些内容以使其具有可解释性 我有一个球的位置和速度的6维向量,以及相应的微分方程组。这描述了运动方程,我想从中计算球的轨迹,并比较RK方法不同阶次的结果 让我们关注三阶RK。我使用的模型实现如下: k1 = h * f(vec_old,omega,phi) k2 = h * f(vec_old + 0.5d0 * k1,omega,phi

我试图在Fortran中实现Runge-Kutta方法,并且面临收敛问题。我不知道我应该展示多少代码,所以我将详细描述这个问题,并请指导我应该在文章中添加/删除哪些内容以使其具有可解释性

我有一个球的位置和速度的6维向量,以及相应的微分方程组。这描述了运动方程,我想从中计算球的轨迹,并比较RK方法不同阶次的结果

让我们关注三阶RK。我使用的模型实现如下:

k1 = h * f(vec_old,omega,phi)
k2 = h * f(vec_old + 0.5d0 * k1,omega,phi)
k3 = h * f(vec_old + 2d0 * k2 - k1,omega,phi)
vec = vec_old + (k1 + 4d0 * k2 + k3) / 6d0
其中
f
是构成运动方程的函数(或相当于我的微分方程系统的RHS)。请注意,
f
与时间无关,因此只有一个参数
h
扮演小时间步长dt的角色

如果我们希望计算有限时间内球的轨迹
总时间
,并考虑总误差
ε
,那么我们需要确保每一步都取误差的比例分数。第一步,我做了以下工作:

vec1 = solve(3,vec_old,h,omega,phi)
vec2 = solve(3,vec_old,h/2d0,omega,phi)
do while (maxval((/(abs(vec1(i) - vec2(i)),i=1,6)/)) > eps * h / (tot_time - current_time))
    h = h / 2d0
    vec1 = solve(3,vec_old,h,omega,phi)
    vec2 = solve(3,vec_old,h/2d0,omega,phi)
end do
vec = (8d0/7d0) * vec2 - (1d0/7d0) * vec1
其中,
solve(3,vec_old,h,omega,phi)
是计算上述单个RK步长的函数
3
表示我们正在使用的RK顺序,
vec_old
是位置速度向量的当前状态,
h,h/2d0
都表示正在使用的时间步长,
omega,phi
只是
f
的一些额外参数。最后,对于第一步,我们设置
current\u time=0d0

关键是,如果我们使用三阶RK,我们应该在$O(h^3)$中有一个错误,因此在
h
中下降得比线性下降得快。因此,我们应该期望while循环最终在足够小的
h
时停止

我的问题是循环不收敛,甚至不接近比率

maxval(...) / eps * (...)
一直保持几乎不变,直到由于精度有限,
eps*h/(tot\u time-current\u time))
变为零

为了完整起见,这是我对
f
的定义:

function f(vec_old,omega,phi) result(vec)
    real(8),intent(in) :: vec_old(6),omega,phi
    real(8) :: vec(6)
    real(8) :: v,Fv

    v = sqrt(vec_old(4)**2+vec_old(5)**2+vec_old(6)**2)
    Fv = 0.0039d0 + 0.0058d0 / (1d0 + exp((v-35d0)/5d0))
    vec(1) = vec_old(4)
    vec(2) = vec_old(5)
    vec(3) = vec_old(6)
    vec(4) = -Fv * v * vec_old(4) + 4.1d-4 * omega * (vec_old(6)*sin(phi) - vec_old(5)*cos(phi))
    vec(5) = -Fv * v * vec_old(5) + 4.1d-4 * omega * vec_old(4)*cos(phi)
    vec(6) = -Fv * v * vec_old(6) - 4.1d-4 * omega * vec_old(4)*sin(phi) - 9.8d0
end function f
有人知道为什么while循环不收敛吗?
如果还需要什么(输出、其他代码等),请告诉我,我会添加它。此外,如果需要修剪,我会修剪任何认为不必要的东西。谢谢

要使用半步法计算步长误差,您需要在两种情况下计算
t+h
处的近似值,这意味着步长为
h/2的两步。现在,将
t+h
处的近似值与
t+h/2
处的近似值进行比较,得出的误差大小为
f(vec(t+h/2))*h/2

因此,更改为三步程序

vec1 = solve(3,vec_old,h,omega,phi)
vec2 = solve(3,vec_old,h/2d0,omega,phi)
vec2 = solve(3,vec2   ,h/2d0,omega,phi)

在这两个位置,
vec2-vec1
的差异应该是有序的
h^4

耶!我在分析中确实弄错了,代码现在运行得很好。顺便说一句,谢谢你,因为向量有不同的单位(三个指数对应位置,三个指数对应速度),这就意味着方程组是由二阶微分方程组成的,范数应该考虑到这一点吗?我的意思是,速度指数在某种程度上有一个额外的因子h。那么,在计算范数时,将“h”中的最后三个指数相乘有意义吗?不,与
h
相乘没有意义。然而,对范数进行缩放是明智的,这样导数向量的每个分量的平均值或大小都是相同的。一般来说,几何或物理对称性应该被保留,所以最后3个分量只有一个固定因子。。。因此,我将尝试想出一些有意义的东西,比如平均时间步长的估计值等,这样分量的大小也可以比较。非常感谢。