用条件语句求解一组常微分方程

Solving a set of ODE with conditional statement

提问人:geo.freitas 提问时间:10/13/2023 最后编辑:toyota Suprageo.freitas 更新时间:10/13/2023 访问量:54

问:

我正在尝试用 Python 求解一组微分方程。基本上,我想绘制下图:

Graph that I want to generate

这是一张图表,显示了营养物质 (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)

但是,生成的图形如下所示:Graph generated by the code

如您所见,营养物质的浓度不会像应有的那样降低,因为har_dil考虑的变量的值只是条件语句的最终值。如果有人能帮助我制定解决这个问题的策略,我将不胜感激。

python matplotlib if 语句 微分方程

评论


答:

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_dilif

(2.) 该表达式显然是 尝试注入一些周期性,如你的第一个图所示。 好。 但是,公平的警告是,询问 FP 数量是否正好等于零是相当命中注定的。 建议你要么把 或者询问模结果是否“接近”零。 也就是说,选择一个小的epsilon并询问是否.t % har_f == 0int(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
一个点的常微分方程变化不会改变精确的解,数值求解器可能会被驱动到小步长,但可能会完全错过该点或其周围的小间隔。最好在这些点停止积分,对参数或状态向量进行预期的更改,然后恢复积分,直到下一个有趣的时间。