刚性检测
概述
许多微分方程表现出某些形式的刚性,从而限制步长大小,进而限制了显式求解方法的有效性.
对于同样的步长,由于与内在的线性代数相关的开销,隐式方法的效率可能会显著低于显式方法.
由于在某些区域,隐式方法可以使用显著增加的步长,该成本可以被抵消.
我们作了多次尝试来提供用户友好的代码,以便自动尝试在运行时检测刚性,并在必要时在适当的方法之间转换.
这里对一些已经提出的自动为代码配备刚性检测设备的策略作一概述.
特别关注的是一个矩阵的主导特征值的估计问题,以描述刚性检测如何在 NDSolve 里实现.
初始化
引言
的数值解.刚性是问题、解法、初始条件和局部误差容差的一个结合体.
刚性出现在许多实际系统中,以及在由直线法求解的偏微分方程的数值解中.
示例
范德波尔振荡器是一个非保守的非线性阻尼振荡器,它是一个常微分方程:
方法 "StiffnessSwitching" 默认时使用一对插值方法:
解
问题是,当解快速变化时,几乎没有用刚性求解器的必要,因为局部准确性是主要问题.
为了提高效率,如果该方法能够自动检测出那些局部准备性(而不是稳定性)更为重要的区域,那将是很有用的.
线性稳定性
显式欧拉法
对于一个特征值 ,线性稳定性的要求表示步长需要满足 ,这是一个非常温和的限制.
然而,对于一个特征值 ,线性稳定性的要求表示步长需要满足 ,这是一个非常严格的限制.
示例
这个例子表明当使用显式 Runge-Kutta 方法求解一个刚性系统时,刚性对步长序列的影响.
隐式欧拉法
类型不敏感(Type Insensitivity)
一个对类型不敏感的求解器在每个步骤对刚性进行确认并有效地作出反应,因此对于问题的类型(有可能是变化的)是不敏感的.
这种类型的求解器中最完善的之一是 LSODA [H83], [P83].
LSODA 的后代求解器如 CVODE 不再纳入刚性检测设备. 原因是 LSODA 使用范数界限来估计主导特征值,而这些界限可以是相当不准确的,这一点将在后面的讨论中看到.
低阶的A(α)-稳定的 BDF 方法意味着 LSODA 和 CVODE 不适合求解具有高准确度的,或者主导特征值具有大的虚部的系统. 其他的方法,如那些基于线性隐式的方案的外推法就不会有这些问题.
关于刚性检测的大部分工作是在80年代和90年代使用独立的 FORTRAN 代码实现的.
此后,出现了新的线性代数技术和有效的软件,这些都可在 Wolfram 语言中获得.
刚性可以是一个短暂的现象,因此检测非刚性是同样重要的 [S77], [B90].
"StiffnessTest" 方法选项
直接估计
检测刚性的一个方便的方法就是直接估计该问题的雅克比 的主导特征值(见 [S77], [P83], [S83], [S84a], [S84c], [R87] 和 [HW96]).
这一个估计往往可以作为数值积分的副产品加以利用,所以代价合理地低.
如果 代表对应于雅可比的主导特征值的特征向量的一个近似,同时 足够小,那么根据中值定理,主导特征值的一个很好的近似是:
Richardson 外推法提供了产生这种形式的量的一个优化序列,如某些显式 Runge–Kutta方法一样
成本最多是两个函数计算,但是往往其中至少有一个是数值积分的副产品,因此它的代价合理地低.
用 表示线性稳定性边界——它是线性稳定性区域和负实轴的交集.
积 给出一个可以和一个方法的线性稳定性边界相比较的估计,以便检测刚性:
描述
方法 "DoubleStep"、"Extrapolation" 和 "ExplicitRungeKutta" 具有选项 "StiffnessTest",它可以用来识别该方法在应用指定的 AccuracyGoal 和 PrecisionGoal 容差时对于一个给定的问题是否是刚性的.
方法选项 "StiffnessTest" 本身接受许多选项来执行 (5) 的一个弱形,允许测试失败指定数目的次数.
这样做的原因是有些问题只在某些区域有轻度的刚性,而一个显式积分方法可能仍然是有效的.
"NonstiffTest" 方法选项
"StiffnessSwitching" 方法具有选项 "NonstiffTest",它用来把一个刚性方法转变回一个非刚性方法.
转化到一个非刚性求解器
对于刚性检测,具有精确到一或二位数字的解的一系列问题就足够了.
我们的目标是找到一种估算 矩阵系列 的主导特征值(的边界),以满足:
NormBound
获取主导特征值的界限的一个简单有效的技术是使用雅可比的范数 , 通常 或者 .
示例
直接特征值计算
选项 "NonstiffTest" 的设置 "Direct" 采用与 Eigenvalues 相同的 LAPACK 程序计算 的主导特征值.
对于较大的问题,直接计算特征值的代价是 ,当与在刚性求解器中进行的线性代数的代价相比时,变得不可接受.
为此,我们已经实现了许多迭代方案. 这些实际是通过在一个较小的子空间中对主导特征空间进行近似,以及对于较小的问题使用稠密特征值方法来工作的.
幂法
Shampine 提出了采用幂法来估计雅可比的主导特征值 [S91].
幂法也许不是一个很备受尊重的方法,但是由于它在 Google 页面排名中的使用,很多人已经重新对其表示兴趣.
描述
属性
推广
幂法可以通过适应性修正来克服等模(equimodular)特征值问题(如 NAPACK).
子空间迭代
子空间(或同时)迭代通过每一步作用于 m 个向量推广了幂法中的思想.
为了防止所有向量收敛到 的同一主导特征向量 的倍数,它们被正交归一化:
Rayleigh–Ritz 投影
收敛性
子空间(或者同时)迭代通过在每一步作用于 个向量,推广了幂法中的思想.
因此,采用比如 或者更多是有益的,即使我们只对主导特征值感兴趣.
误差控制
这是有利的,因为它适用于等模(equimodular)特征值.
因为有序 Schur 分解的使用,要对上三角矩阵 的第一列的位置进行测试.
实施
- LOPSI [SJ81]
- Schur Rayleigh–Ritz 迭代 [BS97]
为基础的. "SRRIT 的一个吸引人的特点是它显示了单调一致性,即当收敛容差减小时,计算得的残差的大小也减小" [LS96].
SRRIT 用到了有序 Schur 分解,其中具有最大模的特征值出现在左上角的项中.
KrylovIteration
给定一个 矩阵 ,其列 组成了一个给定子空间 的正交基:
Rayleigh Ritz 程序包含计算 以及求解相关的特征值问题 .
原问题的近似特征对 , 满足 和 ,它们被称为 Ritz 值和 Ritz 向量.
当 等于与矩阵 和给定初始向量 相关的 Krylov 子空间时,这个过程有效:
描述
Arnoldi 方法是一种基于 Krylov 的投影算法,它计算 Krylov 子空间的一个正交基,并且产生一个投影的 矩阵 其中 .
在 Arnoldi 的情况下, 具有一个未约化(unreduced)的上黑森贝格形式( upper Hessenberg form),即具有一个额外的非零次对角的上三角.
残差 给出了一个对不变子空间的近似的指示,相关的范式 表明了计算 Ritz 对的精度:
重启
如果初始向量 在预期特征值的方向是丰富的话,Ritz 对的收敛速度很快的.
当情况并非如此时,则需要一个重新启动的策略,以避免工作量和内存的过快增长.
显式重启的实现相对简单,但是隐式重启更有效,因为它保留了更大问题的相关特征信息. 然而,隐式重启以数值稳定的方式实现起来会很困难.
另一种方法更容易实现,但是可以达到与隐式重启相同的效果,它是 Krylov–Schur方法 [S01].
实现
- ARPACK [ARPACK98]
- SLEPc [SLEPc05]
Automatic 策略
"Automatic" 设置使用这些方法的一个组合,情形如下.
步骤拒绝
对计算时间的缓存确保了主导特征值估计不在被拒绝的步骤重新计算.
迭代方法选项
"NonstiffTest" 的迭代方法具有可被修改的选项:
默认容差的目的是只有一个正确数位,但往往得到更准确的值——特别是在连续的步骤中几个成功的迭代之后.
延迟和切换
有一点很重要,就是将某种形式的延迟结合进来,以避免一种 "StiffnessSwitching" 方法不断尝试在刚性和非刚性方法之间切换的循环.
为此目的,我们使用 "StiffnessTest" 和 "NonstiffTest" 的选项 "MaxRepetitions" 和 "SafetyFactor".
示例
Van der Pol
StiffnessTest
NonstiffTest
这个例子是一个很好的测试,体现了整体刚性切换架构的行为正如预期.
CUSP
关于神经冲动机制的 cusp catastrophe 模型 [Z72]:
与 Van der Pol 振荡器相结合产生了 CUSP 系统 [HW96]:
利用直线法对扩散项进行离散化从而得到一个维度为 的常微分方程组.
与 Van der Pol 系统不同,因为问题的大小,我们采用迭代方法来进行特征值估计.
步长和阶数选择
雅可比实例
一个到刚性方法的转换出现在 0.00113425 附近,而非刚性的第一个测试出现在下一步 .
Korteweg–deVries
Korteweg–deVries 偏微分方程是在浅水表面的波浪的数学模型:
采用直线法的离散化用来形成由 192 个常微分方程组成的方程组.
步长
一旦在积分开始的时候选择了刚性方法,插值法从来不会切换回非刚性求解器.
雅可比实例
范数界限略被高估,但更重要的是,他们没有提供实部和虚部的相对大小的显示:
选项总结
StiffnessTest
选项名 | 默认值 | |
"MaxRepetitions" | {3,5} | 指定刚性测试 (6) 允许的连续失败的最大次数和失败的总次数的最大值 |
"SafetyFactor" | 指定在刚性测试 (7) 的右侧所使用的安全系数 |