diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index b1bc28f0a..cee35bbd9 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -1090,8 +1090,15 @@ def add_subsystem_timeseries_outputs(phase, phase_name): phase_name, self._get_phase(phase_name, phase_idx)) add_subsystem_timeseries_outputs(phase, phase_name) - if phase_name == 'ascent' and self.mission_method is TWO_DEGREES_OF_FREEDOM: - self._add_groundroll_eq_constraint(phase) + if self.mission_method is TWO_DEGREES_OF_FREEDOM: + + # In GASP, we still use the phase name to infer the phase type. + # We need this information to be available in the builders. + # TODO - Ultimately we should overhaul all of this. + self.phase_info[phase_name]['phase_type'] = phase_name + + if phase_name == 'ascent': + self._add_groundroll_eq_constraint(phase) # loop through phase_info and external subsystems external_parameters = {} @@ -1107,9 +1114,8 @@ def add_subsystem_timeseries_outputs(phase, phase_name): for parameter in parameter_dict: external_parameters[phase_name][parameter] = parameter_dict[parameter] - if self.mission_method in (HEIGHT_ENERGY, SOLVED_2DOF): - traj = setup_trajectory_params( - self.model, traj, self.aviary_inputs, phases, meta_data=self.meta_data, external_parameters=external_parameters) + traj = setup_trajectory_params( + self.model, traj, self.aviary_inputs, phases, meta_data=self.meta_data, external_parameters=external_parameters) self.traj = traj diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index 2da4157c3..42c233736 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -215,3 +215,6 @@ def setup(self): val=174000 * np.ones(nn), units='lbm') self.set_input_defaults(Dynamic.Mission.MACH, val=0 * np.ones(nn), units="unitless") + + from aviary.variable_info.variables import Aircraft + self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units="ft**2") diff --git a/aviary/mission/gasp_based/ode/descent_ode.py b/aviary/mission/gasp_based/ode/descent_ode.py index 0c8cf37eb..9f9b3ab1e 100644 --- a/aviary/mission/gasp_based/ode/descent_ode.py +++ b/aviary/mission/gasp_based/ode/descent_ode.py @@ -11,7 +11,7 @@ from aviary.mission.gasp_based.ode.constraints.speed_constraints import SpeedConstraints from aviary.variable_info.enums import AnalysisScheme, AlphaModes, SpeedType -from aviary.variable_info.variables import Mission, Dynamic +from aviary.variable_info.variables import Aircraft, Mission, Dynamic from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs @@ -232,3 +232,5 @@ def setup(self): val=0 * np.ones(nn), units="unitless") self.set_input_defaults(Dynamic.Mission.THROTTLE, val=0 * np.ones(nn), units="unitless") + + self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units="ft**2") diff --git a/aviary/mission/gasp_based/ode/groundroll_ode.py b/aviary/mission/gasp_based/ode/groundroll_ode.py index 32bdf62f6..a4dcb145b 100644 --- a/aviary/mission/gasp_based/ode/groundroll_ode.py +++ b/aviary/mission/gasp_based/ode/groundroll_ode.py @@ -136,3 +136,5 @@ def setup(self): self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units="kn") self.set_input_defaults(Dynamic.Mission.VELOCITY_RATE, val=np.zeros(nn), units="kn/s") + + self.set_input_defaults(Aircraft.Wing.INCIDENCE, val=1.0, units="deg") diff --git a/aviary/mission/gasp_based/ode/params.py b/aviary/mission/gasp_based/ode/params.py index 8dfcf9ac4..e2f35ea04 100644 --- a/aviary/mission/gasp_based/ode/params.py +++ b/aviary/mission/gasp_based/ode/params.py @@ -6,75 +6,9 @@ class ParamPort(om.ExplicitComponent): param_data = { - Aircraft.Wing.AREA: dict(units="ft**2", val=1370.3), Aircraft.Wing.INCIDENCE: dict(units="deg", val=0), - Aircraft.Wing.HEIGHT: dict(units="ft", val=8), - Aircraft.Wing.SPAN: dict(units="ft", val=117.8), - Mission.Design.GROSS_MASS: dict(units="lbm", val=175400), - Mission.Summary.GROSS_MASS: dict(units="lbm", val=175400), - Mission.Summary.FUEL_FLOW_SCALER: dict(units="unitless", val=1.0), - Mission.Takeoff.AIRPORT_ALTITUDE: dict(units="ft", val=0), - Mission.Landing.AIRPORT_ALTITUDE: dict(units="ft", val=0), Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF: dict(units="deg", val=10), Aircraft.Wing.FLAP_DEFLECTION_LANDING: dict(units="deg", val=40), - Aircraft.Wing.AVERAGE_CHORD: dict(units="ft", val=12.615), - Aircraft.Fuselage.AVG_DIAMETER: dict(units="inch", val=12 * 13.100), - Aircraft.HorizontalTail.AVERAGE_CHORD: dict(units="ft", val=9.577), - Aircraft.HorizontalTail.AREA: dict(units="ft**2", val=375.880), - Aircraft.HorizontalTail.SPAN: dict(units="ft", val=42.254), - Aircraft.VerticalTail.AVERAGE_CHORD: dict(units="ft", val=16.832), - Aircraft.VerticalTail.AREA: dict(units="ft**2", val=469.318), - Aircraft.VerticalTail.SPAN: dict(units="ft", val=27.996), - Aircraft.Fuselage.LENGTH: dict(units="ft", val=129.4), - Aircraft.Nacelle.AVG_LENGTH: dict(units="ft", val=14.5), - Aircraft.Fuselage.WETTED_AREA: dict(units="ft**2", val=4000), - Aircraft.Nacelle.SURFACE_AREA: dict(units="ft**2", val=659.23 / 2), - Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED: dict(units="unitless", val=0.1397), - Aircraft.Strut.CHORD: dict( - units="ft", val=0 - ), # only available if Aviary_option Aircraft.Wing.HAS_STRUT - Aircraft.Wing.ASPECT_RATIO: dict(units="unitless", val=10.13), - Aircraft.Wing.TAPER_RATIO: dict(units="unitless", val=0.33), - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT: dict(units="unitless", val=0.15), - Aircraft.Wing.THICKNESS_TO_CHORD_TIP: dict(units="unitless", val=0.12), - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION: dict(units="unitless", val=0), - Aircraft.Wing.SWEEP: dict(units="deg", val=25), - Aircraft.HorizontalTail.SWEEP: dict(units="deg", val=25), - Aircraft.HorizontalTail.MOMENT_RATIO: dict(units="unitless", val=0.2307), - Aircraft.Wing.MOUNTING_TYPE: dict(units="unitless", val=0), - Aircraft.Design.STATIC_MARGIN: dict(units="unitless", val=0.03), - Aircraft.Design.CG_DELTA: dict(units="unitless", val=0.25), - Aircraft.Wing.FORM_FACTOR: dict(units="unitless", val=1.25), - Aircraft.Fuselage.FORM_FACTOR: dict(units="unitless", val=1.25), - Aircraft.Nacelle.FORM_FACTOR: dict(units="unitless", val=1.5), - Aircraft.VerticalTail.FORM_FACTOR: dict(units="unitless", val=1.25), - Aircraft.HorizontalTail.FORM_FACTOR: dict(units="unitless", val=1.25), - Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR: dict(units="unitless", val=1.1), - Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR: dict(units="unitless", val=0), - Aircraft.Design.DRAG_COEFFICIENT_INCREMENT: dict(units="unitless", val=0.00175), - Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT: dict(units="ft**2", val=0.25), - Aircraft.Wing.CENTER_DISTANCE: dict(units="unitless", val=0.463), - Aircraft.Wing.MIN_PRESSURE_LOCATION: dict(units="unitless", val=0.3), - Aircraft.Wing.MAX_THICKNESS_LOCATION: dict(units="unitless", val=0.4), - Aircraft.Strut.AREA_RATIO: dict(units="unitless", val=0), - Aircraft.Wing.ZERO_LIFT_ANGLE: dict(units="deg", val=-1.2), - Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT: dict(units="unitless", val=0.033), - Aircraft.Wing.FLAP_CHORD_RATIO: dict(units="unitless", val=0.3), - Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP: dict(units="unitless", val=1.2596), - Mission.Takeoff.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.1886), - Mission.Landing.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.8155), - Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT: dict( - units="unitless", val=0.4182 - ), - Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT: dict( - units="unitless", val=1.0293 - ), - Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT: dict( - units="unitless", val=0.0085 - ), - Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT: dict( - units="unitless", val=0.0406 - ), } def setup(self): @@ -149,3 +83,98 @@ def promote_params(sys, trajs=None, phases=None): static_target=True, ) sys.promotes(phasename, inputs=proms) + + +params_for_unit_tests = { + Aircraft.Wing.AREA: dict(units="ft**2", val=1370.3), + Aircraft.Wing.HEIGHT: dict(units="ft", val=8), + Aircraft.Wing.SPAN: dict(units="ft", val=117.8), + Mission.Design.GROSS_MASS: dict(units="lbm", val=175400), + Mission.Summary.GROSS_MASS: dict(units="lbm", val=175400), + Mission.Summary.FUEL_FLOW_SCALER: dict(units="unitless", val=1.0), + Mission.Takeoff.AIRPORT_ALTITUDE: dict(units="ft", val=0), + Mission.Landing.AIRPORT_ALTITUDE: dict(units="ft", val=0), + Aircraft.Wing.AVERAGE_CHORD: dict(units="ft", val=12.615), + Aircraft.Fuselage.AVG_DIAMETER: dict(units="inch", val=12 * 13.100), + Aircraft.HorizontalTail.AVERAGE_CHORD: dict(units="ft", val=9.577), + Aircraft.HorizontalTail.AREA: dict(units="ft**2", val=375.880), + Aircraft.HorizontalTail.SPAN: dict(units="ft", val=42.254), + Aircraft.VerticalTail.AVERAGE_CHORD: dict(units="ft", val=16.832), + Aircraft.VerticalTail.AREA: dict(units="ft**2", val=469.318), + Aircraft.VerticalTail.SPAN: dict(units="ft", val=27.996), + Aircraft.Fuselage.LENGTH: dict(units="ft", val=129.4), + Aircraft.Nacelle.AVG_LENGTH: dict(units="ft", val=14.5), + Aircraft.Fuselage.WETTED_AREA: dict(units="ft**2", val=4000), + Aircraft.Nacelle.SURFACE_AREA: dict(units="ft**2", val=659.23 / 2), + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED: dict(units="unitless", val=0.1397), + Aircraft.Strut.CHORD: dict( + units="ft", val=0 + ), # only available if Aviary_option Aircraft.Wing.HAS_STRUT + Aircraft.Wing.ASPECT_RATIO: dict(units="unitless", val=10.13), + Aircraft.Wing.TAPER_RATIO: dict(units="unitless", val=0.33), + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT: dict(units="unitless", val=0.15), + Aircraft.Wing.THICKNESS_TO_CHORD_TIP: dict(units="unitless", val=0.12), + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION: dict(units="unitless", val=0), + Aircraft.Wing.SWEEP: dict(units="deg", val=25), + Aircraft.HorizontalTail.SWEEP: dict(units="deg", val=25), + Aircraft.HorizontalTail.MOMENT_RATIO: dict(units="unitless", val=0.2307), + Aircraft.Wing.MOUNTING_TYPE: dict(units="unitless", val=0), + Aircraft.Design.STATIC_MARGIN: dict(units="unitless", val=0.03), + Aircraft.Design.CG_DELTA: dict(units="unitless", val=0.25), + Aircraft.Wing.FORM_FACTOR: dict(units="unitless", val=1.25), + Aircraft.Fuselage.FORM_FACTOR: dict(units="unitless", val=1.25), + Aircraft.Nacelle.FORM_FACTOR: dict(units="unitless", val=1.5), + Aircraft.VerticalTail.FORM_FACTOR: dict(units="unitless", val=1.25), + Aircraft.HorizontalTail.FORM_FACTOR: dict(units="unitless", val=1.25), + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR: dict(units="unitless", val=1.1), + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR: dict(units="unitless", val=0), + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT: dict(units="unitless", val=0.00175), + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT: dict(units="ft**2", val=0.25), + Aircraft.Wing.CENTER_DISTANCE: dict(units="unitless", val=0.463), + Aircraft.Wing.MIN_PRESSURE_LOCATION: dict(units="unitless", val=0.3), + Aircraft.Wing.MAX_THICKNESS_LOCATION: dict(units="unitless", val=0.4), + Aircraft.Strut.AREA_RATIO: dict(units="unitless", val=0), + Aircraft.Wing.ZERO_LIFT_ANGLE: dict(units="deg", val=-1.2), + Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT: dict(units="unitless", val=0.033), + Aircraft.Wing.FLAP_CHORD_RATIO: dict(units="unitless", val=0.3), + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP: dict(units="unitless", val=1.2596), + Mission.Takeoff.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.1886), + Mission.Landing.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.8155), + Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT: dict( + units="unitless", val=0.4182 + ), + Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT: dict( + units="unitless", val=1.0293 + ), + Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT: dict( + units="unitless", val=0.0085 + ), + Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT: dict( + units="unitless", val=0.0406 + ), +} + + +def set_params_for_unit_tests(prob): + """ + Helper function to set parameters for several ode tests with the 2DOF method. + + This is needed because the Paramport used to contain default values for some + variables. + + Parameters + ---------- + prob : Problem + OpenMDAO problem that has been setup. + + Returns + ------- + Problem + """ + for key, val in params_for_unit_tests.items(): + try: + prob.set_val(key, val['val'], units=val['units']) + except: + pass + + return prob diff --git a/aviary/mission/gasp_based/ode/test/test_accel_ode.py b/aviary/mission/gasp_based/ode/test/test_accel_ode.py index 3519b14d3..a8d5b56d2 100644 --- a/aviary/mission/gasp_based/ode/test/test_accel_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_accel_ode.py @@ -4,11 +4,12 @@ from openmdao.utils.assert_utils import assert_check_partials from aviary.mission.gasp_based.ode.accel_ode import AccelODE -from aviary.variable_info.options import get_option_defaults -from aviary.utils.test_utils.IO_test_util import check_prob_outputs -from aviary.variable_info.variables import Dynamic +from aviary.mission.gasp_based.ode.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 +from aviary.variable_info.options import get_option_defaults +from aviary.variable_info.variables import Dynamic class AccelerationODETestCase(unittest.TestCase): @@ -35,6 +36,8 @@ def test_accel(self): self.prob.set_val(Dynamic.Mission.VELOCITY, [185, 252], units="kn") self.prob.set_val(Dynamic.Mission.MASS, [174974, 174878], units="lbm") + set_params_for_unit_tests(self.prob) + self.prob.run_model() testvals = { Dynamic.Mission.LIFT: [174974, 174878], diff --git a/aviary/mission/gasp_based/ode/test/test_ascent_ode.py b/aviary/mission/gasp_based/ode/test/test_ascent_ode.py index 32931ac79..153f190cf 100644 --- a/aviary/mission/gasp_based/ode/test/test_ascent_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_ascent_ode.py @@ -5,6 +5,7 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.ascent_ode import AscentODE +from aviary.mission.gasp_based.ode.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.options import get_option_defaults @@ -30,6 +31,8 @@ def test_ascent_partials(self): self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") self.prob.set_val("t_curr", [1, 2], units="s") + set_params_for_unit_tests(self.prob) + self.prob.run_model() tol = tol = 1e-6 diff --git a/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py b/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py index 4f3a01821..0539e8e93 100644 --- a/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py @@ -5,6 +5,7 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.breguet_cruise_ode import BreguetCruiseODESolution +from aviary.mission.gasp_based.ode.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.options import get_option_defaults @@ -34,6 +35,8 @@ def test_cruise(self): self.prob.set_val(Dynamic.Mission.MACH, [0.7, 0.7], units="unitless") + set_params_for_unit_tests(self.prob) + self.prob.run_model() tol = tol = 1e-6 diff --git a/aviary/mission/gasp_based/ode/test/test_climb_ode.py b/aviary/mission/gasp_based/ode/test/test_climb_ode.py index 6badf740b..9d8d5ebe9 100644 --- a/aviary/mission/gasp_based/ode/test/test_climb_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_climb_ode.py @@ -5,11 +5,12 @@ from openmdao.utils.assert_utils import assert_check_partials from aviary.mission.gasp_based.ode.climb_ode import ClimbODE +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests +from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.IO_test_util import check_prob_outputs +from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems class ClimbODETestCase(unittest.TestCase): @@ -43,6 +44,8 @@ def test_start_of_climb(self): # slightly greater than zero to help check partials self.prob.set_val(Aircraft.Wing.INCIDENCE, 0.0000001, units="deg") + set_params_for_unit_tests(self.prob) + self.prob.run_model() testvals = { @@ -79,6 +82,8 @@ def test_end_of_climb(self): self.prob.set_val(Dynamic.Mission.MASS, np.array([174149, 171592]), units="lbm") self.prob.set_val("EAS", np.array([270, 270]), units="kn") + set_params_for_unit_tests(self.prob) + self.prob.run_model() testvals = { diff --git a/aviary/mission/gasp_based/ode/test/test_descent_ode.py b/aviary/mission/gasp_based/ode/test/test_descent_ode.py index c4f7ce494..1c0fd0a1c 100644 --- a/aviary/mission/gasp_based/ode/test/test_descent_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_descent_ode.py @@ -7,12 +7,13 @@ from packaging import version from aviary.mission.gasp_based.ode.descent_ode import DescentODE -from aviary.variable_info.options import get_option_defaults +from aviary.mission.gasp_based.ode.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 from aviary.variable_info.enums import SpeedType +from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Dynamic -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems class DescentODETestCase(unittest.TestCase): @@ -43,6 +44,8 @@ def test_high_alt(self): self.prob.set_val(Dynamic.Mission.ALTITUDE, np.array([36500, 14500]), units="ft") self.prob.set_val(Dynamic.Mission.MASS, np.array([147661, 147572]), units="lbm") + set_params_for_unit_tests(self.prob) + self.prob.run_model() testvals = { @@ -79,6 +82,8 @@ def test_low_alt(self): self.prob.set_val(Dynamic.Mission.MASS, 147410, units="lbm") self.prob.set_val("EAS", 250, units="kn") + set_params_for_unit_tests(self.prob) + self.prob.run_model() testvals = { diff --git a/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py b/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py index 9feb777d4..a1c188f73 100644 --- a/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py @@ -5,6 +5,7 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.flight_path_ode import FlightPathODE +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.variable_info.options import get_option_defaults from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems @@ -30,6 +31,8 @@ def test_case1(self): """ self.prob.setup(check=False, force_alloc_complex=True) + set_params_for_unit_tests(self.prob) + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") self.prob.set_val(Dynamic.Mission.MASS, [100000, 100000], units="lbm") self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units="ft") @@ -66,6 +69,8 @@ def test_case2(self): self.fp.options["ground_roll"] = True self.prob.setup(check=False, force_alloc_complex=True) + set_params_for_unit_tests(self.prob) + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") self.prob.set_val(Dynamic.Mission.MASS, [100000, 100000], units="lbm") self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units="ft") diff --git a/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py b/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py index 6b65ec3b1..d204fc4c6 100644 --- a/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py @@ -5,11 +5,12 @@ from openmdao.utils.assert_utils import assert_check_partials from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE -from aviary.variable_info.options import get_option_defaults +from aviary.mission.gasp_based.ode.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 from aviary.variable_info.variables import Dynamic +from aviary.variable_info.options import get_option_defaults class GroundrollODETestCase(unittest.TestCase): @@ -28,8 +29,11 @@ def test_groundroll_partials(self): """Check partial derivatives""" self.prob.setup(check=False, force_alloc_complex=True) + set_params_for_unit_tests(self.prob) + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") self.prob.set_val("t_curr", [1, 2], units="s") + self.prob.set_val("aircraft:wing:incidence", 0, units="deg") self.prob.run_model() diff --git a/aviary/mission/gasp_based/ode/test/test_rotation_ode.py b/aviary/mission/gasp_based/ode/test/test_rotation_ode.py index ca229adb8..b2f71860d 100644 --- a/aviary/mission/gasp_based/ode/test/test_rotation_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_rotation_ode.py @@ -5,10 +5,11 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.rotation_ode import RotationODE -from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Dynamic +from aviary.mission.gasp_based.ode.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.options import get_option_defaults +from aviary.variable_info.variables import Aircraft, Dynamic class RotationODETestCase(unittest.TestCase): @@ -33,6 +34,8 @@ def test_rotation_partials(self): self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") self.prob.set_val("t_curr", [1, 2], units="s") + set_params_for_unit_tests(self.prob) + self.prob.run_model() tol = 1e-6 diff --git a/aviary/mission/gasp_based/ode/time_integration_base_classes.py b/aviary/mission/gasp_based/ode/time_integration_base_classes.py index eda3e323e..85ab1e42b 100644 --- a/aviary/mission/gasp_based/ode/time_integration_base_classes.py +++ b/aviary/mission/gasp_based/ode/time_integration_base_classes.py @@ -1,7 +1,9 @@ import numpy as np +from scipy import interpolate + import openmdao.api as om from openmdao.utils import units -from scipy import interpolate + from simupy.block_diagram import DEFAULT_INTEGRATOR_OPTIONS, SimulationMixin from simupy.systems import DynamicalSystem @@ -108,6 +110,14 @@ def __init__( self.prob = prob prob.setup(check=False, force_alloc_complex=True) + + # TODO - This is a hack to mimic the behavior of the old paramport, which + # contains some initial default values. It is unclear how actual "parameter" + # values are supposed to propagate from the pre-mission and top ivcs into + # the SGM phases. + from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests + set_params_for_unit_tests(prob) + prob.final_setup() if triggers is None: @@ -490,6 +500,16 @@ def setup_params( continue traj_promote_initial_input[prom_name] = data + # TODO - This is a hack to mimic the behavior of the old paramport, which + # contains some initial default values. It is unclear how actual "parameter" + # values are supposed to propagate from the pre-mission and top ivcs into + # the SGM phases. + from aviary.mission.gasp_based.ode.params import params_for_unit_tests + traj_promote_initial_input = { + **params_for_unit_tests, + **traj_promote_initial_input + } + self.traj_promote_initial_input = { **self.options["param_dict"], **traj_promote_initial_input} for name, kwargs in self.traj_promote_initial_input.items(): diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py index 483ee4a07..aec538e3a 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py @@ -1,11 +1,12 @@ import unittest import numpy as np + import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials from aviary.constants import GRAV_ENGLISH_LBM -from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_control_iter_group import \ UnsteadyControlIterGroup from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_flight_conditions import \ @@ -27,11 +28,6 @@ def _test_unsteady_alpha_thrust_iter_group(self, ground_roll=False): p = om.Problem() - # TODO: paramport - param_port = ParamPort() - - p.model.add_subsystem("params", param_port, promotes=["*"]) - fc = UnsteadySolvedFlightConditions(num_nodes=nn, input_speed_type=SpeedType.TAS, ground_roll=ground_roll) @@ -51,13 +47,13 @@ def _test_unsteady_alpha_thrust_iter_group(self, ground_roll=False): promotes_inputs=["*"], promotes_outputs=["*"]) - for key, data in param_port.param_data.items(): - p.model.set_input_defaults(key, **data) if ground_roll: ig.set_input_defaults("alpha", np.zeros(nn), units="deg") p.setup(force_alloc_complex=True) + set_params_for_unit_tests(p) + p.final_setup() p.set_val(Dynamic.Mission.SPEED_OF_SOUND, 968.076 * np.ones(nn), units="ft/s") diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py index 27472e7a4..8089fe272 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py @@ -1,11 +1,12 @@ import unittest import numpy as np + import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials from aviary.constants import GRAV_ENGLISH_LBM -from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_ode import \ UnsteadySolvedODE from aviary.variable_info.options import get_option_defaults @@ -36,10 +37,6 @@ def _test_unsteady_solved_ode(self, ground_roll=False, input_speed_type=SpeedTyp p.model.add_subsystem("ode", ode, promotes=["*"]) - # TODO: paramport - param_port = ParamPort() - for key, data in param_port.param_data.items(): - p.model.set_input_defaults(key, **data) p.model.set_input_defaults(Dynamic.Mission.MACH, 0.8 * np.ones(nn)) if ground_roll: p.model.set_input_defaults(Dynamic.Mission.MACH, 0.1 * np.ones(nn)) @@ -47,6 +44,8 @@ def _test_unsteady_solved_ode(self, ground_roll=False, input_speed_type=SpeedTyp p.setup(force_alloc_complex=True) + set_params_for_unit_tests(p) + p.final_setup() p.set_val(Dynamic.Mission.SPEED_OF_SOUND, 968.076 * np.ones(nn), units="ft/s") diff --git a/aviary/mission/gasp_based/phases/landing_group.py b/aviary/mission/gasp_based/phases/landing_group.py index 2ece2fd72..b3c3b74fe 100644 --- a/aviary/mission/gasp_based/phases/landing_group.py +++ b/aviary/mission/gasp_based/phases/landing_group.py @@ -197,7 +197,9 @@ def setup(self): ) ParamPort.set_default_vals(self) + self.set_input_defaults(Mission.Landing.INITIAL_MACH, val=0.1) + # landing doesn't change flap or gear position self.set_input_defaults("t_init_flaps_app", val=1e10) self.set_input_defaults("t_init_gear_app", val=1e10) @@ -207,3 +209,5 @@ def setup(self): self.set_input_defaults('aero_ramps.gear_factor:final_val', val=1.) self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=0.) self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=0.) + + self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units="ft**2") diff --git a/aviary/mission/gasp_based/phases/test/test_landing_group.py b/aviary/mission/gasp_based/phases/test/test_landing_group.py index 36e604640..f12714b0f 100644 --- a/aviary/mission/gasp_based/phases/test/test_landing_group.py +++ b/aviary/mission/gasp_based/phases/test/test_landing_group.py @@ -1,17 +1,19 @@ +from packaging import version import unittest import numpy as np + import openmdao import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials -from packaging import version +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.mission.gasp_based.phases.landing_group import LandingSegment -from aviary.variable_info.options import get_option_defaults +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 +from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Dynamic, Mission -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems -from aviary.subsystems.propulsion.utils import build_engine_deck class DLandTestCase(unittest.TestCase): @@ -30,6 +32,8 @@ def setUp(self): def test_dland(self): self.prob.setup(check=False, force_alloc_complex=True) + set_params_for_unit_tests(self.prob) + self.prob.set_val(Mission.Landing.AIRPORT_ALTITUDE, 0, units="ft") self.prob.set_val(Mission.Landing.INITIAL_MACH, 0.1, units="unitless") self.prob.set_val("alpha", 0, units="deg") # doesn't matter diff --git a/aviary/mission/gasp_based/phases/test/test_taxi_group.py b/aviary/mission/gasp_based/phases/test/test_taxi_group.py index 9c679a9b2..950f9f350 100644 --- a/aviary/mission/gasp_based/phases/test/test_taxi_group.py +++ b/aviary/mission/gasp_based/phases/test/test_taxi_group.py @@ -1,17 +1,21 @@ +from packaging import version import unittest import numpy as np + import openmdao import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials -from packaging import version +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.mission.gasp_based.phases.landing_group import LandingSegment -from aviary.variable_info.options import get_option_defaults -from aviary.utils.test_utils.IO_test_util import check_prob_outputs -from aviary.variable_info.variables import Dynamic, Mission 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 +from aviary.variable_info.options import get_option_defaults +from aviary.variable_info.variables import Dynamic, Mission + +# TODO - Why does this test landing instead of taxi? class DLandTestCase(unittest.TestCase): @@ -30,6 +34,8 @@ def setUp(self): def test_dland(self): self.prob.setup(check=False, force_alloc_complex=True) + set_params_for_unit_tests(self.prob) + self.prob.set_val(Mission.Landing.AIRPORT_ALTITUDE, 0, units="ft") self.prob.set_val(Mission.Landing.INITIAL_MACH, 0.1, units="unitless") self.prob.set_val("alpha", 0, units="deg") # doesn't matter diff --git a/aviary/mission/gasp_based/test/test_idle_descent_estimation.py b/aviary/mission/gasp_based/test/test_idle_descent_estimation.py index a4aba9a4d..a8746b1f8 100644 --- a/aviary/mission/gasp_based/test/test_idle_descent_estimation.py +++ b/aviary/mission/gasp_based/test/test_idle_descent_estimation.py @@ -3,18 +3,17 @@ import importlib import openmdao.api as om -from aviary.interface.default_phase_info.two_dof_fiti_deprecated import create_2dof_based_descent_phases -from aviary.interface.default_phase_info.two_dof_fiti import descent_phases, add_default_sgm_args - from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.interface.default_phase_info.two_dof_fiti import descent_phases, add_default_sgm_args + from aviary.mission.gasp_based.idle_descent_estimation import add_descent_estimation_as_submodel +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.variable_info.variables import Aircraft, Dynamic, Settings from aviary.utils.process_input_decks import create_vehicle from aviary.utils.preprocessors import preprocess_propulsion +from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems @unittest.skipUnless(importlib.util.find_spec("pyoptsparse") is not None, "pyoptsparse is not installed") @@ -61,6 +60,8 @@ def test_subproblem(self): prob.setup() + set_params_for_unit_tests(prob) + warnings.filterwarnings('ignore', category=UserWarning) prob.run_model() warnings.filterwarnings('default', category=UserWarning) diff --git a/aviary/subsystems/aerodynamics/aerodynamics_builder.py b/aviary/subsystems/aerodynamics/aerodynamics_builder.py index 58a379bfd..9d4dfe375 100644 --- a/aviary/subsystems/aerodynamics/aerodynamics_builder.py +++ b/aviary/subsystems/aerodynamics/aerodynamics_builder.py @@ -7,6 +7,8 @@ CoreAerodynamicsBuilder : the interface for Aviary's core aerodynamics subsystem builder """ +from itertools import chain + import numpy as np import openmdao.api as om @@ -382,6 +384,34 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): params[var] = {'val': val, 'static_target': True} + else: + + # TODO: 2DOF/Gasp decided on phases based on phase names. We used + # a saved phase_name to determine the correct aero variables to + # promote. Ideally, this should all be refactored. + if phase_info['phase_type'] in ['ascent', 'groundroll', 'rotation']: + all_vars = (AERO_2DOF_INPUTS, AERO_LS_2DOF_INPUTS) + else: + all_vars = (AERO_2DOF_INPUTS, AERO_CLEAN_2DOF_INPUTS) + + for var in chain.from_iterable(all_vars): + + meta = _MetaData[var] + + val = meta['default_value'] + if val is None: + val = _unspecified + units = meta['units'] + + if var in aviary_inputs: + try: + val = aviary_inputs.get_val(var, units) + except TypeError: + val = aviary_inputs.get_val(var) + + params[var] = {'val': val, + 'static_target': True} + return params def report(self, prob, reports_folder, **kwargs): @@ -462,3 +492,58 @@ def report(self, prob, reports_folder, **kwargs): Aircraft.Nacelle.LAMINAR_FLOW_UPPER, Aircraft.Nacelle.WETTED_AREA ] + +AERO_2DOF_INPUTS = [ + Aircraft.Design.CG_DELTA, + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, # drag increment? + Aircraft.Design.STATIC_MARGIN, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, + Aircraft.Fuselage.FORM_FACTOR, + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.WETTED_AREA, + Aircraft.HorizontalTail.AREA, + Aircraft.HorizontalTail.AVERAGE_CHORD, + Aircraft.HorizontalTail.FORM_FACTOR, + Aircraft.HorizontalTail.MOMENT_RATIO, + Aircraft.HorizontalTail.SPAN, + Aircraft.HorizontalTail.SWEEP, + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, + Aircraft.Nacelle.AVG_LENGTH, + Aircraft.Nacelle.FORM_FACTOR, + Aircraft.Nacelle.SURFACE_AREA, + Aircraft.Strut.AREA_RATIO, + Aircraft.Strut.CHORD, + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, + Aircraft.VerticalTail.AREA, + Aircraft.VerticalTail.AVERAGE_CHORD, + Aircraft.VerticalTail.FORM_FACTOR, + Aircraft.VerticalTail.SPAN, + Aircraft.Wing.AVERAGE_CHORD, + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.CENTER_DISTANCE, + Aircraft.Wing.FORM_FACTOR, + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, + Aircraft.Wing.MAX_THICKNESS_LOCATION, + Aircraft.Wing.MIN_PRESSURE_LOCATION, + Aircraft.Wing.MOUNTING_TYPE, + Aircraft.Wing.SPAN, + Aircraft.Wing.SWEEP, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, + Aircraft.Wing.ZERO_LIFT_ANGLE, +] + +AERO_LS_2DOF_INPUTS = [ + Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT, + Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT, + Mission.Takeoff.LIFT_COEFFICIENT_MAX, +] + +AERO_CLEAN_2DOF_INPUTS = [ + Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT, # super drag shift? + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, +] diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index 099210433..ca18abdf1 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -1,9 +1,9 @@ from copy import deepcopy import unittest +from openmdao.core.problem import _clear_problem_names from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from openmdao.core.problem import _clear_problem_names from aviary.interface.default_phase_info.two_dof import phase_info from aviary.interface.methods_for_level1 import run_aviary