我在解决周期性差异 eq 模型时遇到问题。
模型的轨迹是循环的,我想在运行定义的循环时停止它。
为此,我在中运行以下根函数deSolve::ode
:
rootfun <- function (t, y, pars) {
#message("rootfun")
change <- detectChange(t, y)
roots <- c(1, 1)
if (any(change %in% c('turn_on', 'turn_off', 'recording_off'))) roots[1] <- 0
if ('exit' %in% change) {
message('exit')
roots[2] <- 0
}
roots
}
调用:
ode(y = stateVec, times = seq(tStart, tStop, by = tRes), func = dTempFun, parms = NULL,
events = list(func = eventfun, root = T, terminalroot = 2), verbose = T,
rootfunc = rootfun)
作为一个函数,detectChange
当根被触发时给出系统的状态定义eventfun
应该做什么。根有两个组件,当第一个为零时eventfun
运行,而第二个为零时ode
应该停止运行。
在输出中,我希望看到“退出”消息只出现一次,然后ode
返回结果。
相反,我有以下输出:
eventfun
--------------------
Time settings
--------------------
Normal computation of output values of y(t) at t = TOUT
--------------------
Integration settings
--------------------
Model function an R-function:
Jacobian not specified
DLSODAR- A switch to the BDF (stiff) method has occurred
at T (R1), the new step size is (R2): 315.184, 0.0208815
eventfun
turn_on
root found at time 320.5
DLSODAR- A switch to the BDF (stiff) method has occurred
at T (R1), the new step size is (R2): 321.846, 0.00643464
eventfun
turn_off
root found at time 326.768
DLSODAR- A switch to the BDF (stiff) method has occurred
at T (R1), the new step size is (R2): 327.483, 0.00632845
eventfun
recording_off
root found at time 327.638
DLSODAR- A switch to the BDF (stiff) method has occurred
at T (R1), the new step size is (R2): 327.996, 0.00735142
eventfun
turn_on
root found at time 335.069
exit
exit
DLSODAR- One or more components of g has a root
too near to the initial point.
(“eventfun”是在事件函数运行时警告我的标志,“turn_on”、“turn_off”、“recording_off”是由根的第一个组件触发的事件类型,而“exit”仅在以下情况下打印第二个分量为零。)
最后,我们可以看到两个“退出”消息,然后是一个抱怨两个连续根的错误。如果我在每个周期都打印根,则可以看到第二个根分量两次都为零。
为什么会这样?不应该ode
在第二个元素的根第一次为零时停止?对于像 deSolve 这样的简单模型,我没有同样的问题:无法理解如何使用根函数提前停止 ode 求解器。
我发现正确停止的一个技巧ode
是强制两个“退出”状态由非退出根事件分隔。