2016-04-21 4 views
0

Wir sind daran interessiert, ein Ersatzmodell in einem in OpenMDAO implementierten Flugzeugentwurfsprozess zu verwenden. Im Grunde wollen wir einen aerodynamischen Code (wie VSPaero in unserem Ziel) verwenden, um eine Datenbank (mit einem DOE) zu erstellen und dann ein Ersatzzeichen zu erstellen, das im Entwurfsprozess verwendet wird. Es sieht wie Ihr Vorschlag 2) in use of MOE in openMDAO aus und wir möchten auch auf die "Gradienten" -Information des Ersatzes zugreifen, der in dem vollständigen Entwurfsproblem verwendet werden soll.
Wir begannen mit dem Code, den Sie in nested problem question zur Verfügung gestellt haben und versuchen, ein Mock-up-Gehäuse mit vereinfachter Komponente für Aerodynamik zu bauen. Der Beispielcode ist unten (mit Kriging) und wir haben zwei Bedenken, es zu beenden:Verwendung eines Metamodells in einem Entwurfsprozess unter Verwendung eines verschachtelten Ansatzes

  • brauchen wir eine „linearisieren“ Funktion in unserer Komponente zu implementieren, wenn wir Surrogat Gradienteninformationen verwenden wollen: Ich denke, wir sollten verwenden die "calc_gradient" -Funktion von Problem, um dies zu tun. Ist es richtig ?
  • In unserem Beispielcode wird das Training jedes Mal durchgeführt, wenn wir die Komponente aufrufen, was nicht sehr effizient ist: gibt es eine Möglichkeit, es nur einmal aufzurufen oder das Ersatztraining erst nach dem Setup() des größeren Problems durchzuführen (Flugzeugentwurf in unserem Fall)? Hier

ist der Code (sorry es ist ein bisschen zu lang):

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'] 
+0

Ist die Generierung der Aerodaten, zum Trainieren des Ersatzes, ein einmaliger Vorgang. Mit anderen Worten: Generieren Sie es einmal und optimieren Sie dann das Ersatzmodell mithilfe einer gradientenbasierten Methode? Oder möchten Sie die Trainingsdaten im Rahmen der Optimierungsschleife in den Ersatz ändern? –

Antwort

0

Die Art und Weise Sie Ihr Modell eingerichtet haben scheint richtig. Die MetaModel-Komponente trainiert ihre Daten nur einmal (der erste Durchlauf durch das Modell), wie Sie in this part of the source code. sehen können. Jede nachfolgende Iteration verwendet nur den trainierten Ersatz, der bereits dort ist.

Das Meta-Modell ist auch bereits eingerichtet, um analytische Ableitungen der vorhergesagten Ausgabe in Bezug auf die Input-unabhängigen Variablen bereitzustellen. Derivate der Vorhersage in Bezug auf die Trainingspunktwerte sind in der Basisimplementierung nicht verfügbar. Dies erfordert eine komplexere Konfiguration, die zumindest für den Augenblick einige benutzerdefinierte Einstellungen erfordert, die nicht in der Standardbibliothek enthalten sind.

Verwandte Themen