You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenMDAO优化中Newton求解器二次运行收敛失败问题咨询

问题:OpenMDAO中SLSQP驱动下Newton求解器初始点两次计算导致收敛失败?

我在OpenMDAO中使用om.ScipyOptimizeDriver(optimizer='SLSQP')驱动包含Newton求解器的隐式组件模型时,发现驱动会对初始点进行两次计算:第一次求解器收敛正常,第二次却收敛失败。相关输出如下:

Design variables: T = 119.9, r  = [8. 8. 8.]
======
cycle1
======
NL: Newton 0 ; 1.08292488e+09 1
NL: Newton 1 ; 87515540.2 0.0808140455
NL: Newton 2 ; 2017419.33 0.00186293562
NL: Newton 3 ; 127.643094 1.17868835e-07
NL: Newton 4 ; 0.00112882079 1.04238143e-12
NL: Newton Converged

Design variables: T = 119.9, r  = [8. 8. 8.]
======
cycle1
======
NL: Newton 0 ; 0.00112882079 1
NL: Newton 1 ; 3.40715571e-05 0.0301833183
NL: Newton 2 ; 3.51611217e-05 0.031148542
NL: Newton 3 ; 3.01547334e-05 0.0267134817
NL: Newton 4 ; 2.10780761e-05 0.0186726506
NL: Newton 5 ; 1.78959329e-05 0.0158536529
NL: Newton 6 ; 3.52074448e-05 0.0311895788
NL: Newton 7 ; 3.21214883e-05 0.028455791
...
NL: Newton 91 ; 2.47905401e-05 0.021961449
NL: Newton 92 ; 1.78168883e-05 0.0157836288
NL: Newton 93 ; 1.24818173e-05 0.011057395
NL: Newton 94 ; 2.81148656e-05 0.0249064032
NL: Newton 95 ; 1.98432406e-05 0.0175787342
NL: Newton 96 ; 2.33725536e-05 0.0207052828
NL: Newton 97 ; 1.88897422e-05 0.0167340489
NL: Newton 98 ; 4.77892572e-05 0.0423355575
NL: Newton 99 ; 4.26819068e-05 0.0378110568
NL: Newton 100 ; 2.64288629e-05 0.0234128067
NL: NewtonSolver 'NL: Newton' on system 'cycle1' failed to converge in 100 iterations.

我注意到第二次运行时求解器以上一次收敛的输出值为起点,这是否是导致无法进一步降低残差从而收敛失败的原因?若如此,该如何解决此问题?


原因分析与解决方案

你观察到的现象就是核心原因:第二次Newton求解器从第一次收敛后的状态启动,引发了残差震荡无法收敛。SLSQP驱动在初始阶段会先执行一次正向分析(计算目标/约束),紧接着触发梯度计算(默认有限差分),梯度计算时会复用系统前一次的状态,导致Newton从已收敛的极小残差点开始迭代——此时Newton法的步长调整、雅可比矩阵精度问题会让残差出现震荡,无法进一步收敛到满足容限的范围。

以下是几种可行的解决方法:

  • 强制重置求解器初始状态
    在隐式组件的solve_nonlinear方法开头,手动将状态变量重置为初始猜测值,确保每次求解都从干净的起点开始:

    class MyImplicitComp(om.ImplicitComponent):
        def initialize(self):
            self.options.declare('initial_guess', default=0.0)
    
        def solve_nonlinear(self, inputs, outputs, residuals):
            # 重置状态到初始猜测值
            outputs['state_var'] = self.options['initial_guess']
            # 执行Newton求解
            super().solve_nonlinear(inputs, outputs, residuals)
    
  • 开启求解器的reset_on_run参数
    给Newton求解器设置reset_on_run=True,确保每次调用求解器时自动重置状态到初始值,而非复用之前的收敛结果:

    # 假设cycle1是你的隐式系统
    cycle1.nonlinear_solver = om.NewtonSolver()
    cycle1.nonlinear_solver.reset_on_run = True
    # 可同时配置其他求解器参数,比如容限
    cycle1.nonlinear_solver.atol = 1e-10
    cycle1.nonlinear_solver.rtol = 1e-10
    
  • 改用解析梯度替代有限差分
    有限差分的步长扰动可能引发求解器的异常迭代,若能提供解析梯度,不仅能提升计算效率,还能让梯度计算过程更稳定。在隐式组件中实现linearize方法定义雅可比矩阵:

    class MyImplicitComp(om.ImplicitComponent):
        def linearize(self, inputs, outputs, jacobian):
            # 填充残差对状态变量的雅可比元素
            jacobian['residual_name', 'state_var'] = ...
            # 填充残差对输入变量的雅可比元素(如果需要)
            jacobian['residual_name', 'input_var'] = ...
    
  • 调整求解器收敛参数(备选)
    如果残差震荡的数值本身很小,可适当调小Newton求解器的绝对/相对容限,或增加最大迭代次数,但这只是临时缓解,优先推荐前面三种根治方法:

    cycle1.nonlinear_solver.maxiter = 200
    cycle1.nonlinear_solver.atol = 1e-12
    

内容的提问来源于stack exchange,提问作者Kasia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 09:37:20