You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DifferentialEquations.jl中高效获取额外变量d、e、f的输出?

解决DifferentialEquations.jl中获取额外变量的问题

方法一:使用回调函数(推荐用于指定时间点记录)

无需修改原ODE函数,通过SavedValues和SavingCallback安全记录额外变量,规避全局变量和时间点匹配问题:

using DifferentialEquations

# 原ODE函数保持不变
function test1(du,u,p,t)
    a,b,c = p
    
    d=a^0.1*(t+1)
    e=u[1]/a
    f=u[2]/d
    
    du[1] = a*u[1]
    du[2] = d*u[2]
    du[3] = b*u[2] - c*u[3]
end

# 定义生成额外变量的函数
function save_vars(u,t,p)
    a,b,c = p
    d = a^0.1*(t+1)
    e = u[1]/a
    f = u[2]/d
    return (d=d, e=e, f=f) # 返回命名元组,方便后续按名称访问
end

p = (2,0.75,0.8)
u0 = [1.0;1.0;1.0]
tspan = (0.0,3.0)
prob = ODEProblem(test1,u0,tspan,p)

# 指定要保存的时间点
sampletimes = tspan[1]:0.3:tspan[2]
# 初始化存储结构
saved_values = SavedValues(Float64, NamedTuple{(:d,:e,:f), Tuple{Float64,Float64,Float64}})
# 创建回调
cb = SavingCallback(save_vars, saved_values, saveat=sampletimes)

# 求解过程,无需重复设置saveat(若需要状态变量同步在这些点输出,可添加saveat=sampletimes)
sol = solve(prob, callback=cb)

# 访问保存的结果
saved_d = saved_values.saveval.d
saved_e = saved_values.saveval.e
saved_f = saved_values.saveval.f
# 对应的时间点为saved_values.t

该方法优势:

  • 无全局变量,线程安全且代码可维护性高
  • 精确匹配指定保存时间点,避免浮点数精度导致的漏记/重复记录
  • 支持灵活的变量存储格式(元组、数组、字典均可)

方法二:后处理计算(适配所有求解时间点)

若需要在全部求解生成的时间点(包括默认输出的所有点)计算额外变量,直接利用sol的t和u数组批量计算即可,无需修改ODE函数或使用回调:

using DifferentialEquations

# 原ODE函数和求解流程不变
function test1(du,u,p,t)
    a,b,c = p
    
    d=a^0.1*(t+1)
    e=u[1]/a
    f=u[2]/d
    
    du[1] = a*u[1]
    du[2] = d*u[2]
    du[3] = b*u[2] - c*u[3]
end

p = (2,0.75,0.8)
u0 = [1.0;1.0;1.0]
tspan = (0.0,3.0)
prob = ODEProblem(test1,u0,tspan,p)
sol = solve(prob) # 不设置saveat,获取求解器默认输出的全部时间点

# 批量计算额外变量
a,b,c = p
d = @. a^0.1*(sol.t + 1)
e = sol[1,:] ./ a  # sol[1,:]直接获取所有时间点的u[1]
f = sol[2,:] ./ d  # sol[2,:]直接获取所有时间点的u[2]

该方法优势:

  • 实现最简单,无需额外逻辑
  • 自动适配所有求解时间点,无论是默认输出还是saveat指定的点
  • 利用广播机制批量计算,性能高效

原方案的问题说明

  1. 时间点匹配误差:t in sampletimes依赖浮点数精确相等,但求解器实际时间点会因步长调整存在精度偏差,导致漏记或重复记录
  2. 全局变量风险:全局变量i、Out_values会引发线程安全问题,且代码可维护性差
  3. 重复设置的冲突:同时设置saveat和tstops会导致求解器内部处理时间点时出现微小差异——tstops是强制停止点,saveat是插值生成点,二者数值可能不完全一致

内容的提问来源于stack exchange,提问作者eod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 10:06:24