我想使用 deSolve R包中的显式Runge-Kutta方法 ode45 (别名rk45dp7)来解决具有可变步长的ODE问题。< / p>
根据deSolve文档,可以使用ode45方法对 rk 求解器函数使用自适应或可变时间步长,而不是等距时间步,但我很遗憾怎么做。
rk函数的调用方式如下:
rk(y, times, func, parms, rtol = 1e-6, atol = 1e-6, verbose = FALSE, tcrit = NULL,
hmin = 0, hmax = NULL, hini = hmax, ynames = TRUE, method = rkMethod("rk45dp7", ... ),
maxsteps = 5000, dllname = NULL, initfunc = dllname, initpar = parms, rpar = NULL,
ipar = NULL, nout = 0, outnames = NULL, forcings = NULL, initforc = NULL, fcontrol =
NULL, events = NULL, ...)
次是需要对y进行显式估计的时间向量。
对于距离为0.01的等距时间步长,我可以将次写为
times <- seq(0, 100, 0.01)
假设我想解决从0到100的间隔的等式,如何在不给步长的情况下定义次?
非常感谢任何帮助。
答案 0 :(得分:5)
这里有两个问题。首先,如果要指定具有多个增量的时间向量,请使用此(例如):
times <- c(seq(0,0.9,0.1),seq(1,10,1))
times
# [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
这里,[0,1]为0.1,[1,10]为1。
但实际上你不必这样做:参数times=
告诉rk(...)
报告结果的时间。自适应算法内部调整时间增量,以便在参数中指定的时间产生准确的结果。因此,对于自适应算法,例如method="rk45dp7"
,您不必做任何事情。对于非自适应算法,例如method="euler"
,算法使用的时间增量实际上是times=
中指定的增量。你可以在这个简单的例子中看到这个效果,它集成了Van der Pol振荡器。
y.prime <- function(t,y.vector,b) { # Van der Pol oscillator
x <- y.vector[1]
y <- y.vector[2]
x.prime <- y
y.prime <- b*y*(1-x)^2 - x
return(list(c(x=x.prime,y=y.prime)))
}
h <- .001 # time increment
t <- seq(0,10,h) # times to report results
y0 <- c(0.01,0.01) # initial conditions
euler <- rk(y0, t,func=y.prime,parms=1,method="euler")
rk45dp7 <- rk(y0, t,func=y.prime,parms=1, method="rk45dp7")
# plot x vs. y
par(mfrow=c(1,2))
plot(euler[,2],euler[,3], type="l",xlab="X",ylab="Y",main=paste("Euler: h =",format(h,digits=3)))
plot(rk45dp7[,2],rk45dp7[,3], type="l",xlab="X",ylab="Y",main=paste("RK45DP7: h =",format(h,digits=3)))
以下是h
的多个值的结果比较。请注意,对于method="rk45dp7"
,h < 0.5
的结果是稳定的。这是因为rk45dp7
在内部根据需要调整时间增量。对于method="euler"
,结果与rk45dp7
之前的h~0.01
不匹配。