R simecol和稳态:rootfun无法访问SimObj插槽

R simecol和稳态:rootfun无法访问SimObj插槽,r,functional-programming,simulation,ode,R,Functional Programming,Simulation,Ode,我使用包模拟生态模型(作为ODE系统) 使生态模型的使用和共享变得非常容易的框架 通过对象类SimObj() 我想实现一个稳态,一旦导数变得很低,它就会停止模拟 据此, 这样,您就可以轻松地实现它 您只需提供一个自定义解算器来检查导数的值。 问题在于,自定义解算器看起来无法到达目标 方程式SimObj插槽 我想保留等式槽的这个不错的功能来切换 容易区分不同类型的功能反应 以下是可复制的示例: 1.定义模型 我们看到,模拟已提前停止(100而不是300),它已停止,因为稳定 已到达该国 我的问题

我使用包模拟生态模型(作为ODE系统) 使生态模型的使用和共享变得非常容易的框架 通过对象类SimObj()

我想实现一个稳态,一旦导数变得很低,它就会停止模拟

据此, 这样,您就可以轻松地实现它

您只需提供一个自定义解算器来检查导数的值。 问题在于,自定义解算器看起来无法到达目标
方程式
SimObj插槽

我想保留等式槽的这个不错的功能来切换 容易区分不同类型的功能反应

以下是可复制的示例:

1.定义模型

我们看到,模拟已提前停止(100而不是300),它已停止,因为稳定 已到达该国

我的问题是:我怎样才能让用户访问equations插槽
自定义解算器
lsodar

查看您的示例后,我发现您自己的解算器有些“有线”,即不必要的复杂。sim函数调用解算器并获取它所需的内容,因此不需要在其中调用upca_ode。此外,您调用该函数的外部版本,而不是对象,因此它当然无法访问“方程式”

(希望如此)好消息是,rootSolve包已经包含了稳态解算器,您可以使用它

见下面的例子。下面的示例还显示,定义自己的解算器非常容易。请使用正确的参数顺序

希望有帮助

托马斯

library(simecol)
library(rootSolve)

upca <- new("odeModel",
            main = function(time, init, parms) {
              u      <- init[1]
              v      <- init[2]
              w      <- init[3]
              with(as.list(parms), {
                du <-  a * u           - alpha1 * f(u, v, k1)
                dv <- -b * v           + alpha1 * f(u, v, k1) +
                  - alpha2 * f(v, w, k2)
                dw <- -c * (w - wstar) + alpha2 * f(v, w, k2)
                list(c(du, dv, dw))
              })
            },
            equations  = list(
              f1 = function(x, y, k){x*y},           # Lotka-Volterra
              f2 = function(x, y, k){x*y / (1+k*x)}  # Holling II
            ),
            times  = c(from=0, to=300, by=0.1),
            parms  = c(a=1, b=1, c=10, alpha1=0.2, alpha2=1,
                       k1=0.05, k2=0, wstar=0.1),
            init = c(u=10, v=5, w=0.1),
            solver = "lsoda"
)
upca@equations$f <- upca@equations$f2

plotupca <- function(obj, ...) {
  o <- out(obj)
  matplot(o[, 1], o[, -1], type = "l", ...)
  legend("topright", legend = c("u", "v", "w"), lty = 1:3, bg = "white", col = 1:3)
}

test <- sim(upca)
plotupca(test)

upca@equations$f <- upca@equations$f1
test <- sim(upca)
plotupca(test)


steady_state <- function(y, times, func, parms, steady.method) {
  time <- if (steady.method == "stode") {
    0
  } else {
    c(times[1], Inf)
  }
  steady(y, time, func, parms, method=steady.method)$y
}

equations(upca)$f <- equations(upca)$f1
solver(upca) <- steady_state

# fast direct approach, does not work with all models
test <- sim(upca, steady.method="stode")
out(test)

