跳转至

离散积分法

本文内容与 微分方程的离散化 有重合之处,需结合阅读。

概述

我们考虑如下连续系统:

\[\dot{\mathbf{x}} = f(\mathbf{x})\]

一般来说,描述一个系统的状态方程还会包括一个输入变量 \(\mathbf{u}\) ,但在一个控制周期内,输入变量 \(\mathbf{u}\) 不发生变化,可视为常量,因此我们不加以考虑。

我们要解决的问题是,已知连续信号采样保持的周期 \(\Delta t\) 和当前状态量采样结果 \(\mathbf{x}_k\) ,如何求解下一时刻的状态量 \(\mathbf{x}_{k+1}\) ? 这个问题在数值求解、模拟仿真中经常遇到。

解决该问题有两大流派:显式积分法和隐式积分法。显式积分法的计算方式为:

\[\mathbf{x}_{k+1} = f_{\mathrm{explicit}}(\mathbf{x}_{k},\Delta t)\]

隐式积分法的计算方式为:

\[f_{\mathrm{implicit}}(\mathbf{x}_{k+1},\mathbf{x}_k,\Delta t) = 0\]

两者最关键的区别是, \(\mathbf{x}_{k+1}\) 是否在函数 \(f\) 里面。如果“否”,我们就不用解方程,可以直接显式地计算出 \(\mathbf{x}_{k+1}\) ;如果“是”,那我们还得解个方程。

总体而言,隐式积分法虽然计算复杂度高,但精度也略高于显式积分法。下图是某个系统的实验结果,其中前向欧拉法和后向欧拉法精度存在差异,主要是系统特性导致的。从方法本身看,其精度应该是一致的。

显式积分法

前向欧拉法

\[\mathbf{x}_{k+1} = \mathbf{x}_k + \Delta t \cdot f(\mathbf{x}_k)\]

\(\mathbf{x}_{k+1}\)\(\mathbf{x}_k\) 处一阶泰勒展开,用 \(\mathbf{x}_k\) 处的切线替代原函数。

中点法

\[\begin{aligned} \mathbf{x}_{\mathrm{mid}} &= \mathbf{x}_k + \frac{\Delta t}{2} \cdot f(\mathbf{x}_k)\\ \mathbf{x}_{k+1} &= \mathbf{x}_k + \Delta t \cdot f(\mathbf{x}_{\mathrm{mid}}) \end{aligned}\]

RK4

RK4,全称 4 阶 Runge-Kutta 法(龙格库塔法)。

\[\begin{aligned} k_1 &= \Delta t \cdot f(\mathbf{x}_k)\\ k_2 &= \Delta t \cdot f(\mathbf{x}_k + k_1/2)\\ k_3 &= \Delta t \cdot f(\mathbf{x}_k + k_2/2)\\ k_4 &= \Delta t \cdot f(\mathbf{x}_k + k_3)\\ \mathbf{x}_{k+1} &= \mathbf{x}_k + \frac{1}{6}(k_1+2k_2+2k_3+k_4) \end{aligned}\]

隐式积分法

隐式积分法的思路是先写出 \(f_{\mathrm{implicit}}\) ,然后求这个函数以 \(\mathbf{x}_{k+1}\) 为自变量时的零点。

很多时候我们无法形式化地求解方程,最常用的还是各类数值解法,比如牛顿法。

顺嘴提一句,很多库都能求解牛顿法所需的 Jacobian 矩阵,它们用的也是数值法,用前向差分或者中心差分,来近似计算偏导数。

后向欧拉法

\[\mathbf{x}_k+\Delta t \cdot f(\mathbf{x}_{k+1})-\mathbf{x}_{k+1} = 0\]

\(\mathbf{x}_k\)\(\mathbf{x}_{k+1}\) 处一阶泰勒展开,用 \(\mathbf{x}_{k+1}\) 处的切线代替原函数。

隐式中点法

\[\begin{aligned} \mathbf{x}_{k+\frac{1}{2}}=\frac{1}{2}(\mathbf{x}_k+\mathbf{x}_{k+1})\\ \mathbf{x}_k+\Delta t\cdot f\left(\mathbf{x}_{k+\frac{1}{2}}\right)-\mathbf{x}_{k+1} = 0 \end{aligned}\]

Hermite-Simpson 法

\[\begin{aligned} \mathbf{x}_{k+\frac{1}{2}}=\frac{1}{2}(\mathbf{x}_k+\mathbf{x}_{k+1})+\frac{\Delta t}{8}[f(\mathbf{x}_k)-f(\mathbf{x}_{k+1})]\\ \mathbf{x}_k+\frac{\Delta t}{6}\left[f(\mathbf{x}_k)+4f\left(\mathbf{x}_{k+\frac{1}{2}}\right)+f(\mathbf{x}_{k+1})\right]-\mathbf{x}_{k+1}=0 \end{aligned}\]