如何解决R中的这个ode方程?

时间:2016-02-08 09:06:12

标签: r

我喜欢用Runge kutta方法解决R中的以下常微分方程。

dy1 <- (-51.33) * ((1-y[2]) / y[1])

dy2 <- 1.54 * y[1] * (1-y[2]) - 2.14 * y[2]

y1变为零时,dy1将变为无穷大。为避免这种情况,我需要编写R代码,说明当y[1]小于0.001时,停止y[1]导数并保持为零。我粘贴了下面的R代码:

yini <- c(1,0)

intabs <- function (t, y, parms) {
  ifelse (y[1] <= 0.01, dy1 <- 0, no)
  dy1 <- -51.33 * ((1-y[2]) / y[1])
  dy2 <- 1.54 * y[1] * (1-y[2]) - 2.14 * y[2]
  list(c(dy1, dy2))
}

times <- seq(from = 0, to = 1, by = .002)

out <- ode (times = times, y=yini, func = intabs, parms = NULL, method = "rk4")

head (out, n=50)

我使用ifelse语句来表示y[1]小于或等于0.001,然后将dy1保持为零。我收到了结果。但似乎我犯了一些错误,导致dy1的结果为负值。我是编写程序的新手。如果发现错误,请帮忙..

1 个答案:

答案 0 :(得分:0)

ODE函数中的这种跳转(如果编码正确)对于任何步长控制器都是有害的。 ODE函数必须至少与步长控制的积分方法的错误顺序一样平滑,以便按预期工作。如果ODE很僵硬,它仍然会失败。

将表达式1/y去单元化的微创方法是使用

y/(1e-6+y*y)

y>1e-21/y有一个很好的近似值,并且在任何地方都很平滑。更改常量以适应偏离1/y的区域。