大规模复杂系统集成建模与仿真技术漫谈(一):模型太大,跑不动!?
1 系统仿真
对于理工科出身的人,建模仿真这件事是再熟悉不过的了。从学生时代开始,很多人就会开始练习用各种商业软件或手敲代码进行仿真分析,可以说是基本功。当遇到大规模复杂系统时(比如想了解一个复杂系统的动态特性),系统仿真是一个非常合适的方法,事实上在不同工程领域中系统仿真的应用已不胜枚举。
系统仿真本质上是常微分方程的初值问题(ODE - IVP, Ordinary Differential Equation - Initial Value Problem)。工程技术中的很多现象,如控制系统、电力系统、飞行器运动、化学反应过程等,其数学模型都是常微分方程(组)的初值问题,很多偏微分方程也可以简化成常微分方程(组)的初值问题,对ODE - IVP进行计算正是系统仿真的核心内容。
2 模型求解速度
刚开始,我们利用系统仿真处理一些简单问题,一般都会得到不错的效果。随着工作的深入,当模型复杂到一定程度后,一个无法回避的问题就会逐渐浮出水面—“模型太大,跑不动”。
从结果看,“跑不动”是客观事实,但是因为“模型太大”吗?或者反过来说,“小模型”就一定跑的快一些吗?本着探究本质的心态,我们不妨多找几个例子尝试一下。模型的大小没有一个准确定义,暂时就认为微分变量个数是衡量模型大小的主要因素吧。
先找一个看起来“很大”的模型来试试。AMESim在国内系统仿真领域中应用很广,所以我们从它的自带算例中找到了一个看起来很大且多层嵌套的模型:一个整机级液压系统仿真模型。

编译之后可以看到模型确实很大,仅微分变量就有284个。

模型仿真0到5s,耗时接近39s。

现在,再选一个看起来比较“小”的模型,比如这个液体火箭发动机系统模型:

编译之后发现,这个模型确实不算大,微分变量个数仅有57个。
再看看这个模型的运算速度,几乎慢得让人感觉不到它在运算。等这个模型跑完5s的时间要到第二天了。

从上面两个例子来看,求解速度和模型的大小之间的关系似乎并不是看上去那么简单。那么这背后隐藏着怎样的底层逻辑呢?
3 常微分方程的刚性问题
实际上,上述现象是典型的常微分方程“刚性”特征,这一类问题被叫做“刚性问题”。刚性问题在有的文献中也被叫做病态方程或者坏条件方程,其本质是同一个系统中同时含有较大和较小的时间尺度,简单理解就是同时包含高频特性和低频特性。
在实际工程中经常会遇到刚性问题,如控制系统中被控对象惯性较大,具有较大的时间尺度,而控制器则反应灵敏,时间尺度较小;对于飞行动力学来说,其姿态运动较快而质心运动相对较慢;在热流体系统中,压力的波动很快,在流体中以音速传播,而传热过程较慢,一般以质量流速传播;对于复杂的电力系统,受寄生电容的影响,时间特征尺度也会有非常大的差异。

方程刚性的增加会显著降低其收敛域。为了直观展示方程组的刚性对求解的影响,这里给出一个简单的例子:

该方程有解析解图片 ,其中c1和c2是由积分初始条件确定的常数,图片和图片是特征方程的根,图片。当图片是一个较大的正数时,两个特征值对应的解分量尺度相当,这时方程刚性较小,很容易就可以求解,对求解算法和步长没有太多的限制。但是当时图片,图片,同时图片。这时方程的刚性比显著增加。
当设置参数p=2时,使用Runge-Kutta三阶算法,同时将积分最小步长设置成1e-4,很顺利就能求得计算结果,耗时0.0255s。
如果我们将参数p设置为1e-6时,仍然采用最小积分步长为1e-4以Runge-Kutta三阶算法。经测试,低于-7量级的最小步长都无法使计算过程收敛,于是将最小积分步长调整到h=1e-7,这时求解才能正常进行,但所付出的代价就是计算过程变得非常缓慢,从0.0255s变为9.76s。
结果令人震惊,相同的模型,仅仅改变一个系数求解速度立刻降低2个数量级。
可以看出,模型求解效率的高低与模型大小并没有直接的关系,更为贴切的解释应该是:模型规模稍大之后,其内部大概率会涉及不同学科(即多学科联合仿真),这就很容易引入不同的时间特征尺度,进而导致系统(方程组)刚性增加。刚性方程组较难收敛,为了能够顺利求解,需要将积分步长缩小,而更小的积分步长会导致计算次数的增加,次数的增加最终体现在求解速度的降低,即“跑不动”。
搞明白了机理,解决方案就很简单,一个字:拆
4 解决思路
可以想象这样一种解决思路:
将不同时间尺度的模型进行拆分,模型间约定一个通信步长并开展联合仿真(分布式仿真),以避免出现刚性问题;同时,抽象出一个数据交互枢纽,专门负责不同仿真模型间的数据交互和时间同步。
上述思路实际类似“虚拟总线”或“软总线”的理念,通过一个无形的数据总线连接不同的模型同步求解:

将上述思路付诸实践,我们开发出一款软件工具帮我们做这件事情,那么它的原理大致应该是这样的:

不同仿真模型之间的通信机制为:

将上述机制利用代码实现,最终形成一款工业软件-“模型总线”。这是一款面向工业企业的自主研发软件,主要用于跨学科、跨领域大规模复杂系统的集成仿真,主要服务于航空、航天、兵器、汽车、机械等工业领域。


5 测试算例
到这里,思路和工具都有了,我们来试试效果如何,毕竟只有实践才是检验真理的唯一标准。
测试模型的构建分别从“大刚性”和“模拟数值计算”两个方面来考虑。一方面,引入“刚性问题”,可构建如下方程组:

上述方程共有3个特征值:

随着时间的推进,3个特征值的变化为:
时间 | λ1 | λ2 | λ3 |
t=0s | 0 | 0 | -0.04 |
t=1e-2s | 0 | -0.36 | -2180 |
t=100s | 0 | -0.0048 | -4240 |
t=+∞s | 0 | 0 | -1e4 |
可以看出,上述方程随时间推进刚性(λmax/λmin)不断增加,可以作为构建测试模型的素材。
另一方面,引入“模拟数值计算”,可以利用多重循环模拟复杂数值算法。分别构造3个变量a、b、c:

将a、b、c三个变量和刚性方程结合,最终得到了性能测试模型:

上述测试模型同时具有“刚性问题”和“模拟数值计算”的特点,同时a、b、c三个变量虽然都与刚性方程耦合但实际上并不影响其特性(都和0相乘)。
测试方案包含4个内容,分别按照不同的形式对上述模型进行拆分。Test-0表示所有模型用一个求解器串行求解;Test-1表示利用三个求解器对模型进行分布式求解;Test-2表示利用四个求解器对模型进行分布式求解;Test-3表示将方程组也进行拆分,并用五个求解器开展分布式求解。

利用“模型总线”对上述测试方案开展分布式仿真,计算结果如下:

有计算结果可知,适当地拆分模型后其计算耗时由原来的~10小时提升至~1小时,效率提升一个数量级。
这样的结果令人振奋!既然效率提高这么明显,那是否能应用到工程上呢?会不会有新的问题呢?我们留在后续慢慢介绍。