我决定在F90中为NPZD盒子模型编写我自己的求解器(RK4阶)。它似乎在前120个步骤(时间步长= 1天)运行良好,然后它变得不切实际。我缩短了时间步,并遇到了同样的问题。在这一点上,我想知道如何使解算器稳定。或者,如果更好的解决方案是使用其中一个ODEPACK,我不确定如何正确使用。我想保持时间步长= 1天,并且还想学习如何在不缩短时间步的情况下使其保持稳定。
我实际上在Fortran中重写了一个已经在python中完成的代码(由于技术原因,我们现在需要它在Fortran中)我的大学运行它没有问题,但使用python中可用的ODE。在同一个论坛上,有人建议(对其他人)在fortran写自己的求解器,因此我认为我也可以这样做。
以下是求解器和主程序的模块:
subroutine solver(stateSim1E)
type(ModelState) :: stateSim1E,stateSim1E1
type(ModelState) :: stateSim1E2,stateSim1E3,stateSim1E4
stateSim1E1 = dModelState(stateSim1E) !k1
!!$
stateSim1E2 = stateSim1E + 0.5*DTS*stateSim1E1 !cc1 K2
stateSim1E2 = dModelState(stateSim1E2)
stateSim1E3 = stateSim1E + 0.5*DTS*(stateSim1E2)!k3
stateSim1E3 = dModelState(stateSim1E3)
stateSim1E4 = stateSim1E + DTS*(stateSim1E3)!k4
stateSim1E4 = dModelState(stateSim1E4)
stateSim1E = stateSim1E + (DTS/6)*(stateSim1E1 + 2._RK*(stateSim1E2 + stateSim1E3) +stateSim1E4)
end subroutine solver
主程序
program main_npzdsv
use iso_fortran_env
use NumericKinds
use ModelState_class_npzdsv
integer :: i, outFileID,ti
type(ModelState) :: stateSim1E, statePerturbation !,stateSim1E1
!initial conditions
stateSim1E = ModelState(N=N0,P=P0,Z=Z0,D=D0,S = s_mean0, V = s_var0)
ti = 0
do i = 1, NO_T_STEP
ti = i
call getindex(ti)
call solver(stateSim1E)
print*,'new', index, stateSim1E
if( mod(i-1, OUTPUT_FREQUENCY) == 0 ) then
write(outFileID,'(i4)')index
write(outFileID, '(18('// RK_FMT // ', 1x))') stateSim1E%getCurrModelState()
end if
end do
close(outFileID) ! Clean-up for output
close(outFileID2) ! Clean-up for output
end program main_npzdsv
<!/ P>
答案 0 :(得分:1)
首先要考察的是CFL。有时显式方法需要非常小的时间步长,而有时无条件稳定的隐式方法。 对于速度随时间演变的问题,检查CFL实际上很棘手。旋转问题非常具有挑战性。通过旋转,我的意思是当你想要从非常小的扰动运行长时间的模拟以达到逼真的状态。例如,模拟海湾中的水循环。初始瞬态可以产生非常高的速度,这使得很难满足CFL并破坏系统。
如果你绝对希望你的时间步长至少一天,你可能需要增加你的空间步伐。另一个简单的方法是阅读python中使用的工具箱的doc,以获取有关底层方法的信息。
(这不是解决方案,这是一个太长的指示,不能作为评论)