0

我们有兴趣在 OpenMDAO 中实现的飞机设计过程中使用代理模型。基本上,我们希望使用空气动力学代码(例如我们的目标中的 VSPaero)来生成数据库(使用 DOE),然后构建将在设计过程中使用的代理。看起来您的建议 2)在openMDAO 中使用 MOE ,我们还希望访问要在完整设计问题中使用的代理的“梯度”信息。
我们从您在 嵌套问题中提供的代码开始, 并尝试使用简化的空气动力学组件构建模型案例。示例代码如下(使用克里金法),我们有两个问题要完成它:

  • 如果我们想使用代理梯度信息,我们需要在我们的组件中实现一个“线性化”函数:我想我们应该使用问题的“calc_gradient”函数来做到这一点。这样对吗 ?
  • 在我们的示例代码中,每次调用组件时都会进行训练,这不是很有效:有没有办法只调用一次或仅在较大问题的 setup() 之后进行代理训练(飞机设计在我们的例子中)?

这是代码(抱歉有点长):

from openmdao.api import IndepVarComp, Group, Problem, ScipyOptimizer, ExecComp, DumpRecorder, Component, NLGaussSeidel,ScipyGMRES, Newton,SqliteRecorder,MetaModel, \
    KrigingSurrogate, FloatKrigingSurrogate
from openmdao.drivers.latinhypercube_driver import LatinHypercubeDriver, OptimizedLatinHypercubeDriver

from openmdao.solvers.solver_base import NonLinearSolver
import numpy as np
import sys

alpha_test = np.array([0.56, 0.24, 0.30, 0.32, 0.20])
eta_test = np.array([-0.30, -0.14, -0.19, -0.18, -0.12])

num_elem = len(alpha_test)    

class SysAeroSurrogate(Component):
    """ Simulates the presence of an aero surrogate mode using linear aerodynamic model """
    """ coming from pymission code """
    """ https://github.com/OpenMDAO-Plugins/pyMission/blob/master/src/pyMission/aerodynamics.py """    

    def __init__(self, num_elem=1):
        super(SysAeroSurrogate, self).__init__()

        self.add_param('alpha', 0.5)
        self.add_param('eta', -0.33)
        self.add_param('AR', 0.0)
        self.add_param('oswald', 0.0)

        self.add_output('CL',  val=0.0)
        self.add_output('CD',  val=0.0) ## Drag Coefficient        

    def solve_nonlinear(self, params, unknowns, resids):
        """ Compute lift and drag coefficient using angle of attack and tail
        rotation angles. Linear aerodynamics is assumed."""

        alpha = params['alpha']
        eta = params['eta']
        aspect_ratio = params['AR']
        oswald = params['oswald']

        lift_c0 = 0.30
        lift_ca = 6.00
        lift_ce = 0.27
        drag_c0 = 0.015      

        unknowns['CL'] = lift_c0 + lift_ca*alpha*1e-1 + lift_ce*eta*1e-1
        unknowns['CD'] = (drag_c0 + (unknowns['CL'])**2 /(np.pi * aspect_ratio * oswald))/1e-1


class SuroMM(Group):
    def __init__(self):
        super(SuroMM, self).__init__()

        #kriging
        AeroMM = self.add("AeroMM", MetaModel())
        AeroMM.add_param('alpha', val=0.)
        AeroMM.add_param('eta', val=0.)                  
        AeroMM.add_output('CL_MM', val=0., surrogate=FloatKrigingSurrogate())
        AeroMM.add_output('CD_MM', val=0., surrogate=FloatKrigingSurrogate())      


