如何将SNOPT雅可比行列映射回OpenMDAO目标、约束与变量?
定位SNOPT导数符号问题:映射SNOPT行列到OpenMDAO变量/约束/目标
一、映射SNOPT行列到OpenMDAO元素
1. 设计变量(对应SNOPT的Column)
SNOPT输出的Column是从1开始的优化变量索引,对应OpenMDAO全局设计变量的顺序:
- 打印设计变量的全局索引映射,反向查找索引对应的变量名:
desvar_map = prob.driver._get_desvar_index_map() idx_to_desvar = {v: k for k, v in desvar_map.items()} # 例如SNOPT的Column=3,对应OpenMDAO索引为2(需减1) print(idx_to_desvar[3-1]) - 也可直接查看设计变量的定义顺序,列表第N个元素对应SNOPT的Column=N+1:
print(list(prob.model.get_design_vars().keys()))
2. 目标/约束(对应SNOPT的Row)
SNOPT的Row对应目标和约束的全局索引,目标函数通常为Row=1(对应全局索引0),约束按OpenMDAO定义的顺序排列:
- 获取约束的全局索引映射,反向查找索引对应的约束名:
con_map = prob.driver._get_constraint_index_map() idx_to_con = {v: k for k, v in con_map.items()} # 例如SNOPT的Row=5,对应OpenMDAO索引为4(需减1) print(idx_to_con[5-1]) - 目标函数直接对应全局索引0,即你在OpenMDAO中定义的目标变量。
3. 通过pyoptsparse的SNOPT实例查询
在优化运行前后,可通过prob.driver.opt(SNOPT优化器实例)获取更直接的信息:
- 变量顺序:
prob.driver.opt.xOpt的元素顺序与SNOPT的Column顺序完全对应 - 约束/目标顺序:
prob.driver.opt.fOpt为目标值,prob.driver.opt.gOpt为约束值数组,顺序对应SNOPT的Row(Row=1对应目标,Row≥2对应gOpt的索引0开始)
二、导数符号相反的排查方向
尽管check_partials()未发现问题,可从以下方向定位:
- 约束/目标定义方向:检查OpenMDAO中约束的上下界是否与SNOPT预期匹配。比如你需要
c ≥ 0但写成c ≤ 0,或SNOPT被设置为最大化目标(默认是最小化),都会导致导数符号翻转。 - 雅可比组装环节:检查组件间变量连接是否存在反向依赖,比如
promotes操作是否意外改变变量符号,或IndepVarComp的输出是否被反向使用。 - SNOPT验证参数:确认
Verify level=2的有限差分步长合理,不过符号完全相反的情况,大概率是定义问题而非步长误差。
内容的提问来源于stack exchange,提问作者Mark Garnett
相关产品推荐
相关产品推荐

