简体   繁体   English

有没有办法强制 ode() [deSolve-R package] 在 ode 函数的每个积分步骤提供输出

[英]Is there a way to force ode() [deSolve-R package] to provide output at each integration step in the ode function

I would like to extract the value of the state variable at each step of the numerical scheme.我想在数值方案的每个步骤中提取状态变量的值。

The ode() function in the deSolve R package, uses one of the implemented ODE solvers to numerically solve a system of ordinary differential equations. deSolve R 包中的 ode() 函数使用已实现的 ODE 求解器之一对常微分方程组进行数值求解。 To do this it uses a dynamically adjusted integration step based on the value of the Local Truncation Error at the end of each integration.为此,它根据每次积分结束时的局部截断误差值使用动态调整的积分步骤。 The user basically specifies the desired output times which define the timestep grid, that can have a step equal or smaller to the output times.用户基本上指定了定义时间步长网格的所需输出时间,其步长可以等于或小于输出时间。

If we take the Lotka Volterra Predator-Prey model (with logistic prey) as an example:如果我们以 Lotka Volterra Predator-Prey 模型(带有逻辑猎物)为例:

LVmod <- function(Time, State, Pars) {
  with(as.list(c(State, Pars)), {
    Ingestion    <- rIng  * Prey * Predator
    GrowthPrey   <- rGrow * Prey * (1 - Prey/K)
    MortPredator <- rMort * Predator

    dPrey        <- GrowthPrey - Ingestion
    dPredator    <- Ingestion * assEff - MortPredator

    return(list(c(dPrey, dPredator)))
  })
}

with the parameters and state variable defined as:参数和状态变量定义为:


pars  <- c(rIng   = 0.2,    # /day, rate of ingestion
           rGrow  = 1.0,    # /day, growth rate of prey
           rMort  = 0.2 ,   # /day, mortality rate of predator
           assEff = 0.5,    # -, assimilation efficiency
           K      = 10)     # mmol/m3, carrying capacity



yini  <- c(Prey = 1, Predator = 2)

and output requested at a daily timestep:并在每天的时间步请求输出:

times <- seq(0, 200, by = 1)

out   <- ode(yini, times, LVmod, pars)
diagnostics(out)

Looking at the diagnostics we can see that the solver used 282 steps in total while the output is generated for 200 steps (as set in the times object).查看诊断,我们可以看到求解器总共使用了 282 步,而生成的输出是 200 步(如时间对象中设置的那样)。

This difference is a lot bigger for the model that I am running and to do a complete analysis of the stability of my system I need the output at each integration step together with the size of the step.对于我正在运行的模型,这种差异要大得多,为了对系统的稳定性进行完整分析,我需要每个集成步骤的输出以及步骤的大小。 Is there a way to extract this info from ode?有没有办法从 ode 中提取此信息?

So, after a bit of research [1,2]:因此,经过一些研究 [1,2]:

There are two explicit methods that do not adapt the time step: the euler method and the rk4 method.有两种不适应时间步长的显式方法:欧拉方法和rk4方法。 They are implemented in two ways:它们以两种方式实现:

  1. As a rkMethod of the general rk solver.作为一般rk求解器的rkMethod。 In this case the time step used can be specified independently from the times argument, by setting argument hini.在这种情况下,可以通过设置参数 hini 独立于时间参数指定使用的时间步长。 Function ode uses this general code函数 ode 使用这个通用代码
  2. As special solver codes euler and rk4.作为特殊的求解器代码 euler 和 rk4。 These implementations are simplified and with less options to avoid overhead.这些实现被简化,并且避免开销的选项更少。 The timestep used is determined by the time increment in the times argument.使用的时间步长由时间参数中的时间增量确定。

Applied to the LV example, the next two statements both trigger the Euler method, the first using the “special” code with a time step = 1, as imposed by the times argument, the second using the generalized method with a time step set by hini.应用于 LV 示例,接下来的两个语句都触发 Euler 方法,第一个使用时间步长 = 1 的“特殊”代码,如时间参数所强加的,第二个使用时间步长设置为的广义方法希尼。


    out.euler  <- euler(y = state, times = times, func = LVmod, parms = parameters)
    out.rk <- ode(y = state, times = times, func = LVmod, parms = parameters,
                 method = "euler", hini = 0.01)

In this very simple system using the explicit Euler scheme might make sense, however for more complex systems the rk4 would be advisable even though it is still an explicit scheme.在这个非常简单的系统中,使用显式 Euler 方案可能是有意义的,但是对于更复杂的系统,建议使用 rk4,即使它仍然是一个显式方案。

To conclude:总结:

  • There seems to be no way to extract the state values at each step when using the dynamic time step in the ode() function.在 ode() 函数中使用动态时间步长时,似乎无法提取每一步的状态值。
  • You can set a constant step for two explicit schemes: Euler and rk4.您可以为两个显式方案设置恒定步长:Euler 和 rk4。

[1] Soetaert, KER, Petzoldt, T., & Setzer, RW (2010). [1] Soetaert, KER, Petzoldt, T., & Setzer, RW (2010)。 Solving differential equations in R: package deSolve.在 R 中求解微分方程:包 deSolve。 Journal of Statistical Software, 33.统计软件杂志,33。

[2] Soetaert, K., Petzoldt, T., & Setzer, RW (2010). [2] Soetaert, K.、Petzoldt, T. 和 Setzer, RW (2010)。 Package deSolve: solving initial value differential equations in R. J Stat Softw, 33(9), 1-25.包 deSolve:在 R. J Stat Softw, 33(9), 1-25 中求解初值微分方程。

It is possible to watch how the integrator works by putting a print or cat in the model function:可以通过在模型函数中放置 print 或 cat 来观察积分器的工作方式:

library("deSolve")

LVmod <- function(Time, State, Pars) {
  with(as.list(c(State, Pars)), {
    Ingestion    <- rIng  * Prey * Predator
    GrowthPrey   <- rGrow * Prey * (1 - Prey/K)
    MortPredator <- rMort * Predator

    dPrey        <- GrowthPrey - Ingestion
    dPredator    <- Ingestion * assEff - MortPredator
    cat("Time=", Time, "dPrey"=dPrey, "dPredator=", dPredator, "\n")
    return(list(c(dPrey, dPredator)))
  })
}

This works with both, automatic and fixed step solvers.这适用于自动和固定步长求解器。 Please note however, that automatic steppers may sometimes discard steps and try it again, so time is not always monotonous.但是请注意,自动步进器有时可能会放弃步骤并重试,因此时间并不总是单调的。 If you want to save the data for later use, save the data to a list with <<-, ideally by constructing a closure around the simulation.如果您想保存数据以备后用,请将数据保存到带有 <<- 的列表中,理想情况下通过围绕模拟构建一个闭包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM