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