OpenMDAO:ExplicitComponent.compute中不收敛点的正确处理方式问询
处理OpenMDAO中ExplicitComponent不收敛计算点的正确姿势
我来帮你解决这个问题——你尝试在ExplicitComponent的compute里抛AnalysisError来跳过坏点,但发现Scipy驱动又把异常抛出来终止了优化。其实你注意到的_solve_nonlinear里compute返回True标识失败,就是OpenMDAO官方推荐的正确处理方式,结合驱动的一小段配置就能搞定。
核心解决方案:让compute返回失败标志,而非抛出异常
对于ExplicitComponent,不需要用AnalysisError,而是在检测到无法计算的设计点时:
- 给输出设置一个合理的占位值(比如
0或者np.inf,后者能引导优化器主动避开坏点) - 返回
True告诉框架“这个点计算失败了”
修改你的Test1Comp的compute方法:
def compute(self, inputs, outputs): design_z = inputs['design_z'] design_x = inputs['design_x'] design_y = inputs['design_y'] # 检测到计算不收敛的区域 if 0.49999 < design_x < 0.500001: # 设置占位输出,这里把目标设为无穷大让优化器远离 outputs["z"] = 0.0 outputs["y"] = 0.0 outputs['obj'] = np.inf return True # 返回True表示计算失败 # 正常计算逻辑 z = 4/(design_z + 1) y = - design_z - 2*z obj = (y/5.833333 - design_x)**2 + z/2.666667*100*(design_y - design_x**2)**2 outputs["z"] = z outputs["y"] = y outputs['obj'] = obj return False # 返回False表示计算成功
关键驱动配置:让Scipy优化器跳过失败点
光组件返回失败还不够,你需要给ScipyOptimizeDriver加个配置,告诉它遇到计算失败时不要直接抛异常终止,而是跳过这个点继续优化:
prob.driver = ScipyOptimizeDriver() prob.driver.options["optimizer"] = 'SLSQP' prob.driver.options['tol'] = 1e-8 # 新增这行:禁止驱动因分析失败抛出异常 prob.driver.options['raise_exception'] = False # 可选:调整最大迭代次数,给优化器足够空间避开坏点 prob.driver.options['maxiter'] = 1000
为什么这种方式有效?
从你贴的ExplicitComponent._solve_nonlinear源码就能看明白:
failed = self.compute(self._inputs, self._outputs) return bool(failed), 0., 0.
框架会把compute的返回值当作失败标志,当返回True时,组件会向驱动报告“这个点不可行”。而raise_exception=False则让Scipy驱动不会因为这种不可行点就终止优化,而是让优化算法尝试其他设计点。
额外小技巧
如果你的目标是让优化器彻底避开这些坏点,把目标函数设为np.inf是个好办法——因为优化器要最小化目标,会自动远离这些无穷大的区域,比单纯返回失败效率更高。
内容的提问来源于stack exchange,提问作者rJonatan
相关产品推荐
相关产品推荐

