提问人:geo.freitas 提问时间:10/13/2023 最后编辑:toyota Suprageo.freitas 更新时间:10/13/2023 访问量:54
用条件语句求解一组常微分方程
Solving a set of ODE with conditional statement
问:
我正在尝试用 Python 求解一组微分方程。基本上,我想绘制下图:
这是一张图表,显示了营养物质 (Am) 和浮游植物 (Phy) 的浓度如何随时间变化。 我必须将两个变量绘制为时间函数的 Python 代码:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
# parameters
dil = 0.2
har_f = 20
har_pc = 0.95
ext_Am = 100
umax_Phy = 0.693
kAm_Phy = 14
t0 = 0
tf = 100
ns = 200
dt = (tf-t0)/(ns-1)
params = [dil, har_f, har_pc, ext_Am, umax_Phy, kAm_Phy, t0, tf, ns, dt]
def odes(t,x):
dx = [0,0]
har_dil = 0
if t > 0 and t % har_f == 0:
har_dil = har_pc/dt
else:
har_dil = 0
time_dil = params[0] + har_dil
in_Am = params[3] * time_dil
u_Phy = params[4]*x[0]/(x[0]+params[5])
gro_Phy = u_Phy * x[1]
out_Am = x[0] * time_dil
out_Phy = x[1] * time_dil
dx[0] = in_Am - out_Am - gro_Phy
dx[1] = gro_Phy - out_Phy
return dx
# initial conditions:
x0 = [99,1]
# declare a time vector(time window)
tspan = (0,100)
# solving the set of ODEs
sol = solve_ivp(odes,tspan,x0)
fig1,axs_lst = plt.subplots(nrows=1,ncols=1,squeeze=False)
axs_lst[0,0].plot(sol.t,sol.y[0, :],'-',color='red',label='Am')
axs_lst[0,0].plot(sol.t,sol.y[1, :],color='green',label='Phy')
axs_lst[0,0].legend(loc='best',frameon=True,edgecolor='black',fancybox=False)
axs_lst[0,0].set_xlabel('Time [day]',size='12')
axs_lst[0,0].set_ylabel('Concentration [$g\:biomass\:m^{-3}$]',size='12')
axs_lst[0,0].tick_params(axis='both', which='both', direction='in')
axs_lst[0,0].grid(True)
如您所见,营养物质的浓度不会像应有的那样降低,因为har_dil考虑的变量的值只是条件语句的最终值。如果有人能帮助我制定解决这个问题的策略,我将不胜感激。
答:
1赞
J_H
10/13/2023
#1
你写道:
if t == 0:
har_dil = 0
elif t > 0 and t % har_f == 0:
har_dil = har_pc/dt
else:
har_dil = 0
har_dil = 0
好吧,那里发生了几件事。
(1.)你费了不少劲才算出,
然后你无条件地将其归零。
这不可能是你想要的。
建议你把作为助手函数分解出来,
并无条件地分配该函数的结果。har_dil
if
(2.) 该表达式显然是
尝试注入一些周期性,如你的第一个图所示。
好。
但是,公平的警告是,询问 FP 数量是否正好等于零是相当命中注定的。
建议你要么把
或者询问模结果是否“接近”零。
也就是说,选择一个小的epsilon并询问是否.t % har_f == 0
int(t)
abs(t % har_f) < epsilon
评论
0赞
geo.freitas
10/13/2023
是的,确实,这不是故意的。实际上,har_dil = 0 行应该写在 if 语句之前,因为这是通常的值,除非时间是 20 的倍数 (har_f = 20)。正如您建议的那样,我尝试将 abs(t % har_f) < epsilon 一起使用,但生成的图形仍然相同。我还更新了代码,使 har_dil = 0 行位于条件语句之前。
0赞
Lutz Lehmann
10/13/2023
一个点的常微分方程变化不会改变精确的解,数值求解器可能会被驱动到小步长,但可能会完全错过该点或其周围的小间隔。最好在这些点停止积分,对参数或状态向量进行预期的更改,然后恢复积分,直到下一个有趣的时间。
评论