SubmodelComp能否自带Driver?OpenMDAO使用疑问与异常排查
关于OpenMDAO SubmodelComp的用法与问题分析
核心疑问
我正在研究OpenMDAO的SubmodelComp,想确认其正确用法:SubmodelComp是否可以拥有自己的Driver和优化器? 我的应用场景是子模型采用基于梯度的优化,顶层问题使用无梯度优化器处理子问题的离散变量输入,无需获取子模型的梯度。
测试案例与结果
1. 无输入测试案例
import openmdao.api as om sub_prob = om.Problem() sub_prob.model.add_subsystem("paraboloid", om.ExecComp("f = (x-3)**2 + x*y + (y+4)**2 - 3")) sub_prob.driver = om.ScipyOptimizeDriver() sub_prob.driver.options["optimizer"] = "SLSQP" sub_prob.model.add_design_var("paraboloid.x", lower=-50, upper=50) sub_prob.model.add_design_var("paraboloid.y", lower=-50, upper=50) sub_prob.model.add_objective("paraboloid.f") top_prob = om.Problem() submodel = om.SubmodelComp(problem=sub_prob, outputs=[("paraboloid.f", "g")]) top_prob.model.add_subsystem("submodel", submodel, promotes=["*"]) top_prob.setup() top_prob.run_model() print(sub_prob.get_val("paraboloid.f")) print(sub_prob.get_val("paraboloid.x")) print(sub_prob.get_val("paraboloid.y"))
输出符合预期:
Optimization terminated successfully (Exit mode 0) Current function value: -27.333333074220675 Iterations: 6 Function evaluations: 6 Gradient evaluations: 6 Optimization Complete ----------------------------------- [-27.33333307] [6.66712855] [-7.33324946]
2. 添加输入后的测试案例
import openmdao.api as om sub_prob = om.Problem() # modify paraboloid eqn with parameter "a" sub_prob.model.add_subsystem("paraboloid", om.ExecComp("f = (x-3)**2 + x*y + (y+4)**2 + a")) sub_prob.driver = om.ScipyOptimizeDriver() sub_prob.driver.options["optimizer"] = "SLSQP" sub_prob.model.add_design_var("paraboloid.x", lower=-50, upper=50) sub_prob.model.add_design_var("paraboloid.y", lower=-50, upper=50) sub_prob.model.add_objective("paraboloid.f") top_prob = om.Problem() submodel = om.SubmodelComp(problem=sub_prob, inputs=[("paraboloid.a", "a")], outputs=[("paraboloid.f", "g")]) top_prob.model.add_subsystem("submodel", submodel, promotes=["*"]) top_prob.setup() top_prob.set_val("a", val=-3) top_prob.run_model() print(sub_prob.get_val("paraboloid.f")) print(sub_prob.get_val("paraboloid.x")) print(sub_prob.get_val("paraboloid.y"))
优化失败:
Inequality constraints incompatible (Exit mode 4) Current function value: -1e+30 Iterations: 49 Function evaluations: 49 Gradient evaluations: 49 Optimization FAILED. Inequality constraints incompatible ----------------------------------- [-1.e+30] [-50.] [-50.]
3. 修改方程后的测试
将抛物面方程改为f = (x-3)**2 + x*y + (y+4)**2 + a -a,优化成功但出现警告:
Optimization terminated successfully (Exit mode 0) Current function value: -24.333333074220675 Iterations: 6 Function evaluations: 6 Gradient evaluations: 6 Optimization Complete ----------------------------------- [-24.33333307] [6.66712855] [-7.33324946] .......\openmdao\core\total_jac.py:1788: DerivativesWarning:Design variables [('paraboloid.a', inds=[0])] have no impact on the constraints or objective.
问题原因分析
SubmodelComp支持绑定自身的Driver,上述问题既不是功能不支持也不是程序bug,而是子问题的优化逻辑与输入参数的交互存在错误:
无输入测试成功的原因:子问题的设计变量(x、y)与目标函数逻辑自洽,存在有限最小值,SLSQP能正常找到最优解,SubmodelComp触发子问题Driver执行优化的流程完全正常。
添加输入后优化失败的原因:目标函数
f = (x-3)**2 + x*y + (y+4)**2 + a在x、y取边界值-50时,函数值会无限趋近负无穷,SLSQP优化器试图突破边界最小化目标,但被设计变量的上下限约束限制,最终判定约束与目标无法兼容,导致优化失败。修改方程后警告的原因:修改后的方程中
a被抵消,子问题的目标函数与a无关,但OpenMDAO检测到a作为子问题的输入变量,却未对约束或目标产生任何影响,因此抛出警告提示该变量无效。
正确用法建议
- 确保子问题的目标函数在设计变量的边界范围内存在有限最小值,避免优化器试图突破边界无限优化。
- 子问题中的输入参数(如
a)无需设为设计变量,仅通过SubmodelComp的inputs参数传递即可,避免无效变量警告。 - 你的应用场景(子模型梯度优化+顶层无梯度优化)完全可行,只要保证子问题的优化逻辑自洽,顶层传入参数后,子问题能正确执行优化并返回结果。
内容的提问来源于stack exchange,提问作者Mark Garnett
相关产品推荐
相关产品推荐

