分量梯度计算-OpenMDAO 1.7.x

时间:2018-08-22 19:49:10

标签: openmdao

我正在使用“组件”来“包装” MDO Lab的Openaerostruct。当我宣布

    self.deriv_options['type'] = 'fd'

在组件构造函数中,我不必声明“ linearize”方法,并且效果很好。但是我认为通过这样做,我并没有使用“整个” 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']

1 个答案:

答案 0 :(得分:1)

正确的是,将派生类型声明为“ fd”会限制您的性能,而不会利用OAS的更高效派生功能。

在正确的方向上,线性化是要定义的函数,并且需要在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 comp中使用的名称或名称不同,则可能必须转换某些参数或未知名称(例如,根据您的代码,看起来在OAS子模型中锥度为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。