d
t
d
x
(
t
)
∣
t
=
0
=
0
.
完整的求解过程如下代码所示。
import numpy as np
from scipy import integrate
import sympy
def apply_ics(sol, ics, x, known_params):
Apply the initial conditions (ics), given as a dictionary on
the form ics = {y(0): y0, y(x).diff(x).subs(x, 0): yp0, ...},
to the solution of the ODE with independent variable x.
The undetermined integration constants C1, C2, ... are extracted
from the free symbols of the ODE solution, excluding symbols in
the known_params list.
free_params = sol.free_symbols - set(known_params)
eqs = [(sol.lhs.diff(x, n) - sol.rhs.diff(x, n)).subs(x, 0).subs(ics) for n in range(len(ics))]
sol_params = sympy.
solve(eqs, free_params)
return sol.subs(sol_params)
sympy.init_printing()
t, omega0, gamma = sympy.symbols("t, omega_0, gamma", positive=True)
x = sympy.Function('x')
ode = x(t).diff(t, 2) + 2 * gamma * omega0 * x(t).diff(t) + omega0**2*x(t)
ode_sol = sympy.dsolve(ode)
ics = {x(0): 1, x(t).diff(t).subs(t, 0): 0}
x_t_sol = apply_ics(ode_sol, ics, t, [omega0, gamma])
sympy.pprint(x_t_sol)
⎛ _______ _______⎞
⎛ γ 1⎞ ω₀⋅t⋅⎝-γ - ╲╱ γ - 1 ⋅╲╱ γ + 1 ⎠ ⎛ γ
x(t) = ⎜- ───────────── + ─⎟⋅ℯ + ⎜─────────────
⎜ ________ 2⎟ ⎜ ________
⎜ ╱ 2 ⎟ ⎜ ╱ 2
⎝ 2⋅╲╱ γ - 1 ⎠ ⎝2⋅╲╱ γ - 1
⎛ _______ _______⎞
1⎞ ω₀⋅t⋅⎝-γ + ╲╱ γ - 1 ⋅╲╱ γ + 1 ⎠
+ ─⎟⋅ℯ
- [https://vlight.me/2018/05/01/Numerical-Python-Ordinary-Differential-Equations/]
- [https://docs.sympy.org/latest/search.html?q=]
当ODE无法求得解析解时,可以用scipy中的integrate.odeint求数值解来探索其解的部分性质,并辅以可视化,能直观地展现ODE解的函数表达。
以如下一阶非线性(因为函数y幂次为2)ODE为例,
dxdy=x−y(x)2.
现用odeint 求其数值解,代码与可视化如下。
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
import sympy
def plot_direction_field(x, y_x, f_xy, x_lim=(-5, 5), y_lim=(-5, 5), ax=None):
f_np = sympy.lambdify((x, y_x), f_xy, 'numpy')
x_vec = np.linspace(x_lim[0], x_lim[1], 20)
y_vec = np.linspace(y_lim[0], y_lim[1], 20)
if ax is None:
_, ax = plt.subplots(figsize=(4, 4))
dx = x_vec[1] - x_vec[0]
dy = y_vec[1] - y_vec[0]
for m, xx in enumerate(x_vec):
for n, yy in enumerate(y_vec):
Dy = f_np(xx, yy) * dx
Dx = 0.8 * dx**2 / np.sqrt(dx**2 + Dy**2)
Dy = 0.8 * Dy*dy / np.sqrt(dx**2 + Dy**2)
ax.plot([xx - Dx/2, xx + Dx/2], [yy - Dy/2, yy + Dy/2], 'b', lw=0.5)
ax.axis('tight')
ax.set_title(r"$%s$" %(sympy.latex(sympy.Eq(y_x.diff(x), f_xy))), fontsize=18)
return ax
x = sympy.symbols('x')
y = sympy.Function('y')
f = x-y(x)**2
f_np = sympy.lambdify((y(x), x), f)
y0 = 1
xp = np.linspace(0, 5, 100)
yp = integrate.
odeint(f_np, y0, xp)
xn = np.linspace(0, -5, 100)
yn = integrate.odeint(f_np, y0, xm)
fig, ax = plt.subplots(1, 1, figsize=(4, 4))
plot_direction_field(x, y(x), f, ax=ax)
ax.plot(xn, yn, 'b', lw=2)
ax.plot(xp, yp, 'r', lw=2)
plt.show()
右侧曲线跟方向场贴合一致,但左侧蓝线的数值解诡异,明显不满足ODE的表达式,这也说明数值解的局限性。

以求解洛伦兹曲线为例,以下方程组代表曲线在xyz三个方向上的速度,给定一个初始点,可以画出相应的洛伦兹曲线。
\begin{cases} \frac{dx}{dt} = p(y-x), \\ \frac{dy}{dt} = x(r-z), \\ \frac{dz}{dt} = xy-bz,. \end{cases}
⎩⎪⎨⎪⎧dtdx=p(y−x),dtdy=x(r−z),dtdz=xy−bz,.
代码与图如下。
import numpy as np
from scipy.integrate import odeint
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def dmove(Point, t, sets):
point:present location index
sets:super parameters
p, r, b = sets
x, y, z = Point
return np.array([p * (y - x), x * (r - z), x * y - b * z])
t = np.arange(0, 30, 0.001)
P1 = odeint(dmove, (0., 1., 0.), t, args=([10., 28., 3.],))
P2 = odeint(dmove, (0., 1.01, 0.), t, args=([10., 28., 3.],))
fig = plt.figure()
ax = Axes3D(fig)
ax.plot(P1[:, 0], P1[:, 1], P1[:, 2])
ax.plot(P2[:, 0], P2[:, 1], P2[:, 2])
plt.show()
洛伦兹曲线很好地展示了非线性的直观形态,同时也是展示混沌系统的经典例子。这个例子告诉我们,混沌系统可以是一个确定系统,不一定是随机过程,同时它有初值敏感的特征。

参考
scipy.integrate.odeint用法
Python解微分方程微分方程回顾微分方程:python 解析解(SymPy)微分方程:python数值解(SciPY)微分方程组:python数值解微分方程回顾微分方程是用来描述某一类函数与其导数之间的关系的方程,其解是一个符合方程的函数。(解为常数值的是代数方程)微分方程的求解是研究微分方程的重点之一,例如解是否存在,存在是否唯一等等。只有少数类型的微分方程存在解析解;无法求得解析解时,...
标签:程序猿|C++选手|学生
简介:因C语言结识编程,随后转入计算机专业,有幸拿过一些国奖、省奖…已保研。目前正在学习C++/Linux/Python
学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语!
初学Python 小白阶段
文章仅作为自己的学习笔记 用于知识体系建立以及复习
题不在多 学一题 懂一题
知其然 知其所
有很多大学生问我,学习
python有什么用呢?我说:你至少可以用来
解微分方程,如下面的例子,就是
解决
微分方程:y"+a*y'+b*y=0 代码如下:#y"+a*y'+b*y=0
from scipy.integrate import
odeint
from pylab import *
def deriv(y,t): # 返回值是y和y的导数组成的数组
a = -2.0
1.Python解微分方程数值解
Python解微分方程要用到几个库:numpy, matplotlib.pyplot, scipy.integrate,没有的话就
pip install 相应的库就行,本次用的python为3.6.8
我们先来看一下简单的微分方程
但是我们知道了它的初始条件,这对于我们叠代求解很有帮助,也是必须的。
那么现在我们也用Python去解决这一些问题,一般的数值解法有欧拉法、隐式梯形法等,我们也来看看这些算法对叠代的精度有什么区别?
```python
```python
import numpy as np
from scipy.integrate import odeint
from matplotlib
然后,需要定义
微分方程的函数。这个函数需要有两个参数:一个是变量(通常用t表示),另一个是状态变量(通常用y表示)。函数的返回值是状态变量的导数。
例如,假设要
解决如下
微分方程:
dy/dt = -2*y + 4*t
可以定义如下函数:
```
python
def my
ode(y, t):
dydt = -2*y + 4*t
return dydt
接下来,需要指定初值和时间范围:
```
python
y0 = 1.0 # 初始状态变量的值
t = np.linspace(0, 5, 101) # 时间范围,从0到5,共101个点
最后,可以使用
odeint函数
解方程:
```
python
sol =
odeint(my
ode, y0, t)
其中,第一个参数是
微分方程的函数,第二个参数是初始状态变量的值,第三个参数是时间范围。
解出的结果保存在sol变量中。
如果要绘制状态变量随时间变化的图像,可以使用Matplotlib库:
```
python
import matplotlib.pyplot as plt
plt.plot(t, sol)
plt.xlabel('Time')
plt.ylabel('State variable')
plt.show()
这样就可以得到状态变量随时间变化的图像了。
绿宝书 (翻译)
H-H.bph: