常微分方程(ODE)有时很难求解,但 MATLAB 提供了功能强大的符号计算工具来帮助我们。dsolve 函数专门用于计算常微分方程的符号解。
由于是求解微分方程,我们需要一种方法在表达式中表示导数。dsolve 的语法与其他大部分 MATLAB 函数有所不同:它使用字母 D 来表示求导。D2、D3 等表示二阶、三阶等重复求导。任何 D 后面紧跟的字母代表因变量。
例如,方程 $y'' = 0$ 可以用符号表达式 D2y=0 来表示。如果不特别指定,独立变量(自变量)可以手动指定,或者由系统 symvar 规则选定为默认变量(通常是 t 或 x)。
1. 一阶常微分方程
我们以一阶方程 $\frac{dy}{dx} = 1 + y^2$ 为例,求其通解:
>> dsolve('Dy = 1 + y^2') % 寻找通解
ans =
-tan(-x + C1)
注:其中 C1 是积分常数。
如果我们要为同一个方程添加初始条件 $y(0) = 1$,可以这样写:
>> dsolve('Dy = 1 + y^2', 'y(0) = 1') % 添加初始条件
ans =
tan(x + 1/4*pi)
如果你想指定自变量(例如将自变量指定为 v),可以采用如下形式:
>> dsolve('Dy = 1 + y^2', 'y(0) = 1', 'v') % 求解 dy/dv
ans =
tan(v + 1/4*pi)
2. 二阶常微分方程
让我们来看一个带有两个初始条件的二阶微分方程示例:
初始条件:$y'(0) = 0, y(0) = 1$
在 MATLAB 中求解:
>> y = dsolve('D2y = cos(2*x) - y', 'Dy(0) = 0', 'y(0) = 1')
y =
-2/3*cos(x)^2 + 1/3 + 4/3*cos(x)
我们可以使用 simple(或较新版本中的 simplify)来化简结果:
>> y = simple(y) % 化简表达式
y =
-1/3*cos(2*x) + 4/3*cos(x)
包含一阶以上项的方程
通常,我们要解的微分方程会包含多阶导数项,例如:
求该方程的通解(注:原文此处存在笔误使用了 solve,求解微分方程应始终使用 dsolve):
>> y = dsolve('D2y - 2*Dy - 3*y = 0')
y =
C1*exp(-x) + C2*exp(3*x)
加上初始条件 $y(0) = 0$ 和 $y(1) = 1$:
>> y = dsolve('D2y - 2*Dy - 3*y = 0', 'y(0) = 0', 'y(1) = 1')
y =
1/(exp(-1) - exp(3))*exp(-x) - 1/(exp(-1) - exp(3))*exp(3*x)
>> y = simple(y) % 化简结果
y =
-(exp(-x) - exp(3*x))/(exp(3) - exp(-1))
为了让输出结果更符合人类的数学阅读习惯,可以使用 pretty 函数:
>> pretty(y) % 美化输出格式
exp(-x) - exp(3 x)
- ---------------------
exp(3) - exp(-1)
3. 绘制结果图像
得到符号解后,我们通常需要在感兴趣的区域内绘制结果。可以使用 ezplot 快速绘图:
>> ezplot(y, [-6, 2])
(图 22.3 符号函数 $y = -\frac{e^{-x} - e^{3x}}{e^3 - e^{-1}}$ 在 $-6 \le x \le 2$ 区间的图像)
4. 求解微分方程组
dsolve 函数也可以同时处理由多个微分方程组成的方程组。以下面两个线性一阶方程构成的系统为例:
求通解的代码如下:
>> [f, g] = dsolve('Df = 3*f + 4*g', 'Dg = -4*f + 3*g')
f =
C1*exp(3*x)*sin(4*x) + C2*exp(3*x)*cos(4*x)
g =
-C2*exp(3*x)*sin(4*x) + C1*exp(3*x)*cos(4*x)
加上初始条件 $f(0) = 0$ 和 $g(0) = 1$,我们可以得到特解:
>> [f, g] = dsolve('Df = 3*f + 4*g', 'Dg = -4*f + 3*g', 'f(0) = 0', 'g(0) = 1')
f =
exp(3*x)*sin(4*x)
g =
exp(3*x)*cos(4*x)
? 编者提示(关于 MATLAB 版本更新):
在较新的 MATLAB 版本中,符号数学工具箱中的
simple函数已经被整合并推荐使用 simplify 函数替代,以获得更好的化简效果。同样地,传统的绘图函数
ezplot在新版本中已不被推荐,建议使用更为强大且灵活的 fplot 来绘制符号表达式的图像。