def test_loop_compute_oew(): """ Tests a weight computation loop matching the max payload criterion. """ # With payload from npax reader = VariableIO( pth.join(pth.dirname(__file__), "data", "mass_breakdown_inputs.xml")) reader.path_separator = ":" input_vars = reader.read(ignore=[ "data:weight:aircraft:MLW", "data:weight:aircraft:MZFW", "data:weight:aircraft:max_payload", ]).to_ivc() mass_computation = run_system(MassBreakdown(), input_vars) oew = mass_computation["data:weight:aircraft:OWE"] assert oew == pytest.approx(41591, abs=1) # with payload as input reader = VariableIO( pth.join(pth.dirname(__file__), "data", "mass_breakdown_inputs.xml")) reader.path_separator = ":" input_vars = reader.read(ignore=[ "data:weight:aircraft:MLW", "data:weight:aircraft:MZFW", ]).to_ivc() mass_computation = run_system(MassBreakdown(payload_from_npax=False), input_vars) oew = mass_computation["data:weight:aircraft:OWE"] assert oew == pytest.approx(42060, abs=1)
def test_basic_xml_read_and_write_from_vars(cleanup): """ Tests the creation of an XML file from a VariableList instance """ result_folder = pth.join(RESULTS_FOLDER_PATH, "basic_xml") # Check write hand-made component vars = VariableList() vars["geometry/total_surface"] = {"value": [780.3], "units": "m**2"} vars["geometry/wing/span"] = {"value": 42.0, "units": "m", "description": "span of the wing"} vars["geometry/wing/aspect_ratio"] = {"value": [9.8]} vars["geometry/fuselage/length"] = {"value": 40.0, "units": "m"} vars["constants"] = {"value": [-42.0], "description": "the answer"} vars["constants/k1"] = {"value": [1.0, 2.0, 3.0], "units": "kg"} vars["constants/k2"] = {"value": [10.0, 20.0], "description": "Geronimo!"} vars["constants/k3"] = {"value": np.array([100.0, 200.0, 300.0, 400.0]), "units": "m/s"} vars["constants/k4"] = {"value": [-1.0, -2.0, -3.0]} vars["constants/k5"] = {"value": [100.0, 200.0, 400.0, 500.0, 600.0]} vars["constants/k8"] = {"value": [[1e2, 3.4e5], [5.4e3, 2.1]]} # Try writing with non-existing folder assert not pth.exists(result_folder) filename = pth.join(result_folder, "handmade.xml") xml_write = VariableIO(filename, formatter=VariableXmlStandardFormatter()) xml_write.path_separator = "/" xml_write.write(vars) # check (read another IndepVarComp instance from xml) xml_check = VariableIO(filename, formatter=VariableXmlStandardFormatter()) xml_check.path_separator = ":" new_vars = xml_check.read() _check_basic_vars(new_vars) # Check reading hand-made XML (with some format twists) filename = pth.join(DATA_FOLDER_PATH, "basic.xml") xml_read = VariableIO(filename, formatter=VariableXmlStandardFormatter()) xml_read.path_separator = ":" vars = xml_read.read() _check_basic_vars(vars) # write it (with existing destination folder) new_filename = pth.join(result_folder, "basic.xml") xml_write = VariableIO(new_filename, formatter=VariableXmlStandardFormatter()) xml_write.path_separator = ":" xml_write.write(vars) # check (read another IndepVarComp instance from new xml) xml_check = VariableIO(new_filename, formatter=VariableXmlStandardFormatter()) xml_check.path_separator = ":" new_vars = xml_check.read() _check_basic_vars(new_vars) # try to write with bad separator xml_write.formatter.path_separator = "/" with pytest.raises(FastXPathEvalError): xml_write.write(vars)
def test_high_speed_connection(): """ Tests high speed components connection """ # load all inputs reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() register_wrappers() # Run problem with VLM and check obtained value(s) is/(are) correct # noinspection PyTypeChecker problem = run_system(AerodynamicsHighSpeed(propulsion_id=ENGINE_WRAPPER), input_vars, check=True) cd0 = problem["data:aerodynamics:aircraft:cruise:CD0"] assert cd0 == pytest.approx(0.0198, abs=1e-4) coef_k = problem["data:aerodynamics:aircraft:cruise:induced_drag_coefficient"] assert coef_k == pytest.approx(0.0528, abs=1e-4) cl_alpha_wing = problem.get_val("data:aerodynamics:aircraft:cruise:CL_alpha", units="rad**-1") assert cl_alpha_wing == pytest.approx(4.820, abs=1e-3) cl_alpha_htp = problem.get_val("data:aerodynamics:horizontal_tail:cruise:CL_alpha", units="rad**-1") assert cl_alpha_htp == pytest.approx(0.6260, abs=1e-4) cl_alpha_vtp = problem.get_val("data:aerodynamics:vertical_tail:cruise:CL_alpha", units="rad**-1") assert cl_alpha_vtp == pytest.approx(2.8553, abs=1e-4) # Run problem with OPENVSP and check change(s) is/(are) correct # noinspection PyTypeChecker problem = run_system(AerodynamicsHighSpeed(propulsion_id=ENGINE_WRAPPER, use_openvsp=True), input_vars, check=True) coef_k = problem["data:aerodynamics:aircraft:cruise:induced_drag_coefficient"] assert coef_k == pytest.approx(0.0487, abs=1e-4) cl_alpha_wing = problem.get_val("data:aerodynamics:aircraft:cruise:CL_alpha", units="rad**-1") assert cl_alpha_wing == pytest.approx(4.536, abs=1e-3) cl_alpha_htp = problem.get_val("data:aerodynamics:horizontal_tail:cruise:CL_alpha", units="rad**-1") assert cl_alpha_htp == pytest.approx(0.7030, abs=1e-4) cl_alpha_vtp = problem.get_val("data:aerodynamics:vertical_tail:cruise:CL_alpha", units="rad**-1") assert cl_alpha_vtp == pytest.approx(2.8553, abs=1e-4)
def test_v_n_diagram_openvsp(): # load all inputs reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() input_vars.add_output("data:aerodynamics:aircraft:landing:CL_max", 1.9) input_vars.add_output("data:aerodynamics:wing:low_speed:CL_max_clean", 1.5) input_vars.add_output("data:aerodynamics:wing:low_speed:CL_min_clean", -1.5) input_vars.add_output("data:aerodynamics:aircraft:mach_interpolation:CL_alpha_vector", [5.51, 5.51, 5.56, 5.63, 5.71, 5.80]) input_vars.add_output("data:aerodynamics:aircraft:mach_interpolation:mach_vector", [0., 0.15, 0.21, 0.27, 0.33, 0.39]) input_vars.add_output("data:weight:aircraft:MTOW", 1633.0, units="kg") input_vars.add_output("data:aerodynamics:cruise:mach", 0.2488) input_vars.add_output("data:aerodynamics:wing:cruise:induced_drag_coefficient", 0.048) input_vars.add_output("data:aerodynamics:aircraft:cruise:CD0", 0.02733) register_wrappers() # Run problem with VLM and check obtained value(s) is/(are) correct # noinspection PyTypeChecker problem = run_system(ComputeVNopenvspNoVH(propulsion_id=ENGINE_WRAPPER, compute_cl_alpha=True), input_vars) velocity_vect = np.array( [35.986, 35.986, 70.15, 44.367, 0., 0., 83.942, 83.942, 83.942, 117.265, 117.265, 117.265, 117.265, 105.538, 83.942, 0., 31.974, 45.219, 57.554] ) load_factor_vect = np.array( [1., -1., 3.8, -1.52, 0., 0., -1.52, 3.874, -1.874, 3.8, 0., 3.05, -1.05, 0., 0., 0., 1., 2., 2.] ) velocity_array = problem.get_val("data:flight_domain:velocity", units="m/s") load_factor_array = problem["data:flight_domain:load_factor"] assert np.max(np.abs(velocity_vect - velocity_array)) <= 1e-3 assert np.max(np.abs(load_factor_vect - load_factor_array)) <= 1e-3
def get_indep_var_comp(var_names): """ Reads required input data and returns an IndepVarcomp() instance""" reader = VariableIO( pth.join(pth.dirname(__file__), "data", "mass_breakdown_inputs.xml")) reader.path_separator = ":" ivc = reader.read(only=var_names).to_ivc() return ivc
def test_complete_cg(): """ Run computation of all models """ # with data from file reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() input_vars.add_output("data:weight:propulsion:unusable_fuel:mass", 20.0, units="kg") # Run problem and check obtained value(s) is/(are) correct # noinspection PyTypeChecker problem = run_system(CG(propulsion_id=ENGINE_WRAPPER), input_vars, check=True) cg_global = problem.get_val("data:weight:aircraft:CG:aft:x", units="m") assert cg_global == pytest.approx(2.5800, abs=1e-3) cg_ratio = problem.get_val("data:weight:aircraft:CG:aft:MAC_position") assert cg_ratio == pytest.approx(0.1917, abs=1e-3) z_cg_empty_ac = problem.get_val("data:weight:aircraft_empty:CG:z", units="m") assert z_cg_empty_ac == pytest.approx(1.266, abs=1e-3) z_cg_b1 = problem.get_val("data:weight:propulsion:engine:CG:z", units="m") assert z_cg_b1 == pytest.approx(1.255, abs=1e-2)
def get_indep_var_comp(var_names: List[str], test_file: str, xml_file_name: str) -> om.IndepVarComp: """ Reads required input data from xml file and returns an IndepVarcomp() instance""" reader = VariableIO(pth.join(pth.dirname(test_file), "data", xml_file_name)) reader.path_separator = ":" ivc = reader.read(only=var_names).to_ivc() return ivc
def read_inputs(self): """ Reads inputs from the configured input file. """ if self.input_file_path: # Reads input file reader = VariableIO(self.input_file_path) variables = reader.read() ivc = variables.to_ivc() # ivc will be added through add_subsystem, but we must use set_order() to # put it first. # So we need order of existing subsystem to provide the full order list to # set_order() to get order of systems, we use system_iter() that can be used # only after setup(). # But we will not be allowed to use add_subsystem() after setup(). # So we use setup() on a copy of current instance, and get order from this copy tmp_prob = deepcopy(self) tmp_prob.setup() previous_order = [ system.name for system in tmp_prob.model.system_iter(recurse=False) if system.name != "_auto_ivc" # OpenMDAO 3.2+ specific : _auto_ivc is an output of system_iter() but is not # accepted as input of set_order() ] self.model.add_subsystem(INPUT_SYSTEM_NAME, ivc, promotes=["*"]) self.model.set_order([INPUT_SYSTEM_NAME] + previous_order)
def test_takeoff_phase_connections(): """ Tests complete take-off phase connection with speeds """ # load all inputs reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" ivc = reader.read().to_ivc() register_wrappers() # noinspection PyTypeChecker problem = run_system(TakeOffPhase(propulsion_id=ENGINE_WRAPPER), ivc) vr = problem.get_val("data:mission:sizing:takeoff:VR", units='m/s') assert vr == pytest.approx(36.28, abs=1e-2) vloff = problem.get_val("data:mission:sizing:takeoff:VLOF", units='m/s') assert vloff == pytest.approx(42.52, abs=1e-2) v2 = problem.get_val("data:mission:sizing:takeoff:V2", units='m/s') assert v2 == pytest.approx(47.84, abs=1e-2) tofl = problem.get_val("data:mission:sizing:takeoff:TOFL", units='m') assert tofl == pytest.approx(341.49, abs=1) duration = problem.get_val("data:mission:sizing:takeoff:duration", units='s') assert duration == pytest.approx(20.5, abs=1e-1) fuel1 = problem.get_val("data:mission:sizing:takeoff:fuel", units='kg') assert fuel1 == pytest.approx(0.246, abs=1e-2) fuel2 = problem.get_val("data:mission:sizing:initial_climb:fuel", units='kg') assert fuel2 == pytest.approx(0.075, abs=1e-2)
def test_compute_static_margin(): """ Tests computation of static margin """ reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() input_vars.add_output("data:weight:aircraft:CG:aft:MAC_position", 0.20) problem = run_system(ComputeStaticMargin(), input_vars) static_margin = problem["data:handling_qualities:static_margin"] assert static_margin == pytest.approx(0.55, rel=1e-2)
def convert_xml(file_path: str, translator: VarXpathTranslator): """ Modifies given XML file by translating XPaths according to provided translator :param file_path: :param translator: """ reader = VariableIO(file_path, formatter=VariableXmlBaseFormatter(translator)) vars = reader.read() VariableIO(file_path).write(vars)
def test_evaluate_owe(): """ Tests a simple evaluation of Operating Weight Empty from sample XML data. """ reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() # noinspection PyTypeChecker mass_computation = run_system( ComputeOperatingWeightEmpty(propulsion_id=ENGINE_WRAPPER), input_vars) oew = mass_computation.get_val("data:weight:aircraft:OWE", units="kg") assert oew == pytest.approx(1031.500, abs=1)
def test_compute_to_rotation_limit(): """ Tests the computation of the forward most possible CG location for the TO rotation in case HTP area is fixed""" reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() input_vars.add_output("data:geometry:horizontal_tail:area", 3.78) problem = run_system(ComputeTORotationLimitGroup(propulsion_id=ENGINE_WRAPPER), input_vars) to_rotation_limit = problem["data:handling_qualities:to_rotation_limit:x"] assert to_rotation_limit == pytest.approx(2.99, rel=1e-2) to_rotation_limit_ratio = problem["data:handling_qualities:to_rotation_limit:MAC_position"] assert to_rotation_limit_ratio == pytest.approx(-0.0419, rel=1e-2)
def test_balked_landing_limit(): """ Tests the computation of the forward most possible CG location for a balked landing in case HTP area is fixed""" reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() input_vars.add_output("data:geometry:horizontal_tail:area", 3.78) problem = run_system(ComputeBalkedLandingLimit(propulsion_id=ENGINE_WRAPPER), input_vars) balked_landing_limit = problem["data:handling_qualities:balked_landing_limit:x"] assert balked_landing_limit == pytest.approx(3.43, rel=1e-2) balked_landing_limit_ratio = problem["data:handling_qualities:balked_landing_limit:MAC_position"] assert balked_landing_limit_ratio == pytest.approx(0.24, rel=1e-2)
def test_evaluate_oew(): """ Tests a simple evaluation of Operating Empty Weight from sample XML data. """ reader = VariableIO( pth.join(pth.dirname(__file__), "data", "mass_breakdown_inputs.xml")) reader.path_separator = ":" input_vars = reader.read().to_ivc() mass_computation = run_system(OperatingWeightEmpty(), input_vars) oew = mass_computation["data:weight:aircraft:OWE"] assert oew == pytest.approx(41591, abs=1)
def test_loop_compute_owe(): """ Tests a weight computation loop matching the max payload criterion. """ # with payload computed from NPAX reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read(ignore=[ "data:weight:aircraft:max_payload", "data:weight:aircraft:MTOW", ]).to_ivc() input_vars.add_output("data:mission:sizing:fuel", 0.0, units="kg") # noinspection PyTypeChecker mass_computation_1 = run_system( MassBreakdown(propulsion_id=ENGINE_WRAPPER, payload_from_npax=True), input_vars, check=True, ) oew = mass_computation_1.get_val("data:weight:aircraft:OWE", units="kg") assert oew == pytest.approx(1026.20, abs=1e-2) # 1098.66 (without MTOW local loop) # with payload as input reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read(ignore=[ "data:weight:aircraft:MTOW", ]).to_ivc() input_vars.add_output("data:mission:sizing:fuel", 0.0, units="kg") # noinspection PyTypeChecker mass_computation_2 = run_system( MassBreakdown(propulsion_id=ENGINE_WRAPPER, payload_from_npax=False), input_vars, check=False, ) oew = mass_computation_2.get_val("data:weight:aircraft:OWE", units="kg") assert oew == pytest.approx(1009.19, abs=1e-2) # 1098.66 (without MTOW local loop)
def test_complete_cg(): """ Run computation of all models """ # with data from file reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() # Run problem and check obtained value(s) is/(are) correct problem = run_system(CG(), input_vars, check=True) cg_global = problem.get_val("data:weight:aircraft:CG:aft:x", units="m") assert cg_global == pytest.approx(3.46, abs=1e-1) cg_ratio = problem.get_val("data:weight:aircraft:CG:aft:MAC_position") assert cg_ratio == pytest.approx(0.20, abs=1e-2)
def test_update_vt_area(): """ Tests computation of the vertical tail area """ # Research independent input value in .xml file reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() input_vars.add_output("data:aerodynamics:fuselage:cruise:CnBeta", -0.0599) # Run problem and check obtained value(s) is/(are) correct register_wrappers() problem = run_system(UpdateVTArea(propulsion_id=ENGINE_WRAPPER), input_vars) vt_area = problem.get_val("data:geometry:vertical_tail:area", units="m**2") assert vt_area == pytest.approx( 1.751, abs=1e-2) # old-version obtained value 2.4m²
def test_compute_balked_landing(): """ Tests computation of static margin """ reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() problem = run_system( ComputeBalkedLandingLimit(propulsion_id=ENGINE_WRAPPER), input_vars) x_cg_balked_landing_limit = problem[ "data:handling_qualities:balked_landing_limit:x"] assert x_cg_balked_landing_limit == pytest.approx(2.0738, rel=1e-2) x_cg_ratio_balked_landing_limit = problem[ "data:handling_qualities:balked_landing_limit:MAC_position"] assert x_cg_ratio_balked_landing_limit == pytest.approx(-0.23, rel=1e-2)
def test_compute_to_rotation_limit(): """ Tests computation of static margin """ reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() problem = run_system( ComputeTORotationLimitGroup(propulsion_id=ENGINE_WRAPPER), input_vars) x_cg_rotation_limit = problem[ "data:handling_qualities:to_rotation_limit:x"] assert x_cg_rotation_limit == pytest.approx(1.9355, rel=1e-2) x_cg_ratio_rotation_limit = problem[ "data:handling_qualities:to_rotation_limit:MAC_position"] assert x_cg_ratio_rotation_limit == pytest.approx(-0.3451, rel=1e-2)
def test_compute_static_margin(): """ Tests computation of static margin """ reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() problem = run_system(ComputeStaticMargin(), input_vars) stick_fixed_static_margin = problem[ "data:handling_qualities:stick_fixed_static_margin"] assert stick_fixed_static_margin == pytest.approx(0.0479, rel=1e-2) free_elevator_factor = problem[ "data:aerodynamics:cruise:neutral_point:free_elevator_factor"] assert free_elevator_factor == pytest.approx(0.7217, rel=1e-2) stick_free_static_margin = problem[ "data:handling_qualities:stick_free_static_margin"] assert stick_free_static_margin == pytest.approx(-0.0253, rel=1e-2)
def test_low_speed_connection(): """ Tests low speed components connection """ # Clear saved polar results (for wing and htp airfoils) clear_polar_results() # load all inputs reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() register_wrappers() # Run problem with VLM # noinspection PyTypeChecker run_system(AerodynamicsLowSpeed(propulsion_id=ENGINE_WRAPPER, use_openvsp=False), input_vars) # Run problem with OPENVSP # noinspection PyTypeChecker run_system(AerodynamicsLowSpeed(propulsion_id=ENGINE_WRAPPER, use_openvsp=True), input_vars)
def get_problem(self, read_inputs: bool = False, auto_scaling: bool = False) -> FASTOADProblem: """ Builds the OpenMDAO problem from current configuration. :param read_inputs: if True, the created problem will already be fed with variables from the input file :param auto_scaling: if True, automatic scaling is performed for design variables and constraints :return: the problem instance """ if not self._conf_dict: raise RuntimeError("read configuration file first") if read_inputs: reader = VariableIO(self.input_file_path) variables = reader.read() input_ivc = variables.to_ivc() else: input_ivc = None problem = FASTOADProblem(self._build_model(input_ivc)) problem.input_file_path = self.input_file_path problem.output_file_path = self.output_file_path driver = self._conf_dict.get(KEY_DRIVER, "") if driver: problem.driver = _om_eval(driver) if self.get_optimization_definition(): self._add_constraints(problem.model, auto_scaling) self._add_objectives(problem.model) if read_inputs: self._add_design_vars(problem.model, auto_scaling) if self._configuration_modifier: self._configuration_modifier.modify(problem) return problem
def test_low_speed_connection(): """ Tests low speed components connection """ # load all inputs reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() register_wrappers() # Run problem with VLM and check obtained value(s) is/(are) correct # noinspection PyTypeChecker problem = run_system(AerodynamicsLowSpeed(propulsion_id=ENGINE_WRAPPER), input_vars, check=True) cd0 = problem["data:aerodynamics:aircraft:low_speed:CD0"] assert cd0 == pytest.approx(0.0452, abs=1e-4) coef_k = problem["data:aerodynamics:aircraft:low_speed:induced_drag_coefficient"] assert coef_k == pytest.approx(0.0530, abs=1e-4) cl_alpha_wing = problem.get_val("data:aerodynamics:aircraft:low_speed:CL_alpha", units="rad**-1") assert cl_alpha_wing == pytest.approx(4.705, abs=1e-3) cl_max_clean = problem["data:aerodynamics:wing:low_speed:CL_max_clean"] assert cl_max_clean == pytest.approx(1.4456, abs=1e-4) cl_max_takeoff = problem["data:aerodynamics:aircraft:takeoff:CL_max"] assert cl_max_takeoff == pytest.approx(1.5675, abs=1e-4) cl_max_landing = problem["data:aerodynamics:aircraft:landing:CL_max"] assert cl_max_landing == pytest.approx(2.0245, abs=1e-4) cl_alpha_htp = problem.get_val("data:aerodynamics:horizontal_tail:low_speed:CL_alpha", units="rad**-1") assert cl_alpha_htp == pytest.approx(0.6202, abs=1e-4) # Run problem with OPENVSP and check change(s) is/(are) correct # noinspection PyTypeChecker problem = run_system(AerodynamicsLowSpeed(propulsion_id=ENGINE_WRAPPER, use_openvsp=True), input_vars, check=True) coef_k = problem["data:aerodynamics:aircraft:low_speed:induced_drag_coefficient"] assert coef_k == pytest.approx(0.0487, abs=1e-4) cl_alpha_wing = problem.get_val("data:aerodynamics:aircraft:low_speed:CL_alpha", units="rad**-1") assert cl_alpha_wing == pytest.approx(4.459, abs=1e-3) cl_max_clean = problem["data:aerodynamics:wing:low_speed:CL_max_clean"] assert cl_max_clean == pytest.approx(1.5352, abs=1e-4) cl_max_takeoff = problem["data:aerodynamics:aircraft:takeoff:CL_max"] assert cl_max_takeoff == pytest.approx(1.6571, abs=1e-4) cl_max_landing = problem["data:aerodynamics:aircraft:landing:CL_max"] assert cl_max_landing == pytest.approx(2.1141, abs=1e-4) cl_alpha_htp = problem.get_val("data:aerodynamics:horizontal_tail:low_speed:CL_alpha", units="rad**-1") assert cl_alpha_htp == pytest.approx(0.6967, abs=1e-4)
def test_loop_cruise_distance(): """ Tests a distance computation loop matching the descent value/TLAR total range. """ # Get the parameters from .xml reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" ivc = reader.read().to_ivc() # Run problem and check obtained value(s) is/(are) correct register_wrappers() # noinspection PyTypeChecker problem = run_system(Sizing(propulsion_id=ENGINE_WRAPPER), ivc) m_total = problem.get_val("data:mission:sizing:fuel", units="kg") assert m_total == pytest.approx(117.20, abs=1e-1) climb_distance = problem.get_val("data:mission:sizing:main_route:climb:distance", units="NM") cruise_distance = problem.get_val("data:mission:sizing:main_route:cruise:distance", units="NM") descent_distance = problem.get_val("data:mission:sizing:main_route:descent:distance", units="NM") total_distance = problem.get_val("data:TLAR:range", units="NM") error_distance = total_distance - (climb_distance + cruise_distance + descent_distance) assert error_distance == pytest.approx(0.0, abs=1e-1)
def test_loop_compute_owe(): """ Tests a weight computation loop matching the max payload criterion. """ # Payload is computed from NPAX_design reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read(ignore=[ "data:weight:aircraft:max_payload", "data:weight:aircraft:MLW", ]).to_ivc() input_vars.add_output("data:mission:sizing:fuel", 0.0, units="kg") # noinspection PyTypeChecker mass_computation = run_system( MassBreakdown(propulsion_id=ENGINE_WRAPPER, payload_from_npax=True), input_vars, check=True, ) oew = mass_computation.get_val("data:weight:aircraft:OWE", units="kg") assert oew == pytest.approx(1031.539, abs=1)
def test_basic_xml_partial_read_and_write_from_vars(cleanup): """ Tests the creation of an XML file from an IndepVarComp instance with only and ignore options """ result_folder = pth.join(RESULTS_FOLDER_PATH, "basic_partial_xml") # Read full IndepVarComp filename = pth.join(DATA_FOLDER_PATH, "basic.xml") xml_read = VariableIO(filename, formatter=VariableXmlStandardFormatter()) vars = xml_read.read(ignore=["does_not_exist"]) _check_basic_vars(vars) # Add something to ignore and write it vars["should_be_ignored:pointless"] = {"value": 0.0} vars["should_also_be_ignored"] = {"value": -10.0} badvar_filename = pth.join(result_folder, "with_bad_var.xml") xml_write = VariableIO(badvar_filename, formatter=VariableXmlStandardFormatter()) xml_write.write(vars, ignore=["does_not_exist"]) # Check with non-existent var in ignore list tree = etree.parse(badvar_filename) assert float(tree.xpath("should_be_ignored/pointless")[0].text.strip()) == 0.0 assert float(tree.xpath("should_also_be_ignored")[0].text.strip()) == -10.0 # Check partial reading with 'ignore' xml_read = VariableIO(badvar_filename, formatter=VariableXmlStandardFormatter()) new_vars = xml_read.read(ignore=["should_be_ignored:pointless", "should_also_be_ignored"]) _check_basic_vars(new_vars) # Check partial reading with 'only' ok_vars = [ "geometry:total_surface", "geometry:wing:span", "geometry:wing:aspect_ratio", "geometry:fuselage:length", "constants", "constants:k1", "constants:k2", "constants:k3", "constants:k4", "constants:k5", "constants:k8", ] new_vars2 = xml_read.read(only=ok_vars) _check_basic_vars(new_vars2) # Check partial writing with 'ignore' varok_filename = pth.join(result_folder, "with_bad_var.xml") xml_write = VariableIO(varok_filename, formatter=VariableXmlStandardFormatter()) xml_write.write(vars, ignore=["should_be_ignored:pointless", "should_also_be_ignored"]) xml_read = VariableIO(varok_filename, formatter=VariableXmlStandardFormatter()) new_vars = xml_read.read() _check_basic_vars(new_vars) # Check partial writing with 'only' varok2_filename = pth.join(result_folder, "with_bad_var.xml") xml_write = VariableIO(varok2_filename, formatter=VariableXmlStandardFormatter()) xml_write.write(vars, only=ok_vars) xml_read = VariableIO(varok2_filename, formatter=VariableXmlStandardFormatter()) new_vars = xml_read.read() _check_basic_vars(new_vars)
def test_v_n_diagram_vlm(): # load all inputs reader = VariableIO(pth.join(pth.dirname(__file__), "data", XML_FILE)) reader.path_separator = ":" input_vars = reader.read().to_ivc() cl_wing_airfoil = np.zeros(POLAR_POINT_COUNT) cdp_wing_airfoil = np.zeros(POLAR_POINT_COUNT) cl_htp_airfoil = np.zeros(POLAR_POINT_COUNT) cdp_htp_airfoil = np.zeros(POLAR_POINT_COUNT) cl_wing_airfoil[0:38] = np.array( [0.1391, 0.1988, 0.2581, 0.3177, 0.377, 0.4903, 0.5477, 0.6062, 0.6647, 0.7226, 0.7807, 0.838, 0.8939, 0.9473, 1.1335, 1.1968, 1.2451, 1.296, 1.3424, 1.4014, 1.4597, 1.5118, 1.5575, 1.6006, 1.6383, 1.664, 1.6845, 1.7023, 1.7152, 1.7196, 1.7121, 1.6871, 1.6386, 1.563, 1.4764, 1.3993, 1.3418, 1.2981] ) cdp_wing_airfoil[0:38] = np.array( [0.00143, 0.00147, 0.00154, 0.00163, 0.00173, 0.00196, 0.00214, 0.00235, 0.0026, 0.00287, 0.00317, 0.00349, 0.00385, 0.00424, 0.00572, 0.00636, 0.00701, 0.00777, 0.00908, 0.00913, 0.00923, 0.00982, 0.01098, 0.01221, 0.01357, 0.01508, 0.01715, 0.01974, 0.02318, 0.02804, 0.035, 0.04486, 0.05824, 0.07544, 0.09465, 0.1133, 0.1299, 0.14507] ) cl_htp_airfoil[0:41] = np.array( [-0., 0.0582, 0.117, 0.1751, 0.2333, 0.291, 0.3486, 0.4064, 0.4641, 0.5216, 0.5789, 0.6356, 0.6923, 0.747, 0.8027, 0.8632, 0.9254, 0.9935, 1.0611, 1.127, 1.1796, 1.227, 1.2762, 1.3255, 1.3756, 1.4232, 1.4658, 1.5084, 1.5413, 1.5655, 1.5848, 1.5975, 1.6002, 1.5894, 1.5613, 1.5147, 1.4515, 1.3761, 1.2892, 1.1988, 1.1276] ) cdp_htp_airfoil[0:41] = np.array( [0.00074, 0.00075, 0.00078, 0.00086, 0.00095, 0.00109, 0.00126, 0.00145, 0.00167, 0.00191, 0.00218, 0.00249, 0.00283, 0.00324, 0.00365, 0.00405, 0.00453, 0.00508, 0.00559, 0.00624, 0.00679, 0.0074, 0.00813, 0.00905, 0.01, 0.01111, 0.0126, 0.01393, 0.0155, 0.01743, 0.01993, 0.02332, 0.0282, 0.03541, 0.04577, 0.05938, 0.07576, 0.0944, 0.11556, 0.13878, 0.16068] ) input_vars.add_output("data:aerodynamics:wing:cruise:CL", cl_wing_airfoil) input_vars.add_output("data:aerodynamics:wing:cruise:CDp", cdp_wing_airfoil) input_vars.add_output("data:aerodynamics:horizontal_tail:cruise:CL", cl_htp_airfoil) input_vars.add_output("data:aerodynamics:horizontal_tail:cruise:CDp", cdp_htp_airfoil) input_vars.add_output("data:aerodynamics:aircraft:landing:CL_max", 1.949) input_vars.add_output("data:aerodynamics:wing:low_speed:CL_max_clean", 1.4818) input_vars.add_output("data:aerodynamics:wing:low_speed:CL_min_clean", -1.1614) input_vars.add_output("data:weight:aircraft:MTOW", 1633.0, units="kg") input_vars.add_output("data:aerodynamics:cruise:mach", 0.2488) input_vars.add_output("data:aerodynamics:wing:cruise:induced_drag_coefficient", 0.048) input_vars.add_output("data:aerodynamics:aircraft:cruise:CD0", 0.02733) input_vars.add_output("data:aerodynamics:aircraft:mach_interpolation:CL_alpha_vector", [5.235, 5.235, 5.297, 5.381, 5.484, 5.606]) input_vars.add_output("data:aerodynamics:aircraft:mach_interpolation:mach_vector", [0., 0.15, 0.214, 0.275, 0.332, 0.386]) register_wrappers() # Run problem with VLM and check obtained value(s) is/(are) correct # noinspection PyTypeChecker problem = run_system(ComputeVNvlmNoVH(propulsion_id=ENGINE_WRAPPER, compute_cl_alpha=True), input_vars) velocity_vect = np.array( [36.206, 40.897, 70.579, 50.421, 0., 0., 75.561, 75.561, 75.561, 105.556, 105.556, 105.556, 105.556, 95.001, 83.942, 0., 31.57, 44.647, 56.826] ) load_factor_vect = np.array( [1., -1., 3.8, -1.52, 0., 0., -1.52, 3.8, -1.52, 3.8, 0., 2.764, -0.764, 0., 0., 0., 1., 2., 2.] ) velocity_array = problem.get_val("data:flight_domain:velocity", units="m/s") load_factor_array = problem["data:flight_domain:load_factor"] assert np.max(np.abs(velocity_vect - velocity_array)) <= 1e-3 assert np.max(np.abs(load_factor_vect - load_factor_array)) <= 1e-3