Julia中对数刻度下ODE求解结果的绘图质量优化问题
问题根源
- 对数坐标对小数值区间的采样密度敏感度远高于线性坐标:默认求解器仅按数值误差阈值保存离散点,小数值区域点密度不足就会出现折线感。
- 固定
saveat=0.001报错的原因是部分参数下量子相结束点和经典相积分终点几乎重合,区间长度小于固定步长时会生成步长为0的非法序列。 - 原回调采用浮点数全等判断
==1.0,容易触发边界异常,导致经典相积分区间过短。
可行解决方案(无需手动调整saveat)
1. 用求解器内置插值按需重采样(最推荐)
DifferentialEquations.jl返回的解对象自带高精度连续插值,不需要依赖求解时保存的离散点,绘图前主动生成均匀采样点即可保证任意刻度下的平滑度,完全避免修改求解参数。
修改绘图代码为:
# 先生成解对象 sol1 = alpha_of_phi!(10000.0,-0.0009,0.0074847,2.0) sol2 = alpha_of_phi!(16.0,-0.1,0.00001,2.0) # 自定义ϕ采样网格,点数按需调整即可 t_grid = range(-2.0, 2.0, length=2000) # 用解的插值功能生成对应α值 plot(t_grid, sol1.(t_grid), yaxis=:log, label="参数组1") plot!(t_grid, sol2.(t_grid), label="参数组2")
2. 动态设置saveat避免报错
如果希望求解时直接保存足够的点,可以根据经典相的实际区间长度动态生成采样序列,永远不会触发步长为0的错误:
把solclass = solve(probclass,Tsit5())替换为:
t_start, t_end = classspan # 区间过短就直接保存端点,否则按固定间隔采样 if t_end - t_start < 1e-6 solclass = solve(probclass,Tsit5(), saveat=[t_start, t_end]) else # 按每0.001间隔采样,区间长度不够时自动适配 solclass = solve(probclass,Tsit5(), saveat=range(t_start, t_end, step=min(0.001, (t_end-t_start)/2))) end
3. 优化回调判断逻辑提升稳定性
把原全等判断的回调条件改为阈值判断,避免浮点数精度问题导致的区间异常:
condition(v,ϕ,integrator) = abs((ϕ*s2*sin(2*d*v[1])+2*d*sinh(s2*v[1]*ϕ))/(-v[1]*s2*sin(2*d*v[1])+2*d*cos(2*d*v[1])+2*d*cosh(s2*v[1]*ϕ)) - 1.0) < 1e-6
4. 优化解拼接逻辑避免重复点
原代码拼接量子相和经典相结果时会重复保存区间交界点,可能导致对数坐标下出现异常折点,修改拼接代码:
# 去掉量子相最后一个和经典相第一个重复的点 solu = append!(solquant[1,:][1:end-1], solclass[1,:]) solt = append!(solquant.t[1:end-1], solclass.t)
内容的提问来源于stack exchange,提问作者Free_ion
相关产品推荐
相关产品推荐

