我使用deSolve
包中的ode()
函数在R中编写了一个ODE模型。该方程预测了叶面农药质量的演变。app1
等于施用的农药质量(在第156天),并且该函数应该跟踪毒物的演变。我注意到变量mf
(叶片质量)的输出总是等于0,即使它应该随着时间的推移而变化(从第156天开始)。我不确定是什么导致了这个问题。有人能帮助我理解我做错了什么吗?
library(deSolve)
mod <- function(t, yini, param, Precip) {
app1 <- ifelse(t == 156, 1.12, 0)
jgrow <- 32
igrow <- ifelse(t >= 136 & t < 169, t - 136, ifelse(t > 168, 0.9, ifelse(t < 136, 0, NA)))
cover <- 0.9 * igrow / jgrow
P = Precip[t]
with(as.list(c(yini, param)), {
mharv = ifelse(t== 201, mf, 0)
d_MF <- (app1 * sa * (1-drift)*cover*sa)- (mf* exp(-kf*dt)) + (yf * (mf* exp(-kf*dt))) - mf * (1-exp(-fet * P * dt)) - mharv
return(list(c(d_MF)))
})}
params <- list(drift = 0.1, dt = 1, kf = 0.023, sa = 32.4, fet = 0.2, yf = 0.6)
t <- seq(1, 365, by = 1)
Precip=rep(0, 365)
Precip[155:205] =c(0, 0.96, 0.71, 0, 0, 0.08, 14.99, 0.2, 0.2, 0.25, 0, 0, 0.1, 0, 3.66, 0, 0.13, 0, 5.28, 0.03, 0, 0, 3.15, 0.84, 1.83, 0.03, 0, 2.29, 0, 0, 0.15, 1.65, 0, 0.91, 0.18, 2.01, 0, 0, 0, 0, 0, 3.17, 0.1, 0, 1.45, 0.25, 0, 0.03, 0.46, 0.03, 0)
y0 <- c(mf = 0)
sol <- ode(y = y0, times = t, func = mod, parms = params, Precip = Precip)
2条答案
按热度按时间yws3nbqq1#
这里是一个解决方案的一部分。时间被四舍五入与
floor
和precip
转换为一个强制函数与常数插值。igrow <- ifelse(...)
-函数看起来很奇怪,尤其是模型中的值永远不应该是NA。编辑
为了回答OP的评论,为什么“应用后第2天功能达到最大值”,我们可以应用以下修改:
在模型函数中,将
app1
替换如下。在状态向量c()
之后添加一些内部变量作为return
中的额外输出也是一个好主意。然后定义一个新的强制:
我们看到,只需要相关的时间步长。
然后必须修改对
ode
的调用以包含新的强制。减少时间步长非常重要,这样求解器的自动步长算法就不会忽略外部强制。可以通过在t
-向量中设置较小的时间步长或通过附加参数hmax
来完成。然而,一个小的时间步长会减慢模拟的速度。为了避免这种情况,可以使用事件机制。然后,您必须重新制定模型,使其在导数中不包含
app1
,而是计算它对mf
的影响。然后,在事件发生时,它被直接和瞬间添加到mf
。ubof19bj2#
app1
和mharv
实际上始终为零,几乎可以肯定斜率函数不会在该特定点处进行评估,即使如此,该单点尖峰也仅具有可忽略的影响。出于同样的原因,在调用
mod
时,t
几乎肯定不会是整数,当试图使用t
作为整数索引时,应该会得到一个错误,但可能会自动截断。所以最后,导数表达式中的每一项都有一个因子为零,使零函数成为正确的解。