Skip to content

Commit

Permalink
Merge pull request #514 from jkirk5/regional_turboprop
Browse files Browse the repository at this point in the history
Turboprop with gearbox integration
  • Loading branch information
jkirk5 authored Nov 19, 2024
2 parents 7a7703f + b043ee4 commit 8fc550d
Show file tree
Hide file tree
Showing 24 changed files with 4,996 additions and 3,012 deletions.
2 changes: 2 additions & 0 deletions aviary/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
GRAV_METRIC_FLOPS = 9.80665 # m/s^2
GRAV_ENGLISH_FLOPS = 32.17399 # ft/s^2
GRAV_ENGLISH_LBM = 1.0 # lbf/lbm
# TODO this does not match what dymos atmosphere comp predicts, which leads to subtle
# problems such as density ratio not being 1 at sea level
RHO_SEA_LEVEL_ENGLISH = 0.0023769 # slug/ft^3
RHO_SEA_LEVEL_METRIC = 1.225 # kg/m^3
MU_TAKEOFF = 0.02 # TODO: fill in coefficient of friction for takeoff
Expand Down
65 changes: 41 additions & 24 deletions aviary/mission/gasp_based/ode/landing_eom.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class GlideConditionComponent(om.ExplicitComponent):
"""

def setup(self):
self.add_input("rho_app", val=0.0, units="slug/ft**3", desc="air density")
self.add_input(
Dynamic.Mission.DENSITY, val=0.0, units="slug/ft**3", desc="air density"
)
add_aviary_input(self, Mission.Landing.MAXIMUM_SINK_RATE, val=900.0)
self.add_input(Dynamic.Mission.MASS, val=0.0, units="lbm",
desc="aircraft mass at start of landing")
Expand Down Expand Up @@ -94,19 +96,34 @@ def setup(self):

self.declare_partials(
Mission.Landing.INITIAL_VELOCITY,
[Dynamic.Mission.MASS, Aircraft.Wing.AREA, "CL_max", "rho_app",
Mission.Landing.GLIDE_TO_STALL_RATIO],
[
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
Dynamic.Mission.DENSITY,
Mission.Landing.GLIDE_TO_STALL_RATIO,
],
)
self.declare_partials(
Mission.Landing.STALL_VELOCITY, [
Dynamic.Mission.MASS, Aircraft.Wing.AREA, "CL_max", "rho_app"]
Mission.Landing.STALL_VELOCITY,
[
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
Dynamic.Mission.DENSITY,
],
)
self.declare_partials(
"TAS_touchdown",
[Mission.Landing.GLIDE_TO_STALL_RATIO, Dynamic.Mission.MASS,
Aircraft.Wing.AREA, "CL_max", "rho_app"],
[
Mission.Landing.GLIDE_TO_STALL_RATIO,
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
Dynamic.Mission.DENSITY,
],
)
self.declare_partials("density_ratio", ["rho_app"])
self.declare_partials("density_ratio", [Dynamic.Mission.DENSITY])
self.declare_partials("wing_loading_land", [
Dynamic.Mission.MASS, Aircraft.Wing.AREA])
self.declare_partials(
Expand All @@ -116,7 +133,7 @@ def setup(self):
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
"rho_app",
Dynamic.Mission.DENSITY,
Mission.Landing.GLIDE_TO_STALL_RATIO,
],
)
Expand All @@ -128,7 +145,7 @@ def setup(self):
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
"rho_app",
Dynamic.Mission.DENSITY,
Mission.Landing.GLIDE_TO_STALL_RATIO,
],
)
Expand All @@ -140,7 +157,7 @@ def setup(self):
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
"rho_app",
Dynamic.Mission.DENSITY,
Mission.Landing.GLIDE_TO_STALL_RATIO,
Mission.Landing.MAXIMUM_SINK_RATE,
],
Expand All @@ -152,7 +169,7 @@ def setup(self):
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
"rho_app",
Dynamic.Mission.DENSITY,
Mission.Landing.BRAKING_DELAY,
],
)
Expand All @@ -165,7 +182,7 @@ def setup(self):
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
"CL_max",
"rho_app",
Dynamic.Mission.DENSITY,
Mission.Landing.GLIDE_TO_STALL_RATIO,
],
)
Expand Down Expand Up @@ -274,17 +291,17 @@ def compute_partials(self, inputs, J):
J[Mission.Landing.INITIAL_VELOCITY, "CL_max"] = dTasGlide_dClMax = (
dTasStall_dClMax * glide_to_stall_ratio
)
J[Mission.Landing.INITIAL_VELOCITY, "rho_app"] = dTasGlide_dRhoApp = (
dTasStall_dRhoApp * glide_to_stall_ratio
)
J[Mission.Landing.INITIAL_VELOCITY, Dynamic.Mission.DENSITY] = (
dTasGlide_dRhoApp
) = (dTasStall_dRhoApp * glide_to_stall_ratio)
J[Mission.Landing.INITIAL_VELOCITY,
Mission.Landing.GLIDE_TO_STALL_RATIO] = TAS_stall

J[Mission.Landing.STALL_VELOCITY, Dynamic.Mission.MASS] = \
dTasStall_dWeight * GRAV_ENGLISH_LBM
J[Mission.Landing.STALL_VELOCITY, Aircraft.Wing.AREA] = dTasStall_dWingArea
J[Mission.Landing.STALL_VELOCITY, "CL_max"] = dTasStall_dClMax
J[Mission.Landing.STALL_VELOCITY, "rho_app"] = dTasStall_dRhoApp
J[Mission.Landing.STALL_VELOCITY, Dynamic.Mission.DENSITY] = dTasStall_dRhoApp

J["TAS_touchdown", Mission.Landing.GLIDE_TO_STALL_RATIO] = dTasTd_dGlideToStallRatio = (
0.5 * TAS_stall
Expand All @@ -296,11 +313,11 @@ def compute_partials(self, inputs, J):
J["TAS_touchdown", "CL_max"] = dTasTd_dClMax = (
touchdown_velocity_ratio * dTasStall_dClMax
)
J["TAS_touchdown", "rho_app"] = dTasTd_dRhoApp = (
J["TAS_touchdown", Dynamic.Mission.DENSITY] = dTasTd_dRhoApp = (
touchdown_velocity_ratio * dTasStall_dRhoApp
)

J["density_ratio", "rho_app"] = 1 / RHO_SEA_LEVEL_ENGLISH
J["density_ratio", Dynamic.Mission.DENSITY] = 1 / RHO_SEA_LEVEL_ENGLISH

J["wing_loading_land", Dynamic.Mission.MASS] = GRAV_ENGLISH_LBM / wing_area
J["wing_loading_land", Aircraft.Wing.AREA] = -weight / wing_area**2
Expand All @@ -323,7 +340,7 @@ def compute_partials(self, inputs, J):
* (-rate_of_sink_max / (60.0 * TAS_glide**2))
* dTasGlide_dClMax
)
J["theta", "rho_app"] = dTheta_dRhoApp = (
J["theta", Dynamic.Mission.DENSITY] = dTheta_dRhoApp = (
(1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5)
* (-rate_of_sink_max / (60.0 * TAS_glide**2))
* dTasGlide_dRhoApp
Expand Down Expand Up @@ -361,7 +378,7 @@ def compute_partials(self, inputs, J):
* (1 / np.cos(theta)) ** 2
* dTheta_dClMax
)
J["glide_distance", "rho_app"] = (
J["glide_distance", Dynamic.Mission.DENSITY] = (
-approach_alt
/ (np.tan(theta)) ** 2
* (1 / np.cos(theta)) ** 2
Expand Down Expand Up @@ -475,7 +492,7 @@ def compute_partials(self, inputs, J):
dInter1_dWingArea * inter2 + inter1 * dInter2_dWingArea
)
J["tr_distance", "CL_max"] = dInter1_dClMax * inter2 + inter1 * dInter2_dClMax
J["tr_distance", "rho_app"] = (
J["tr_distance", Dynamic.Mission.DENSITY] = (
dInter1_dRhoApp * inter2 + inter1 * dInter2_dRhoApp
)
J["tr_distance", Mission.Landing.GLIDE_TO_STALL_RATIO] = (
Expand All @@ -490,7 +507,7 @@ def compute_partials(self, inputs, J):
time_delay * dTasTd_dWeight * GRAV_ENGLISH_LBM
J["delay_distance", Aircraft.Wing.AREA] = time_delay * dTasTd_dWingArea
J["delay_distance", "CL_max"] = time_delay * dTasTd_dClMax
J["delay_distance", "rho_app"] = time_delay * dTasTd_dRhoApp
J["delay_distance", Dynamic.Mission.DENSITY] = time_delay * dTasTd_dRhoApp
J["delay_distance", Mission.Landing.BRAKING_DELAY] = TAS_touchdown

flare_alt = (
Expand Down Expand Up @@ -553,7 +570,7 @@ def compute_partials(self, inputs, J):
* (2 * theta * dTheta_dClMax - 2 * gamma_touchdown * dGammaTd_dClMax)
)
)
J["flare_alt", "rho_app"] = (
J["flare_alt", Dynamic.Mission.DENSITY] = (
1
/ (2.0 * G * (landing_flare_load_factor - 1.0))
* (
Expand Down
22 changes: 11 additions & 11 deletions aviary/mission/gasp_based/ode/landing_ode.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ def setup(self):
(Dynamic.Mission.MACH, Mission.Landing.INITIAL_MACH),
],
promotes_outputs=[
(Dynamic.Mission.DENSITY, "rho_app"),
(Dynamic.Mission.SPEED_OF_SOUND, "sos_app"),
(Dynamic.Mission.TEMPERATURE, "T_app"),
(Dynamic.Mission.STATIC_PRESSURE, "P_app"),
("viscosity", "viscosity_app"),
(Dynamic.Mission.DYNAMIC_PRESSURE, "q_app"),
Dynamic.Mission.DENSITY,
Dynamic.Mission.SPEED_OF_SOUND,
Dynamic.Mission.TEMPERATURE,
Dynamic.Mission.STATIC_PRESSURE,
"viscosity",
Dynamic.Mission.DYNAMIC_PRESSURE,
],
)

Expand All @@ -64,12 +64,12 @@ def setup(self):
promotes_inputs=[
"*",
(Dynamic.Mission.ALTITUDE, Mission.Landing.INITIAL_ALTITUDE),
(Dynamic.Mission.DENSITY, "rho_app"),
(Dynamic.Mission.SPEED_OF_SOUND, "sos_app"),
("viscosity", "viscosity_app"),
Dynamic.Mission.DENSITY,
Dynamic.Mission.SPEED_OF_SOUND,
"viscosity",
("airport_alt", Mission.Landing.AIRPORT_ALTITUDE),
(Dynamic.Mission.MACH, Mission.Landing.INITIAL_MACH),
(Dynamic.Mission.DYNAMIC_PRESSURE, "q_app"),
Dynamic.Mission.DYNAMIC_PRESSURE,
("flap_defl", Aircraft.Wing.FLAP_DEFLECTION_LANDING),
("t_init_flaps", "t_init_flaps_app"),
("t_init_gear", "t_init_gear_app"),
Expand Down Expand Up @@ -100,7 +100,7 @@ def setup(self):
"glide",
GlideConditionComponent(),
promotes_inputs=[
"rho_app",
Dynamic.Mission.DENSITY,
Mission.Landing.MAXIMUM_SINK_RATE,
Dynamic.Mission.MASS,
Aircraft.Wing.AREA,
Expand Down
16 changes: 4 additions & 12 deletions aviary/mission/gasp_based/ode/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,10 @@ def promote_params(sys, trajs=None, phases=None):
Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP: dict(units="unitless", val=1.2596),
Mission.Takeoff.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.1886),
Mission.Landing.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.8155),
Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(
units="unitless", val=0.4182
),
Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(
units="unitless", val=1.0293
),
Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(
units="unitless", val=0.0085
),
Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(
units="unitless", val=0.0406
),
Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=0.4182),
Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=1.0293),
Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=0.0085),
Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=0.0406),
}


Expand Down
7 changes: 4 additions & 3 deletions aviary/mission/gasp_based/ode/test/test_landing_eom.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from aviary.mission.gasp_based.ode.landing_eom import (
GlideConditionComponent, LandingAltitudeComponent,
LandingGroundRollComponent)
from aviary.variable_info.variables import Aircraft, Mission
from aviary.variable_info.variables import Aircraft, Mission, Dynamic


class LandingAltTestCase(unittest.TestCase):
Expand Down Expand Up @@ -55,7 +55,7 @@ def setUp(self):
)

self.prob.model.set_input_defaults(
"rho_app", RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3"
Dynamic.Mission.DENSITY, RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3"
) # value from online calculator

self.prob.model.set_input_defaults(
Expand Down Expand Up @@ -137,7 +137,8 @@ def test_case1(self):
prob.model.add_subsystem(
"group", GlideConditionComponent(), promotes=["*"])
prob.model.set_input_defaults(
"rho_app", RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3")
Dynamic.Mission.DENSITY, RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3"
)
prob.model.set_input_defaults(
Mission.Landing.MAXIMUM_SINK_RATE, 900, units="ft/min")
prob.model.set_input_defaults("mass", 165279, units="lbm")
Expand Down
Loading

0 comments on commit 8fc550d

Please sign in to comment.