大家好,在上一篇博文中,我介绍了如何使用Scipy库计算定积分和二重积分,感兴趣的可以看一下:https://blog.csdn.net/dgvv4/article/details/124226759
本文将继续使用 scipy.integrate 库求解常微分方程。
微分方程是指一个方程中有导数,表示未知函数的导数以及自变量之间关系的方程。未知函数是一元函数的微分方程称作常微分方程。未知函数是多元函数的微分方程称作偏微分方程。微分方程中出现的未知函数最高阶导数的阶数,成为微分方程的阶。例如:
或
'''
scipy.integrate中微分方程的求解方法
# -------------------------------------- #
odeint 常微分方程的通用函数
ode 求解常微分和偏微分
complex_ode 在复数域求解微分方程
# -------------------------------------- #
'''
本文之介绍 scipy.integrate.odeint() 求解常微分方程的方法,该函数的参数如下:
'''
参数
# -------------------------------------- #
func 常微分方程函数
y0 微分方程求解出的原函数的初值,导数:2x 原函数: x^(2) + y0
t 微分方程的自变量数值序列
args 元组。func被积函数的自变量以外,需要的其他变量的参数,
# -------------------------------------- #
返回值:对应自变量序列的原函数的值
'''
求解常微分方程 ,由于计算机不会计算出具体的公式,只会根据传进去的数据,计算出求解后的计算结果数据,因此自变量 x 应该传入一组数值序列 np.linspace(0, 10, 100) 。设置求解后的原函数初值y0=0
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
# 定义导数 y'=x, 求出原函数
def diff(y, x):
res = np.array(x)
# 返回导数
return res
# 给出x的范围, 从0到10产生100个数
x = np.linspace(0, 10, 100)
# 求原函数, 初值为0, 自变量为x
y = odeint(func=diff, y0=0, t=x) # y.shape=[100,1]
# 绘制导函数曲线
plt.plot(x, np.array(x), label='derivative')
# 绘制求解后的曲线
plt.plot(x, y[:,0], label='origin') # y[:,0].shape=(100,)
plt.grid() # 网格
plt.legend() # 图例
plt.show()
绘制原导函数的曲线,和求解出的原函数的曲线
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
# 定义导数 y'=x, 求出原函数
def diff(y, x, k, n, b):
res = k * (np.array(x) ** n) + b
# 返回导数
return res
# 给出x的范围, 从0到10产生100个数
x = np.linspace(0, 10, 100)
# 求原函数, 初值为100, 自变量为x, k,n,b=(3.0, 2, 4.0)
y = odeint(func=diff, y0=100.0, t=x, args=(3.0, 2, 4.0)) # y.shape=[100,1]
# 绘制导函数曲线
plt.plot(x, 3.0*(np.array(x)**2)+4.0, label='derivative')
# 绘制计算结果函数曲线
plt.plot(x, y[:,0], label='origin') # y[:,0].shape=(100,)
plt.grid() # 网格
plt.legend() # 图例
plt.show()
绘制原导函数的曲线,和求解出的结果函数的曲线
洛伦兹方程是大气流体动力学模型的一个简化的常微分方程组:
该模型将大气流体运动的强度 x 与水平和垂直方向的温度变化 y 和 z 联系了起来。参数 称为普兰特系数,r 是规范化的瑞利数,b 和几何形状相关。洛伦兹方程是非线性方程组,无法求出解析解,必须使用数值方法求解上述微分方程组。
首先需要定义出洛伦兹函数 lorenz,位置参数 w 包含三维坐标 (x, y, z),参数 p 代表普兰特系数。构建和上面公式相同的导函数。自变量为 t,计算出三个坐标对于自变量 t 的导函数。
求解后的位置坐标点初始值 (x0, y0, z0)=(0.0, 1.0, 0.0),args对应三个洛伦兹参数 (p, r, b)=(10.0, 28.0, 3.0)
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
# 定义洛伦兹函数, 位置矢量w, 三个参数p、r、b
def lorenz(w, t, p, r, b):
x, y, z = w.tolist() # tolist()是把数组中的值作为列表元素, 生成列表与原数组结构相同
# 计算导数 dx/dt, dy/dt, dz/dt
return p*(y-x), x*(r-z)-y, x*y-b*z
# 自变量的取值序列, 0到30,步长0.02
t = np.arange(0, 30, 0.02)
# x, y, z的初值
initial_val = (0.0, 1.0, 0.0)
# 求解常微分方程, args是p、r、b的值, track.shape=(1500, 3)
track = odeint(func=lorenz, y0=initial_val, t=t, args=(10.0, 28.0, 3.0))
# 绘图
fig = plt.figure()
ax=fig.gca(projection='3d') # 三维绘图
# 取出xyz坐标点值
x, y, z = track[:,0], track[:,1], track[:,2]
ax.plot(x,y,z)
plt.show()
绘制洛伦兹方程求解出的x,y,z坐标