openmdao - 分量梯度计算 - OpenMDAO 1.7.x
问题描述
我正在使用“组件”来“包装”MDO 实验室的 Openaerostruct。当我宣布
self.deriv_options['type'] = 'fd'
在组件构造函数中,我不必声明“线性化”方法,它工作正常。但我认为,通过这样做,我没有使用“整个” Openaerostruct 功能,因为该代码已经实现了“线性化方法”,应该(我猜)提高我的代码性能。
所以,我试图设置类似:
def linearize(self, params, unknowns, resids):
self.OAS_prob.prob.calc_gradient(params,unknowns,mode='rev')
也试过:
def linearize(self, params, unknowns, resids):
self.OAS_prob.prob.calc_gradient(indep_list= ['alpha','taper'], unknown_list=['CL','CD'],mode='rev')
和:
def linearize(self, params, unknowns, resids):
taper = params['taper']
alpha = params['alpha']
CD= unknowns['CD']
CL = unknowns['CL']
self.OAS_prob.prob.calc_gradient(indep_list= [taper,alpha], unknown_list=[CD,CL],mode='rev')
但我收到以下错误:
Can't determine size of unknowns ['CD', 'CL']
Can't determine size of unknowns [0.09583431121084045, 0.015186066036484149] ## for the last one
我有两个问题:
1-有没有办法在组件而不是组中使用“calc_gradient”,还是我在尝试一些不可能的事情?
2-如果第一个是肯定的,我是否应该期待某种性能改进,因为 Openaerostruct 已经实现了“线性化”方法?
提前致谢!!
Ps:我想做的是类似于这个简单的例子:
class Aero_Struct(Component):
def __init__(self):
super(Aero_Struct, self).__init__()
self.add_param('taper', val=0.)
self.add_param('alpha', val=0.)
self.add_output('CD', val=0.)
self.add_output('CL', val=0.)
prob_dict = {'type' : 'aero',
'v':30.,
'optimize' : False}
self.OAS_prob = OASProblem(prob_dict)
surf_dict = {'num_y' : 7,
'num_x' : 2,
'wing_type' : 'rect',
'alpha': 2.,
'CD0' : 0.015,
'symmetry' : True,
'num_twist_cp' : 5,
'taper': 0.5,
'num_thickness_cp' : 2}
self.OAS_prob.add_surface(surf_dict)
self.deriv_options['type'] = 'fd'
self.OAS_prob.setup()
def solve_nonlinear(self, params, unknowns, resids):
taper = params['taper']
self.OAS_prob.prob['wing.taper'] = taper
alpha = params['alpha']
self.OAS_prob.prob['alpha'] = alpha
self.OAS_prob.run()
unknowns['CD'] = self.OAS_prob.prob['wing_perf.CD']
unknowns['CL'] = self.OAS_prob.prob['wing_perf.CL']
解决方案
您是对的,将您的衍生类型声明为“fd”会限制您的性能,并且不会利用 OAS 更有效的衍生产品。
您也处于正确的轨道上,linearize 是要定义的函数,并且您需要计算 OAS openmdao 模型上的导数并返回它们。这是一个简单的 openmdao 1.7x 模型中的线性化:
def linearize(self, params, unknowns, resids):
""" Jacobian for Sellar discipline 1."""
J = {}
J['y','x'] = 1.0
return J
您需要将子openmdao的calc_gradient返回的导数打包到J字典中并返回。如果您在 OAS_prob 中使用的参数与 AeroStruct 组合中的不同,则可能需要转换一些参数或未知名称(例如,根据您的代码,在 OAS 子模型中,taper 似乎是wing.taper。)
总而言之,它可能看起来更像这样。
def linearize(self, params, unknowns, resids):
derivs = self.OAS_prob.prob.calc_gradient(indep_list= ['alpha', 'wing.taper'], unknown_list=['wing_perf.CL','wing_perf.CD'], mode='rev')
J = {}
J['CL', 'alpha'] = derivs['wing_perf.CL']['alpha']
J['CL', 'taper'] = derivs['wing_perf.CL']['wing.taper']
J['CD', 'alpha'] = derivs['wing_perf.CD']['alpha']
J['CD', 'taper'] = derivs['wing_perf.CD']['wing.taper']
return J
因此,主要是您忘记从子问题中的 calc_gradient 调用中解包派生类并将它们返回到外部 openmdao。
推荐阅读
- django - 在 Django Rest 中合并来自两个数据库的查询集
- javascript - 带有用户输入的 2 个目的地的 Google-map API 方向服务
- python - 如何用 Python 抓取 NBA 表格?
- javascript - JavaScript:如何使用较少重复的代码重构 if..else 语句?
- wordpress - 我们如何使用 wordpress REST API 创建帖子和页面?
- java - Java 无法找到正则表达式的匹配项
- apache-spark - 如何在 Cloudera 集群上分发 JDBC jar?
- sqlite - sqlite3:分离数据库产生数据库被锁定错误
- dart - 如何解决一些飞镖代码的奇怪行为
- excel - 如何仅计算具有值而不是函数的行