Tutorial 25 - V-n Diagram#
Welcome to this tutorial on performing V-n diagram analysis of a turbofan aircraft using RCAIDE. This guide will walk you through the code, explain its components, and highlight where modifications can be made to customize the simulation for different vehicle designs.
1. Header and Imports#
The Imports section is divided into two parts: general-purpose Python libraries and simulation-specific libraries.
[1]:
from RCAIDE.Library.Methods.Powertrain.Propulsors.Internal_Combustion_Engine import design_internal_combustion_engine
import sys
import os
import numpy as np
2. RCAIDE Imports#
The RCAIDE Imports section includes the core modules needed for the simulation. These libraries provide specialized classes and tools for building, analyzing, and running aircraft models.
Key Imports:#
RCAIDE: The core package is imported directly. This approach allows us to access specific classes and methods from RCAIDE without repeatedly importing individual components at the top of the script.
``Units`` Module: The Units module is a standardized way to handle unit conversions within RCAIDE. It ensures consistent units across all inputs and outputs, reducing the likelihood of conversion errors.
[2]:
import RCAIDE
from RCAIDE.Framework.Core import Data,Units
from RCAIDE.Library.Methods.Performance import generate_V_n_diagram
from RCAIDE.Library.Methods.Powertrain.Converters.Rotor import design_propeller
Vehicle Setup#
The ``vehicle_setup`` function defines the baseline configuration of the aircraft. This section builds the vehicle step-by-step by specifying its components, geometric properties, and high-level parameters.
A detailed description of the vehicle setup is provided in the a tutorial coming soon.
[3]:
def vehicle_setup():
#------------------------------------------------------------------------------------------------------------------------------------
# ################################################# Vehicle-level Properties ########################################################
#------------------------------------------------------------------------------------------------------------------------------------
vehicle = RCAIDE.Vehicle()
vehicle.tag = 'Cessna_172'
vehicle.mass_properties.max_takeoff = 2550. * Units.pounds
vehicle.mass_properties.takeoff = 2550. * Units.pounds
vehicle.mass_properties.max_zero_fuel = 2550. * Units.pounds
vehicle.mass_properties.cargo = 0.
# envelope properties
vehicle.flight_envelope.ultimate_load = 5.7
vehicle.flight_envelope.positive_limit_load = 3.8
vehicle.flight_envelope.design_range = 750 * Units.nmi
vehicle.flight_envelope.design_dynamic_pressure = 1929.1574740443007
vehicle.flight_envelope.design_mach_number = 0.18745866156304694
# basic parameters
vehicle.reference_area = 174. * Units.feet**2
vehicle.passengers = 4
#------------------------------------------------------------------------------------------------------------------------------------
# ##################################################### Landing Gear ################################################################
#------------------------------------------------------------------------------------------------------------------------------------
main_gear = RCAIDE.Library.Components.Landing_Gear.Main_Landing_Gear()
main_gear.strut_length = 12. * Units.inches
vehicle.append_component(main_gear)
nose_gear = RCAIDE.Library.Components.Landing_Gear.Nose_Landing_Gear()
nose_gear.strut_length = 6. * Units.inches
vehicle.append_component(nose_gear)
#------------------------------------------------------------------------------------------------------------------------------------
# ######################################################## Wings ####################################################################
#------------------------------------------------------------------------------------------------------------------------------------
# ------------------------------------------------------------------
# Main Wing
# ------------------------------------------------------------------
wing = RCAIDE.Library.Components.Wings.Main_Wing()
wing.tag = 'main_wing'
wing.sweeps.quarter_chord = 0.0 * Units.deg
wing.thickness_to_chord = 0.12
wing.areas.reference = 174. * Units.feet**2
wing.spans.projected = 36. * Units.feet + 1. * Units.inches
wing.chords.root = 66. * Units.inches
wing.chords.tip = 45. * Units.inches
wing.chords.mean_aerodynamic = 58. * Units.inches
wing.taper = wing.chords.tip/wing.chords.root
wing.aspect_ratio = wing.spans.projected**2. / wing.areas.reference
wing.twists.root = 3.0 * Units.degrees
wing.twists.tip = 1.5 * Units.degrees
wing.origin = [[80.* Units.inches,0, 0.820]]
wing.aerodynamic_center = [22.* Units.inches,0,0]
wing.vertical = False
wing.symmetric = True
wing.high_lift = True
wing.dynamic_pressure_ratio = 1.0
# control surfaces -------------------------------------------
flap = RCAIDE.Library.Components.Wings.Control_Surfaces.Flap()
flap.tag = 'flap'
flap.span_fraction_start = 0.15
flap.span_fraction_end = 0.324
flap.deflection = 1.0 * Units.deg
flap.chord_fraction = 0.19
wing.append_control_surface(flap)
slat = RCAIDE.Library.Components.Wings.Control_Surfaces.Slat()
slat.tag = 'slat'
slat.span_fraction_start = 0.324
slat.span_fraction_end = 0.963
slat.deflection = 1.0 * Units.deg
slat.chord_fraction = 0.1
wing.append_control_surface(slat)
RCAIDE.Library.Methods.Geometry.Planform.wing_planform(wing)
# add to vehicle
vehicle.append_component(wing)
# ------------------------------------------------------------------
# Horizontal Stabilizer
# ------------------------------------------------------------------
wing = RCAIDE.Library.Components.Wings.Horizontal_Tail()
wing.tag = 'horizontal_stabilizer'
wing.sweeps.quarter_chord = 0.0 * Units.deg
wing.thickness_to_chord = 0.12
wing.areas.reference = 5800. * Units.inches**2
wing.spans.projected = 136. * Units.inches
wing.chords.root = 55. * Units.inches
wing.chords.tip = 30. * Units.inches
wing.chords.mean_aerodynamic = 43. * Units.inches
wing.taper = wing.chords.tip/wing.chords.root
wing.aspect_ratio = wing.spans.projected**2. / wing.areas.reference
wing.twists.root = 0.0 * Units.degrees
wing.twists.tip = 0.0 * Units.degrees
wing.origin = [[246.* Units.inches,0,0]]
wing.aerodynamic_center = [20.* Units.inches,0,0]
wing.vertical = False
wing.symmetric = True
wing.high_lift = False
wing.dynamic_pressure_ratio = 0.9
elevator = RCAIDE.Library.Components.Wings.Control_Surfaces.Elevator()
elevator.tag = 'elevator'
elevator.span_fraction_start = 0.1
elevator.span_fraction_end = 0.9
elevator.deflection = 0.0 * Units.deg
elevator.chord_fraction = 0.35
wing.append_control_surface(elevator)
vehicle.append_component(wing)
# ------------------------------------------------------------------
# Vertical Stabilizer
# ------------------------------------------------------------------
wing = RCAIDE.Library.Components.Wings.Vertical_Tail()
wing.tag = 'vertical_stabilizer'
wing.sweeps.quarter_chord = 25. * Units.deg
wing.thickness_to_chord = 0.12
wing.areas.reference = 3500. * Units.inches**2
wing.spans.projected = 73. * Units.inches
wing.chords.root = 66. * Units.inches
wing.chords.tip = 27. * Units.inches
wing.chords.mean_aerodynamic = 48. * Units.inches
wing.taper = wing.chords.tip/wing.chords.root
wing.aspect_ratio = wing.spans.projected**2. / wing.areas.reference
wing.twists.root = 0.0 * Units.degrees
wing.twists.tip = 0.0 * Units.degrees
wing.origin = [[237.* Units.inches,0,0]]
wing.aerodynamic_center = [20.* Units.inches,0,0]
wing.vertical = True
wing.symmetric = False
wing.t_tail = False
wing.dynamic_pressure_ratio = 1.0
rudder = RCAIDE.Library.Components.Wings.Control_Surfaces.Rudder()
rudder.tag = 'rudder'
rudder.span_fraction_start = 0.1
rudder.span_fraction_end = 0.9
rudder.deflection = 0.0 * Units.deg
rudder.chord_fraction = 0.4
wing.append_control_surface(rudder)
# add to vehicle
vehicle.append_component(wing)
#------------------------------------------------------------------------------------------------------------------------------------
# ########################################################## Fuselage ###############################################################
#------------------------------------------------------------------------------------------------------------------------------------
fuselage = RCAIDE.Library.Components.Fuselages.Tube_Fuselage()
# define cabin
cabin = RCAIDE.Library.Components.Fuselages.Cabins.Cabin()
economy_class = RCAIDE.Library.Components.Fuselages.Cabins.Classes.Economy()
economy_class.number_of_seats_abrest = 2
economy_class.number_of_rows = 2
economy_class.galley_lavatory_percent_x_locations = []
economy_class.emergency_exit_percent_x_locations = []
economy_class.type_A_exit_percent_x_locations = []
cabin.append_cabin_class(economy_class)
fuselage.append_cabin(cabin)
fuselage.differential_pressure = 8*Units.psi # Maximum differential pressure
fuselage.width = 42. * Units.inches # Width of the fuselage
fuselage.heights.maximum = 62. * Units.inches # Height of the fuselage
fuselage.lengths.total = 326. * Units.inches # Length of the fuselage
fuselage.lengths.tail = 161. * Units.inches
fuselage.lengths.cabin = 105. * Units.inches
fuselage.mass_properties.volume = .4*fuselage.lengths.total*(np.pi/4.)*(fuselage.heights.maximum**2.) #try this as approximation
fuselage.mass_properties.internal_volume = .3*fuselage.lengths.total*(np.pi/4.)*(fuselage.heights.maximum**2.)
fuselage.areas.wetted = 30000. * Units.inches**2.
fuselage.fineness.nose = 1.6
fuselage.fineness.tail = 2.
fuselage.lengths.nose = 60. * Units.inches
fuselage.heights.at_quarter_length = 62. * Units.inches
fuselage.heights.at_three_quarters_length = 62. * Units.inches
fuselage.heights.at_wing_root_quarter_chord = 23. * Units.inches
fuselage.areas.front_projected = fuselage.width* fuselage.heights.maximum
fuselage.effective_diameter = 50. * Units.inches
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Segment()
segment.tag = 'segment_0'
segment.percent_x_location = 0.0000
segment.percent_z_location = 0.0000
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Super_Ellipse_Segment()
segment.tag = 'segment_1'
segment.percent_x_location = 0.02077
segment.percent_z_location = 0.0
segment.height = 0.31619
segment.width = 0.33071
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Rounded_Rectangle_Segment()
segment.tag = 'segment_2'
segment.percent_x_location = 0.03852
segment.percent_z_location = -0.02000
segment.height = 0.73441
segment.width = 0.40654
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Rounded_Rectangle_Segment()
segment.tag = 'segment_3'
segment.percent_x_location = 0.16595
segment.percent_z_location = -0.01226
segment.height = 1.00366
segment.width = 0.90341
segment.radius = 0.29143
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Rounded_Rectangle_Segment()
segment.tag = 'segment_4'
segment.percent_x_location = 0.24391
segment.percent_z_location = 0.01016
segment.height = 1.52704
segment.width = 1.06680
segment.radius = 0.43714
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Rounded_Rectangle_Segment()
segment.tag = 'segment_5'
segment.percent_x_location = 0.43388
segment.percent_z_location = 0.0132
segment.height = 1.50557
segment.width = 1.06680
segment.radius = 0.4007
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Rounded_Rectangle_Segment()
segment.tag = 'segment_6'
segment.percent_x_location = 0.53122
segment.percent_z_location = -0.00895
segment.height = 0.97386
segment.width = 0.73776
segment.radius = 0.29143
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Ellipse_Segment()
segment.tag = 'segment_7'
segment.percent_x_location = 0.74233
segment.percent_z_location = 0
segment.height = 0.55067
segment.width = 0.4517
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Segment()
segment.tag = 'segment_9'
segment.percent_x_location = 0.98310
segment.percent_z_location = 0
segment.height = 0.17226
segment.width = 0.18068
fuselage.segments.append(segment)
# Segment
segment = RCAIDE.Library.Components.Fuselages.Segments.Segment()
segment.tag = 'segment_9'
segment.percent_x_location = 1.0
segment.percent_z_location = 0.00189
fuselage.segments.append(segment)
# add to vehicle
vehicle.append_component(fuselage)
#------------------------------------------------------------------------------------------------------------------------------------
# ########################################################## Energy Network #########################################################
#------------------------------------------------------------------------------------------------------------------------------------
#initialize the fuel network
net = RCAIDE.Framework.Networks.Fuel()
# add the network to the vehicle
vehicle.append_energy_network(net)
#------------------------------------------------------------------------------------------------------------------------------------
# Bus
#------------------------------------------------------------------------------------------------------------------------------------
fuel_line = RCAIDE.Library.Components.Powertrain.Distributors.Fuel_Line()
#------------------------------------------------------------------------------------------------------------------------------------
# Fuel Tank & Fuel
#------------------------------------------------------------------------------------------------------------------------------------
fuel_tank = RCAIDE.Library.Components.Powertrain.Sources.Fuel_Tanks.Fuel_Tank()
fuel_tank.origin = vehicle.wings.main_wing.origin
fuel_tank.fuel = RCAIDE.Library.Attributes.Propellants.Aviation_Gasoline()
fuel_tank.fuel.mass_properties.mass = 319 *Units.lbs
fuel_tank.mass_properties.center_of_gravity = wing.mass_properties.center_of_gravity
fuel_tank.volume = fuel_tank.fuel.mass_properties.mass/fuel_tank.fuel.density
fuel_line.fuel_tanks.append(fuel_tank)
#------------------------------------------------------------------------------------------------------------------------------------
# Propulsor
#------------------------------------------------------------------------------------------------------------------------------------
ice_prop = RCAIDE.Library.Components.Powertrain.Propulsors.Internal_Combustion_Engine()
# Engine
engine = RCAIDE.Library.Components.Powertrain.Converters.Engine()
engine.sea_level_power = 180. * Units.horsepower
engine.flat_rate_altitude = 0.0
engine.rated_speed = 2700. * Units.rpm
engine.power_specific_fuel_consumption = 0.52 * Units['lb/hp/hr']
ice_prop.engine = engine
# Propeller
prop = RCAIDE.Library.Components.Powertrain.Converters.Propeller()
prop.tag = 'propeller'
prop.number_of_blades = 2.0
prop.tip_radius = 76./2. * Units.inches
prop.hub_radius = 8. * Units.inches
prop.cruise.design_freestream_velocity = 119. * Units.knots
prop.cruise.design_angular_velocity = 2650. * Units.rpm
prop.cruise.design_Cl = 0.8
prop.cruise.design_altitude = 12000. * Units.feet
prop.cruise.design_power = .64 * 180. * Units.horsepower
prop.variable_pitch = True
ospath = os.path.abspath(os.path.join('Notebook'))
separator = os.path.sep
rel_path = os.path.dirname(ospath) + separator + '..' + separator + '..' + separator + 'VnV' + separator + 'Vehicles' + separator
airfoil_path = rel_path
airfoil = RCAIDE.Library.Components.Airfoils.Airfoil()
airfoil.tag = 'NACA_4412'
airfoil.coordinate_file = airfoil_path + 'Airfoils' + separator + 'NACA_4412.txt' # absolute path
airfoil.polar_files =[ airfoil_path + 'Airfoils' + separator + 'Polars' + separator + 'NACA_4412_polar_Re_50000.txt',
airfoil_path + 'Airfoils' + separator + 'Polars' + separator + 'NACA_4412_polar_Re_100000.txt',
airfoil_path + 'Airfoils' + separator + 'Polars' + separator + 'NACA_4412_polar_Re_200000.txt',
airfoil_path + 'Airfoils' + separator + 'Polars' + separator + 'NACA_4412_polar_Re_500000.txt',
airfoil_path + 'Airfoils' + separator + 'Polars' + separator + 'NACA_4412_polar_Re_1000000.txt']
prop.append_airfoil(airfoil)
prop.airfoil_polar_stations = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
ice_prop.propeller = prop
# design propeller ICE
design_internal_combustion_engine(ice_prop)
net.propulsors.append(ice_prop)
#------------------------------------------------------------------------------------------------------------------------------------
# Assign propulsors to fuel line to network
fuel_line.assigned_propulsors = [[ice_prop.tag]]
#------------------------------------------------------------------------------------------------------------------------------------
# Append fuel line to fuel line to network
net.fuel_lines.append(fuel_line)
#------------------------------------------------------------------------------------------------------------------------------------
# Avionics
#------------------------------------------------------------------------------------------------------------------------------------
Wuav = 2. * Units.lbs
avionics = RCAIDE.Library.Components.Powertrain.Systems.Avionics()
avionics.mass_properties.uninstalled = Wuav
vehicle.avionics = avionics
#------------------------------------------------------------------------------------------------------------------------------------
# Vehicle Definition Complete
#------------------------------------------------------------------------------------------------------------------------------------
return vehicle
Vehicle Aerodynamic Analysis Setup#
The setup for aerodynamic analysis involves:
Initialize Analyses: Create a vehicle analysis object and append Earth as the planetary environment and the US Standard Atmosphere 1976 model.
Define Conditions: Set altitude (
0 m
) and ISA deviation (0
).Vehicle Setup: Configure the vehicle with
normal
category, FAR part23
, and lift coefficient limits (3
and-1.5
).Generate V-n Diagram: Calculate and plot the flight envelope using
generate_V_n_diagram
.
[4]:
analyses = RCAIDE.Framework.Analyses.Vehicle()
# ------------------------------------------------------------------
# Planet Analysis
planet = RCAIDE.Framework.Analyses.Planets.Earth()
analyses.append(planet)
# ------------------------------------------------------------------
# Atmosphere Analysis
atmosphere = RCAIDE.Framework.Analyses.Atmospheric.US_Standard_1976()
atmosphere.features.planet = planet.features
analyses.append(atmosphere)
altitude = 0 * Units.m
delta_ISA = 0
vehicle = vehicle_setup()
vehicle.flight_envelope.category = 'normal'
vehicle.flight_envelope.FAR_part_number = '23'
vehicle.flight_envelope.maximum_lift_coefficient = 3
vehicle.flight_envelope.minimum_lift_coefficient = -1.5
V_n_data = generate_V_n_diagram(vehicle,analyses,altitude,delta_ISA)
Performing Weights Analysis
--------------------------------------------------------
Propulsion Architecture: Conventional
Aircraft Type : General_Aviation
Method : FLOPS
Aircraft operating empty weight will be overwritten
Aircraft center of gravity location will be overwritten
Aircraft moment of intertia tensor will be overwritten
Mission Solver Initiated
0%| | 0/100 [00:00<?, ?it/s]
Solving cruise segment.
100%|██████████| 100/100 [00:01<00:00, 61.83it/s]