class SurrogateAero(Component):

    def __init__(self):
        super(SurrogateAero, self).__init__()

        ## Inputs to this subprob

        self.add_param('alpha', val=0.5*np.ones(num_elem)) ## Angle of attack
        self.add_param('eta', val=0.5*np.ones(num_elem)) ## Tail rotation angle    
        self.add_param('AR', 0.0)
        self.add_param('oswald', 0.0)           

        ## Unknowns for this sub prob
        self.add_output('CD',  val=np.zeros(num_elem))
        self.add_output('CL',  val=np.zeros(num_elem))  

        #####
        self.problem = prob = Problem()
        prob.root = Group()

        prob.root.add('d1', SuroMM(), promotes=['*'])
        prob.setup()

        #### training of metamodel        
        prob['AeroMM.train:alpha'] = DOEX1
        prob['AeroMM.train:eta'] = DOEX2               
        prob['AeroMM.train:CL_MM'] = DOEY1
        prob['AeroMM.train:CD_MM'] =DOEY2

    def solve_nonlinear(self, params, unknowns, resids):

        CL_temp=np.zeros(num_elem)
        CD_temp=np.zeros(num_elem)        

        prob = self.problem

        # Pass values into our problem
        for i in range(len(params['alpha'])):
            prob['AeroMM.alpha'] = params['alpha'][i]
            prob['AeroMM.eta'] = params['eta'][i]

            # Run problem
            prob.run()

            CL_temp[i] = prob['AeroMM.CL_MM']
            CD_temp[i] = prob['AeroMM.CD_MM']        

        # Pull values from problem
        unknowns['CL'] =  CL_temp
        unknowns['CD'] =  CD_temp


if __name__ == "__main__":

###### creation of database with DOE #####
    top = Problem()
    root = top.root = Group()

    root.add('comp', SysAeroSurrogate(), promotes=['*'])
    root.add('p1', IndepVarComp('alpha', val=0.50), promotes=['*'])
    root.add('p2', IndepVarComp('eta',val=0.50), promotes=['*'])
    root.add('p3', IndepVarComp('AR', 10.), promotes=['*'])
    root.add('p4', IndepVarComp('oswald',  0.92), promotes=['*'])     

    top.driver = OptimizedLatinHypercubeDriver(num_samples=16, seed=0, population=20, generations=4, norm_method=2)
    top.driver.add_desvar('alpha', lower=-5.0*(np.pi/180.0)*1e-1, upper=15.0*(np.pi/180.0)*1e-1)
    top.driver.add_desvar('eta', lower=-5.0*(np.pi/180.0)*1e-1, upper=15.0*(np.pi/180.0)*1e-1)

    top.driver.add_objective('CD')

    recorder = SqliteRecorder('Aero')
    recorder.options['record_params'] = True
    recorder.options['record_unknowns'] = True
    recorder.options['record_resids'] = False
    recorder.options['record_metadata'] = False
    top.driver.add_recorder(recorder)

    top.setup()
    top.run()

    import sqlitedict
    db = sqlitedict.SqliteDict( 'Aero', 'openmdao' )
    print( list( db.keys() ) )
    DOEX1 = []
    DOEX2 = []
    DOEY1 = []
    DOEY2 = []
    for i in list(db.keys()):
            data = db[i]
            p = data['Parameters']
            DOEX1.append(p['comp.alpha'])
            DOEX2.append(p['comp.eta'])

            p = data['Unknowns']
            DOEY1.append(p['CL'])
            DOEY2.append(p['CD'])

    ################  use of surrogate model ######

    prob2 = Problem(root=Group())
    prob2.root.add('SurrAero', SurrogateAero(), promotes=['*'])

    prob2.root.add('v1', IndepVarComp('alpha', val=alpha_test), promotes=['*'])
    prob2.root.add('v2', IndepVarComp('eta',val=eta_test), promotes=['*'])

    prob2.setup()

    prob2.run()

    print'CL predicted:', prob2['CL']
    print'CD predicted:', prob2['CD']
4

1 回答 1

0

您设置模型的方式似乎是正确的。MetaModel 组件只会训练其数据一次(第一次通过模型),正如您在这部分源代码中看到的那样。每次后续迭代,它只使用已经存在的训练有素的代理。

元模型也已经设置为提供预测输出相对于输入自变量的解析导数。关于训练点值的预测导数在基本实现中不可用。这需要更复杂的设置,至少目前,需要一些标准库中没有的自定义设置。

于 2016-04-21T17:26:26.323 回答