OpenSees 模型收敛性问题

在使用 OpenSees 进行非线性模拟时,经常遇到模型不收敛的情况。本文提供一个程序包,来帮助 OpenSees 模型收敛。对于非线性比较强,迭代时出现振荡收敛的模型有一定的效果。这个程序包名称为 SmartAnalyze 。如果您已经了解什么是 SmartAnalyze ,可以直接到下载区下载程序包。还有很多其它小工具,可以在本站的下载部分按需要下载。

当模型不收敛时,控制台会提示

1
2
3
4
5
6
WARNING: CTest*::test() - failed to converge
after * iterations
current EnergyIncr: * Norm deltaX: *, Norm deltaR: *
*::solveCurrentStep() - The ConvergenceTest object failed in test()
StaticAnalysis::analyze() - the Algorithm failed at iteration: * with domain at load factor *
OpenSees > analyze failed, returned: -3 error flag

一般来讲,返回错误代码 -3 时,就是在迭代的过程中模型不收敛。这时可以尝试使用本文提供的 SmartAnalyze

值得注意的是,如果返回错误代码 -2 ,比如以下信息

1
2
3
4
WARNING BandGenLinLapackSolver::solve() -factorization failed, matrix singular U(i,i) = 0, i= 2
DisplacementControl::newStep(void) - failed in solver
StaticAnalysis::analyze() - the Integrator failed at iteration: 0 with domain at load factor 0
OpenSees > analyze failed, returned: -2 error flag

则不是收敛性问题,而是模型刚度矩阵异常。这时需要检查模型的连接是否出错。可以借助本站的站内工具OpenSees Online Visualizer来查看模型的几何形状和振型信息。

SmartAnalyze

SmartAnalyze 是一段可复用的代码,用于帮助模型收敛。它支持两种分析模式,一种是时程分析,一种是静力分析。下面分别介绍使用方法。

用 SmartAnalyze 进行时程分析

用通常的方式进行建模。不需要指定 algorithmtestanalysis 。在分析部分,使用以下代码

1
2
3
4
5
6
source SmartAnalyze.tcl
constraints Transformation
numberer Plain
system BandGeneral
integrator Newmark 0.5 0.25
SmartAnalyzeTransient $dt $npts

即可。其中 $dt 为分析步长, npts 为分析步数量。

SmartAnalyze 会采用以下几种方式来改善模型的收敛性

  1. 如果 test 返回的范数不是过大,增加 test 的次数,避免无效的迭代;
  2. 如果增加 test 的次数无效,依用户指定改变 algorithm ,对每个 algorithm 都尝试 1 步骤中的改变 test 次数;
  3. 如果改变的 algorithm 都无效,减小时间步长,重新迭代;
  4. 如果时间步长很小仍不收敛,用户可以选择放宽 test 的容许值;
  5. 如果还是不收敛,返回错误信息。

旧版本中使用 algorithm Linear 使本步强制收敛的方法被弃用,因为基本得不到可用的结果。

SmartAnalyze 定义了很多初始值,用户可以直接使用这些初始值,也可以在模型中指定初始值。例如:

1
2
3
4
set control(printPer) 20 ;# 每20次分析输出一次进度信息
set control(tryAlterAlgoTypes) True ;# 不收敛时切换algorithm
set control(algoTypes) {20 30} ;# 切换的algorithm从这个list中选取
SmartAnalyzeTransient $dt $npts control ;# 使用以上设置进行分析

控制参数的具体使用方法,请读者自行阅读代码中的 Readme 部分。

用 SmartAnalyze 进行静力分析

使用方法和动力分析类似。无须指定 algorithmtestanalysis ,也无须指定 integrator 。程序自动采用 DisplacementControl 来控制加载。

SmartAnalyze 要求输入一个 list 作为加载制度,可以自动完成这个加载制度的分析。例如

1
2
3
4
5
6
source SmartAnalyze.tcl
constraints Transformation
numberer Plain
system BandGeneral
set protocol {1 -1 1 -1 0}
SmartAnalyzeStatic $node $dof $maxStep $protocol

可以完成一段往复加载。其中, $node 是加载控制节点的编号, dof 是加载自由度, $step 是最大步长, $protocol 是加载制度。上例中定义的加载制度是对指定节点往复加载两次,每次位移幅值为1。注意程序默认它的首项为正。

同样,进行静力分析时,也可以重新定义程序的参数,和动力分析的参数相同。

4.0以上版本更新

从使用OpenSees以来,类似于SmartAnalyze的程序编写过很多种。SmartAnalyze 2.2是我首次公开发布的版本。这一版本通过递推调用来实现,存在的问题是代码复杂,可读性差。还有一个问题是当时程分析步长缩小之后,程序就不再跑在地震波的采样点上了,会对结果有细微的影响。在3.0版本之前,我也编写过一个递归调用的版本。但是它存在问题是,递归嵌套的次数过多的时候,TCL解释器会报错。

基于以上原因,我将代码重构为4以上版本。它混合了递推和递归两种实现方法。基本思路是,先把整个分析分解为确定长度的小块,在小块内部递归实现,而在小块外部则递推实现。对于动力分析,每个step长度作为一个小块。对于静力分析,每个不大于maxStep的长度作为一个小块。这样处理可以使代码更简洁,而又不会陷入递归陷阱。

另一个较大的变化是,对于control参数的输入,之前是采用TCL提供的 dict 的数据结构。这个数据结构与其它语言的dict很像,所以就使用了。但在使用过程中发现,dict不能直接用指针取值,而必须通过一个函数 dict get $var key 来实现。这就造成了代码看上去不够简洁。后来发现了TCL的 array ,它和其它语言的array不同,是可以设置键名的,直接通过 $ 取值,要方便很多。所以决定在重构代码时,采用 array 完全替换 dict 。请用户在使用新版本时注意修改 control 的定义方法。

Tcl 版 SmartAnalyze 下载

SmartAnalyze 源代码目前托管在 Gitee 中,但是其代码挂件服务很不稳定,现在把代码复制一份放在本站内。其源文件可点此下载。推荐使用现在的4+版本。如果需要之前的3+版本,在这里下载。

Python 版 SmartAnalyze 下载

华南理工大学黄狄昉同学使用相同的算法将 SmartAnalyze 在 Python 版的 OpenSees 中实现。使用方法类似,其源文件可点此下载。在此对黄同学表示感谢!

源代码

以下源代码都托管在 Github 中,仓库地址为 https://github.com/Hanlin-Dong/SmartAnalyze ,欢迎 Pull Request。需要阅读源代码请到仓库中寻找,本页不再加载源代码。