## slower, simulates model until approx. steady
test <- sim(upca, steady.method="runsteady")
out(test)
库(simecol)
库(rootSolve)
upca
upca_ode <- function(time, init, parms) {
  u <- init["u"]
  v <- init["v"]
  w <- init["w"]
  with(as.list(parms), {
    du <- a * u - alpha1 * f(u, v, k1)
    dv <- -b * v + alpha1 * f(u, v, k1) - alpha2 * f(v, w, k2)
    dw <- -c * (w - wstar) + alpha2 * f(v, w, k2)
    list(c(du, dv, dw))
})
}
upca <- upca_model()
equations(upca)$f <- equations(upca)$f2
test <- sim(upca)
plotupca <- function(obj, ...) {
  o <- out(obj)
  matplot(o[, 1], o[, -1], type = "l", ...)
  legend("topright", legend = c("u", "v", "w"), lty = 1:3,, bg = "white",
    col = 1:3)
}

plotupca(test)
equations(upca)$f <- equations(upca)$f1
test <- sim(upca)
plotupca(test)
steady_state_upca <- function(time, init, func, parms) {
  root <- function(time, init, parms) {
    dstate <- unlist(upca_ode(time, init, parms))
    return(sum(abs(dstate)) - 1e-4)
  }
  lsodar(time, init, func, parms, rootfun = root)
}

equations(upca)$f <- equations(upca)$f1
solver(upca) <- steady_state_upca
test <- sim(upca)
#> Error in f(u, v, k1) : impossible de trouver la fonction "f"                
upca_ode <- function(time, init, parms) {
  u <- init["u"]
  v <- init["v"]
  w <- init["w"]
  # Definition of the function f:
  f <- function(x, y, k){x * y}
  with(as.list(parms), {
    du <- a * u - alpha1 * f(u, v, k1)
    dv <- -b * v + alpha1 * f(u, v, k1) - alpha2 * f(v, w, k2)
    dw <- -c * (w - wstar) + alpha2 * f(v, w, k2)

    list(c(du, dv, dw))
})
}

upca <- upca_model()
equations(upca)$f <- equations(upca)$f1
solver(upca) <- steady_state_upca
test <- sim(upca)
plotupca(test)
library(simecol)
library(rootSolve)

upca <- new("odeModel",
            main = function(time, init, parms) {
              u      <- init[1]
              v      <- init[2]
              w      <- init[3]
              with(as.list(parms), {
                du <-  a * u           - alpha1 * f(u, v, k1)
                dv <- -b * v           + alpha1 * f(u, v, k1) +
                  - alpha2 * f(v, w, k2)
                dw <- -c * (w - wstar) + alpha2 * f(v, w, k2)
                list(c(du, dv, dw))
              })
            },
            equations  = list(
              f1 = function(x, y, k){x*y},           # Lotka-Volterra
              f2 = function(x, y, k){x*y / (1+k*x)}  # Holling II
            ),
            times  = c(from=0, to=300, by=0.1),
            parms  = c(a=1, b=1, c=10, alpha1=0.2, alpha2=1,
                       k1=0.05, k2=0, wstar=0.1),
            init = c(u=10, v=5, w=0.1),
            solver = "lsoda"
)
upca@equations$f <- upca@equations$f2

plotupca <- function(obj, ...) {
  o <- out(obj)
  matplot(o[, 1], o[, -1], type = "l", ...)
  legend("topright", legend = c("u", "v", "w"), lty = 1:3, bg = "white", col = 1:3)
}

test <- sim(upca)
plotupca(test)

upca@equations$f <- upca@equations$f1
test <- sim(upca)
plotupca(test)


steady_state <- function(y, times, func, parms, steady.method) {
  time <- if (steady.method == "stode") {
    0
  } else {
    c(times[1], Inf)
  }
  steady(y, time, func, parms, method=steady.method)$y
}

equations(upca)$f <- equations(upca)$f1
solver(upca) <- steady_state

# fast direct approach, does not work with all models
test <- sim(upca, steady.method="stode")
out(test)

## slower, simulates model until approx. steady
test <- sim(upca, steady.method="runsteady")
out(test)