diff --git a/aviary/mission/energy_state/ode/landing_eom.py b/aviary/mission/energy_state/ode/landing_eom.py index c619a88e13..4e4848da0f 100644 --- a/aviary/mission/energy_state/ode/landing_eom.py +++ b/aviary/mission/energy_state/ode/landing_eom.py @@ -160,13 +160,13 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='N') - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') self.add_output( 'forces_perpendicular', @@ -317,14 +317,14 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='N') - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') self.add_output( 'forces_horizontal', @@ -475,10 +475,10 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='N') self.add_output( 'forces_horizontal', diff --git a/aviary/mission/energy_state/ode/range_rate.py b/aviary/mission/energy_state/ode/range_rate.py index dfee0e2037..5e9d76863c 100644 --- a/aviary/mission/energy_state/ode/range_rate.py +++ b/aviary/mission/energy_state/ode/range_rate.py @@ -20,21 +20,21 @@ def setup(self): add_aviary_input( self, Dynamic.Mission.ALTITUDE_RATE, - val=np.ones(nn), + shape=nn, desc='climb rate', units='m/s', ) add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.ones(nn), + shape=nn, desc='current velocity', units='m/s', ) add_aviary_output( self, Dynamic.Mission.DISTANCE_RATE, - val=np.ones(nn), + shape=nn, desc='current horizontal velocity (assumed no wind)', units='m/s', ) diff --git a/aviary/mission/energy_state/ode/required_thrust.py b/aviary/mission/energy_state/ode/required_thrust.py index 9ebf904782..b4fa4a2dbe 100644 --- a/aviary/mission/energy_state/ode/required_thrust.py +++ b/aviary/mission/energy_state/ode/required_thrust.py @@ -18,32 +18,28 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.zeros(nn), units='N', desc='drag force') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='N', desc='drag force') add_aviary_input( self, Dynamic.Mission.ALTITUDE_RATE, - val=np.zeros(nn), + shape=nn, units='m/s', - desc='rate of change of altitude', ) add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.zeros(nn), + shape=nn, units='m/s', desc=Dynamic.Mission.VELOCITY, ) add_aviary_input( self, Dynamic.Mission.VELOCITY_RATE, - val=np.zeros(nn), + shape=nn, units='m/s**2', - desc='rate of change of velocity', ) - add_aviary_input( - self, Dynamic.Vehicle.MASS, val=np.zeros(nn), units='kg', desc='mass of the aircraft' - ) - self.add_output('thrust_required', val=np.zeros(nn), units='N', desc='required thrust') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') + self.add_output('thrust_required', shape=nn, units='N') ar = np.arange(nn) self.declare_partials('thrust_required', Dynamic.Vehicle.DRAG, rows=ar, cols=ar) diff --git a/aviary/mission/energy_state/ode/takeoff_eom.py b/aviary/mission/energy_state/ode/takeoff_eom.py index f67054c210..7ba94fdd6d 100644 --- a/aviary/mission/energy_state/ode/takeoff_eom.py +++ b/aviary/mission/energy_state/ode/takeoff_eom.py @@ -25,14 +25,13 @@ def setup(self): nn = options['num_nodes'] - self.add_input('mass', val=np.ones(nn), units='kg', desc='current mass of the aircraft') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') add_aviary_input( self, Dynamic.Atmosphere.DENSITY, - val=np.ones(nn), + shape=nn, units='kg/m**3', - desc='current atmospheric density', ) self.add_input('area', val=1.0, units='m**2', desc='surface area contributing to lift') @@ -207,11 +206,11 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') + add_aviary_input(self, Dynamic.Mission.VELOCITY, shape=nn, units='m/s') - add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units='m/s') - add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, shape=nn, units='m/s') + add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, shape=nn, units='m/s') def setup_partials(self): options = self.options @@ -283,7 +282,7 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') self.add_input( 'forces_horizontal', @@ -395,10 +394,10 @@ def setup(self): units='m/s**2', ) - add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units='m/s') - add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, shape=nn, units='m/s') + add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, shape=nn, units='m/s') - add_aviary_output(self, Dynamic.Mission.VELOCITY_RATE, val=np.ones(nn), units='m/s**2') + add_aviary_output(self, Dynamic.Mission.VELOCITY_RATE, shape=nn, units='m/s**2') rows_cols = np.arange(nn) @@ -446,8 +445,8 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units='m/s') - add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, shape=nn, units='m/s') + add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, shape=nn, units='m/s') self.add_input( 'acceleration_horizontal', @@ -466,7 +465,7 @@ def setup(self): add_aviary_output( self, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - val=np.zeros(nn), + shape=nn, units='rad/s', ) @@ -539,14 +538,14 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='N') - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') self.add_output( 'forces_horizontal', @@ -765,14 +764,14 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, shape=nn, units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='N') - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') self.add_output( 'climb_gradient_forces_horizontal', diff --git a/aviary/mission/energy_state/ode/test/test_landing_ode.py b/aviary/mission/energy_state/ode/test/test_landing_ode.py index 8c536db882..cfd8178f7c 100644 --- a/aviary/mission/energy_state/ode/test/test_landing_ode.py +++ b/aviary/mission/energy_state/ode/test/test_landing_ode.py @@ -1,19 +1,20 @@ import unittest +import numpy as np import openmdao.api as om from openmdao.utils.testing_utils import use_tempdirs from aviary.mission.energy_state.ode.landing_ode import FlareODE -from aviary.validation_cases.validation_data.test_data.advanced_single_aisle_data import ( - detailed_landing_flare, - inputs, - landing_subsystem_options, -) from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import set_aviary_initial_values from aviary.utils.preprocessors import preprocess_options from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.validation_cases.validation_data.test_data.advanced_single_aisle_data import ( + detailed_landing_flare, + inputs, + landing_subsystem_options, +) from aviary.validation_cases.validation_tests import do_validation_test from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic diff --git a/aviary/mission/energy_state/ode/test/test_takeoff_eom.py b/aviary/mission/energy_state/ode/test/test_takeoff_eom.py index aeaadea167..2a68777e4c 100644 --- a/aviary/mission/energy_state/ode/test/test_takeoff_eom.py +++ b/aviary/mission/energy_state/ode/test/test_takeoff_eom.py @@ -15,12 +15,12 @@ TakeoffEOM, VelocityRate, ) +from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_data.test_data.advanced_single_aisle_data import ( detailed_takeoff_climbing, detailed_takeoff_ground, inputs, ) -from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_tests import do_validation_test from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -134,6 +134,7 @@ def test_StallSpeed(self): tol = 1e-6 prob = om.Problem() prob.model.add_subsystem('stall_speed', StallSpeed(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.ones(2), units='kg') prob.model.set_input_defaults(Dynamic.Atmosphere.DENSITY, np.array([1, 2]), units='kg/m**3') prob.model.set_input_defaults('area', 10, units='m**2') prob.model.set_input_defaults('lift_coefficient_max', 5000, units='unitless') @@ -200,6 +201,7 @@ def test_Accelerations(self): prob.model.set_input_defaults('forces_vertical', [50.0, 100.0], units='N') prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Dynamic.Vehicle.MASS, np.ones(2)) prob.run_model() assert_near_equal(prob['acceleration_horizontal'], np.array([100.0, 200.0]), tol) diff --git a/aviary/mission/energy_state/phases/simplified_landing.py b/aviary/mission/energy_state/phases/simplified_landing.py index 7e193de4fe..8bc135c263 100644 --- a/aviary/mission/energy_state/phases/simplified_landing.py +++ b/aviary/mission/energy_state/phases/simplified_landing.py @@ -10,23 +10,22 @@ class LandingCalc(om.ExplicitComponent): """Calculate the distance covered over the ground and approach velocity during landing.""" def setup(self): - add_aviary_input(self, Mission.FINAL_MASS, val=150_000) + add_aviary_input(self, Mission.FINAL_MASS) add_aviary_input( self, Dynamic.Atmosphere.DENSITY, - val=1.225, units='kg/m**3', desc='atmospheric density', ) - add_aviary_input(self, Aircraft.Wing.AREA, val=700) + add_aviary_input(self, Aircraft.Wing.AREA) - add_aviary_input(self, Mission.Landing.LIFT_COEFFICIENT_MAX, val=3) + add_aviary_input(self, Mission.Landing.LIFT_COEFFICIENT_MAX) - add_aviary_output(self, Mission.Landing.GROUND_DISTANCE, val=0) + add_aviary_output(self, Mission.Landing.GROUND_DISTANCE) - add_aviary_output(self, Mission.Landing.INITIAL_VELOCITY, val=0) + add_aviary_output(self, Mission.Landing.INITIAL_VELOCITY) self.declare_partials( Mission.Landing.INITIAL_VELOCITY, diff --git a/aviary/mission/energy_state/phases/simplified_takeoff.py b/aviary/mission/energy_state/phases/simplified_takeoff.py index 041bba461e..181c62660a 100644 --- a/aviary/mission/energy_state/phases/simplified_takeoff.py +++ b/aviary/mission/energy_state/phases/simplified_takeoff.py @@ -24,9 +24,7 @@ def setup(self): add_aviary_input( self, Dynamic.Atmosphere.DENSITY, - val=1.225, units='kg/m**3', - desc='atmospheric density', ) self.add_input('planform_area', val=7, units='m**2', desc='area of the wings') @@ -104,26 +102,24 @@ def setup(self): desc='mass of the aircraft', ) - add_aviary_input(self, Mission.Takeoff.FUEL_MASS, val=10.0e3) + add_aviary_input(self, Mission.Takeoff.FUEL_MASS) add_aviary_input( self, Dynamic.Atmosphere.DENSITY, - val=1.225, units='kg/m**3', - desc='atmospheric density', ) - add_aviary_input(self, Aircraft.Wing.AREA, val=7) - add_aviary_input(self, Mission.Takeoff.LIFT_COEFFICIENT_MAX, val=2) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=100_000) - add_aviary_input(self, Mission.Takeoff.LIFT_OVER_DRAG, val=2) - add_aviary_input(self, Mission.Takeoff.CLIMBOUT_THRUST_FRACTION, val=1) + add_aviary_input(self, Aircraft.Wing.AREA) + add_aviary_input(self, Mission.Takeoff.LIFT_COEFFICIENT_MAX) + add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST) + add_aviary_input(self, Mission.Takeoff.LIFT_OVER_DRAG) + add_aviary_input(self, Mission.Takeoff.CLIMBOUT_THRUST_FRACTION) - add_aviary_output(self, Mission.Takeoff.GROUND_DISTANCE, val=0) - add_aviary_output(self, Mission.Takeoff.FINAL_VELOCITY, val=0, units='m/s') - add_aviary_output(self, Mission.Takeoff.FINAL_MASS, val=0) - add_aviary_output(self, Mission.Takeoff.FINAL_ALTITUDE, val=0) + add_aviary_output(self, Mission.Takeoff.GROUND_DISTANCE) + add_aviary_output(self, Mission.Takeoff.FINAL_VELOCITY, units='m/s') + add_aviary_output(self, Mission.Takeoff.FINAL_MASS) + add_aviary_output(self, Mission.Takeoff.FINAL_ALTITUDE) def setup_partials(self): self.declare_partials( @@ -215,9 +211,6 @@ def compute_partials(self, inputs, J): rad_Rot = ramp_weight / (S * Cl_max * rho_ratio) den_Cout = 1.0 + climbout_thrust / ramp_weight - 0.90 / L_over_D - S * Cl_max * (thrust / ramp_weight - (0.20 + 0.00550 * ramp_weight / S) / L_over_D) - S * Cl_max * (-thrust / ramp_weight**2 - (0.00550 / S) / L_over_D) - dRD_dM = ( 17 / den_RD - 17 diff --git a/aviary/mission/energy_state/phases/test/test_building_landing.py b/aviary/mission/energy_state/phases/test/test_building_landing.py index 015e7968db..9c6c825aa8 100644 --- a/aviary/mission/energy_state/phases/test/test_building_landing.py +++ b/aviary/mission/energy_state/phases/test/test_building_landing.py @@ -5,7 +5,7 @@ from openmdao.utils.testing_utils import use_tempdirs from aviary.mission.energy_state.phases.build_landing import Landing -from aviary.variable_info.variables import Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission @use_tempdirs @@ -24,6 +24,10 @@ def test_case1(self): prob = om.Problem() prob.model = landing prob.setup(force_alloc_complex=True) + prob.set_val( + Mission.FINAL_MASS, + val=150_000, + ) prob.run_model() partial_data = prob.check_partials( out_stream=None, method='cs', compact_print=False, excludes=['*atmosphere*'] diff --git a/aviary/mission/energy_state/phases/test/test_building_takeoff.py b/aviary/mission/energy_state/phases/test/test_building_takeoff.py index 78bd640938..eff10308f5 100644 --- a/aviary/mission/energy_state/phases/test/test_building_takeoff.py +++ b/aviary/mission/energy_state/phases/test/test_building_takeoff.py @@ -26,6 +26,7 @@ def test_case1(self): Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 200000, units='lbf' ) prob.setup(force_alloc_complex=True) + prob.set_val(Mission.Takeoff.LIFT_OVER_DRAG, 2) prob.run_model() partial_data = prob.check_partials( out_stream=None, method='cs', compact_print=False, excludes=['*atmosphere*'] diff --git a/aviary/mission/energy_state/phases/test/test_simplified_landing.py b/aviary/mission/energy_state/phases/test/test_simplified_landing.py index 2620c1578f..caf7669360 100644 --- a/aviary/mission/energy_state/phases/test/test_simplified_landing.py +++ b/aviary/mission/energy_state/phases/test/test_simplified_landing.py @@ -53,32 +53,6 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -class LandingCalcTest2(unittest.TestCase): - """Test mass-weight conversion.""" - - def setUp(self): - import aviary.mission.energy_state.phases.simplified_landing as landing - - landing.GRAV_ENGLISH_LBM = 1.1 - - def tearDown(self): - import aviary.mission.energy_state.phases.simplified_landing as landing - - landing.GRAV_ENGLISH_LBM = 1.0 - - def test_case1(self): - prob = om.Problem() - prob.model.add_subsystem( - 'land', - LandingCalc(), - promotes=['*'], - ) - prob.setup(check=False, force_alloc_complex=True) - - partial_data = prob.check_partials(out_stream=None, method='cs') - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) - - @use_tempdirs class LandingGroupTest(unittest.TestCase): """Test the computation of LandingGroup.""" diff --git a/aviary/mission/energy_state/phases/test/test_simplified_takeoff.py b/aviary/mission/energy_state/phases/test/test_simplified_takeoff.py index 4f8a0dcbd0..9288fb4b2c 100644 --- a/aviary/mission/energy_state/phases/test/test_simplified_takeoff.py +++ b/aviary/mission/energy_state/phases/test/test_simplified_takeoff.py @@ -53,33 +53,6 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) # check the partial derivatives -class StallSpeedTest2(unittest.TestCase): - """Test mass-weight conversion.""" - - def setUp(self): - import aviary.mission.energy_state.phases.simplified_takeoff as takeoff - - takeoff.GRAV_ENGLISH_LBM = 1.1 - - def tearDown(self): - import aviary.mission.energy_state.phases.simplified_takeoff as takeoff - - takeoff.GRAV_ENGLISH_LBM = 1.0 - - def test_case1(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - 'comp', - StallSpeed(), - promotes=['*'], - ) - self.prob.setup(check=False, force_alloc_complex=True) - self.prob.run_model() - - partial_data = self.prob.check_partials(out_stream=None, method='cs') - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) - - @use_tempdirs class FinalConditionsTest(unittest.TestCase): """Test final conditions computation in FinalTakeoffConditions class.""" @@ -151,6 +124,26 @@ def test_case1(self): prob.model.set_input_defaults('v_stall', val=100, units='m/s') # default value GROSS_MASS = 150000 will worsen the output prob.model.set_input_defaults('mass', val=181200.0, units='lbm') + prob.model.set_input_defaults(Mission.Takeoff.FUEL_MASS, val=577, units='lbm') # check + prob.model.set_input_defaults( + Dynamic.Atmosphere.DENSITY, + val=constants.RHO_SEA_LEVEL_ENGLISH, + units='slug/ft**3', + ) # check + prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.0, units='ft**2') # check + prob.model.set_input_defaults( + Mission.Takeoff.LIFT_COEFFICIENT_MAX, val=2.0000, units='unitless' + ) # check + prob.model.set_input_defaults( + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=28928.0 * 2, units='lbf' + ) # check + prob.model.set_input_defaults( + Mission.Takeoff.CLIMBOUT_THRUST_FRACTION, val=1, units='unitless' + ) + prob.model.set_input_defaults( + Mission.Takeoff.LIFT_OVER_DRAG, val=17.354, units='unitless' + ) # check + prob.setup(check=False, force_alloc_complex=True) partial_data = prob.check_partials(out_stream=None, method='cs') diff --git a/aviary/mission/ode/altitude_rate.py b/aviary/mission/ode/altitude_rate.py index 3de5842bb5..b5e1582f4c 100644 --- a/aviary/mission/ode/altitude_rate.py +++ b/aviary/mission/ode/altitude_rate.py @@ -4,6 +4,7 @@ import aviary.constants as constants from aviary.variable_info.variables import Dynamic +from aviary.variable_info.functions import add_aviary_input, add_aviary_output class AltitudeRate(om.ExplicitComponent): @@ -20,29 +21,25 @@ def setup(self): add_aviary_input( self, Dynamic.Mission.SPECIFIC_ENERGY_RATE, - val=np.ones(nn), - desc='current specific power', + shape=nn, units='m/s', ) add_aviary_input( self, Dynamic.Mission.VELOCITY_RATE, - val=np.ones(nn), - desc='current acceleration', + shape=nn, units='m/s**2', ) add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.ones(nn), - desc='current velocity', + shape=nn, units='m/s', ) add_aviary_output( self, Dynamic.Mission.ALTITUDE_RATE, - val=np.ones(nn), - desc='current climb rate', + shape=nn, units='m/s', ) diff --git a/aviary/mission/ode/specific_energy_rate.py b/aviary/mission/ode/specific_energy_rate.py index 9eaff2412f..207fd8c587 100644 --- a/aviary/mission/ode/specific_energy_rate.py +++ b/aviary/mission/ode/specific_energy_rate.py @@ -21,27 +21,23 @@ def setup(self): add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.ones(nn), + shape=nn, desc='current velocity', units='m/s', ) - add_aviary_input( - self, Dynamic.Vehicle.MASS, val=np.ones(nn), desc='current mass', units='kg' - ) + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, desc='current mass', units='kg') add_aviary_input( self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, - val=np.ones(nn), + shape=nn, desc='current thrust', units='N', ) - add_aviary_input( - self, Dynamic.Vehicle.DRAG, val=np.ones(nn), desc='current drag', units='N' - ) + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, desc='current drag', units='N') add_aviary_output( self, Dynamic.Mission.SPECIFIC_ENERGY_RATE, - val=np.ones(nn), + shape=nn, desc='current specific power', units='m/s', ) diff --git a/aviary/mission/solved_two_dof/ode/groundroll_eom.py b/aviary/mission/solved_two_dof/ode/groundroll_eom.py index 3de99af335..ff2474706e 100644 --- a/aviary/mission/solved_two_dof/ode/groundroll_eom.py +++ b/aviary/mission/solved_two_dof/ode/groundroll_eom.py @@ -15,56 +15,50 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='lbm') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='lbm') add_aviary_input( self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, - val=np.ones(nn), - desc=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + shape=nn, units='lbf', ) add_aviary_input( self, Dynamic.Vehicle.LIFT, - val=np.ones(nn), - desc=Dynamic.Vehicle.LIFT, + shape=nn, units='lbf', ) add_aviary_input( self, Dynamic.Vehicle.DRAG, - val=np.ones(nn), - desc=Dynamic.Vehicle.DRAG, + shape=nn, units='lbf', ) add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.ones(nn), - desc='true air speed', + shape=nn, units='ft/s', ) - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), units='rad') - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0) - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='deg') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') + add_aviary_input(self, Aircraft.Wing.INCIDENCE) + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') add_aviary_input(self, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, units='unitless') add_aviary_output( self, Dynamic.Mission.VELOCITY_RATE, - val=np.ones(nn), - desc='TAS rate', + shape=nn, units='ft/s**2', ) add_aviary_output( self, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - val=np.ones(nn), - desc='flight path angle rate', + shape=nn, units='rad/s', ) - add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), units='ft/s') - add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), units='ft/s') + add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, shape=nn, units='ft/s') + add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, shape=nn, units='ft/s') self.add_output('normal_force', val=np.ones(nn), desc='normal forces', units='lbf') self.add_output('fuselage_pitch', val=np.ones(nn), desc='fuselage pitch angle', units='deg') self.add_output( diff --git a/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py b/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py index 7d24c1a84e..798ae2c14e 100644 --- a/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py +++ b/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py @@ -49,6 +49,7 @@ def test_groundroll_partials(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Dynamic.Vehicle.MASS, [1.0, 1.0], units='lbm') self.prob.run_model() diff --git a/aviary/mission/solved_two_dof/ode/test/test_unsteady_solved_ode.py b/aviary/mission/solved_two_dof/ode/test/test_unsteady_solved_ode.py index c86b1a2ccb..c5ac559a71 100644 --- a/aviary/mission/solved_two_dof/ode/test/test_unsteady_solved_ode.py +++ b/aviary/mission/solved_two_dof/ode/test/test_unsteady_solved_ode.py @@ -6,8 +6,8 @@ from openmdao.utils.testing_utils import use_tempdirs from aviary.constants import GRAV_ENGLISH_LBM -from aviary.mission.two_dof.ode.test.params import set_params_for_unit_tests from aviary.mission.solved_two_dof.ode.unsteady_solved_ode import UnsteadySolvedODE +from aviary.mission.two_dof.ode.test.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.variable_info.enums import SpeedType diff --git a/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py b/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py index 1c216e700e..a6c8797445 100644 --- a/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py +++ b/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py @@ -47,12 +47,12 @@ def setup(self): add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, shape=nn, units='N') add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, desc=Dynamic.Vehicle.LIFT, units='N') add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, desc=Dynamic.Vehicle.DRAG, units='N') - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0, units='rad') - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') + add_aviary_input(self, Aircraft.Wing.INCIDENCE, units='rad') + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='rad') add_aviary_input(self, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, units='unitless') if not self.options['ground_roll']: - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') self.add_input( 'dh_dr', val=np.zeros(nn), desc='d(alt)/d(range)', units='m/distance_units' ) diff --git a/aviary/mission/solved_two_dof/ode/unsteady_solved_flight_conditions.py b/aviary/mission/solved_two_dof/ode/unsteady_solved_flight_conditions.py index ed2eb3bde1..95abef904c 100644 --- a/aviary/mission/solved_two_dof/ode/unsteady_solved_flight_conditions.py +++ b/aviary/mission/solved_two_dof/ode/unsteady_solved_flight_conditions.py @@ -69,29 +69,26 @@ def setup(self): add_aviary_input( self, Dynamic.Atmosphere.DENSITY, - val=np.zeros(nn), + shape=nn, units='kg/m**3', - desc='density of air', ) add_aviary_input( self, Dynamic.Atmosphere.SPEED_OF_SOUND, - val=np.zeros(nn), + shape=nn, units='m/s', - desc='speed of sound', ) add_aviary_output( self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, - val=np.zeros(nn), + shape=nn, units='N/m**2', - desc='dynamic pressure', ) self.add_output( 'dTAS_dt_approx', - val=np.zeros(nn), + shape=nn, units='m/s**2', desc='approximated rate of change of true airspeed', ) @@ -102,16 +99,14 @@ def setup(self): Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad', - desc='flight path angle', ) if in_type is SpeedType.TAS: add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.zeros(nn), + shape=nn, units='m/s', - desc='true air speed', ) self.add_input( @@ -130,9 +125,8 @@ def setup(self): add_aviary_output( self, Dynamic.Atmosphere.MACH, - val=np.zeros(nn), + shape=nn, units='unitless', - desc='Mach number', ) elif in_type is SpeedType.EAS: @@ -158,25 +152,22 @@ def setup(self): add_aviary_output( self, Dynamic.Mission.VELOCITY, - val=np.zeros(nn), + shape=nn, units='m/s', - desc='true air speed', ) add_aviary_output( self, Dynamic.Atmosphere.MACH, - val=np.zeros(nn), + shape=nn, units='unitless', - desc='Mach number', ) else: add_aviary_input( self, Dynamic.Atmosphere.MACH, - val=np.zeros(nn), + shape=nn, units='unitless', - desc='Mach number', ) self.add_input( 'dmach_dr', @@ -200,9 +191,8 @@ def setup(self): add_aviary_output( self, Dynamic.Mission.VELOCITY, - val=np.zeros(nn), + shape=nn, units='m/s', - desc='true air speed', ) def setup_partials(self): diff --git a/aviary/mission/two_dof/ode/accel_eom.py b/aviary/mission/two_dof/ode/accel_eom.py index 5d1a1ff096..41db2185eb 100644 --- a/aviary/mission/two_dof/ode/accel_eom.py +++ b/aviary/mission/two_dof/ode/accel_eom.py @@ -22,44 +22,38 @@ def setup(self): add_aviary_input( self, Dynamic.Vehicle.MASS, - val=np.ones(nn) * 1e6, + shape=nn, units='lbm', - desc='total mass of the aircraft', ) add_aviary_input( self, Dynamic.Vehicle.DRAG, - val=np.zeros(nn), + shape=nn, units='lbf', - desc='drag on aircraft', ) add_aviary_input( self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, - val=np.zeros(nn), + shape=nn, units='lbf', - desc='total thrust', ) add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.zeros(nn), + shape=nn, units='ft/s', - desc='true air speed', ) self.add_output( Dynamic.Mission.VELOCITY_RATE, - val=np.zeros(nn), + shape=nn, units='ft/s**2', - desc='rate of change of true air speed', ) add_aviary_output( self, Dynamic.Mission.DISTANCE_RATE, - val=np.zeros(nn), + shape=nn, units='ft/s', - desc='rate of change of horizontal distance covered', ) def setup_partials(self): diff --git a/aviary/mission/two_dof/ode/breguet_cruise_eom.py b/aviary/mission/two_dof/ode/breguet_cruise_eom.py index 9a4b466f2f..5c390ab898 100644 --- a/aviary/mission/two_dof/ode/breguet_cruise_eom.py +++ b/aviary/mission/two_dof/ode/breguet_cruise_eom.py @@ -36,7 +36,7 @@ def setup(self): add_aviary_input( self, Dynamic.Vehicle.Propulsion.FUEL_MASS_FLOW_RATE_NEGATIVE_TOTAL, - 0.74 * np.ones(nn), + shape=nn, units='lbm/h', ) @@ -272,16 +272,14 @@ def setup(self): add_aviary_input( self, Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, - 10.0 * np.ones(nn), + shape=nn, units='kW*h', - desc='total energy consumption, comes from propulsion', ) add_aviary_input( self, Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, - 0.74 * np.ones(nn), + shape=nn, units='kW', - desc='total energy consumption, comes from propulsion', ) self.add_output( diff --git a/aviary/mission/two_dof/ode/constraints/flight_constraints.py b/aviary/mission/two_dof/ode/constraints/flight_constraints.py index 06efcfd6aa..cb9802cf54 100644 --- a/aviary/mission/two_dof/ode/constraints/flight_constraints.py +++ b/aviary/mission/two_dof/ode/constraints/flight_constraints.py @@ -26,19 +26,17 @@ def setup(self): add_aviary_input( self, Dynamic.Vehicle.MASS, - val=np.ones(nn), + shape=nn, units='lbm', - desc='mass of aircraft', ) - add_aviary_input(self, Aircraft.Wing.AREA, val=2) + add_aviary_input(self, Aircraft.Wing.AREA) add_aviary_input( self, Dynamic.Atmosphere.DENSITY, - val=np.ones(nn), + shape=nn, units='slug/ft**3', - desc='density of air', ) self.add_input( 'CL_max', @@ -49,26 +47,24 @@ def setup(self): add_aviary_input( self, Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.ones(nn), + shape=nn, units='rad', - desc='flight path angle', ) - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=1.0, units='rad') + add_aviary_input(self, Aircraft.Wing.INCIDENCE, units='rad') add_aviary_input( self, Dynamic.Vehicle.ANGLE_OF_ATTACK, - val=np.ones(nn), + shape=nn, units='rad', - desc='angle of attack', ) + add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.ones(nn), + shape=nn, units='ft/s', - desc='true airspeed', ) self.add_output( diff --git a/aviary/mission/two_dof/ode/constraints/speed_constraints.py b/aviary/mission/two_dof/ode/constraints/speed_constraints.py index 51f4a1bf1d..a4ffa397a9 100644 --- a/aviary/mission/two_dof/ode/constraints/speed_constraints.py +++ b/aviary/mission/two_dof/ode/constraints/speed_constraints.py @@ -37,9 +37,8 @@ def setup(self): add_aviary_input( self, Dynamic.Atmosphere.MACH, - val=np.ones(nn), + shape=nn, units='unitless', - desc='Mach number', ) self.add_output( diff --git a/aviary/mission/two_dof/ode/constraints/test/test_flight_constraints.py b/aviary/mission/two_dof/ode/constraints/test/test_flight_constraints.py index 7e4e42cd66..306f179a33 100644 --- a/aviary/mission/two_dof/ode/constraints/test/test_flight_constraints.py +++ b/aviary/mission/two_dof/ode/constraints/test/test_flight_constraints.py @@ -50,27 +50,5 @@ def test_case1(self): assert_check_partials(partial_data, atol=3e-11, rtol=1e-12) -class FlightConstraintTestCase2(unittest.TestCase): - """Test mass-weight conversion.""" - - def setUp(self): - import aviary.mission.two_dof.ode.constraints.flight_constraints as constraints - - constraints.GRAV_ENGLISH_LBM = 1.1 - - def tearDown(self): - import aviary.mission.two_dof.ode.constraints.flight_constraints as constraints - - constraints.GRAV_ENGLISH_LBM = 1.0 - - def test_case1(self): - prob = om.Problem() - prob.model.add_subsystem('group', FlightConstraints(num_nodes=2), promotes=['*']) - prob.setup(check=False, force_alloc_complex=True) - - partial_data = prob.check_partials(out_stream=None, method='cs') - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) - - if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/two_dof/ode/flight_eom.py b/aviary/mission/two_dof/ode/flight_eom.py index 56cee79f97..de5fb913d8 100644 --- a/aviary/mission/two_dof/ode/flight_eom.py +++ b/aviary/mission/two_dof/ode/flight_eom.py @@ -18,57 +18,49 @@ def setup(self): add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.zeros(nn), + shape=nn, units='ft/s', - desc='true air speed', ) add_aviary_input( self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, - val=np.zeros(nn), + shape=nn, units='lbf', - desc='net thrust', - ) - add_aviary_input( - self, Dynamic.Vehicle.DRAG, val=np.zeros(nn), units='lbf', desc='net drag on aircraft' ) + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='lbf') add_aviary_input( self, Dynamic.Vehicle.MASS, - val=np.zeros(nn), + shape=nn, units='lbm', - desc='mass of aircraft', ) add_aviary_input( self, Dynamic.Vehicle.ANGLE_OF_ATTACK, - val=np.ones(nn), + shape=nn, units='rad', - desc='angle of attack of aircraft', ) add_aviary_output( self, Dynamic.Mission.ALTITUDE_RATE, - val=np.zeros(nn), + shape=nn, units='ft/s', - desc='rate of change of altitude', ) add_aviary_output( self, Dynamic.Mission.DISTANCE_RATE, - val=np.zeros(nn), + shape=nn, units='ft/s', - desc='rate of change of horizontal distance covered', ) self.add_output( 'required_lift', - val=np.zeros(nn), + shape=nn, units='lbf', desc='lift required in order to maintain calculated flight path angle', ) - add_aviary_output(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), units='rad') + add_aviary_output(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') def setup_partials(self): nn = self.options['num_nodes'] diff --git a/aviary/mission/two_dof/ode/flight_path_eom.py b/aviary/mission/two_dof/ode/flight_path_eom.py index 7967dde39a..e486968103 100644 --- a/aviary/mission/two_dof/ode/flight_path_eom.py +++ b/aviary/mission/two_dof/ode/flight_path_eom.py @@ -26,51 +26,47 @@ def setup(self): nn = self.options['num_nodes'] ground_roll = self.options['ground_roll'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='lbm') - add_aviary_input( - self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='lbf' - ) - add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='lbf') - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='lbf') - add_aviary_input( - self, Dynamic.Mission.VELOCITY, val=np.ones(nn), desc='true air speed', units='ft/s' - ) - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), units='rad') - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0) + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=(nn), units='lbm') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, shape=(nn), units='lbf') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=(nn), units='lbf') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=(nn), units='lbf') + add_aviary_input(self, Dynamic.Mission.VELOCITY, shape=(nn), units='ft/s') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=(nn), units='rad') + add_aviary_input(self, Aircraft.Wing.INCIDENCE, units='deg') add_aviary_input(self, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, units='unitless') - self.add_output( + add_aviary_output( + self, Dynamic.Mission.VELOCITY_RATE, - val=np.ones(nn), - desc='TAS rate', + shape=(nn), units='ft/s**2', tags=['dymos.state_rate_source:velocity', 'dymos.state_units:kn'], ) if not ground_roll: - self.add_output( + add_aviary_output( + self, Dynamic.Mission.ALTITUDE_RATE, - val=np.ones(nn), - desc='altitude rate', + shape=(nn), units='ft/s', - tags=['dymos.state_rate_source:altitude', 'dymos.state_units:ft'], + # tags=['dymos.state_rate_source:altitude', 'dymos.state_units:ft'], ) - self.add_output( + add_aviary_output( + self, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - val=np.ones(nn), - desc='flight path angle rate', + shape=(nn), units='rad/s', tags=[ 'dymos.state_rate_source:flight_path_angle', 'dymos.state_units:rad', ], ) - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.ones(nn), units='deg') + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=(nn), units='deg') - self.add_output( + add_aviary_output( + self, Dynamic.Mission.DISTANCE_RATE, - val=np.ones(nn), - desc='distance rate', + shape=(nn), units='ft/s', tags=['dymos.state_rate_source:distance', 'dymos.state_units:ft'], ) diff --git a/aviary/mission/two_dof/ode/landing_eom.py b/aviary/mission/two_dof/ode/landing_eom.py index 85026e7cfe..c1ddd11ddf 100644 --- a/aviary/mission/two_dof/ode/landing_eom.py +++ b/aviary/mission/two_dof/ode/landing_eom.py @@ -10,10 +10,10 @@ class LandingAltitudeComponent(om.ExplicitComponent): """Compute the landing altitude.""" def setup(self): - add_aviary_input(self, Mission.Landing.OBSTACLE_HEIGHT, val=50.0) - add_aviary_input(self, Mission.Landing.AIRPORT_ALTITUDE, val=0.0) + add_aviary_input(self, Mission.Landing.OBSTACLE_HEIGHT) + add_aviary_input(self, Mission.Landing.AIRPORT_ALTITUDE) - add_aviary_output(self, Mission.Landing.INITIAL_ALTITUDE, val=0.0) + add_aviary_output(self, Mission.Landing.INITIAL_ALTITUDE) self.declare_partials(Mission.Landing.INITIAL_ALTITUDE, '*', val=1) @@ -32,27 +32,26 @@ class GlideConditionComponent(om.ExplicitComponent): """Compute the initial conditions of the 2DOF glide phase.""" def setup(self): - add_aviary_input(self, Dynamic.Atmosphere.DENSITY, val=0.0, units='slug/ft**3') - add_aviary_input(self, Mission.Landing.MAXIMUM_SINK_RATE, val=900.0) - add_aviary_input(self, Dynamic.Vehicle.MASS, val=0.0, units='lbm') - add_aviary_input(self, Aircraft.Wing.AREA, val=1.0) - add_aviary_input(self, Mission.Landing.GLIDE_TO_STALL_RATIO, val=1.3) + add_aviary_input(self, Dynamic.Atmosphere.DENSITY, units='slug/ft**3') + add_aviary_input(self, Mission.Landing.MAXIMUM_SINK_RATE) + add_aviary_input(self, Dynamic.Vehicle.MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.AREA) + add_aviary_input(self, Mission.Landing.GLIDE_TO_STALL_RATIO) self.add_input( 'CL_max', val=0.0, units='unitless', desc='CLMX: max CL at approach altitude' ) - add_aviary_input(self, Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, val=1.15) - add_aviary_input(self, Mission.Landing.TOUCHDOWN_SINK_RATE, val=5.0) - add_aviary_input(self, Mission.Landing.INITIAL_ALTITUDE, val=0.0) - add_aviary_input(self, Mission.Landing.BRAKING_DELAY, val=1.0) + add_aviary_input(self, Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR) + add_aviary_input(self, Mission.Landing.TOUCHDOWN_SINK_RATE) + add_aviary_input(self, Mission.Landing.INITIAL_ALTITUDE) + add_aviary_input(self, Mission.Landing.BRAKING_DELAY) add_aviary_output( self, Mission.Landing.INITIAL_VELOCITY, - val=0.0, desc='glide speed calculated using TAS_stall', ) - add_aviary_output(self, Mission.Landing.STALL_VELOCITY, val=0.0) + add_aviary_output(self, Mission.Landing.STALL_VELOCITY) self.add_output('TAS_touchdown', val=0.0, units='ft/s', desc='VTD: touchdown speed') self.add_output( @@ -534,7 +533,7 @@ def setup(self): self.add_input('touchdown_CD', val=0.0, units='unitless', desc='CDRL: CD at touchdown') self.add_input('touchdown_CL', val=0.0, units='unitless', desc='CLRL: CL at touchdown') - add_aviary_input(self, Mission.Landing.STALL_VELOCITY, val=0.0) + add_aviary_input(self, Mission.Landing.STALL_VELOCITY) self.add_input('TAS_touchdown', val=0.0, units='ft/s', desc='VTD: velocity at touchdown') self.add_input( 'thrust_idle', @@ -570,7 +569,6 @@ def setup(self): add_aviary_input( self, Dynamic.Vehicle.MASS, - val=0.0, units='lbm', desc='WL: aircraft mass at start of landing', ) @@ -578,7 +576,6 @@ def setup(self): self, Mission.Landing.BRAKING_FRICTION_COEFFICIENT, units='unitless', - desc='braking friction coefficient', ) self.add_output( @@ -587,7 +584,7 @@ def setup(self): units='ft', desc='DLG: distance during braked ground roll', ) - add_aviary_output(self, Mission.Landing.GROUND_DISTANCE, val=0.0) + add_aviary_output(self, Mission.Landing.GROUND_DISTANCE) self.add_output( 'average_acceleration', val=0.0, diff --git a/aviary/mission/two_dof/ode/takeoff_eom.py b/aviary/mission/two_dof/ode/takeoff_eom.py index b09efc6343..b8f9fe3617 100644 --- a/aviary/mission/two_dof/ode/takeoff_eom.py +++ b/aviary/mission/two_dof/ode/takeoff_eom.py @@ -54,40 +54,36 @@ def setup(self): nn = self.options['num_nodes'] ground_roll = self.options['ground_roll'] - add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='lbm') - add_aviary_input( - self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='lbf' - ) - add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='lbf') - add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='lbf') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='lbm') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, shape=nn, units='lbf') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, units='lbf') + add_aviary_input(self, Dynamic.Vehicle.DRAG, shape=nn, units='lbf') add_aviary_input( self, Dynamic.Mission.VELOCITY, - val=np.ones(nn), + shape=nn, desc='true air speed', units='ft/s', ) - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), units='rad') - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0) + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units='rad') + add_aviary_input(self, Aircraft.Wing.INCIDENCE, units='deg') add_aviary_input(self, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, units='unitless') add_aviary_output( self, Dynamic.Mission.VELOCITY_RATE, - val=np.ones(nn), + shape=nn, desc='TAS rate', units='ft/s**2', ) - add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), units='ft/s') - add_aviary_output( - self, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, val=np.ones(nn), units='rad/s' - ) + add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, shape=nn, units='ft/s') + add_aviary_output(self, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, shape=nn, units='rad/s') if not ground_roll: - add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.ones(nn), units='deg') + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') - add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), units='ft/s') + add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, shape=nn, units='ft/s') self.add_output('normal_force', val=np.ones(nn), desc='normal forces', units='lbf') self.add_output('fuselage_pitch', val=np.ones(nn), desc='fuselage pitch angle', units='deg') diff --git a/aviary/mission/two_dof/ode/taxi_eom.py b/aviary/mission/two_dof/ode/taxi_eom.py index 791fe7f705..bf928b8393 100644 --- a/aviary/mission/two_dof/ode/taxi_eom.py +++ b/aviary/mission/two_dof/ode/taxi_eom.py @@ -14,11 +14,9 @@ def setup(self): add_aviary_input( self, Dynamic.Vehicle.Propulsion.FUEL_MASS_FLOW_RATE_NEGATIVE_TOTAL, - val=1.0, units='lbm/s', - desc='fuel flow rate', ) - add_aviary_input(self, Mission.GROSS_MASS, val=175400.0) + add_aviary_input(self, Mission.GROSS_MASS) self.add_output( 'taxi_fuel_consumed', @@ -29,7 +27,6 @@ def setup(self): add_aviary_output( self, Dynamic.Vehicle.MASS, - val=175000.0, units='lbm', desc='mass after taxi', ) diff --git a/aviary/mission/two_dof/ode/taxi_ode.py b/aviary/mission/two_dof/ode/taxi_ode.py index f70fd7e3ea..b6a43c3220 100644 --- a/aviary/mission/two_dof/ode/taxi_ode.py +++ b/aviary/mission/two_dof/ode/taxi_ode.py @@ -5,7 +5,6 @@ from aviary.mission.two_dof.ode.two_dof_ode import TwoDOFODE from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilder from aviary.utils.aviary_values import AviaryValues -from aviary.utils.option_to_var import add_opts2vals, create_opts2vals from aviary.variable_info.enums import SpeedType from aviary.variable_info.variable_meta_data import CoreMetaData from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -19,16 +18,6 @@ def setup(self): subsystems = self.options['subsystems'] user_options = self.options['user_options'] - # NOTE calling add_opts2vals in this way makes Mission.Taxi.MACH a required variable. - # This is because ODE was relying on old behavior of NamedValues.get_item() which returns - # (None, None) in option_to_var.py to avoid errors. - # Pulling the default from the MetaData if it does not exist instead. - # TODO find a better way to handle this - if Mission.Taxi.MACH not in options: - default_val = CoreMetaData[Mission.Taxi.MACH]['default_value'] - options.set_val(Mission.Taxi.MACH, default_val, 'unitless') - add_opts2vals(self, create_opts2vals([Mission.Taxi.MACH]), options) - alias_comp = om.ExecComp( 'alt=airport_alt', alt={ @@ -78,8 +67,6 @@ def setup(self): self.add_subsystem('taxifuel', TaxiFuelComponent(), promotes=['*']) - self.set_input_defaults(Mission.Taxi.MACH, 0) - # Throttle Idle num_engine_types = len(options.get_val(Aircraft.Engine.NUM_ENGINES)) self.set_input_defaults( diff --git a/aviary/mission/two_dof/ode/test/test_accel_eom.py b/aviary/mission/two_dof/ode/test/test_accel_eom.py index 77a665723b..7c28276288 100644 --- a/aviary/mission/two_dof/ode/test/test_accel_eom.py +++ b/aviary/mission/two_dof/ode/test/test_accel_eom.py @@ -57,27 +57,5 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -class AccelerationTestCase2(unittest.TestCase): - """Test mass-weight conversion.""" - - def setUp(self): - import aviary.mission.two_dof.ode.accel_eom as accel - - accel.GRAV_ENGLISH_LBM = 1.1 - - def tearDown(self): - import aviary.mission.two_dof.ode.accel_eom as accel - - accel.GRAV_ENGLISH_LBM = 1.0 - - def test_case1(self): - prob = om.Problem() - prob.model.add_subsystem('group', AccelerationRates(num_nodes=2), promotes=['*']) - prob.setup(check=False, force_alloc_complex=True) - - partial_data = prob.check_partials(out_stream=None, method='cs') - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) - - if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py b/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py index cc64f5a013..d7d30f8e30 100644 --- a/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py +++ b/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py @@ -5,10 +5,7 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from openmdao.utils.testing_utils import use_tempdirs -from aviary.mission.two_dof.ode.breguet_cruise_ode import ( - BreguetCruiseODE, - ElectricBreguetCruiseODE, -) +from aviary.mission.two_dof.ode.breguet_cruise_ode import BreguetCruiseODE, ElectricBreguetCruiseODE from aviary.mission.two_dof.ode.test.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems @@ -59,7 +56,7 @@ def test_cruise(self): self.prob.run_model() tol = tol = 1e-6 - assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([1.0, 1.0]), tol) + assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([0.0, 0.0]), tol) assert_near_equal(self.prob[Dynamic.Mission.DISTANCE], np.array([0.0, 923.39168758]), tol) assert_near_equal(self.prob['time'], np.array([0, 8280.30660691]), tol) assert_near_equal( @@ -69,7 +66,7 @@ def test_cruise(self): ) assert_near_equal( self.prob[Dynamic.Mission.ALTITUDE_RATE_MAX], - np.array([-17.17541759, -16.15718646]), + np.array([3.88465429, 4.90288542]), tol, ) @@ -118,13 +115,14 @@ def test_electric_cruise(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, [10, 10]) set_params_for_unit_tests(self.prob) self.prob.run_model() tol = tol = 1e-6 - assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([1.0, 1.0]), tol) + assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([0.0, 0.0]), tol) assert_near_equal(self.prob[Dynamic.Mission.DISTANCE], np.array([0.0, 66.37436515]), tol) assert_near_equal(self.prob['time'], np.array([0, 595.19714299]), tol) assert_near_equal( @@ -134,7 +132,7 @@ def test_electric_cruise(self): ) assert_near_equal( self.prob[Dynamic.Mission.ALTITUDE_RATE_MAX], - np.array([-17.16778983, -16.14909135]), + np.array([3.89228205, 4.91098053]), tol, ) assert_near_equal( diff --git a/aviary/mission/two_dof/ode/test/test_flight_eom.py b/aviary/mission/two_dof/ode/test/test_flight_eom.py index dcfee5b762..2c05957697 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_eom.py +++ b/aviary/mission/two_dof/ode/test/test_flight_eom.py @@ -118,6 +118,7 @@ def setUp(self): self.prob.model.set_input_defaults( Dynamic.Vehicle.MASS, np.array([171481, 171481]), units='lbm' ) + self.prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, np.ones(2)) self.prob.setup(check=False, force_alloc_complex=True) diff --git a/aviary/mission/two_dof/ode/test/test_flight_path_eom.py b/aviary/mission/two_dof/ode/test/test_flight_path_eom.py index b10567b9e6..f6fd362592 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_path_eom.py +++ b/aviary/mission/two_dof/ode/test/test_flight_path_eom.py @@ -19,6 +19,14 @@ def setUp(self): ) self.prob.model.set_input_defaults(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.02) self.prob.setup(check=False, force_alloc_complex=True) + self.prob.set_val(Dynamic.Vehicle.MASS, [1.0, 1.0], units='lbm') + self.prob.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [1.0, 1.0], units='rad') + self.prob.set_val(Dynamic.Mission.VELOCITY_RATE, [1.0, 1.0], units='ft/s**2') + self.prob.set_val(Dynamic.Mission.VELOCITY, [1.0, 1.0], units='ft/s') + self.prob.set_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, [1.0, 1.0], units='lbf') + self.prob.set_val(Dynamic.Vehicle.LIFT, [1.0, 1.0], units='lbf') + self.prob.set_val(Dynamic.Vehicle.DRAG, [1.0, 1.0], units='lbf') + self.prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [1.0, 1.0], units='deg') def test_case1(self): # ground_roll = False (the aircraft is not confined to the ground) @@ -47,6 +55,13 @@ def test_case2(self): """ground_roll = True (the aircraft is confined to the ground).""" self.fp.options['ground_roll'] = True self.prob.setup(force_alloc_complex=True) + self.prob.set_val(Dynamic.Vehicle.MASS, [1.0, 1.0], units='lbm') + self.prob.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [1.0, 1.0], units='rad') + self.prob.set_val(Dynamic.Mission.VELOCITY_RATE, [1.0, 1.0], units='ft/s**2') + self.prob.set_val(Dynamic.Mission.VELOCITY, [1.0, 1.0], units='ft/s') + self.prob.set_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, [1.0, 1.0], units='lbf') + self.prob.set_val(Dynamic.Vehicle.LIFT, [1.0, 1.0], units='lbf') + self.prob.set_val(Dynamic.Vehicle.DRAG, [1.0, 1.0], units='lbf') tol = 1e-6 self.prob.run_model() @@ -88,6 +103,14 @@ def test_case1(self): ) prob.model.set_input_defaults(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.02) prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Dynamic.Vehicle.MASS, [1.0, 1.0], units='lbm') + prob.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [1.0, 1.0], units='rad') + prob.set_val(Dynamic.Mission.VELOCITY_RATE, [1.0, 1.0], units='ft/s**2') + prob.set_val(Dynamic.Mission.VELOCITY, [1.0, 1.0], units='ft/s') + prob.set_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, [1.0, 1.0], units='lbf') + prob.set_val(Dynamic.Vehicle.LIFT, [1.0, 1.0], units='lbf') + prob.set_val(Dynamic.Vehicle.DRAG, [1.0, 1.0], units='lbf') + prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [1.0, 1.0], units='deg') partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) @@ -100,6 +123,13 @@ def test_case2(self): ) prob.setup(check=False, force_alloc_complex=True) prob.setup(force_alloc_complex=True) + prob.set_val(Dynamic.Vehicle.MASS, [1.0, 1.0], units='lbm') + prob.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [1.0, 1.0], units='rad') + prob.set_val(Dynamic.Mission.VELOCITY_RATE, [1.0, 1.0], units='ft/s**2') + prob.set_val(Dynamic.Mission.VELOCITY, [1.0, 1.0], units='ft/s') + prob.set_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, [1.0, 1.0], units='lbf') + prob.set_val(Dynamic.Vehicle.LIFT, [1.0, 1.0], units='lbf') + prob.set_val(Dynamic.Vehicle.DRAG, [1.0, 1.0], units='lbf') partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) @@ -107,3 +137,6 @@ def test_case2(self): if __name__ == '__main__': unittest.main() + # test = FlightPathEOMTestCase() + # test.setUp() + # test.test_case1() diff --git a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py index 4929e80f8d..6ec2a1870b 100644 --- a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py +++ b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py @@ -56,7 +56,7 @@ def test_cruise(self): self.prob.run_model() tol = tol = 1e-6 - assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([1.0, 1.0]), tol) + assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([0.0, 0.0]), tol) assert_near_equal(self.prob[Dynamic.Mission.DISTANCE], np.array([0.0, 923.39168758]), tol) assert_near_equal(self.prob['time'], np.array([0, 8280.30660691]), tol) assert_near_equal( @@ -66,7 +66,7 @@ def test_cruise(self): ) assert_near_equal( self.prob[Dynamic.Mission.ALTITUDE_RATE_MAX], - np.array([-17.17541759, -16.15718646]), + np.array([3.88465429, 4.90288542]), tol, ) diff --git a/aviary/mission/two_dof/ode/test/test_taxi_ode.py b/aviary/mission/two_dof/ode/test/test_taxi_ode.py index 9efa79fe5e..79c2f0d524 100644 --- a/aviary/mission/two_dof/ode/test/test_taxi_ode.py +++ b/aviary/mission/two_dof/ode/test/test_taxi_ode.py @@ -6,8 +6,8 @@ from openmdao.utils.testing_utils import use_tempdirs from packaging import version -from aviary.mission.two_dof.ode.test.params import set_params_for_unit_tests from aviary.mission.two_dof.ode.taxi_ode import TaxiSegment +from aviary.mission.two_dof.ode.test.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs diff --git a/aviary/mission/two_dof/ode/v_rotate_comp.py b/aviary/mission/two_dof/ode/v_rotate_comp.py index aef9fdbe67..d045269cb2 100644 --- a/aviary/mission/two_dof/ode/v_rotate_comp.py +++ b/aviary/mission/two_dof/ode/v_rotate_comp.py @@ -8,21 +8,20 @@ class VRotateComp(om.ExplicitComponent): """ Component that computes V_rotate based on vehicle properties and speed buffers. - Note: This component is not used. + NOTE: This component is not used. """ def setup(self): - # Temporarily set this to shape (1, 1) to avoid OpenMDAO bug + # TODO: Temporarily set this to shape (1, 1) to avoid OpenMDAO bug add_aviary_input(self, Dynamic.Vehicle.MASS, shape=(1, 1), units='lbm') add_aviary_input( self, Dynamic.Atmosphere.DENSITY, shape=(1,), units='slug/ft**3', - val=RHO_SEA_LEVEL_ENGLISH, - desc='sea-level atmospheric density', + # val=RHO_SEA_LEVEL_ENGLISH, ) - add_aviary_input(self, Aircraft.Wing.AREA, val=1.0) + add_aviary_input(self, Aircraft.Wing.AREA) self.add_input('CL_max', shape=(1,), units='unitless', desc='Maximum lift coefficient') self.add_input( 'dV1', diff --git a/aviary/models/external_subsystems/detailed_battery/model/battery_premission.py b/aviary/models/external_subsystems/detailed_battery/model/battery_premission.py index ee9f2e3ba2..6d40ffc61c 100644 --- a/aviary/models/external_subsystems/detailed_battery/model/battery_premission.py +++ b/aviary/models/external_subsystems/detailed_battery/model/battery_premission.py @@ -32,13 +32,13 @@ def setup(self): add_aviary_input(self, Aircraft.Battery.VOLTAGE, meta_data=ExtendedMetaData) add_aviary_input(self, Aircraft.Battery.Cell.VOLUME, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.N_SERIES, val=0.0, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.N_PARALLEL, val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.N_SERIES, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.N_PARALLEL, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.MASS, val=0.0, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.HEAT_CAPACITY, val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.MASS, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.HEAT_CAPACITY, meta_data=ExtendedMetaData) # unconnected output used for test checking - add_aviary_output(self, Aircraft.Battery.VOLUME, val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.VOLUME, meta_data=ExtendedMetaData) self.declare_partials( Aircraft.Battery.N_SERIES, [Aircraft.Battery.VOLTAGE, Aircraft.Battery.Cell.VOLTAGE_LOW] diff --git a/aviary/models/external_subsystems/detailed_battery/model/cell_comp.py b/aviary/models/external_subsystems/detailed_battery/model/cell_comp.py index 8a2fd7655a..2e495aada2 100644 --- a/aviary/models/external_subsystems/detailed_battery/model/cell_comp.py +++ b/aviary/models/external_subsystems/detailed_battery/model/cell_comp.py @@ -15,81 +15,77 @@ def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): - n = self.options['num_nodes'] + nn = self.options['num_nodes'] # Inputs add_aviary_input( self, Dynamic.Battery.CURRENT, - val=3.25 * np.ones(n), + shape=nn, meta_data=ExtendedMetaData, ) # Static Constants add_aviary_input( self, Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, meta_data=ExtendedMetaData ) - add_aviary_input(self, Aircraft.Battery.N_PARALLEL, val=40.0, meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.N_SERIES, val=128.0, meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.N_PARALLEL, meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.N_SERIES, meta_data=ExtendedMetaData) # Integrated State Variables add_aviary_input( self, Dynamic.Battery.STATE_OF_CHARGE, - val=0.98 * np.ones(n), + shape=nn, meta_data=ExtendedMetaData, ) add_aviary_input( self, Dynamic.Battery.VOLTAGE_THEVENIN, - val=np.ones(n), + shape=nn, meta_data=ExtendedMetaData, ) # Map Inputs From The Interpolation Component - self.add_input('U_oc', val=4.16 * np.ones(n), units='V', desc='Open-circuit voltage') + self.add_input('U_oc', val=4.16 * np.ones(nn), units='V', desc='Open-circuit voltage') self.add_input( 'C_Th', - val=2000.0 * np.ones(n), + val=2000.0 * np.ones(nn), units='F', desc='Thevenin RC parallel capacitance (polarization)', ) self.add_input( 'R_Th', - val=0.01 * np.ones(n), + val=0.01 * np.ones(nn), units='ohm', desc='Thevenin RC parallel resistance (polarization)', ) self.add_input( - 'R_0', val=0.01 * np.ones(n), units='ohm', desc='Internal resistance of the battery' + 'R_0', val=0.01 * np.ones(nn), units='ohm', desc='Internal resistance of the battery' ) # Outputs add_aviary_output( self, Dynamic.Battery.STATE_OF_CHARGE_RATE, - val=np.ones(n), + shape=nn, meta_data=ExtendedMetaData, ) add_aviary_output( self, Dynamic.Battery.VOLTAGE_THEVENIN_RATE, - val=np.ones(n), + shape=nn, meta_data=ExtendedMetaData, ) add_aviary_output( self, Dynamic.Battery.VOLTAGE, - val=416 * np.ones(n), + shape=nn, meta_data=ExtendedMetaData, ) - add_aviary_output( - self, Dynamic.Battery.HEAT_OUT, val=np.ones(n), meta_data=ExtendedMetaData - ) - add_aviary_output( - self, Dynamic.Battery.EFFICIENCY, val=np.ones(n), meta_data=ExtendedMetaData - ) + add_aviary_output(self, Dynamic.Battery.HEAT_OUT, shape=nn, meta_data=ExtendedMetaData) + add_aviary_output(self, Dynamic.Battery.EFFICIENCY, shape=nn, meta_data=ExtendedMetaData) # Partials self.declare_partials(of='*', wrt='*', dependent=False) - ar = np.arange(n) + ar = np.arange(nn) self.declare_partials( of=Dynamic.Battery.STATE_OF_CHARGE_RATE, diff --git a/aviary/subsystems/aerodynamics/flops_based/mux_component.py b/aviary/subsystems/aerodynamics/flops_based/mux_component.py index 4fd09aa6e4..ffb8407a35 100644 --- a/aviary/subsystems/aerodynamics/flops_based/mux_component.py +++ b/aviary/subsystems/aerodynamics/flops_based/mux_component.py @@ -79,27 +79,27 @@ def setup(self): if self.num_nacelles > 0: add_aviary_input( - self, Aircraft.Nacelle.WETTED_AREA, np.zeros(num_engine_models), units='ft**2' + self, Aircraft.Nacelle.WETTED_AREA, shape=num_engine_models, units='ft**2' ) add_aviary_input( - self, Aircraft.Nacelle.FINENESS, np.zeros(num_engine_models), units='unitless' + self, Aircraft.Nacelle.FINENESS, shape=num_engine_models, units='unitless' ) add_aviary_input( self, Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - np.zeros(num_engine_models), + shape=num_engine_models, units='ft', ) add_aviary_input( self, Aircraft.Nacelle.LAMINAR_FLOW_UPPER, - np.zeros(num_engine_models), + shape=num_engine_models, units='unitless', ) add_aviary_input( self, Aircraft.Nacelle.LAMINAR_FLOW_LOWER, - np.zeros(num_engine_models), + shape=num_engine_models, units='unitless', ) nc += self.num_nacelles diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py index 3ed74dde88..00369cad71 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py @@ -17,7 +17,7 @@ def setup(self): units='unitless', desc='VLAM8: sensitivity of flap clean wing maximum lift coefficient to wing sweep angle', ) - add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, desc='INGASP.SA', units='ft/s') + add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, units='ft/s') # from component 3 outputs add_aviary_input(self, Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, units='unitless') @@ -84,7 +84,6 @@ def setup(self): self, Dynamic.Atmosphere.STATIC_PRESSURE, units='lbf/ft**2', - desc='INGASP.P0', ) add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') @@ -124,10 +123,8 @@ def setup(self): add_aviary_input( self, Dynamic.Atmosphere.KINEMATIC_VISCOSITY, - val=0.15723e-03, - desc='INGASP.XKV', ) - add_aviary_input(self, Dynamic.Atmosphere.TEMPERATURE, units='degR', desc='INGASP.T0') + add_aviary_input(self, Dynamic.Atmosphere.TEMPERATURE, units='degR') # outputs @@ -139,9 +136,7 @@ def setup(self): ) self.add_output( Dynamic.Atmosphere.MACH, - val=0.17522, units='unitless', - desc='SMN: Mach number', ) self.add_output('reynolds', val=157.1111, units='unitless', desc='RNW: reynolds number') diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index 51ac0e2fc2..cc5c2ac0ba 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -172,20 +172,18 @@ def setup_partials(self): ) def compute(self, inputs, outputs): - ( - wing_area, - wingspan, - avg_chord, - taper_ratio, - tc_ratio_root, - wing_loc, - htail_loc, - span_htail, - span_vtail, - htail_area, - htail_chord, - cabin_width, - ) = inputs.values() + wing_area = inputs[Aircraft.Wing.AREA] + wingspan = inputs[Aircraft.Wing.SPAN] + avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + wing_loc = inputs[Aircraft.Wing.VERTICAL_MOUNT_LOCATION] + htail_loc = inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_MOUNT_LOCATION] + span_htail = inputs[Aircraft.HorizontalTail.SPAN] + span_vtail = inputs[Aircraft.VerticalTail.SPAN] + htail_area = inputs[Aircraft.HorizontalTail.AREA] + htail_chord = inputs[Aircraft.HorizontalTail.AVERAGE_CHORD] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] verbosity = self.options[Settings.VERBOSITY] if wing_area == 0.0: @@ -341,20 +339,18 @@ def setup_partials(self): ) def compute(self, inputs, outputs): - ( - mach, - static_margin, - delta_cg, - AR, - sweep_c4, - htail_loc, - htail_sweep, - h_tail_moment, - sbar, - cbar, - hbar, - bbar, - ) = inputs.values() + mach = inputs[Dynamic.Atmosphere.MACH] + static_margin = inputs[Aircraft.Design.STATIC_MARGIN] + delta_cg = inputs[Aircraft.Design.CG_DELTA] + AR = inputs[Aircraft.Wing.ASPECT_RATIO] + sweep_c4 = inputs[Aircraft.Wing.SWEEP] + htail_loc = inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_MOUNT_LOCATION] + htail_sweep = inputs[Aircraft.HorizontalTail.SWEEP] + h_tail_moment = inputs[Aircraft.HorizontalTail.MOMENT_RATIO] + sbar = inputs['sbar'] + cbar = inputs['cbar'] + hbar = inputs['hbar'] + bbar = inputs['bbar'] verbosity = self.options[Settings.VERBOSITY] if h_tail_moment == 0.0: @@ -683,7 +679,7 @@ def setup(self): add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, shape=nn, units='ft/s') add_aviary_input( - self, Dynamic.Atmosphere.KINEMATIC_VISCOSITY, val=1.0, shape=nn, units='ft**2/s' + self, Dynamic.Atmosphere.KINEMATIC_VISCOSITY, shape=nn, units='ft**2/s' ) self.add_input('ufac', units='unitless', shape=nn, desc='UFAC') @@ -692,12 +688,10 @@ def setup(self): # user could input these directly or use functions to estimate from geometry add_aviary_input(self, Aircraft.Wing.FORM_FACTOR, units='unitless') - add_aviary_input( self, Aircraft.Fuselage.FORM_FACTOR, units='unitless', - desc='FFFUS: fuselage form drag factor', ) add_aviary_input( @@ -705,63 +699,40 @@ def setup(self): ) add_aviary_input(self, Aircraft.VerticalTail.FORM_FACTOR, units='unitless') - add_aviary_input(self, Aircraft.HorizontalTail.FORM_FACTOR, units='unitless') - add_aviary_input(self, Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, units='unitless') - add_aviary_input(self, Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, units='unitless') # miscellaneous top-level inputs - add_aviary_input(self, Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, units='unitless') - add_aviary_input(self, Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, units='ft**2') - add_aviary_input(self, Aircraft.Wing.MIN_PRESSURE_LOCATION, units='unitless') - add_aviary_input(self, Aircraft.Wing.MAX_THICKNESS_LOCATION, units='unitless') # geometric user inputs - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') - add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') - add_aviary_input(self, Aircraft.Strut.AREA_RATIO, units='unitless') # geometric data from sizing - add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.HorizontalTail.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.VerticalTail.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') - add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, shape=num_engine_type, units='ft') - add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') - add_aviary_input(self, Aircraft.Nacelle.SURFACE_AREA, shape=num_engine_type, units='ft**2') - add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') - add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, units='unitless') - add_aviary_input(self, Aircraft.Strut.CHORD, units='ft') self.add_input( 'interference_independent_of_shielded_area', units='unitless' - ) # Is this used? - (self.add_input('drag_loss_due_to_shielded_wing_area', units='unitless'),) # Is this used? + ) + self.add_input('drag_loss_due_to_shielded_wing_area', units='unitless') self.add_input( 'siwb', units='unitless', @@ -923,52 +894,50 @@ def setup_partials(self): ) def compute(self, inputs, outputs): - ( - mach, - sos, - nu, - ufac, - ff_wing, - ff_fus, - ff_nac, - ff_vtail, - ff_htail, - wing_fus_intf, - strut_fus_intf, - cd0_inc, - fe_fus_inc, - wing_min_pressure_loc, - wing_max_thickness_loc, - AR, - sweep_c4, - taper_ratio, - strut_wing_area_ratio, - avg_chord, - htail_chord, - vtail_chord, - fus_len, - nac_len, - htail_area, - fus_SA, - nacelle_area, - wing_area, - vtail_area, - tc_ratio, - strut_chord, - feintwf, - areashieldwf, - siwb, - fcffc, - fcfhtc, - fckic, - fcfnc, - fpylnd, - fcfstrc, - fcfvtc, - fcfwc, - fexcrt, - pct_excr, - ) = inputs.values() + mach = inputs[Dynamic.Atmosphere.MACH] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] + nu = inputs[Dynamic.Atmosphere.KINEMATIC_VISCOSITY] + ufac = inputs['ufac'] + ff_wing = inputs[Aircraft.Wing.FORM_FACTOR] + ff_fus = inputs[Aircraft.Fuselage.FORM_FACTOR] + ff_nac = inputs[Aircraft.Nacelle.FORM_FACTOR] + ff_vtail = inputs[Aircraft.VerticalTail.FORM_FACTOR] + ff_htail = inputs[Aircraft.HorizontalTail.FORM_FACTOR] + wing_fus_intf = inputs[Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR] + strut_fus_intf = inputs[Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR] + cd0_inc = inputs[Aircraft.Design.DRAG_COEFFICIENT_INCREMENT] + fe_fus_inc = inputs[Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT] + wing_min_pressure_loc = inputs[Aircraft.Wing.MIN_PRESSURE_LOCATION] + wing_max_thickness_loc = inputs[Aircraft.Wing.MAX_THICKNESS_LOCATION] + AR = inputs[Aircraft.Wing.ASPECT_RATIO] + sweep_c4 = inputs[Aircraft.Wing.SWEEP] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + strut_wing_area_ratio = inputs[Aircraft.Strut.AREA_RATIO] + avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] + htail_chord = inputs[Aircraft.HorizontalTail.AVERAGE_CHORD] + vtail_chord = inputs[Aircraft.VerticalTail.AVERAGE_CHORD] + fus_len = inputs[Aircraft.Fuselage.LENGTH] + nac_len = inputs[Aircraft.Nacelle.AVG_LENGTH] + htail_area = inputs[Aircraft.HorizontalTail.AREA] + fus_SA = inputs[Aircraft.Fuselage.WETTED_AREA] + nacelle_area = inputs[Aircraft.Nacelle.SURFACE_AREA] + wing_area = inputs[Aircraft.Wing.AREA] + vtail_area = inputs[Aircraft.VerticalTail.AREA] + tc_ratio = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED] + strut_chord = inputs[Aircraft.Strut.CHORD] + feintwf = inputs['interference_independent_of_shielded_area'] + areashieldwf = inputs['drag_loss_due_to_shielded_wing_area'] + siwb = inputs['siwb'] + fcffc = inputs[Aircraft.Fuselage.DRAG_FACTOR] + fcfhtc = inputs[Aircraft.HorizontalTail.DRAG_FACTOR] + fckic = inputs[Aircraft.Design.INTERFERENCE_DRAG_FACTOR] + fcfnc = inputs[Aircraft.Nacelle.DRAG_FACTOR] + fpylnd = inputs[Aircraft.Nacelle.PYLON_DRAG_FACTOR] + fcfstrc = inputs[Aircraft.Strut.DRAG_FACTOR] + fcfvtc = inputs[Aircraft.VerticalTail.DRAG_FACTOR] + fcfwc = inputs[Aircraft.Wing.DRAG_FACTOR] + fexcrt = inputs[Aircraft.Design.EXCRESCENCE_DRAG_FACTOR] + pct_excr = inputs[Aircraft.Design.PERCENT_EXCRESCENCE_DRAG] num_engines = self.options[Aircraft.Engine.NUM_ENGINES] num_engine_type = len(num_engines) @@ -1329,26 +1298,24 @@ def setup_partials(self): ) def compute(self, inputs, outputs): - ( - alt, - CL, - gross_mass_initial, - flap_defl, - wing_height, - airport_alt, - flap_chord_ratio, - dCL_flaps_model, - dCD_flaps_model, - dCL_flaps_coef, - CDI_factor, - avg_chord, - wingspan, - wing_area, - cf, - SA5, - SA6, - SA7, - ) = inputs.values() + alt = inputs[Dynamic.Mission.ALTITUDE] + CL = inputs[Dynamic.Vehicle.LIFT_COEFFICIENT] + gross_mass_initial = inputs[Aircraft.Design.GROSS_MASS] + flap_defl = inputs['flap_defl'] + wing_height = inputs[Aircraft.Wing.HEIGHT] + airport_alt = inputs['airport_alt'] + flap_chord_ratio = inputs[Aircraft.Wing.FLAP_CHORD_RATIO] + dCL_flaps_model = inputs['dCL_flaps_model'] + dCD_flaps_model = inputs['dCD_flaps_model'] + dCL_flaps_coef = inputs['dCL_flaps_coef'] + CDI_factor = inputs['CDI_factor'] + avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] + wingspan = inputs[Aircraft.Wing.SPAN] + wing_area = inputs[Aircraft.Wing.AREA] + cf = inputs['cf'] + SA5 = inputs['SA5'] + SA6 = inputs['SA6'] + SA7 = inputs['SA7'] gross_wt_initial = gross_mass_initial * GRAV_ENGLISH_LBM # profile drag @@ -1432,22 +1399,20 @@ def setup_partials(self): ) def compute(self, inputs, outputs): - ( - mach, - CL, - div_drag_supercrit, - subsonic_factor, - supersonic_factor, - lift_factor, - zero_lift_factor, - fcmpc, - cf, - SA1, - SA2, - SA5, - SA6, - SA7, - ) = inputs.values() + mach = inputs[Dynamic.Atmosphere.MACH] + CL = inputs[Dynamic.Vehicle.LIFT_COEFFICIENT] + div_drag_supercrit = inputs[Aircraft.Design.DRAG_DIVERGENCE_SHIFT] + subsonic_factor = inputs[Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR] + supersonic_factor = inputs[Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR] + lift_factor = inputs[Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR] + zero_lift_factor = inputs[Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR] + fcmpc = inputs[Aircraft.Design.COMPRESSIBILITY_DRAG_FACTOR] + cf = inputs['cf'] + SA1 = inputs['SA1'] + SA2 = inputs['SA2'] + SA5 = inputs['SA5'] + SA6 = inputs['SA6'] + SA7 = inputs['SA7'] mach_div = SA1 + SA2 * CL + div_drag_supercrit @@ -1530,22 +1495,20 @@ def setup_partials(self): self.declare_partials('kclge', dynvars, rows=ar, cols=ar, method='cs') def compute(self, inputs, outputs): - ( - alpha, - alt, - lift_curve_slope, - alpha0, - sweep_c4, - AR, - wing_height, - airport_alt, - flap_defl, - flap_chord_ratio, - taper_ratio, - dCL_flaps_model, - avg_chord, - wingspan, - ) = inputs.values() + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + alt = inputs[Dynamic.Mission.ALTITUDE] + lift_curve_slope = inputs['lift_curve_slope'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + sweep_c4 = inputs[Aircraft.Wing.SWEEP] + AR = inputs[Aircraft.Wing.ASPECT_RATIO] + wing_height = inputs[Aircraft.Wing.HEIGHT] + airport_alt = inputs['airport_alt'] + flap_defl = inputs['flap_defl'] + flap_chord_ratio = inputs[Aircraft.Wing.FLAP_CHORD_RATIO] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + dCL_flaps_model = inputs['dCL_flaps_model'] + avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] + wingspan = inputs[Aircraft.Wing.SPAN] # ground effects - factor on lift-curve slope hac = wing_height + alt - airport_alt @@ -1670,16 +1633,14 @@ def setup_partials(self): ) def compute(self, inputs, outputs): - ( - alpha, - lift_curve_slope, - lift_ratio, - alpha0, - CL_max_flaps, - dCL_flaps_model, - kclge, - flap_factor, - ) = inputs.values() + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + lift_curve_slope = inputs['lift_curve_slope'] + lift_ratio = inputs['lift_ratio'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs['CL_max_flaps'] + dCL_flaps_model = inputs['dCL_flaps_model'] + kclge = inputs['kclge'] + flap_factor = inputs['flap_factor'] # clw_base = kclge * lift_curve_slope * deg2rad(alpha - alpha0) # clw = clw_base + dCL_flaps_model @@ -2156,7 +2117,10 @@ def setup_partials(self): self.declare_partials('CL_max', [Aircraft.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP]) def compute(self, inputs, outputs): - _, lift_curve_slope, lift_ratio, alpha0, CL_max_flaps = inputs.values() + lift_curve_slope = inputs['lift_curve_slope'] + lift_ratio = inputs['lift_ratio'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs[Aircraft.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] if self.options['output_alpha']: CL = inputs[Dynamic.Vehicle.LIFT_COEFFICIENT] clw = CL / (1 + lift_ratio) diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index 4f0564cf7d..c59beaae72 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -9,7 +9,13 @@ from openmdao.utils.testing_utils import use_tempdirs from aviary.subsystems.aerodynamics.gasp_based.gaspaero import ( + BWBSIWB, + SIWB, AeroGeom, + BWBAeroSetup, + BWBBodyLiftCurveSlope, + BWBLiftCoeff, + BWBLiftCoeffClean, CruiseAero, DragCoef, DragCoefClean, @@ -17,21 +23,14 @@ LiftCoeff, LiftCoeffClean, LowSpeedAero, - SIWB, UFac, - Xlifts, WingTailRatios, - BWBBodyLiftCurveSlope, - BWBLiftCoeff, - BWBLiftCoeffClean, - BWBAeroSetup, - BWBSIWB, + Xlifts, ) -from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import FormFactor, BWBFormFactor from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.variable_info.variables import Aircraft, Dynamic here = os.path.abspath(os.path.dirname(__file__)) cruise_data = pd.read_csv(os.path.join(here, 'data', 'aero_data_cruise.csv')) @@ -378,7 +377,7 @@ def test_case2(self): class LiftCoeffTest(unittest.TestCase): - """Test partials of LiftCoeff""" + """Test partials of LiftCoeff.""" def test_case1(self): prob = om.Problem() @@ -406,7 +405,7 @@ def test_case1(self): class LiftCoeffCleanTest(unittest.TestCase): - """Test partials of LiftCoeffClean""" + """Test partials of LiftCoeffClean.""" def test_case1(self): prob = om.Problem() @@ -470,12 +469,10 @@ def test_case2(self): class UFacTest(unittest.TestCase): - """Test UFac computation""" + """Test UFac computation.""" def test_case1(self): - """ - aircraft of tube and wing type (not used in AeroSetup) - """ + """Aircraft of tube and wing type (not used in AeroSetup).""" prob = om.Problem() prob.model.add_subsystem( @@ -501,9 +498,7 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) def test_case2(self): - """ - BWB case with smooth derivative (used in BWBAeroSetup) - """ + """BWB case with smooth derivative (used in BWBAeroSetup).""" options = get_option_defaults() options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') @@ -533,9 +528,7 @@ def test_case2(self): assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) def test_case3(self): - """ - BWB case without smoothness, hence exactly the same as GASP (used in BWBAeroSetup) - """ + """BWB case without smoothness, hence exactly the same as GASP (used in BWBAeroSetup).""" options = get_option_defaults() options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') @@ -566,7 +559,7 @@ def test_case3(self): class SIWBTest(unittest.TestCase): - """Test fuselage form factor computation and SIWB computation""" + """Test fuselage form factor computation and SIWB computation.""" def test_case1(self): prob = om.Problem() @@ -591,7 +584,7 @@ def test_case1(self): class BWBSIWBTest(unittest.TestCase): - """Test fuselage form factor computation and SIWB computation""" + """Test fuselage form factor computation and SIWB computation.""" def test_case1(self): prob = om.Problem() @@ -617,7 +610,7 @@ def test_case1(self): class WingTailRatiosTest(unittest.TestCase): def test_case1(self): - """BWB data""" + """BWB data.""" prob = om.Problem() prob.model.add_subsystem( 'wing_tail_ratio', @@ -929,7 +922,7 @@ def test_case1(self): class GroundEffectTest(unittest.TestCase): - """Test fuselage form factor computation and SIWB computation""" + """Test fuselage form factor computation and SIWB computation.""" def test_case1(self): prob = om.Problem() @@ -969,7 +962,7 @@ def test_case1(self): class BWBBodyLiftCurveSlopeTest(unittest.TestCase): - """Body lift curve slope test for BWB""" + """Body lift curve slope test for BWB.""" def test_case1(self): prob = om.Problem() @@ -995,7 +988,7 @@ def test_case1(self): class BWBLiftCoeffTest(unittest.TestCase): - """Body lift curve slope test for BWB""" + """Body lift curve slope test for BWB.""" def test_case1(self): prob = om.Problem() @@ -1071,7 +1064,7 @@ def test_case2(self): class BWBLiftCoeffCleanTest(unittest.TestCase): - """Body lift curve slope test for BWB""" + """Body lift curve slope test for BWB.""" def test_case1(self): prob = om.Problem() @@ -1145,7 +1138,7 @@ def test_case2(self): class DragCoefTest(unittest.TestCase): def test_case1(self): - """BWB data""" + """BWB data.""" prob = om.Problem() prob.model.add_subsystem( 'drag_coeff', @@ -1190,7 +1183,7 @@ def test_case1(self): assert_near_equal(prob['dCD_gear_full'], [0.01619421, 0.01619421], tol) def test_case2(self): - """BWB data""" + """BWB data.""" prob = om.Problem() prob.model.add_subsystem( 'drag_coeff', @@ -1237,7 +1230,7 @@ def test_case2(self): class DragCoefCleanTest(unittest.TestCase): def test_case1(self): - """BWB data""" + """BWB data.""" prob = om.Problem() prob.model.add_subsystem( 'drag_coeff_clean', @@ -1284,7 +1277,7 @@ def test_case1(self): assert_near_equal(prob[Dynamic.Vehicle.DRAG_COEFFICIENT], [0.02251097, 0.02251097], tol) def test_case2(self): - """BWB data""" + """BWB data.""" prob = om.Problem() prob.model.add_subsystem( 'drag_coeff_clean', @@ -1449,7 +1442,7 @@ def test_case1(self): GASP resport by ctaer.f ALPHA = 3.611767 CL = CLREQ = 0.41069 - CD = 0.014738 + CD = 0.014738. """ prob = self.prob options = self.options @@ -1490,7 +1483,7 @@ def test_case1(self): assert_near_equal(prob[Dynamic.Vehicle.DRAG], [43.92679357, 43.92679357], tol) def test_case2(self): - """output_alpha = True""" + """output_alpha = True.""" prob = self.prob options = self.options @@ -1629,7 +1622,7 @@ def setUp(self): prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') def test_case1(self): - """BWB data with lift_required = False""" + """BWB data with lift_required = False.""" prob = self.prob options = self.options options.set_val('output_alpha', False) @@ -1793,9 +1786,8 @@ def test_case1(self): DELCDF = DCDTO = 0.0062256 CL = 0.07507, 0.23964, 0.40422 CD = 0.01853, 0.01866, 0.02070 - CL/CD = 4.05136, 12.84433, 19.53199 + CL/CD = 4.05136, 12.84433, 19.53199. """ - prob = self.prob tol = 1e-6 aoas = [-2.0, 0.0, 2.0] @@ -1948,9 +1940,8 @@ def test_case1(self): DELCDF = DCDLD = 0.0105864 CL = 0.18551, 0.35009, 0.51467 CD = 0.02299, 0.02292, 0.02482 - CL/CD = 8.06918, 15.27225, 20.74018 + CL/CD = 8.06918, 15.27225, 20.74018. """ - prob = self.prob tol = 1e-6 aoas = [-2.0, 0.0, 2.0] diff --git a/aviary/subsystems/energy/battery_sizing.py b/aviary/subsystems/energy/battery_sizing.py index 12fa33bf65..0fd3c11929 100644 --- a/aviary/subsystems/energy/battery_sizing.py +++ b/aviary/subsystems/energy/battery_sizing.py @@ -19,32 +19,26 @@ def setup(self): add_aviary_input( self, Aircraft.Battery.PACK_MASS, - val=0.0, units='kg', desc='mass of energy-storing components of battery', ) add_aviary_input( self, Aircraft.Battery.ADDITIONAL_MASS, - val=0.0, units='kg', desc='mass of non energy-storing components of battery', ) add_aviary_input( self, Aircraft.Battery.PACK_ENERGY_DENSITY, - val=0.0, units='kJ/kg', desc='energy density of battery pack', ) - add_aviary_output( - self, Aircraft.Battery.MASS, val=0.0, units='kg', desc='total battery mass' - ) + add_aviary_output(self, Aircraft.Battery.MASS, units='kg', desc='total battery mass') add_aviary_output( self, Aircraft.Battery.ENERGY_CAPACITY, - val=0.0, units='kJ', desc='total battery energy storage', ) diff --git a/aviary/subsystems/geometry/gasp_based/test/test_override.py b/aviary/subsystems/geometry/gasp_based/test/test_override.py index 360dfd2b0a..afc986b0c3 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_override.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_override.py @@ -14,7 +14,7 @@ from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variable_meta_data import CoreMetaData -from aviary.variable_info.variables import Aircraft +from aviary.variable_info.variables import Aircraft, Dynamic @use_tempdirs @@ -133,6 +133,8 @@ def test_case_aero_coeffs(self): warnings.simplefilter('ignore', om.PromotionWarning) prob.setup() + prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, val=1.0) + prob.run_model() assert_near_equal(self.prob[Aircraft.Wing.FORM_FACTOR], 2.47320154, 1e-6) @@ -168,7 +170,7 @@ def test_case_emp_geo(self): if __name__ == '__main__': - # unittest.main() - test = GASPOverrideTestCase() - test.setUp() - test.test_case_emp_geo() + unittest.main() + # test = GASPOverrideTestCase() + # test.setUp() + # test.test_case_aero_coeffs() diff --git a/aviary/subsystems/mass/flops_based/test/test_engine.py b/aviary/subsystems/mass/flops_based/test/test_engine.py index 1acac1dcfe..fc8290ead0 100644 --- a/aviary/subsystems/mass/flops_based/test/test_engine.py +++ b/aviary/subsystems/mass/flops_based/test/test_engine.py @@ -13,11 +13,11 @@ from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_tests import ( + Version, flops_validation_test, get_flops_case_names, get_flops_options, print_case, - Version, ) from aviary.variable_info.variables import Aircraft, Settings diff --git a/aviary/subsystems/mass/gasp_based/engine.py b/aviary/subsystems/mass/gasp_based/engine.py index e867d98304..e34b7797ba 100644 --- a/aviary/subsystems/mass/gasp_based/engine.py +++ b/aviary/subsystems/mass/gasp_based/engine.py @@ -7,9 +7,7 @@ class TotalEngineMass(om.ExplicitComponent): - """ - Computation of total engine mass, nacelle mass, pylon mass. - """ + """Computation of total engine mass, nacelle mass, pylon mass.""" def initialize(self): add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) @@ -41,10 +39,8 @@ def setup(self): add_aviary_input( self, Aircraft.Engine.Propeller.MASS, - # val=np.full(num_engine_type, 0.000000001), - val=np.zeros(num_engine_type), + shape=num_engine_type, units='lbm', - desc='WPROP1: mass of one propeller', ) # add_aviary_output(self, Aircraft.Engine.MASS, units='lbm') @@ -54,7 +50,7 @@ def setup(self): 'pylon_mass', units='lbm', desc='WPYLON: mass of each pylon', - val=np.zeros(num_engine_type), + shape=num_engine_type, ) def setup_partials(self): @@ -189,9 +185,7 @@ def compute_partials(self, inputs, J): class EnginePODMass(om.ExplicitComponent): - """ - Computation of engine pod mass and total engine pod mass. - """ + """Computation of engine pod mass and total engine pod mass.""" def initialize(self): add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) @@ -269,9 +263,7 @@ def compute_partials(self, inputs, J): class AdditionalEngineMass(om.ExplicitComponent): - """ - Computation of additional engine mass. - """ + """Computation of additional engine mass.""" def initialize(self): add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) @@ -389,10 +381,8 @@ def setup(self): add_aviary_input( self, Aircraft.Engine.Propeller.MASS, - # val=np.full(num_engine_type, 0.000000001), - val=np.zeros(num_engine_type), + shape=num_engine_type, units='lbm', - desc='WPROP1: mass of one propeller', ) add_aviary_input(self, Aircraft.Engine.POD_MASS, shape=num_engine_type, units='lbm') add_aviary_input(self, Aircraft.Engine.ADDITIONAL_MASS, shape=num_engine_type, units='lbm') diff --git a/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py b/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py index 12d027d0c4..d13f6df46a 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py +++ b/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py @@ -4,18 +4,18 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from openmdao.utils.testing_utils import use_tempdirs -from aviary.validation_cases.validation_data.test_data.V3_bug_fixed_IO import ( - V3_bug_fixed_non_metadata, - V3_bug_fixed_options, -) from aviary.subsystems.geometry.gasp_based.size_group import SizeGroup from aviary.subsystems.mass.gasp_based.mass_premission import MassPremission from aviary.subsystems.mass.gasp_based.mass_summation import StructureMass from aviary.utils.aviary_values import AviaryValues +from aviary.validation_cases.validation_data.test_data.V3_bug_fixed_IO import ( + V3_bug_fixed_non_metadata, + V3_bug_fixed_options, +) from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Mission from aviary.variable_info.variable_meta_data import CoreMetaData +from aviary.variable_info.variables import Aircraft, Mission @use_tempdirs diff --git a/aviary/subsystems/propulsion/engine_scaling.py b/aviary/subsystems/propulsion/engine_scaling.py index b1dc9ca737..ef3173d426 100644 --- a/aviary/subsystems/propulsion/engine_scaling.py +++ b/aviary/subsystems/propulsion/engine_scaling.py @@ -2,7 +2,7 @@ import openmdao.api as om from aviary.subsystems.propulsion.utils import EngineModelVariables, max_variables -from aviary.variable_info.functions import add_aviary_input, add_aviary_option +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Dynamic, Mission MACH = EngineModelVariables.MACH @@ -53,7 +53,7 @@ def setup(self): nn = self.options['num_nodes'] engine_variables = self.options['engine_variables'] - add_aviary_input(self, Aircraft.Engine.SCALE_FACTOR, val=1.0) + add_aviary_input(self, Aircraft.Engine.SCALE_FACTOR) self.add_input( Dynamic.Atmosphere.MACH, @@ -73,15 +73,17 @@ def setup(self): ) if variable is FUEL_FLOW: - self.add_output( + add_aviary_output( + self, Dynamic.Vehicle.Propulsion.FUEL_MASS_FLOW_RATE_NEGATIVE, - val=np.zeros(nn), + shape=nn, units=engine_variables[variable], ) else: - self.add_output( + add_aviary_output( + self, variable.value, - val=np.zeros(nn), + shape=nn, units=engine_variables[variable], ) diff --git a/aviary/subsystems/propulsion/engine_sizing.py b/aviary/subsystems/propulsion/engine_sizing.py index c150c03f51..9aef9394ec 100644 --- a/aviary/subsystems/propulsion/engine_sizing.py +++ b/aviary/subsystems/propulsion/engine_sizing.py @@ -17,9 +17,9 @@ def initialize(self): add_aviary_option(self, Aircraft.Engine.REFERENCE_SLS_THRUST, units='lbf') def setup(self): - add_aviary_input(self, Aircraft.Engine.SCALE_FACTOR, val=1.0) + add_aviary_input(self, Aircraft.Engine.SCALE_FACTOR) - add_aviary_output(self, Aircraft.Engine.SCALED_SLS_THRUST, val=0.0) + add_aviary_output(self, Aircraft.Engine.SCALED_SLS_THRUST) # variables that also may require scaling # TODO - inlet_weight diff --git a/aviary/subsystems/propulsion/propeller/hamilton_standard.py b/aviary/subsystems/propulsion/propeller/hamilton_standard.py index 987abe2319..48d0d2ff05 100644 --- a/aviary/subsystems/propulsion/propeller/hamilton_standard.py +++ b/aviary/subsystems/propulsion/propeller/hamilton_standard.py @@ -466,17 +466,17 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, val=0.0, units='ft') + add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, units='ft') add_aviary_input( self, Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, - val=np.zeros(nn), + shape=nn, units='ft/s', ) - add_aviary_input(self, Dynamic.Vehicle.Propulsion.SHAFT_POWER, val=np.zeros(nn), units='hp') - add_aviary_input(self, Dynamic.Atmosphere.DENSITY, val=np.zeros(nn), units='slug/ft**3') - add_aviary_input(self, Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='ft/s') - add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, val=np.zeros(nn), units='ft/s') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.SHAFT_POWER, shape=nn, units='hp') + add_aviary_input(self, Dynamic.Atmosphere.DENSITY, shape=nn, units='slug/ft**3') + add_aviary_input(self, Dynamic.Mission.VELOCITY, shape=nn, units='ft/s') + add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, shape=nn, units='ft/s') self.add_output('power_coefficient', val=np.zeros(nn), units='unitless') self.add_output('advance_ratio', val=np.zeros(nn), units='unitless') @@ -615,15 +615,14 @@ def setup(self): self.add_input('power_coefficient', val=np.zeros(nn), units='unitless') self.add_input('advance_ratio', val=np.zeros(nn), units='unitless') - add_aviary_input(self, Dynamic.Atmosphere.MACH, val=np.zeros(nn), units='unitless') + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') self.add_input('tip_mach', val=np.zeros(nn), units='unitless') add_aviary_input( - self, Aircraft.Engine.Propeller.ACTIVITY_FACTOR, val=0.0, units='unitless' + self, Aircraft.Engine.Propeller.ACTIVITY_FACTOR, units='unitless' ) # Actitivty Factor per Blade add_aviary_input( self, Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, - val=0.0, units='unitless', ) # blade integrated lift coeff @@ -957,14 +956,14 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, val=0.0, units='ft') + add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, units='ft') self.add_input('install_loss_factor', val=np.zeros(nn), units='unitless') self.add_input('thrust_coefficient', val=np.zeros(nn), units='unitless') self.add_input('comp_tip_loss_factor', val=np.zeros(nn), units='unitless') add_aviary_input( self, Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, - val=np.zeros(nn), + shape=nn, units='ft/s', ) self.add_input(Dynamic.Atmosphere.DENSITY, val=np.zeros(nn), units='slug/ft**3') @@ -972,7 +971,7 @@ def setup(self): self.add_input('power_coefficient', val=np.zeros(nn), units='unitless') self.add_output('thrust_coefficient_comp_loss', val=np.zeros(nn), units='unitless') - add_aviary_output(self, Dynamic.Vehicle.Propulsion.THRUST, val=np.zeros(nn), units='lbf') + add_aviary_output(self, Dynamic.Vehicle.Propulsion.THRUST, shape=nn, units='lbf') # keep them for reporting but don't seem to be required self.add_output('propeller_efficiency', val=np.zeros(nn), units='unitless') self.add_output('install_efficiency', val=np.zeros(nn), units='unitless') diff --git a/aviary/subsystems/propulsion/propeller/propeller_performance.py b/aviary/subsystems/propulsion/propeller/propeller_performance.py index cefbf873cf..f4c74e0033 100644 --- a/aviary/subsystems/propulsion/propeller/propeller_performance.py +++ b/aviary/subsystems/propulsion/propeller/propeller_performance.py @@ -35,26 +35,26 @@ def initialize(self): def setup(self): num_nodes = self.options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.VELOCITY, val=np.zeros(num_nodes), units='ft/s') + add_aviary_input(self, Dynamic.Mission.VELOCITY, shape=num_nodes, units='ft/s') add_aviary_input( self, Dynamic.Atmosphere.SPEED_OF_SOUND, - val=np.zeros(num_nodes), + shape=num_nodes, units='ft/s', ) - add_aviary_input(self, Dynamic.Vehicle.Propulsion.RPM, val=np.zeros(num_nodes), units='rpm') - add_aviary_input(self, Aircraft.Engine.Propeller.TIP_MACH_MAX, val=1.0, units='unitless') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.RPM, shape=num_nodes, units='rpm') + add_aviary_input(self, Aircraft.Engine.Propeller.TIP_MACH_MAX, units='unitless') - add_aviary_input(self, Aircraft.Engine.Propeller.TIP_SPEED_MAX, val=0.0, units='ft/s') - add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, val=0.0, units='ft') + add_aviary_input(self, Aircraft.Engine.Propeller.TIP_SPEED_MAX, units='ft/s') + add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, units='ft') add_aviary_output( self, Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, - val=np.zeros(num_nodes), + shape=num_nodes, units='ft/s', ) - self.add_output('propeller_tip_speed_limit', val=np.zeros(num_nodes), units='ft/s') + self.add_output('propeller_tip_speed_limit', shape=num_nodes, units='ft/s') def setup_partials(self): num_nodes = self.options['num_nodes'] diff --git a/aviary/subsystems/propulsion/propulsion_premission.py b/aviary/subsystems/propulsion/propulsion_premission.py index ece7d5752b..0aaee3bd0a 100644 --- a/aviary/subsystems/propulsion/propulsion_premission.py +++ b/aviary/subsystems/propulsion/propulsion_premission.py @@ -208,9 +208,9 @@ def initialize(self): def setup(self): num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, val=np.zeros(num_engine_type)) + add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type) - add_aviary_output(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=0.0) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST) def setup_partials(self): num_engines = self.options[Aircraft.Engine.NUM_ENGINES] diff --git a/aviary/subsystems/test/test_flops_based_premission.py b/aviary/subsystems/test/test_flops_based_premission.py index bfec5bda3e..706a982d4f 100644 --- a/aviary/subsystems/test/test_flops_based_premission.py +++ b/aviary/subsystems/test/test_flops_based_premission.py @@ -15,12 +15,12 @@ get_geom_and_mass_subsystems, ) from aviary.validation_cases.validation_tests import ( + Version, flops_validation_test, get_flops_case_names, get_flops_inputs, get_flops_outputs, print_case, - Version, ) from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Mission, Settings diff --git a/aviary/utils/develop_metadata.py b/aviary/utils/develop_metadata.py index e67f14ec0d..7351a2421f 100644 --- a/aviary/utils/develop_metadata.py +++ b/aviary/utils/develop_metadata.py @@ -1,14 +1,14 @@ def add_meta_data( key: str, meta_data: dict, - units='unitless', + units: str = 'unitless', default_value=0.0, - types=None, + types: type | None = None, multivalue: bool = False, option: bool = False, - desc: str = None, - historical_name=None, - _check_unique=True, + desc: str | None = None, + historical_name: dict | None = None, + _check_unique: bool = True, ): """ Add new meta data associated with variables in the Aviary data hierarchy. diff --git a/aviary/utils/engine_deck_conversion.py b/aviary/utils/engine_deck_conversion.py index c65d5fac69..2cd96f2480 100644 --- a/aviary/utils/engine_deck_conversion.py +++ b/aviary/utils/engine_deck_conversion.py @@ -716,24 +716,20 @@ def setup(self): add_aviary_input( self, Dynamic.Atmosphere.MACH, - val=np.zeros(nn), - desc='current Mach number', + shape=nn, units='unitless', ) add_aviary_input( self, Dynamic.Atmosphere.TEMPERATURE, - val=np.zeros(nn), - desc='current atmospheric temperature', + shape=nn, units='degR', ) add_aviary_input( self, Dynamic.Atmosphere.STATIC_PRESSURE, - _PSLS_PSF, units='psf', shape=nn, - desc='Ambient static pressure', ) self.add_output('t2', units='degR', shape=nn, desc='Engine inlet total temperature') diff --git a/aviary/utils/option_to_var.py b/aviary/utils/option_to_var.py deleted file mode 100644 index 11e59d8aa9..0000000000 --- a/aviary/utils/option_to_var.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -Utilities to create a component that converts an option into an output. -""" - -import openmdao.api as om - -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_output - - -def create_opts2vals(all_options: list, output_units: dict = {}): - """ - create_opts2vals creates a component that converts options to outputs. - - Parameters - ---------- - all_options : list of strings - Each string is the name of an option in aviary_options. - output_units : dict of units, optional - This optional input allows the user to specify the units that will be used while - adding the outputs. Only the outputs that shouldn't use their default units need - to be specified. Each key should match one of the names in all_options, and each - value must be a string representing a valid unit in openMDAO. - - Returns - ------- - OptionsToValues : ExplicitComponent - An explicit component that takes in an AviaryValues object that contains any - options that need to be converted to outputs. There are no inputs to this - component, only outputs. If the resulting component is added directly to a - Group, the output variables will have the same name as the options they - represent. If you need to rename them to prevent conflicting names in the - group, running add_opts2vals will add the prefix "option:" to the name. - """ - - def configure_output(option_name: str, aviary_options: AviaryValues): - option_data = aviary_options.get_item(option_name) - out_units = ( - output_units[option_name] if option_name in output_units.keys() else option_data[1] - ) - return {'val': option_data[0], 'units': out_units} - - class OptionsToValues(om.ExplicitComponent): - def initialize(self): - self.options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - ) - - def setup(self): - for option_name in all_options: - output_data = configure_output(option_name, self.options['aviary_options']) - add_aviary_output( - self, - option_name, - val=output_data['val'], - units=output_data['units'], - ) - - def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - for option_name in all_options: - output_data = configure_output(option_name, aviary_options) - # uses default value if not present - if option_name in aviary_options: - outputs[option_name] = aviary_options.get_val( - option_name, units=output_data['units'] - ) - - return OptionsToValues - - -def add_opts2vals(Group: om.Group, OptionsToValues, aviary_options: AviaryValues): - """ - Add the OptionsToValues component to the specified Group. - - Parameters - ---------- - Group : Group - The group or model the component should be added to. - OptionsToValues : ExplicitComponent - This is the explicit component that was created by create_opts2vals. - aviary_options : AviaryValues - aviary_options is an AviaryValues object that contains all of the options - that need to be converted to outputs. - - Returns - ------- - Opts2Vals : Group - A group that wraps the OptionsToValues component in order to rename its - variables with a prefix to keep them separate from any similarly named - variables in the original group the component is being added to. - """ - - class Opts2Vals(om.Group): - def initialize(self): - self.options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - ) - - def setup(self): - self.add_subsystem('options_to_values', OptionsToValues(aviary_options=aviary_options)) - - def configure(self): - all_output_data = self.options_to_values.list_outputs(out_stream=None) - list_of_outputs = [(name, 'option:' + name) for name, data in all_output_data] - self.promotes('options_to_values', list_of_outputs) - - Group.add_subsystem( - 'opts2vals', Opts2Vals(aviary_options=aviary_options), promotes_outputs=['*'] - ) - - return Group diff --git a/aviary/utils/test/test_functions.py b/aviary/utils/test/test_functions.py index 7e15f01423..d8357ec502 100644 --- a/aviary/utils/test/test_functions.py +++ b/aviary/utils/test/test_functions.py @@ -3,59 +3,8 @@ import unittest from pathlib import Path -import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal - from aviary.api import top_dir from aviary.utils.functions import convert_strings_to_data, get_path -from aviary.utils.option_to_var import add_opts2vals, create_opts2vals -from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Mission - - -class TestOpts2Vals(unittest.TestCase): - """Test the functionality of create_opts2vals function.""" - - def setUp(self): - self.options = get_option_defaults() - self.options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') - self.options.set_val(Aircraft.Design.CRUISE_ALTITUDE, val=35, units='kft') - - def test_default_units(self): - tol = 1e-4 - self.prob = om.Problem() - OptionsToValues = create_opts2vals( - [ - Aircraft.CrewPayload.NUM_PASSENGERS, - Aircraft.Design.CRUISE_ALTITUDE, - ] - ) - add_opts2vals(self.prob.model, OptionsToValues, self.options) - self.prob.setup() - self.prob.run_model() - - assert_near_equal(self.prob['option:' + Aircraft.CrewPayload.NUM_PASSENGERS], 180, tol) - assert_near_equal(self.prob['option:' + Aircraft.Design.CRUISE_ALTITUDE], 35, tol) - - def test_specified_units(self): - tol = 1e-4 - self.prob = om.Problem() - OptionsToValues = create_opts2vals( - [ - Aircraft.CrewPayload.NUM_PASSENGERS, - Aircraft.Design.CRUISE_ALTITUDE, - ], - output_units={Aircraft.Design.CRUISE_ALTITUDE: 'm'}, - ) - add_opts2vals(self.prob.model, OptionsToValues, self.options) - self.prob.setup() - self.prob.run_model() - - altitude_in_meters = om.convert_units(35000, 'ft', 'm') - assert_near_equal(self.prob['option:' + Aircraft.CrewPayload.NUM_PASSENGERS], 180, tol) - assert_near_equal( - self.prob['option:' + Aircraft.Design.CRUISE_ALTITUDE], altitude_in_meters, tol - ) class TestGetPath(unittest.TestCase): diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 912a0718b1..eb1341e6fb 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -4,9 +4,9 @@ from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from aviary.core.aviary_problem import AviaryProblem -from aviary.validation_cases.validation_data.test_data.advanced_single_aisle_data import inputs from aviary.models.missions.energy_state_default import phase_info as energy_state_phase_info from aviary.models.missions.two_dof_default import phase_info as two_dof_phase_info +from aviary.validation_cases.validation_data.test_data.advanced_single_aisle_data import inputs class BaseProblemPhaseTestCase(unittest.TestCase): diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index 0c031c07bd..d3116045fd 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -110,4 +110,4 @@ def test_bench_GwGm_IPOPT_Breguet_Cruise(self): # unittest.main() test = ProblemPhaseTestCase() test.setUp() - test.test_bench_GwGm_IPOPT_Breguet_Cruise() + test.test_bench_GwGm_SNOPT() diff --git a/aviary/variable_info/functions.py b/aviary/variable_info/functions.py index 7793847aac..4e6f2b261f 100644 --- a/aviary/variable_info/functions.py +++ b/aviary/variable_info/functions.py @@ -20,50 +20,49 @@ def add_aviary_input( - comp, - varname, - val=None, - units=None, - desc=None, - shape_by_conn=False, - meta_data=CoreMetaData, - shape=None, - primal_name=None, + comp: Component, + varname: str, + units: str | None = None, + desc: str | None = None, + shape_by_conn: bool = False, + meta_data: dict = CoreMetaData, + shape: tuple | None = None, + primal_name: str | None = None, + **kwargs, ): """ - This function provides a clean way to add variables from the - variable hierarchy into components as Aviary inputs. It takes - the standard OpenMDAO inputs of the variable's name, initial - value, units, and description, as well as the component which - the variable is being added to. + This function provides a clean way to add variables from the variable hierarchy into components + as inputs. Unless explicitly provided, information on the variable's units and description come + from variable metadata. Default value is always taken from metadata. + + Information Parameters ---------- comp: Component - OpenMDAO component to add this variable. + OpenMDAO component the variable `varname` will be added as an input to. varname: str Name of variable. - val: float or ndarray - Default value for variable. - units: str - (Optional) when specifying val, units should also be specified. - desc: str - (Optional) description text for the variable. - shape_by_conn: bool + units: str, optional + Desired units for the variable. Units will be checked for compatibility with the default + units for this variable in metadata. + desc: str, optional + Description text for the variable. + shape_by_conn: bool, optional Set to True to infer the shape from the connected output. - meta_data: dict - (Optional) Aviary metadata dictionary. If unspecified, the built-in metadata will - be used. - shape: tuple - (Optional) shape for this input. - primal_name : str or None - Valid python name to represent the variable in compute_primal if 'name' is not a valid - python name. + meta_data: dict, optional + Aviary metadata dictionary. If unspecified, the default Aviary variable metadata will be used. + shape: tuple, optional + Shape for this input. + primal_name : str, optional + Valid Python name to represent the variable in compute_primal if 'name' is not a valid + Python name. + **kwargs + Extra arguments for `add_input` """ meta = meta_data[varname] - # units of None are overwritten with defaults. Overwriting units with None is - # unnecessary as it will cause errors down the line if the default is not already - # None + + val = meta['default_value'] default_units = meta['units'] if units is None: @@ -72,28 +71,18 @@ def add_aviary_input( if desc is None: desc = meta['desc'] - if val is None: - if shape is None: - val = meta['default_value'] - if val is None: - val = 0.0 - else: - val = meta['default_value'] - if val is None: - val = np.zeros(shape) - else: - val = np.ones(shape) * val - - # val was not provided but different units were - if units != default_units: - try: - # convert the default units to requested units - val = wrapped_convert_units((val, default_units), units) - except ValueError: - raise ValueError( - f'The requested units {units} for input {varname} in component ' - f'{comp.name} are invalid.' - ) + if shape is not None: + val = np.ones(shape) * val + + if units != default_units: + try: + # convert the default units to requested units + val = wrapped_convert_units((val, default_units), units) + except ValueError: + raise ValueError( + f'The requested units {units} for input {varname} in component ' + f'{comp.name} are invalid.' + ) # check types val = cast_type(varname, val, meta_data) @@ -107,55 +96,54 @@ def add_aviary_input( shape_by_conn=shape_by_conn, shape=shape, primal_name=primal_name, + **kwargs, ) def add_aviary_output( - comp, - varname, - val=None, - units=None, - desc=None, - shape_by_conn=False, - meta_data=CoreMetaData, - shape=None, - primal_name=None, + comp: Component, + varname: str, + units: str | None = None, + desc: str | None = None, + shape_by_conn: bool = False, + meta_data: dict = CoreMetaData, + shape: tuple | None = None, + primal_name: str | None = None, + **kwargs, ): """ - This function provides a clean way to add variables from the - variable hierarchy into components as Aviary outputs. It takes - the standard OpenMDAO inputs of the variable's name, initial - value, units, and description, as well as the component which - the variable is being added to. + This function provides a clean way to add variables from the variable hierarchy into components + as outputs. Unless explicitly provided, information on the variable's units and description come + from variable metadata. Default value is always taken from metadata. + + Information Parameters ---------- comp: Component - OpenMDAO component to add this variable. + OpenMDAO component the variable `varname` will be added as an output to. varname: str Name of variable. - val: float or ndarray - (Optional) Default value for variable. If not specified, the value from metadata - is used. - units: str - (Optional) when specifying val, units should also be specified. - desc: str - (Optional) description text for the variable. - shape_by_conn: bool + units: str, optional + Desired units for the variable. Units will be checked for compatibility with the default + units for this variable in metadata. + desc: str, optional + Description text for the variable. + shape_by_conn: bool, optional Set to True to infer the shape from the connected output. - meta_data: dict - (Optional) Aviary metadata dictionary. If unspecified, the built-in metadata will - be used. - shape: tuple - (Optional) shape for this input. - primal_name : str or None - Valid python name to represent the variable in compute_primal if 'name' is not a valid - python name. + meta_data: dict, optional + Aviary metadata dictionary. If unspecified, the default Aviary variable metadata will be used. + shape: tuple, optional + Shape for this output. + primal_name : str, optional + Valid Python name to represent the variable in compute_primal if 'name' is not a valid + Python name. + **kwargs + Extra arguments for `add_output` """ meta = meta_data[varname] - # units of None are overwritten with defaults. Overwriting units with None is - # unnecessary as it will cause errors down the line if the default is not already - # None + + val = meta['default_value'] default_units = meta['units'] if units is None: @@ -164,28 +152,18 @@ def add_aviary_output( if desc is None: desc = meta['desc'] - if val is None: - if shape is None: - val = meta['default_value'] - if val is None: - val = 0.0 - else: - val = meta['default_value'] - if val is None: - val = np.zeros(shape) - else: - val = np.ones(shape) * val - - # val was not provided but different units were - if units != default_units: - try: - # convert the default units to requested units - val = wrapped_convert_units((val, default_units), units) - except ValueError: - raise ValueError( - f'The requested units {units} for output {varname} in component ' - f'{comp.name} are invalid.' - ) + if shape is not None: + val = np.ones(shape) * val + + if units != default_units: + try: + # convert the default units to requested units + val = wrapped_convert_units((val, default_units), units) + except ValueError: + raise ValueError( + f'The requested units {units} for output {varname} in component ' + f'{comp.name} are invalid.' + ) # check types val = cast_type(varname, val, meta_data) @@ -198,13 +176,22 @@ def add_aviary_output( desc=desc, shape_by_conn=shape_by_conn, primal_name=primal_name, + **kwargs, ) -def add_aviary_option(comp, name, val=_unspecified, units=None, desc=None, meta_data=CoreMetaData): +def add_aviary_option( + comp: Component, + name: str, + val=_unspecified, + units: str | None = None, + desc: str | None = None, + meta_data: dict = CoreMetaData, + **kwargs, +): """ - Adds an option to an Aviary component. Default values from the metadata are used unless a new - value is specified. + Adds an option from the Aviary variable hierarchy to a component. Default values are taken from + metadata where optional information is not provided. Parameters ---------- @@ -212,14 +199,16 @@ def add_aviary_option(comp, name, val=_unspecified, units=None, desc=None, meta_ OpenMDAO component to add this option. name: str Name of variable. - val: float or ndarray - (Optional) Default value for option. If not specified, the value from metadata is used. - desc: str - (Optional) description text for the variable. - units: str - (Optional) OpenMDAO units string. This can be specified for variables with units. - meta_data: dict - (Optional) Aviary metadata dictionary. If unspecified, the built-in metadata will be used. + val: float or ndarray, optional + Default value for option. If not specified, the value from metadata is used. + desc: str, optional + Description text for the variable. + units: str, optional + OpenMDAO units string. This can be specified for variables with units. + meta_data: dict, optional + Aviary metadata dictionary. If unspecified, the default Aviary variable metadata will be used. + **kwargs + Extra arguments for `add_option` """ meta = meta_data[name] @@ -230,9 +219,6 @@ def add_aviary_option(comp, name, val=_unspecified, units=None, desc=None, meta_ 'get be set to its intended value.' ) - # units of None are overwritten with defaults. Overwriting units with None is - # unnecessary as it will cause errors down the line if the default is not already - # None default_units = meta['units'] if units is None: @@ -283,10 +269,12 @@ def add_aviary_option(comp, name, val=_unspecified, units=None, desc=None, meta_ ) elif isinstance(val, Enum): - comp.options.declare(name, default=val, types=types, desc=desc, set_function=enum_setter) + comp.options.declare( + name, default=val, types=types, desc=desc, set_function=enum_setter, **kwargs + ) else: - comp.options.declare(name, default=val, types=types, desc=desc) + comp.options.declare(name, default=val, types=types, desc=desc, **kwargs) def override_aviary_vars( diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index dfef2a2cb2..7f6133e50d 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -3132,7 +3132,7 @@ default_value=1.0, ) -# Misnamed. This sets if Aircraft.Furnishings.MASS_SCALER is used as a coefficient for additional +# TODO Misnamed. This sets if Aircraft.Furnishings.MASS_SCALER is used as a coefficient for additional # furnishings weight and the alternative (False) is to use the emperical equation. The variable toggle # based on gross mass and num_pax is bad Aviary behavior and should occur in fortran_to_aviary instead add_meta_data( @@ -7693,9 +7693,9 @@ meta_data=_MetaData, historical_name={'GASP': None, 'FLOPS': None}, units='unitless', - desc='speed during taxi, must be nonzero if pycycle is enabled', - option=True, - default_value=0.0001, + desc='speed during taxi', + option=False, + default_value=0.0, ) # .----------------. .----------------. .----------------. .----------------. .----------------. .-----------------. .----------------. .----------------.