Source code for RCAIDE.Framework.Analyses.Aerodynamics.Vortex_Lattice_Method

# RCAIDE/Framework/Analyses/Aerodynamics/Vortex_Lattice_Method.py
#  
# Created:  Jul 2023, M. Clarke

# ----------------------------------------------------------------------------------------------------------------------
#  IMPORT
# ----------------------------------------------------------------------------------------------------------------------

# RCAIDE imports   
from RCAIDE.Framework.Core                                     import Data, Units
from RCAIDE.Framework.Analyses                                 import Process 
from RCAIDE.Library.Methods.Aerodynamics                       import Common
from .Aerodynamics                                             import Aerodynamics 
from RCAIDE.Framework.Analyses.Common.Process_Geometry         import Process_Geometry 
from RCAIDE.Library.Methods.Aerodynamics.Vortex_Lattice_Method import *   

# package imports 
import numpy as np 
import os,pickle

# ----------------------------------------------------------------------------------------------------------------------
#  Vortex_Lattice_Method
# ---------------------------------------------------------------------------------------------------------------------- 
[docs] class Vortex_Lattice_Method(Aerodynamics): """This is a subsonic aerodynamic buildup analysis based on the vortex lattice method Assumptions: Stall effects are negligible Source: N/A Inputs: None Outputs: None Properties Used: N/A """ def __defaults__(self): """This sets the default values and methods for the analysis. Assumptions: None Source: N/A Inputs: None Outputs: None Properties Used: N/A """ self.tag = 'Vortex_Lattice_Method' self.vehicle = Data() self.process = Process() self.process.initialize = Process() # settings self.settings.propeller_wake_model = False self.settings.number_of_spanwise_vortices = 30 self.settings.number_of_chordwise_vortices = 15 self.settings.number_of_fuselage_spanwise_vortices = 4 self.settings.number_of_fuselage_chordwise_vortices = 10 self.settings.model_fuselage = False self.settings.spanwise_cosine_spacing = True self.settings.vortex_distribution = Data() self.settings.leading_edge_suction_multiplier = 1.0 self.settings.use_VORLAX_matrix_calculation = False self.settings.floating_point_precision = np.float32 # conditions table, used for surrogate model training self.training = Data() self.training.angle_of_attack = np.array([ -2. , 1E-20 , 2.0, 5.0, 8.0, 12., 45.]) * Units.deg self.training.Mach = np.array([0.1 , 0.3, 0.5, 0.65 , 0.85 , 0.9, 1.3, 1.5 , 2.0 , 2.5 , 3.5]) self.training.subsonic = None self.training.supersonic = None self.training.transonic = None self.training.altitude = 0 self.training.speed_of_sound = 343 self.training.angle_purtubation = 10 * Units.deg self.training.speed_purtubation = 5 self.training.rate_purtubation = 0.05 * Units.deg / Units.sec # 0.05 * Units.deg / Units.sec self.training.control_surface_purtubation = 10 * Units.deg self.training.sideslip_angle = np.array([10 , 5.0 ]) * Units.deg self.training.aileron_deflection = np.array([10 , 5.0 ]) * Units.deg self.training.elevator_deflection = np.array([10 , 5.0 ]) * Units.deg self.training.rudder_deflection = np.array([10 , 1E-3 ]) * Units.deg self.training.flap_deflection = np.array([10 , 1E-3 ]) * Units.deg self.training.slat_deflection = np.array([10 , 1E-3 ]) * Units.deg self.training.u = np.array([10 , 5 ]) * Units.m / Units.sec self.training.v = np.array([10 , 5 ]) * Units.m / Units.sec self.training.w = np.array([10 , 5 ]) * Units.m / Units.sec self.training.pitch_rate = np.array([0.05 ,1E-20 ]) * Units.deg / Units.sec self.training.roll_rate = np.array([0.05 ,1E-20 ]) * Units.deg / Units.sec self.training.yaw_rate = np.array([0.05 ,1E-20 ]) * Units.deg / Units.sec # control surface flags self.aileron_flag = False self.flap_flag = False self.rudder_flag = False self.elevator_flag = False self.slat_flag = False # surrogoate models self.surrogates = Data() # blending function self.surrogates.subsonic_smoothing_min = 0.85 self.surrogates.subsonic_smoothing_max = 0.95 self.surrogates.supersonic_smoothing_min = 1.05 self.surrogates.supersonic_smoothing_max = 1.15 # build the evaluation process compute = Process() compute.lift = Process() compute.lift.inviscid_wings = None compute.lift.fuselage = Common.Lift.fuselage_correction compute.drag = Process() compute.drag.parasite = Process() compute.drag.parasite.wings = Process_Geometry('wings') compute.drag.parasite.wings.wing = Common.Drag.parasite_drag_wing compute.drag.parasite.fuselages = Process_Geometry('fuselages') compute.drag.parasite.fuselages.fuselage = Common.Drag.parasite_drag_fuselage compute.drag.parasite.booms = Process_Geometry('booms') compute.drag.parasite.booms.boom = Common.Drag.parasite_drag_fuselage compute.drag.parasite.nacelles = Common.Drag.parasite_drag_nacelle compute.drag.parasite.pylons = Common.Drag.parasite_drag_pylon compute.drag.parasite.total = Common.Drag.parasite_total compute.drag.induced = Common.Drag.induced_drag compute.drag.cooling = Common.Drag.cooling_drag compute.drag.compressibility = Common.Drag.compressibility_drag compute.drag.miscellaneous = Common.Drag.miscellaneous_drag compute.drag.form = Common.Drag.form_drag compute.drag.trim = Common.Drag.trim_drag compute.drag.total = Common.Drag.total_drag self.process.compute = compute
[docs] def initialize(self, vehicle): use_surrogate = self.settings.use_surrogate reuse_training_data = self.settings.reuse_training_data # If we are using the surrogate if use_surrogate == True: # training data if reuse_training_data: with open(self.filename, 'rb') as file: self.training = pickle.load(file) print("\n Aerodynamic training data loaded. Delete the file and rerun to regenerate.") else: print("\n Creating aerodynamic surrogate ...") train_VLM_surrogates(self, vehicle) if self.settings.store_training_data: with open(self.filename, 'wb') as file: pickle.dump(self.training, file) build_VLM_surrogates(self, vehicle) # build the evaluation process compute = self.process.compute if use_surrogate == True: compute.lift.inviscid_wings = evaluate_surrogate else: compute.lift.inviscid_wings = evaluate_no_surrogate return
[docs] def evaluate(self,state, vehicle): """The default evaluate function. Assumptions: None Source: N/A Inputs: None Outputs: results <RCAIDE data class> Properties Used: self.settings self.vehicle """ settings = self.settings results = self.process.compute(state,settings,vehicle) return results