繁体   English   中英

使用forloop求解python中的耦合微分方程

[英]Using a forloop to solve coupled differential equations in python

我正在尝试求解一组微分方程,但我一直难以完成这项工作。 我的微分方程包含一个“i”下标,表示从 1 到 n 的数字。 我尝试按如下方式实现 forloop,但我一直收到此索引错误(错误消息如下)。 我曾尝试更改初始条件 (y0) 和其他值,但似乎没有任何效果。 在此代码中,我使用的是 solve_ivp。 代码如下:

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.integrate import solve_ivp

def testmodel(t, y):
    X = y[0]
    Y = y[1]
    J = y[2]
    Q = y[3]
    a = 3
    S = 0.4
    K = 0.8
    L = 2.3
    n = 100 
    for i in range(1,n+1):
        dXdt[i] = K**a+(Q[i]**a) - S*X[i]
        dYdt[i] = (K*X[i])-(L*Y[i])
        dJdt[i] = S*Y[i]-(K*Q[i])
        dQdt[i] = K*X[i]/L+J[i]
        return dXdt, dYdt, dJdt, dQdt
t_span= np.array([0, 120])
times = np.linspace(t_span[0], t_span[1], 1000) 
y0 = 0,0,0,0
soln = solve_ivp(testmodel, t_span, y0, t_eval=times, 
vectorized=True)
t = soln.t
X = soln.y[0]
Y = soln.y[1]
J = soln.y[2]
Q = soln.y[3]

plt.plot(t, X,linewidth=2, color='red')
plt.show()    

我得到的错误是

IndexError                Traceback (most recent call last)
<ipython-input-107-3a0cfa6e42ed> in testmodel(t, y)
     15     n = 100
     16     for i in range(1,n+1):
 --> 17     dXdt[i] = K**a+(Q[i]**a) - S*X[i]
   
 IndexError: index 1 is out of bounds for axis 0 with size 1

我已经分散了 web 来解决这个问题,但我一直无法对这个问题应用任何解决方案。 我不确定我做错了什么以及实际要改变什么。

我试图删除“vectorized=True”参数,但随后收到一条错误消息,指出我无法索引标量变量。 这令人困惑,因为我认为这些值不应该是标量。 我如何解决这个问题,我的最终目标是plot这些微分方程。 先感谢您。

很高兴您为标准求解器提供矢量化 ODE function 以进行多点计算。 但默认方法是显式 RK45,显式方法不使用雅可比矩阵。 因此不需要对偏导数的差商进行多点求值。

本质上,坐标 arrays 的大小始终为 1,因为评估是在单个点进行的,因此例如Q是一个长度为 1 的数组,唯一有效的索引是 0。请记住,在所有“真正的”编程语言中,数组索引从 0 开始。只有一些 CAS 脚本语言使用“更数学”的 1 作为索引开始。 (设置n=100并忽略求解器提供的 arrays 的长度也是错误的。)

你可以避免所有这些并通过考虑到标准算术运算是按元素应用 numpy arrays 来缩短你的例程,所以

def testmodel(t, y):
    X,Y,J,Q = y
    a = 3; S = 0.4; K = 0.8; L = 2.3
    dXdt = K**a + Q**a - S*X
    dYdt = K*X - L*Y
    dJdt = S*Y - K*Q
    dQdt = K*X/L + J
    return dXdt, dYdt, dJdt, dQdt

使用相同的动态修改多个隔间的代码

您需要将 state 的平面向量传递给求解器。第一个设计决策是如何在平面向量中排列隔间及其组件。 与现有代码最兼容的一种变体是将相同的组件聚集在一起。 然后在 ODE function 中,第一个操作是分离出这些簇。

    X,Y,J,Q = y.reshape([4,-1])

这会将输入向量分成 4 个等长的片段。 最后,您需要扭转这种分裂,以便导数再次处于平面向量中。

    return np.concatenate([dXdt, dYdt, dJdt, dQdt])

其他一切都保持不变。 除了初始向量,它需要有 4 个长度为N的片段,其中包含隔间的数据。 这可能只是

    y0 = np.zeros(4*N)

如果初始数据来自任何其他来源,并且以每个隔间的记录为单位,则您可能必须在展平之前转置结果数组。

请注意,此构造矢量化,因此请将该选项的默认值False保留为未设置。

对于像圆圈这样的统一交互模式,我建议使用numpy.roll来继续避免使用显式循环。 对于看起来像 a.network 的交互模式,可以使用连接矩阵和掩码,如Using python built-in functions for coupled ODEs

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM