首页 > 解决方案 > 分量梯度计算 - 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']

标签: openmdao

解决方案


您是对的,将您的衍生类型声明为“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。


推荐阅读