求解器选择:NonlinearBlockGS vs牛顿求解器

问题描述

我有两个openmdao组,组之间具有循环依赖性。我使用“复杂”步骤计算导数。我有一个用于依赖项的非线性求解器,并使用SLSQP优化了我的目标函数。问题在于非线性求解器的选择。当我使用NonlinearBlockGS时,优化将在12次迭代中成功完成。但是,当我将NewtonSolverDirectsolverScipyKrylov一起使用时,即使使用maxiter=2000,优化也会失败(超过了迭代限制)。循环连接收敛,但是仅仅是设计变量没有达到最佳值。连续迭代中的设计变量之间的差约为1e-5。这就增加了所需的迭代次数。同样,当我将初始猜测值更改为更接近最佳值的值时,它也会起作用。

为了进一步检查,我将模型转换为IDF(通过创建耦合变量和一致性约束的副本),从而消除了对求解器的需求。现在,优化已经成功进行了5次迭代,其结果类似于使用NonlinearBlockGS时的结果。

为什么会这样?我想念什么吗?我何时应该在其他对象上使用NewtonSolver?我知道不看代码就很难回答。但这仅仅是我的代码中包含多个组件,而且我无法用玩具模型重现该问题。因此,任何一般见解都将受到赞赏。

解决方法

在没有看到代码的情况下,您说对了,很难提供详细的信息。

从广义上讲,牛顿收敛有时会比NLBGS麻烦得多(注意:这不是绝对正确的,但是是一个很好的经验法则)。因此,我猜测正在发生的是在您的第一次或第二次迭代中,牛顿求解器实际上并没有收敛。您可以通过设置newton.options['iprint']=2并在优化程序进行迭代时查看迭代历史记录来进行检查。

在优化过程中使用求解器时,至关重要的是,还要确保set it to throw an error on non-convergence.一些优化器可以处理此错误,并且会在行搜索中回溯。其他人只会死。无论哪种方式,它都很重要。否则,您最终会给优化器一个未知的情况,即它不知道是未收敛的。

这很糟糕,原因有两个。首先,它获得的目标和约束值将是错误的!其次,也许更重要的是,其计算的导数将是错误的!您可以阅读详细信息(在理论手册中),但总而言之,OpenMDAO使用的解析导数方法假设残差已变为0。如果不是这种情况,则数学会崩溃。即使您正在执行完整的模型有限差分,非收敛模型也是一个问题。当您尝试FD时,只会得到嘈杂的垃圾。2

因此,假设您正确设置了模型,并且线性求解器设置了问题(由于它与NLBGS兼容,听起来像是这样做的),那么牛顿求解器很可能没有收敛。使用iprint(可能与driver debug printing结合使用)亲自检查一下。如果真是那样,您需要弄清楚如何使牛顿表现得更好。

有些tips here很笼统。您也可以尝试使用armijo line search,它通常可以以一定的速度来稳定牛顿求解。

最后...牛顿并不是在所有情况下的最佳答案。如果NLBGS更稳定且计算便宜,则应使用它。我为您希望与牛顿一起工作感到高兴。您绝对应该找出原因,但事实并非如此,但是如果事实证明牛顿无法可靠地解决您的耦合问题,那也可以!

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...