From 6e79ec2831140dfe3d221d0101ce7a9ef4ad3184 Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Fri, 21 Feb 2025 09:18:22 +0100 Subject: [PATCH 01/10] plotting for mode_1 is improved --- .../src/energy_based/energy_based_refactored.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/constraint_analysis/src/energy_based/energy_based_refactored.cpp b/constraint_analysis/src/energy_based/energy_based_refactored.cpp index d7e9e093..59233c69 100644 --- a/constraint_analysis/src/energy_based/energy_based_refactored.cpp +++ b/constraint_analysis/src/energy_based/energy_based_refactored.cpp @@ -140,7 +140,19 @@ void EnergyBased::operator()() /* Plot the complete design chart with constraints, boundaries and design point*/ std::string plotting = this->configuration()->at("module_configuration_file/control_settings/plot_output/enable/value"); + if (plotting == "true") { + /*Define relevant Wing_loading range. Selected values should be valid for all possible configurations*/ + WS_start = 50; + WS_end = 820; + WS_size = WS_end - WS_start + 1; // Range from 50 to 820, inclusive + std::vector<double> W_over_S_data(WS_size); + + /*Transform from kg/m^2 into N/m^2*/ + for (int i = 0; i < WS_size; ++i) { + W_over_S_data[i] = (WS_start + i) * 9.81; + } + assess_constraints(W_over_S_data, constraint_analysis_tool, mission_data, engine); ConstraintAnalysis_Plot ca_plot; ca_plot.fill_infeasible_area(W_over_S_data, min_finder.dominant_thrust_to_weight, boundaries); -- GitLab From 621477c15889f1616da30b011c60dcd84b357146 Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Sun, 23 Feb 2025 22:21:58 +0100 Subject: [PATCH 02/10] plotting fix --- .../energy_based/energy_based_refactored.cpp | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/constraint_analysis/src/energy_based/energy_based_refactored.cpp b/constraint_analysis/src/energy_based/energy_based_refactored.cpp index 59233c69..4b4d16b6 100644 --- a/constraint_analysis/src/energy_based/energy_based_refactored.cpp +++ b/constraint_analysis/src/energy_based/energy_based_refactored.cpp @@ -105,7 +105,9 @@ void EnergyBased::operator()() break; } } - + + Mattingly::constraint_analysis constraint_analysis_plotting = constraint_analysis_tool; + readMission mission_data(missionCSV); assess_constraints(W_over_S_data, constraint_analysis_tool, mission_data, engine); @@ -140,22 +142,26 @@ void EnergyBased::operator()() /* Plot the complete design chart with constraints, boundaries and design point*/ std::string plotting = this->configuration()->at("module_configuration_file/control_settings/plot_output/enable/value"); - if (plotting == "true") { - /*Define relevant Wing_loading range. Selected values should be valid for all possible configurations*/ - WS_start = 50; - WS_end = 820; - WS_size = WS_end - WS_start + 1; // Range from 50 to 820, inclusive - std::vector<double> W_over_S_data(WS_size); - /*Transform from kg/m^2 into N/m^2*/ + WS_start = 50; for (int i = 0; i < WS_size; ++i) { W_over_S_data[i] = (WS_start + i) * 9.81; } - assess_constraints(W_over_S_data, constraint_analysis_tool, mission_data, engine); + + this->constraint_list = {}; + this->boundaries = {}; + + assess_constraints(W_over_S_data, constraint_analysis_plotting, mission_data, engine); + + Simple_Analysis min_finder_2 = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->boundaries); + + min_finder_2.find_dominant_curve(); + ConstraintAnalysis_Plot ca_plot; - ca_plot.fill_infeasible_area(W_over_S_data, min_finder.dominant_thrust_to_weight, boundaries); + ca_plot.fill_infeasible_area(W_over_S_data, min_finder_2.dominant_thrust_to_weight, boundaries); + for (auto ca_case : this->constraint_list) { ca_plot.add_curve(ca_case.wing_loading, ca_case.thrust_to_weight, ca_case.constraint_case); -- GitLab From 6314d7953daa1b7d4b7b621bbb3b2f0e3a379e9a Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Mon, 24 Feb 2025 08:38:01 +0100 Subject: [PATCH 03/10] refactoring completed --- constraint_analysis/CMakeLists.txt | 2 +- .../src/energy_based/energy_based.cpp | 406 ++++++++++-------- .../energy_based/energy_based_refactored.cpp | 365 ---------------- 3 files changed, 226 insertions(+), 547 deletions(-) delete mode 100644 constraint_analysis/src/energy_based/energy_based_refactored.cpp diff --git a/constraint_analysis/CMakeLists.txt b/constraint_analysis/CMakeLists.txt index 20918bf4..564eb7d2 100644 --- a/constraint_analysis/CMakeLists.txt +++ b/constraint_analysis/CMakeLists.txt @@ -7,7 +7,7 @@ set(MODULE_SOURCES src/constraint_analysis.cpp src/ca_parser.cpp src/io/aircraft_xml.cpp - src/energy_based/energy_based_refactored.cpp + src/energy_based/energy_based.cpp ) add_executable(${MODULE_NAME} diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index 7cc47455..4b4d16b6 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -62,6 +62,7 @@ void EnergyBased::operator()() int WS_start = 0; int WS_end = 0; size_t WS_size = 1; + if (mode_selection == "mode_0") { /*Define relevant Wing_loading range. Selected values should be valid for all possible configurations*/ @@ -71,8 +72,8 @@ void EnergyBased::operator()() } else if (mode_selection == "mode_1") { - WS_start = this->aircraft_xml()->at("aircraft_exchange_file/sizing_point/wing_loading/value"); - WS_size = 1; // Constant W/S + WS_start = this->aircraft_xml()->at("aircraft_exchange_file/sizing_point/wing_loading/value"); + WS_size = 1; // Constant W/S } std::vector<double> W_over_S_data(WS_size); @@ -82,6 +83,8 @@ void EnergyBased::operator()() W_over_S_data[i] = (WS_start + i) * 9.81; } + Engine engine = Engine(this->engine_directory()); + Mattingly::constraint_analysis constraint_analysis_tool; atmosphere atm; @@ -92,31 +95,8 @@ void EnergyBased::operator()() constraint_analysis_tool.atm = atm; - double CD = 0.0; - double CL = 0.0; - std::vector<double> CD_vector = {}; - std::vector<double> CL_vector = {}; - - Engine engine = Engine(this->engine_directory()); - auto calculate_thrust_lapse = [&atm, &engine](double M, double altitude) { - const double thrust_lapse = engine.get_thrust_lapse("cruise", atm, M, altitude); - return thrust_lapse; - }; - - auto get_num_engines = [&]() { - double num_engines = 0; - - // Get the node vector for all defined propulsion systems - auto propulsors = this->aircraft_xml()->getVector( - "aircraft_exchange_file/requirements_and_specifications/design_specification/propulsion/propulsor"); - - // Increment num_engines for each propulsor - for (const auto& propulsor : propulsors) { - num_engines += 1; - } - return num_engines; - }; std::filesystem::path missionCSV = this->mission_directory(); + for (const auto& entry : fs::directory_iterator(this->mission_directory())) { std::string filename = entry.path().filename().string(); @@ -125,157 +105,15 @@ void EnergyBased::operator()() break; } } - readMission mission_data(missionCSV); - - /* Take-off Segment */ - double CL_max_TO = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxT-O/value"); - double s_G_TO = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); - double takeoff_climb_angle = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/takeoff_climb/takeoff_climb_angle/value"); - double M_TO = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/takeoff_ground_roll/Mach_TO/value"); - double thrust_lapse_TO = calculate_thrust_lapse(M_TO, 0.0); - double weight_fraction_TO = mission_data.get_beta(" takeoff", 1.0); //from mission analysis - const auto to_ground_roll = constraint_analysis_tool.takeoff_ground_roll( - W_over_S_data, - weight_fraction_TO, - thrust_lapse_TO, - M_TO, - 0.0, - s_G_TO, - CL_max_TO); - - readPolar takeoff_config(this->polar(), "takeoff", "linear", M_TO); - std::vector<double> coeffs = takeoff_config.quadratic_coefficients(); - double K_1 = coeffs[0]; - double K_2 = coeffs[1]; - double C_D0 = coeffs[2]; - - for (int i = 0; i < W_over_S_data.size(); ++i) { - CD = takeoff_config.getCD(W_over_S_data[i], 1.0, weight_fraction_TO, M_TO, 0.0); - CD_vector.push_back(CD); - }; - const auto to_climb_angle = constraint_analysis_tool.takeoff_climb_angle( - W_over_S_data, - CD_vector, - weight_fraction_TO, - thrust_lapse_TO, - M_TO, - 0.0, - CL_max_TO, - takeoff_climb_angle); - - /* OEI Climb */ - double climb_speed = this->aircraft_xml()->at( - "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/design_mission/climb_speed_schedule/climb_speed_below_FL100/value"); - double climb_gradient_OEI = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/OEI_climb/climb_gradient_OEI/value"); - double M_climb = climb_speed / atm.getSpeedOfSound(0.0); - - double num_engines = get_num_engines(); - - readPolar climb_config(this->polar(), "takeoff", "linear", M_TO); - for (int i = 0; i < W_over_S_data.size(); ++i) { - CD = climb_config.getCD(W_over_S_data[i], 1.0, weight_fraction_TO, (climb_speed / atm.getSpeedOfSound(0.0)), 0.0); - CD_vector.push_back(CD); - }; + Mattingly::constraint_analysis constraint_analysis_plotting = constraint_analysis_tool; - double thrust_factor_OEI = thrust_lapse_TO *((num_engines - 1)/ num_engines); - double climb_rate_OEI = climb_gradient_OEI * climb_speed; - double weight_fraction_climb_OEI = mission_data.get_beta(" takeoff"); - /*minimal climb rate of 2.4% defined in CS25 for second segment climb*/ - const auto climb_OEI = constraint_analysis_tool.constant_speed_climb( - W_over_S_data, - CD_vector, - weight_fraction_climb_OEI, - thrust_factor_OEI, - M_climb, - 0.0, - climb_rate_OEI); /* DEFINE CLIMB RATE CONSTRAINT */ - - /* Service Ceiling */ - double altitude_max = this->aircraft_xml()->at( - "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_operating_altitude/value"); - double M_cruise = this->aircraft_xml()->at( - "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/study_mission/initial_cruise_mach_number/value"); - - double M_polar = M_cruise; - double weight_fraction_climb_service_ceiling = mission_data.get_beta(" climb_to_cruise"); - - bool polar_read = false; - readPolar clean_config_M_max(this->polar(), "clean", "linear", M_TO); - while (!polar_read) { - try { - clean_config_M_max = readPolar(this->polar(), "clean", "linear", M_polar); - if (clean_config_M_max.CD_polar.size() >= 1) - { - polar_read = true; - } - else { - M_polar += 0.01; - }; - } - catch (...) { - M_polar += 0.01; - } - } - double thrust_lapse_segment = calculate_thrust_lapse(M_cruise, altitude_max); - CD_vector = {}; - CL_vector = {}; - coeffs = clean_config_M_max.quadratic_coefficients(); - K_1 = coeffs[0]; - K_2 = coeffs[1]; - C_D0 = coeffs[2]; - - for (int i = 0; i < W_over_S_data.size(); ++i) { - CD = clean_config_M_max.getCD(W_over_S_data[i], 1.0, weight_fraction_climb_service_ceiling, M_polar, altitude_max); - CD_vector.push_back(CD); - }; + readMission mission_data(missionCSV); - double minimum_climb_rate = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/SEP/minimum_climb_rate/value"); - - /* Service ceiling with the minimum climb rate requirement */ - const auto service_ceiling = constraint_analysis_tool.constant_speed_climb( - W_over_S_data, - CD_vector, - weight_fraction_climb_service_ceiling, - thrust_lapse_segment, - M_cruise, - altitude_max, - minimum_climb_rate); - - /* Landing */ - double thrust_lapse_landing = calculate_thrust_lapse(M_TO, 0.0); - double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); - double my_B = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/additional_requirements/landing_gear/braking_coefficient/value"); - double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); - readPolar landing_config(this->polar(), "landing", "linear", M_TO); - double CD_max_L = landing_config.interpCD(CL_max_L); - double max_landing_weight = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_landing_mass/mass_properties/mass/value"); - double MTOM = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_takeoff_mass/mass_properties/mass/value"); - double weight_fraction_landing = max_landing_weight / MTOM; - const auto landing = constraint_analysis_tool.braking_roll(CD_max_L, CL_max_L, weight_fraction_landing, thrust_lapse_landing, M_TO, 0.0, my_B, s_G_L); - - /* Gust */ - double AoA_1 = landing_config.interpalpha(CL_max_L); - double AoA_2 = landing_config.interpalpha(CL_max_L - CL_max_L * 0.9); - double CL_alpha = (CL_max_L - (CL_max_L - CL_max_L * 0.9)) / ((AoA_1 - AoA_2) * PI / 180.0); - double V_TO_L = M_TO * atm.getSpeedOfSound(0.0); - double w_g = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_speed/value"); - double dn_G = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_load_factor/value"); - const auto gust = constraint_analysis_tool.gust(CL_alpha, 0.0, V_TO_L, w_g, dn_G, weight_fraction_TO); - - /*Define Constraint out of each non-vertical constraint case*/ - Constraint Case1(W_over_S_data, to_ground_roll, "Takeoff Ground Roll"); - Constraint Case2(W_over_S_data, to_climb_angle, "Takeoff Climb Angle"); - Constraint Case3(W_over_S_data, climb_OEI, "OEI Climb"); - Constraint Case4(W_over_S_data, service_ceiling, "Service Ceiling"); - - std::vector<Constraint> constraint_list = { Case1, Case2, Case3, Case4 }; - - /* Define boundaries out of vertical constraint cases*/ - std::vector<double> boundaries = { gust, landing }; + assess_constraints(W_over_S_data, constraint_analysis_tool, mission_data, engine); /* Define Simple_Analysis*/ - Simple_Analysis min_finder = Simple_Analysis(constraint_list, this->aircraft_xml(), boundaries); + Simple_Analysis min_finder = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->boundaries); /* Find dominant curve of the design chart*/ min_finder.find_dominant_curve(); @@ -294,28 +132,234 @@ void EnergyBased::operator()() /*Update design point in ACxml*/ min_finder.update_design_point(); - std::string plot_dir_string=this->plot_dir().string(); + std::string plot_dir_string = this->plot_dir().string(); // Add output of design point in logfile - myRuntimeInfo->out << "New wing loading: " << min_finder.design_wing_loading * 9.81 << " N/m^2. New thrust to weight ratio: " << min_finder.design_thrust_to_weight << std::endl; + myRuntimeInfo->out << "New wing loading: " << min_finder.design_wing_loading * 9.81 << " N/m^2. New thrust to weight ratio: " << min_finder.design_thrust_to_weight << std::endl; min_finder.write_design_point(plot_dir_string + "/csv_files/design_point.csv"); /* Plot the complete design chart with constraints, boundaries and design point*/ std::string plotting = this->configuration()->at("module_configuration_file/control_settings/plot_output/enable/value"); if (plotting == "true") { + + WS_start = 50; + for (int i = 0; i < WS_size; ++i) { + W_over_S_data[i] = (WS_start + i) * 9.81; + } + + this->constraint_list = {}; + this->boundaries = {}; + + assess_constraints(W_over_S_data, constraint_analysis_plotting, mission_data, engine); + + Simple_Analysis min_finder_2 = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->boundaries); + + min_finder_2.find_dominant_curve(); + ConstraintAnalysis_Plot ca_plot; - ca_plot.fill_infeasible_area(W_over_S_data, min_finder.dominant_thrust_to_weight, boundaries); - ca_plot.add_curve(W_over_S_data, to_ground_roll, "Takeoff Ground Roll"); - ca_plot.add_curve(W_over_S_data, to_climb_angle, "Takeoff Climb Angle"); - ca_plot.add_curve(W_over_S_data, climb_OEI, "OEI Climb"); - ca_plot.add_curve(W_over_S_data, service_ceiling, "Service Ceiling"); - ca_plot.add_curve(landing, "Landing"); - ca_plot.add_curve(gust, "Gust"); + ca_plot.fill_infeasible_area(W_over_S_data, min_finder_2.dominant_thrust_to_weight, boundaries); + + for (auto ca_case : this->constraint_list) + { + ca_plot.add_curve(ca_case.wing_loading, ca_case.thrust_to_weight, ca_case.constraint_case); + } + for (auto boundary : this->boundaries) + { + ca_plot.add_curve(boundary, "W/S limit"); + } ca_plot.add_curve({ min_finder.design_wing_loading * 9.81 }, { min_finder.design_thrust_to_weight }, "Design Point"); ca_plot.save_figure(plot_dir_string + "/constraint_plot.svg"); }; } + +void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattingly::constraint_analysis& constraint_analysis_tool, readMission& mission_data, Engine& engine) +{ + auto calculate_thrust_lapse = [&constraint_analysis_tool, &engine](double M, double altitude) { + const double thrust_lapse = engine.get_thrust_lapse("cruise", constraint_analysis_tool.atm, M, altitude); + return thrust_lapse; + }; + + auto get_num_engines = [&]() { + double num_engines = 0; + + // Get the node vector for all defined propulsion systems + auto propulsors = this->aircraft_xml()->getVector( + "aircraft_exchange_file/requirements_and_specifications/design_specification/propulsion/propulsor"); + + // Increment num_engines for each propulsor + for (const auto& propulsor : propulsors) { + num_engines += 1; + } + return num_engines; + }; + + auto std_constraints = this->configuration()->at( + "module_configuration_file/program_settings/constraint_selection/standard_set").getChildren(); + + for (auto constraint : std_constraints) + { + std::string activated = constraint->at("active/value"); + if (activated == "true") + { + double CD = 0.0; + double CL = 0.0; + std::vector<double> CD_vector = {}; + std::vector<double> CL_vector = {}; + + if (constraint->name == "takeoff_ground_roll") + { + double CL_max_TO = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxT-O/value"); + double s_G_TO = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); + double M = constraint->at("Mach_TO/value"); + double thrust_lapse = calculate_thrust_lapse(M, 0.0); + double weight_fraction = mission_data.get_beta(" takeoff", 1.0); //from mission analysis + const auto constraint_vector = constraint_analysis_tool.takeoff_ground_roll( + W_over_S_data, + weight_fraction, + thrust_lapse, + M, + 0.0, + s_G_TO, + CL_max_TO); + Constraint Case(W_over_S_data, constraint_vector, constraint->name); + this->constraint_list.push_back(Case); + } + else if (constraint->name == "takeoff_climb") + { + double M = constraint->at("Mach_TO/value"); + double takeoff_climb_angle = constraint->at("takeoff_climb_angle/value"); + double thrust_lapse = calculate_thrust_lapse(M, 0.0); + double weight_fraction = mission_data.get_beta(" takeoff", 1.0); //from mission analysis + double CL_max_TO = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxT-O/value"); + readPolar takeoff_config(this->polar(), "takeoff", "linear", M); + CD = takeoff_config.interpCD(CL_max_TO); + for (int i = 0; i < W_over_S_data.size(); ++i) { + CD_vector.push_back(CD); + }; + const auto constraint_vector = constraint_analysis_tool.takeoff_climb_angle( + W_over_S_data, + CD_vector, + weight_fraction, + thrust_lapse, + M, + 0.0, + CL_max_TO, + takeoff_climb_angle); + Constraint Case(W_over_S_data, constraint_vector, constraint->name); + this->constraint_list.push_back(Case); + } + else if (constraint->name == "OEI_climb") + { + /* OEI Climb */ + double climb_speed = this->aircraft_xml()->at( + "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/design_mission/climb_speed_schedule/climb_speed_below_FL100/value"); + double climb_gradient_OEI = constraint->at("climb_gradient_OEI/value"); + double M = climb_speed / constraint_analysis_tool.atm.getSpeedOfSound(0.0); + double weight_fraction = mission_data.get_beta(" takeoff"); //from mission analysis + double thrust_lapse = calculate_thrust_lapse(M, 0.0); + double num_engines = get_num_engines(); + + readPolar climb_config(this->polar(), "takeoff", "linear", M); + for (int i = 0; i < W_over_S_data.size(); ++i) { + CD = climb_config.getCD(W_over_S_data[i], 1.0, weight_fraction, (climb_speed / constraint_analysis_tool.atm.getSpeedOfSound(0.0)), 0.0); + CD_vector.push_back(CD); + }; + + double thrust_factor_OEI = thrust_lapse * ((num_engines - 1) / num_engines); + double climb_rate_OEI = climb_gradient_OEI * climb_speed; + /*minimal climb rate of 2.4% defined in CS25 for second segment climb*/ + const auto constraint_vector = constraint_analysis_tool.constant_speed_climb( + W_over_S_data, + CD_vector, + weight_fraction, + thrust_factor_OEI, + M, + 0.0, + climb_rate_OEI); /* DEFINE CLIMB RATE CONSTRAINT */ + Constraint Case(W_over_S_data, constraint_vector, constraint->name); + this->constraint_list.push_back(Case); + } + else if (constraint->name == "top_of_climb") + { + + } + else if (constraint->name == "cruise") + { + + } + else if (constraint->name == "SEP") + { + /* Service Ceiling */ + double altitude = this->aircraft_xml()->at( + "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_operating_altitude/value"); + double M = this->aircraft_xml()->at( + "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/study_mission/initial_cruise_mach_number/value"); + + double weight_fraction = mission_data.get_beta(" climb_to_cruise"); + readPolar clean_config_M_cruise(this->polar(), "clean", "linear", M); + double thrust_lapse = calculate_thrust_lapse(M, altitude); + CD_vector = {}; + CL_vector = {}; + + for (int i = 0; i < W_over_S_data.size(); ++i) { + CD = clean_config_M_cruise.getCD(W_over_S_data[i], 1.0, weight_fraction, M, altitude); + CD_vector.push_back(CD); + } + + double minimum_climb_rate = constraint->at("minimum_climb_rate/value"); + + /* Service ceiling with the minimum climb rate requirement */ + const auto constraint_vector = constraint_analysis_tool.constant_speed_climb( + W_over_S_data, + CD_vector, + weight_fraction, + thrust_lapse, + M, + altitude, + minimum_climb_rate); + Constraint Case(W_over_S_data, constraint_vector, constraint->name); + this->constraint_list.push_back(Case); + } + else if (constraint->name == "approach_speed") + { + + } + else if (constraint->name == "landing_field_length") + { + /* Landing */ + double M = constraint->at("Mach/value"); + double thrust_lapse = calculate_thrust_lapse(M, 0.0); + double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); + double my_B = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/additional_requirements/landing_gear/braking_coefficient/value"); + double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); + readPolar landing_config(this->polar(), "landing", "linear", M); + double CD_max_L = landing_config.interpCD(CL_max_L); + double max_landing_weight = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_landing_mass/mass_properties/mass/value"); + double MTOM = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_takeoff_mass/mass_properties/mass/value"); + double weight_fraction = max_landing_weight / MTOM; + const auto constraint_border = constraint_analysis_tool.braking_roll(CD_max_L, CL_max_L, weight_fraction, thrust_lapse, M, 0.0, my_B, s_G_L); + this->boundaries.push_back(constraint_border); + } + else if (constraint->name == "gust") + { + /* Gust */ + double M = constraint->at("Mach/value"); + readPolar landing_config(this->polar(), "landing", "linear", M); + double weight_fraction = mission_data.get_beta(" takeoff", 1.0); //from mission analysis + double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); + double AoA_1 = landing_config.interpalpha(CL_max_L); + double AoA_2 = landing_config.interpalpha(CL_max_L - CL_max_L * 0.9); + double CL_alpha = (CL_max_L - (CL_max_L - CL_max_L * 0.9)) / ((AoA_1 - AoA_2) * PI / 180.0); + double V_TO_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_approach_speed/value"); + double w_g = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_speed/value"); + double dn_G = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_load_factor/value"); + const auto constraint_border = constraint_analysis_tool.gust(CL_alpha, 0.0, V_TO_L, w_g, dn_G, weight_fraction); + this->boundaries.push_back(constraint_border); + } + } + }; +}; \ No newline at end of file diff --git a/constraint_analysis/src/energy_based/energy_based_refactored.cpp b/constraint_analysis/src/energy_based/energy_based_refactored.cpp deleted file mode 100644 index 4b4d16b6..00000000 --- a/constraint_analysis/src/energy_based/energy_based_refactored.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * UNICADO - UNIversity Conceptual Aircraft Design and Optimization - * - * Copyright (C) 2024 UNICADO consortium - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * Description: - * This file is part of UNICADO. - */ - -#include "energy_based.h" -#include <algorithm> -#include <filesystem> -#include <format> -#include <list> -#include <ranges> -#include <cmath> -#include <vector> -#include <numbers> -#include <iostream> -#include <string> -#include <moduleBasics/module.h> -#include <engine/engine.h> -#include "../../include/constraint_analysis/ca_functions.h" -#include "../../include/constraint_analysis/ca_parser.h" -#include "../constraint_analysis.h" -#include "../../include/constraint_analysis/ca_plotting.h" -#include "../io/aircraft_xml.h" -#include "../../include/constraint_analysis/ca_minfinder.h" - - -void EnergyBased::initialize() -{ - if (!this->aircraft_xml()) { - throw std::runtime_error("[EnergyBased::initialize()] aircraft_xml is null!"); - }; - if (!this->configuration()) { - throw std::runtime_error("[EnergyBased::initialize()] config_xml is null!"); - }; - if (!this->polar()) { - throw std::runtime_error("[EnergyBased::initialize()] polar_xml is null!"); - }; -} - -void EnergyBased::operator()() -{ - - const std::string mode_selection(this->configuration()->at("module_configuration_file/program_settings/mode_selection/value")); - - int WS_start = 0; - int WS_end = 0; - size_t WS_size = 1; - - if (mode_selection == "mode_0") - { - /*Define relevant Wing_loading range. Selected values should be valid for all possible configurations*/ - WS_start = 50; - WS_end = 820; - WS_size = WS_end - WS_start + 1; // Range from 50 to 820, inclusive - } - else if (mode_selection == "mode_1") - { - WS_start = this->aircraft_xml()->at("aircraft_exchange_file/sizing_point/wing_loading/value"); - WS_size = 1; // Constant W/S - } - - std::vector<double> W_over_S_data(WS_size); - - /*Transform from kg/m^2 into N/m^2*/ - for (int i = 0; i < WS_size; ++i) { - W_over_S_data[i] = (WS_start + i) * 9.81; - } - - Engine engine = Engine(this->engine_directory()); - - Mattingly::constraint_analysis constraint_analysis_tool; - - atmosphere atm; - - // Set atmosphere according to the delta ISA requirement for the sizing process - double temperature_ISA = ISA_TEMPERATURE + this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/design_mission/delta_ISA/value"); - atm.setAtmosphere(0.0, temperature_ISA, ISA_PRESSURE); - - constraint_analysis_tool.atm = atm; - - std::filesystem::path missionCSV = this->mission_directory(); - - for (const auto& entry : fs::directory_iterator(this->mission_directory())) { - std::string filename = entry.path().filename().string(); - - if (filename.find("design_mission") != std::string::npos && filename.find("_out.csv") != std::string::npos) { - missionCSV /= filename; - break; - } - } - - Mattingly::constraint_analysis constraint_analysis_plotting = constraint_analysis_tool; - - readMission mission_data(missionCSV); - - assess_constraints(W_over_S_data, constraint_analysis_tool, mission_data, engine); - - /* Define Simple_Analysis*/ - Simple_Analysis min_finder = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->boundaries); - - /* Find dominant curve of the design chart*/ - min_finder.find_dominant_curve(); - - double safety_factor = this->configuration()->at("module_configuration_file/program_settings/safety_factor/value"); - - const double buffer_factor(this->configuration()->at("module_configuration_file/program_settings/buffer_factor/value")); - - /*Get the previous design point*/ - double previous_WS = this->aircraft_xml()->at("aircraft_exchange_file/sizing_point/wing_loading/value"); - double previous_TW = this->aircraft_xml()->at("aircraft_exchange_file/sizing_point/thrust_to_weight/value"); - - /*Find design point with safety factor*/ - min_finder.find_converged_design_point(previous_TW, previous_WS * 9.81, safety_factor, buffer_factor); - - /*Update design point in ACxml*/ - min_finder.update_design_point(); - - std::string plot_dir_string = this->plot_dir().string(); - - // Add output of design point in logfile - - myRuntimeInfo->out << "New wing loading: " << min_finder.design_wing_loading * 9.81 << " N/m^2. New thrust to weight ratio: " << min_finder.design_thrust_to_weight << std::endl; - - min_finder.write_design_point(plot_dir_string + "/csv_files/design_point.csv"); - - /* Plot the complete design chart with constraints, boundaries and design point*/ - std::string plotting = this->configuration()->at("module_configuration_file/control_settings/plot_output/enable/value"); - if (plotting == "true") { - - WS_start = 50; - for (int i = 0; i < WS_size; ++i) { - W_over_S_data[i] = (WS_start + i) * 9.81; - } - - this->constraint_list = {}; - this->boundaries = {}; - - assess_constraints(W_over_S_data, constraint_analysis_plotting, mission_data, engine); - - Simple_Analysis min_finder_2 = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->boundaries); - - min_finder_2.find_dominant_curve(); - - ConstraintAnalysis_Plot ca_plot; - - ca_plot.fill_infeasible_area(W_over_S_data, min_finder_2.dominant_thrust_to_weight, boundaries); - - for (auto ca_case : this->constraint_list) - { - ca_plot.add_curve(ca_case.wing_loading, ca_case.thrust_to_weight, ca_case.constraint_case); - } - for (auto boundary : this->boundaries) - { - ca_plot.add_curve(boundary, "W/S limit"); - } - ca_plot.add_curve({ min_finder.design_wing_loading * 9.81 }, { min_finder.design_thrust_to_weight }, "Design Point"); - - ca_plot.save_figure(plot_dir_string + "/constraint_plot.svg"); - }; -} - -void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattingly::constraint_analysis& constraint_analysis_tool, readMission& mission_data, Engine& engine) -{ - auto calculate_thrust_lapse = [&constraint_analysis_tool, &engine](double M, double altitude) { - const double thrust_lapse = engine.get_thrust_lapse("cruise", constraint_analysis_tool.atm, M, altitude); - return thrust_lapse; - }; - - auto get_num_engines = [&]() { - double num_engines = 0; - - // Get the node vector for all defined propulsion systems - auto propulsors = this->aircraft_xml()->getVector( - "aircraft_exchange_file/requirements_and_specifications/design_specification/propulsion/propulsor"); - - // Increment num_engines for each propulsor - for (const auto& propulsor : propulsors) { - num_engines += 1; - } - return num_engines; - }; - - auto std_constraints = this->configuration()->at( - "module_configuration_file/program_settings/constraint_selection/standard_set").getChildren(); - - for (auto constraint : std_constraints) - { - std::string activated = constraint->at("active/value"); - if (activated == "true") - { - double CD = 0.0; - double CL = 0.0; - std::vector<double> CD_vector = {}; - std::vector<double> CL_vector = {}; - - if (constraint->name == "takeoff_ground_roll") - { - double CL_max_TO = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxT-O/value"); - double s_G_TO = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); - double M = constraint->at("Mach_TO/value"); - double thrust_lapse = calculate_thrust_lapse(M, 0.0); - double weight_fraction = mission_data.get_beta(" takeoff", 1.0); //from mission analysis - const auto constraint_vector = constraint_analysis_tool.takeoff_ground_roll( - W_over_S_data, - weight_fraction, - thrust_lapse, - M, - 0.0, - s_G_TO, - CL_max_TO); - Constraint Case(W_over_S_data, constraint_vector, constraint->name); - this->constraint_list.push_back(Case); - } - else if (constraint->name == "takeoff_climb") - { - double M = constraint->at("Mach_TO/value"); - double takeoff_climb_angle = constraint->at("takeoff_climb_angle/value"); - double thrust_lapse = calculate_thrust_lapse(M, 0.0); - double weight_fraction = mission_data.get_beta(" takeoff", 1.0); //from mission analysis - double CL_max_TO = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxT-O/value"); - readPolar takeoff_config(this->polar(), "takeoff", "linear", M); - CD = takeoff_config.interpCD(CL_max_TO); - for (int i = 0; i < W_over_S_data.size(); ++i) { - CD_vector.push_back(CD); - }; - const auto constraint_vector = constraint_analysis_tool.takeoff_climb_angle( - W_over_S_data, - CD_vector, - weight_fraction, - thrust_lapse, - M, - 0.0, - CL_max_TO, - takeoff_climb_angle); - Constraint Case(W_over_S_data, constraint_vector, constraint->name); - this->constraint_list.push_back(Case); - } - else if (constraint->name == "OEI_climb") - { - /* OEI Climb */ - double climb_speed = this->aircraft_xml()->at( - "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/design_mission/climb_speed_schedule/climb_speed_below_FL100/value"); - double climb_gradient_OEI = constraint->at("climb_gradient_OEI/value"); - double M = climb_speed / constraint_analysis_tool.atm.getSpeedOfSound(0.0); - double weight_fraction = mission_data.get_beta(" takeoff"); //from mission analysis - double thrust_lapse = calculate_thrust_lapse(M, 0.0); - double num_engines = get_num_engines(); - - readPolar climb_config(this->polar(), "takeoff", "linear", M); - for (int i = 0; i < W_over_S_data.size(); ++i) { - CD = climb_config.getCD(W_over_S_data[i], 1.0, weight_fraction, (climb_speed / constraint_analysis_tool.atm.getSpeedOfSound(0.0)), 0.0); - CD_vector.push_back(CD); - }; - - double thrust_factor_OEI = thrust_lapse * ((num_engines - 1) / num_engines); - double climb_rate_OEI = climb_gradient_OEI * climb_speed; - /*minimal climb rate of 2.4% defined in CS25 for second segment climb*/ - const auto constraint_vector = constraint_analysis_tool.constant_speed_climb( - W_over_S_data, - CD_vector, - weight_fraction, - thrust_factor_OEI, - M, - 0.0, - climb_rate_OEI); /* DEFINE CLIMB RATE CONSTRAINT */ - Constraint Case(W_over_S_data, constraint_vector, constraint->name); - this->constraint_list.push_back(Case); - } - else if (constraint->name == "top_of_climb") - { - - } - else if (constraint->name == "cruise") - { - - } - else if (constraint->name == "SEP") - { - /* Service Ceiling */ - double altitude = this->aircraft_xml()->at( - "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_operating_altitude/value"); - double M = this->aircraft_xml()->at( - "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/study_mission/initial_cruise_mach_number/value"); - - double weight_fraction = mission_data.get_beta(" climb_to_cruise"); - readPolar clean_config_M_cruise(this->polar(), "clean", "linear", M); - double thrust_lapse = calculate_thrust_lapse(M, altitude); - CD_vector = {}; - CL_vector = {}; - - for (int i = 0; i < W_over_S_data.size(); ++i) { - CD = clean_config_M_cruise.getCD(W_over_S_data[i], 1.0, weight_fraction, M, altitude); - CD_vector.push_back(CD); - } - - double minimum_climb_rate = constraint->at("minimum_climb_rate/value"); - - /* Service ceiling with the minimum climb rate requirement */ - const auto constraint_vector = constraint_analysis_tool.constant_speed_climb( - W_over_S_data, - CD_vector, - weight_fraction, - thrust_lapse, - M, - altitude, - minimum_climb_rate); - Constraint Case(W_over_S_data, constraint_vector, constraint->name); - this->constraint_list.push_back(Case); - } - else if (constraint->name == "approach_speed") - { - - } - else if (constraint->name == "landing_field_length") - { - /* Landing */ - double M = constraint->at("Mach/value"); - double thrust_lapse = calculate_thrust_lapse(M, 0.0); - double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); - double my_B = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/additional_requirements/landing_gear/braking_coefficient/value"); - double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); - readPolar landing_config(this->polar(), "landing", "linear", M); - double CD_max_L = landing_config.interpCD(CL_max_L); - double max_landing_weight = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_landing_mass/mass_properties/mass/value"); - double MTOM = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_takeoff_mass/mass_properties/mass/value"); - double weight_fraction = max_landing_weight / MTOM; - const auto constraint_border = constraint_analysis_tool.braking_roll(CD_max_L, CL_max_L, weight_fraction, thrust_lapse, M, 0.0, my_B, s_G_L); - this->boundaries.push_back(constraint_border); - } - else if (constraint->name == "gust") - { - /* Gust */ - double M = constraint->at("Mach/value"); - readPolar landing_config(this->polar(), "landing", "linear", M); - double weight_fraction = mission_data.get_beta(" takeoff", 1.0); //from mission analysis - double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); - double AoA_1 = landing_config.interpalpha(CL_max_L); - double AoA_2 = landing_config.interpalpha(CL_max_L - CL_max_L * 0.9); - double CL_alpha = (CL_max_L - (CL_max_L - CL_max_L * 0.9)) / ((AoA_1 - AoA_2) * PI / 180.0); - double V_TO_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_approach_speed/value"); - double w_g = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_speed/value"); - double dn_G = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_load_factor/value"); - const auto constraint_border = constraint_analysis_tool.gust(CL_alpha, 0.0, V_TO_L, w_g, dn_G, weight_fraction); - this->boundaries.push_back(constraint_border); - } - } - }; -}; \ No newline at end of file -- GitLab From f79aaaf41b4c6e96afe5947dfb81cdd1b385238b Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Mon, 24 Feb 2025 11:14:08 +0100 Subject: [PATCH 04/10] plotting should be fixed --- constraint_analysis/src/energy_based/energy_based.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index 9a3ea3d7..f82e6b59 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -145,6 +145,11 @@ void EnergyBased::operator()() if (plotting == "true") { WS_start = 50; + WS_end = 820; + WS_size = WS_end - WS_start + 1; // Range from 50 to 820, inclusive + + std::vector<double> W_over_S_data(WS_size); + for (int i = 0; i < WS_size; ++i) { W_over_S_data[i] = (WS_start + i) * 9.81; } -- GitLab From a7758272d1be6f3a598a4a81491cc39181b4bb2a Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Mon, 24 Feb 2025 15:30:07 +0100 Subject: [PATCH 05/10] bug-fixes to solve issues caused by disabling the gust and field length constraints --- .../constraint_analysis/ca_minfinder.h | 60 +++++++++++-------- .../src/energy_based/energy_based.cpp | 18 ++++-- .../src/energy_based/energy_based.h | 3 +- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/constraint_analysis/include/constraint_analysis/ca_minfinder.h b/constraint_analysis/include/constraint_analysis/ca_minfinder.h index 67412817..ea0e3777 100644 --- a/constraint_analysis/include/constraint_analysis/ca_minfinder.h +++ b/constraint_analysis/include/constraint_analysis/ca_minfinder.h @@ -58,24 +58,27 @@ class Simple_Analysis : Analysis { public: std::vector<double> dominant_thrust_to_weight = {}; - std::vector<double> wing_loading_boundaries = {}; + double lower_wing_loading_boundary = {}; + double upper_wing_loading_boundary = {}; std::vector<double> wing_loading_vec = {}; double design_thrust_to_weight = 1000.0; double design_wing_loading = 0.0; - Simple_Analysis(std::vector<Constraint> constraint_list, std::vector<double> boundaries) : Analysis(constraint_list) + Simple_Analysis(std::vector<Constraint> constraint_list, std::vector<double> lower_boundaries, std::vector<double> upper_boundaries) : Analysis(constraint_list) { dominant_thrust_to_weight = constraint_list[0].thrust_to_weight; wing_loading_vec = constraint_list[0].wing_loading; - wing_loading_boundaries = boundaries; + lower_wing_loading_boundary = *std::max_element(lower_boundaries.begin(), lower_boundaries.end()); + upper_wing_loading_boundary = *std::min_element(upper_boundaries.begin(), upper_boundaries.end()); }; - Simple_Analysis(std::vector<Constraint> constraint_list, std::shared_ptr<node> acXML, std::vector<double> boundaries) : + Simple_Analysis(std::vector<Constraint> constraint_list, std::shared_ptr<node> acXML, std::vector<double> lower_boundaries, std::vector<double> upper_boundaries) : Analysis(constraint_list, acXML) { dominant_thrust_to_weight = constraint_list[0].thrust_to_weight; wing_loading_vec = constraint_list[0].wing_loading; - wing_loading_boundaries = boundaries; + lower_wing_loading_boundary = *std::max_element(lower_boundaries.begin(), lower_boundaries.end()); + upper_wing_loading_boundary = *std::min_element(upper_boundaries.begin(), upper_boundaries.end()); }; void find_dominant_curve() { @@ -90,7 +93,7 @@ public: void find_design_point(const double& safety_factor) { - std::sort(wing_loading_boundaries.begin(), wing_loading_boundaries.end()); + std::vector<double> wing_loading_boundaries = { lower_wing_loading_boundary, upper_wing_loading_boundary }; std::vector<double> xlims = {}; for (auto x_limit : wing_loading_boundaries) { auto it = std::distance(wing_loading_vec.begin(), std::lower_bound(wing_loading_vec.begin(), wing_loading_vec.end(), x_limit)); @@ -112,29 +115,38 @@ public: void find_converged_design_point(const double& previous_TW, const double& previous_WS, const double& safety_factor, const double& buffer_factor) { - std::sort(wing_loading_boundaries.begin(), wing_loading_boundaries.end()); - std::vector<double> xlims = {}; - for (auto x_limit : wing_loading_boundaries) { - auto it = std::distance(wing_loading_vec.begin(), std::lower_bound(wing_loading_vec.begin(), wing_loading_vec.end(), x_limit)); - xlims.push_back(it); + std::vector<double> wing_loading_boundaries = { lower_wing_loading_boundary, upper_wing_loading_boundary }; + if (upper_wing_loading_boundary < lower_wing_loading_boundary) + { + design_thrust_to_weight = previous_TW; + design_wing_loading = previous_WS; + std::cout << "infeasable design space, loadings are not adjusted" << std::endl; } - std::vector<double> limited_TW(dominant_thrust_to_weight.begin() + xlims[0], dominant_thrust_to_weight.begin() + xlims[1]); - int i = xlims[0]; - for (double point : limited_TW) + else { - if (point <= design_thrust_to_weight) + std::vector<double> xlims = {}; + for (auto x_limit : wing_loading_boundaries) { + auto it = std::distance(wing_loading_vec.begin(), std::lower_bound(wing_loading_vec.begin(), wing_loading_vec.end(), x_limit)); + xlims.push_back(it); + } + std::vector<double> limited_TW(dominant_thrust_to_weight.begin() + xlims[0], dominant_thrust_to_weight.begin() + xlims[1]); + int i = xlims[0]; + for (double point : limited_TW) { - design_thrust_to_weight = point; - design_wing_loading = wing_loading_vec[i]; + if (point <= design_thrust_to_weight) + { + design_thrust_to_weight = point; + design_wing_loading = wing_loading_vec[i]; + } + i++; } - i++; - } - design_thrust_to_weight = design_thrust_to_weight * (1.0 + safety_factor); + design_thrust_to_weight = design_thrust_to_weight * (1.0 + safety_factor); - double relative_change_TW = sqrt(pow(1 - previous_TW / design_thrust_to_weight, 2)); - if (relative_change_TW <= buffer_factor/100.0) { design_thrust_to_weight = previous_TW; }; - double relative_change_WS = sqrt(pow(1 - previous_WS / design_wing_loading, 2)); - if (relative_change_WS <= buffer_factor/100.0) { design_wing_loading = previous_WS; }; + double relative_change_TW = sqrt(pow(1 - previous_TW / design_thrust_to_weight, 2)); + if (relative_change_TW <= buffer_factor / 100.0) { design_thrust_to_weight = previous_TW; }; + double relative_change_WS = sqrt(pow(1 - previous_WS / design_wing_loading, 2)); + if (relative_change_WS <= buffer_factor / 100.0) { design_wing_loading = previous_WS; }; + }; }; template<typename T> diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index f82e6b59..a72b0a5a 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -83,6 +83,9 @@ void EnergyBased::operator()() W_over_S_data[i] = (WS_start + i) * 9.81; } + this->lower_boundaries.push_back(50.0 * 9.81); + this->upper_boundaries.push_back(820.0 * 9.81); + Engine engine = Engine(this->engine_directory()); Mattingly::constraint_analysis constraint_analysis_tool; @@ -113,7 +116,7 @@ void EnergyBased::operator()() assess_constraints(W_over_S_data, constraint_analysis_tool, mission_data, engine); /* Define Simple_Analysis*/ - Simple_Analysis min_finder = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->boundaries); + Simple_Analysis min_finder = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->lower_boundaries, this->upper_boundaries); /* Find dominant curve of the design chart*/ min_finder.find_dominant_curve(); @@ -155,23 +158,26 @@ void EnergyBased::operator()() } this->constraint_list = {}; - this->boundaries = {}; + this->lower_boundaries = { 50. * 9.81 }; + this->upper_boundaries = { 820. * 9.81 }; assess_constraints(W_over_S_data, constraint_analysis_plotting, mission_data, engine); - Simple_Analysis min_finder_2 = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->boundaries); + Simple_Analysis min_finder_2 = Simple_Analysis(this->constraint_list, this->aircraft_xml(), this->lower_boundaries, this->upper_boundaries); min_finder_2.find_dominant_curve(); ConstraintAnalysis_Plot ca_plot; + std::vector<double> boundaries = { min_finder_2.lower_wing_loading_boundary , min_finder_2.upper_wing_loading_boundary }; + ca_plot.fill_infeasible_area(W_over_S_data, min_finder_2.dominant_thrust_to_weight, boundaries); for (auto ca_case : this->constraint_list) { ca_plot.add_curve(ca_case.wing_loading, ca_case.thrust_to_weight, ca_case.constraint_case); } - for (auto boundary : this->boundaries) + for (auto boundary : boundaries) { ca_plot.add_curve(boundary, "W/S limit"); } @@ -347,7 +353,7 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin double MTOM = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_takeoff_mass/mass_properties/mass/value"); double weight_fraction = max_landing_weight / MTOM; const auto constraint_border = constraint_analysis_tool.braking_roll(CD_max_L, CL_max_L, weight_fraction, thrust_lapse, M, 0.0, my_B, s_G_L); - this->boundaries.push_back(constraint_border); + this->upper_boundaries.push_back(constraint_border); } else if (constraint->name == "gust") { @@ -363,7 +369,7 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin double w_g = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_speed/value"); double dn_G = this->configuration()->at("module_configuration_file/program_settings/constraint_selection/standard_set/gust/gust_load_factor/value"); const auto constraint_border = constraint_analysis_tool.gust(CL_alpha, 0.0, V_TO_L, w_g, dn_G, weight_fraction); - this->boundaries.push_back(constraint_border); + this->lower_boundaries.push_back(constraint_border); } } }; diff --git a/constraint_analysis/src/energy_based/energy_based.h b/constraint_analysis/src/energy_based/energy_based.h index b8c56b24..3e48c381 100644 --- a/constraint_analysis/src/energy_based/energy_based.h +++ b/constraint_analysis/src/energy_based/energy_based.h @@ -70,7 +70,8 @@ public: void assess_constraints(std::vector<double>& W_over_S_data, Mattingly::constraint_analysis& constraint_analysis_tool, readMission& mission_data, Engine& engine); std::vector<Constraint> constraint_list = {}; - std::vector<double> boundaries = {}; + std::vector<double> lower_boundaries = {}; + std::vector<double> upper_boundaries = {}; }; // namespace design #endif // SRC_CONSTRAINT_ANALYSIS_ENERGY_BASED_H_ \ No newline at end of file -- GitLab From 814b1d846ee9985e227b5cccda819f40b77f0f8f Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Thu, 27 Feb 2025 08:01:01 +0100 Subject: [PATCH 06/10] approach speed constraint added - will be improved --- .../constraint_analysis_conf.xml | 16 ++++++++++++-- .../constraint_analysis/ca_functions.h | 1 + constraint_analysis/src/ca_functions.cpp | 22 +++++++++++++++++++ .../src/energy_based/energy_based.cpp | 17 +++++++++++++- 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/constraint_analysis/constraint_analysis_conf.xml b/constraint_analysis/constraint_analysis_conf.xml index b48efabd..24d27639 100644 --- a/constraint_analysis/constraint_analysis_conf.xml +++ b/constraint_analysis/constraint_analysis_conf.xml @@ -5,7 +5,7 @@ <value>CSMR-2020.xml</value> </aircraft_exchange_file_name> <aircraft_exchange_file_directory description="Specify the direction in which the aircraft exchange file can be found"> - <value>../projects/CSMR/CSMR-2020/</value> + <value>../projects/</value> </aircraft_exchange_file_directory> <own_tool_level description="Specify the tool level of this tool"> <value>3</value> @@ -54,7 +54,7 @@ <value>Energy_Based</value> </method> <mode_selection description="The method of sizign, mode_0 changes both T/W and W/S, mode_1 changes only the T/W"> - <value>mode_0</value> + <value>mode_1</value> </mode_selection> <buffer_factor description="The buffer in percentage, if the rate of change of the design point parameters is less than this percentage, it remains constant"> <value>0.0</value> @@ -113,6 +113,18 @@ <active> <value>true</value> </active> + <Mach> + <value>0.2</value> + </Mach> + <free_roll_time> + <value>5.0</value> + </free_roll_time> + <k_TD> + <value>1.15</value> + </k_TD> + <obstacle_height> + <value>10</value> + </obstacle_height> </approach_speed> <landing_field_length> <active> diff --git a/constraint_analysis/include/constraint_analysis/ca_functions.h b/constraint_analysis/include/constraint_analysis/ca_functions.h index a5126853..3c1e611c 100644 --- a/constraint_analysis/include/constraint_analysis/ca_functions.h +++ b/constraint_analysis/include/constraint_analysis/ca_functions.h @@ -184,6 +184,7 @@ namespace Mattingly { */ auto min_speed(double CL_max, double altitude, double Mach, double weight_fraction) -> const double; + auto constraint_analysis::approach_speed(double V_app, double CL_max, double weight_fraction, double s_A, double C_D, double h_obs, double k_TD, double altitude) -> const double; private: // Membervariables diff --git a/constraint_analysis/src/ca_functions.cpp b/constraint_analysis/src/ca_functions.cpp index 738e8186..43496ff3 100644 --- a/constraint_analysis/src/ca_functions.cpp +++ b/constraint_analysis/src/ca_functions.cpp @@ -195,5 +195,27 @@ namespace Mattingly { return W_over_S; } + auto constraint_analysis::approach_speed(double V_app, double CL_max, double weight_fraction, double s_A, double C_D, double h_obs, double k_TD, double altitude) -> const double { + + double W_over_S; + + double V_stall = 0.0; + + // this is a 4th order polynomial with coefficients (a*x^4 + b*x^3 + c*x^2 + d*x + e = 0) + double a = -k_TD * CL_max; + double b = 0.; + double c = pow(V_app, 2.) * CL_max + 2. * h_obs * CL_max - s_A * k_TD; + double d = 0.; + double e = -s_A * V_app; + + double del = pow(c, 2.) - 4. * a * e; + + V_stall = std::sqrt((-c + sqrt(del)) / (2. * a)); + V_stall = std::sqrt((-c - sqrt(del)) / (2. * a)); + + + return pow(V_stall,2.)/(2.*weight_fraction/(atm.getDensity(altitude)*CL_max)); + } + } diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index a72b0a5a..671ebf37 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -337,7 +337,22 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin } else if (constraint->name == "approach_speed") { - + double t_FR = constraint->at("free_roll_time/value"); + double k_TD = constraint->at("k_TD/value"); + double h_obs = constraint->at("obstacle_height/value"); + double M = constraint->at("Mach/value"); + double V_app = this->aircraft_xml()->at( + "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_approach_speed/value"); + double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); + double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); + double s_A = s_G_L * 0.4; // find a way to get the touchdown speed + readPolar landing_config(this->polar(), "landing", "linear", M); + double CD_max_L = landing_config.interpCD(CL_max_L); + double max_landing_weight = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_landing_mass/mass_properties/mass/value"); + double MTOM = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_takeoff_mass/mass_properties/mass/value"); + double weight_fraction = max_landing_weight / MTOM; + const auto approach = constraint_analysis_tool.approach_speed(V_app, CL_max_L, weight_fraction, s_A, CD_max_L, h_obs, k_TD, 0.0); + this->upper_boundaries.push_back(approach); } else if (constraint->name == "landing_field_length") { -- GitLab From 45fd8d1b26ba25ba1f901b8f29c9bb4ca5b2b5e4 Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Thu, 27 Feb 2025 08:06:11 +0100 Subject: [PATCH 07/10] landing field length adjustment --- constraint_analysis/src/energy_based/energy_based.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index 671ebf37..1e261450 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -344,7 +344,7 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin double V_app = this->aircraft_xml()->at( "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_approach_speed/value"); double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); - double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); + double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/landing_field_length/value"); double s_A = s_G_L * 0.4; // find a way to get the touchdown speed readPolar landing_config(this->polar(), "landing", "linear", M); double CD_max_L = landing_config.interpCD(CL_max_L); @@ -361,7 +361,7 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin double thrust_lapse = calculate_thrust_lapse(M, 0.0); double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); double my_B = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/additional_requirements/landing_gear/braking_coefficient/value"); - double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/takeoff_distance/value"); + double s_G_L = 0.6*this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/landing_field_length/value"); readPolar landing_config(this->polar(), "landing", "linear", M); double CD_max_L = landing_config.interpCD(CL_max_L); double max_landing_weight = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_landing_mass/mass_properties/mass/value"); -- GitLab From b5d5e95ffd58371d989528bf4f215d69c41d84aa Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Thu, 27 Feb 2025 08:10:46 +0100 Subject: [PATCH 08/10] small fix --- constraint_analysis/src/ca_functions.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/constraint_analysis/src/ca_functions.cpp b/constraint_analysis/src/ca_functions.cpp index 43496ff3..8d6e6230 100644 --- a/constraint_analysis/src/ca_functions.cpp +++ b/constraint_analysis/src/ca_functions.cpp @@ -210,9 +210,7 @@ namespace Mattingly { double del = pow(c, 2.) - 4. * a * e; - V_stall = std::sqrt((-c + sqrt(del)) / (2. * a)); - V_stall = std::sqrt((-c - sqrt(del)) / (2. * a)); - + V_stall = std::max(std::sqrt((-c + sqrt(del)) / (2. * a)), std::sqrt((-c - sqrt(del)) / (2. * a))); return pow(V_stall,2.)/(2.*weight_fraction/(atm.getDensity(altitude)*CL_max)); } -- GitLab From 2c3b72f7a1c0c498e6dfa2a90634eebec90cdd4d Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Thu, 27 Feb 2025 10:04:22 +0100 Subject: [PATCH 09/10] fix --- .../constraint_analysis_conf.xml | 16 ++++------------ constraint_analysis/src/ca_functions.cpp | 6 ++---- .../src/energy_based/energy_based.cpp | 19 +++---------------- 3 files changed, 9 insertions(+), 32 deletions(-) diff --git a/constraint_analysis/constraint_analysis_conf.xml b/constraint_analysis/constraint_analysis_conf.xml index 24d27639..87827f45 100644 --- a/constraint_analysis/constraint_analysis_conf.xml +++ b/constraint_analysis/constraint_analysis_conf.xml @@ -54,7 +54,7 @@ <value>Energy_Based</value> </method> <mode_selection description="The method of sizign, mode_0 changes both T/W and W/S, mode_1 changes only the T/W"> - <value>mode_1</value> + <value>mode_0</value> </mode_selection> <buffer_factor description="The buffer in percentage, if the rate of change of the design point parameters is less than this percentage, it remains constant"> <value>0.0</value> @@ -109,27 +109,19 @@ <value>0.508</value> </minimum_climb_rate> </SEP> - <approach_speed> + <landing_field_length> <active> <value>true</value> </active> <Mach> <value>0.2</value> </Mach> - <free_roll_time> - <value>5.0</value> - </free_roll_time> <k_TD> - <value>1.15</value> + <value>1.10</value> </k_TD> <obstacle_height> - <value>10</value> + <value>15.4</value> </obstacle_height> - </approach_speed> - <landing_field_length> - <active> - <value>true</value> - </active> <Mach> <value>0.2</value> </Mach> diff --git a/constraint_analysis/src/ca_functions.cpp b/constraint_analysis/src/ca_functions.cpp index 8d6e6230..a4e9375f 100644 --- a/constraint_analysis/src/ca_functions.cpp +++ b/constraint_analysis/src/ca_functions.cpp @@ -195,10 +195,8 @@ namespace Mattingly { return W_over_S; } - auto constraint_analysis::approach_speed(double V_app, double CL_max, double weight_fraction, double s_A, double C_D, double h_obs, double k_TD, double altitude) -> const double { - - double W_over_S; - + auto constraint_analysis::approach_speed(double V_app, double CL_max, double weight_fraction, double s_A, double C_D, double h_obs, double k_TD, double altitude) -> const double + { double V_stall = 0.0; // this is a 4th order polynomial with coefficients (a*x^4 + b*x^3 + c*x^2 + d*x + e = 0) diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index 803ba58e..cbb35926 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -335,17 +335,15 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin Constraint Case(W_over_S_data, constraint_vector, constraint->name); this->constraint_list.push_back(Case); } - else if (constraint->name == "approach_speed") + else if (constraint->name == "landing_field_length") { - double t_FR = constraint->at("free_roll_time/value"); double k_TD = constraint->at("k_TD/value"); double h_obs = constraint->at("obstacle_height/value"); double M = constraint->at("Mach/value"); double V_app = this->aircraft_xml()->at( "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_approach_speed/value"); double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); - double s_G_L = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/landing_field_length/value"); - double s_A = s_G_L * 0.4; // find a way to get the touchdown speed + double s_A = h_obs / std::tan(3. * std::numbers::pi / 180.); readPolar landing_config(this->polar(), "landing", "linear", M); double CD_max_L = landing_config.interpCD(CL_max_L); double max_landing_weight = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_landing_mass/mass_properties/mass/value"); @@ -353,21 +351,10 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin double weight_fraction = max_landing_weight / MTOM; const auto approach = constraint_analysis_tool.approach_speed(V_app, CL_max_L, weight_fraction, s_A, CD_max_L, h_obs, k_TD, 0.0); this->upper_boundaries.push_back(approach); - } - else if (constraint->name == "landing_field_length") - { /* Landing */ - double M = constraint->at("Mach/value"); double thrust_lapse = calculate_thrust_lapse(M, 0.0); - double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); double my_B = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/additional_requirements/landing_gear/braking_coefficient/value"); - double s_G_L = 0.6 * this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/landing_field_length/value"); - // s_G_L as braking distance = 60% of landing field length - readPolar landing_config(this->polar(), "landing", "linear", M); - double CD_max_L = landing_config.interpCD(CL_max_L); - double max_landing_weight = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_landing_mass/mass_properties/mass/value"); - double MTOM = this->aircraft_xml()->at("aircraft_exchange_file/analysis/masses_cg_inertia/maximum_takeoff_mass/mass_properties/mass/value"); - double weight_fraction = max_landing_weight / MTOM; + double s_G_L = 0.6 * this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/landing_field_length/value") - s_A; const auto constraint_border = constraint_analysis_tool.braking_roll(CD_max_L, CL_max_L, weight_fraction, thrust_lapse, M, 0.0, my_B, s_G_L); this->upper_boundaries.push_back(constraint_border); } -- GitLab From 06ce5c2aa56a1c6ddf606a53f560042874905b3e Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Thu, 27 Feb 2025 12:21:58 +0100 Subject: [PATCH 10/10] free roll added --- .../constraint_analysis_conf.xml | 7 +++++-- .../include/constraint_analysis/ca_functions.h | 5 ++++- constraint_analysis/src/ca_functions.cpp | 18 ++++++++++++++++-- .../src/energy_based/energy_based.cpp | 6 +++++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/constraint_analysis/constraint_analysis_conf.xml b/constraint_analysis/constraint_analysis_conf.xml index 87827f45..5d913201 100644 --- a/constraint_analysis/constraint_analysis_conf.xml +++ b/constraint_analysis/constraint_analysis_conf.xml @@ -5,7 +5,7 @@ <value>CSMR-2020.xml</value> </aircraft_exchange_file_name> <aircraft_exchange_file_directory description="Specify the direction in which the aircraft exchange file can be found"> - <value>../projects/</value> + <value>../projects2/</value> </aircraft_exchange_file_directory> <own_tool_level description="Specify the tool level of this tool"> <value>3</value> @@ -117,8 +117,11 @@ <value>0.2</value> </Mach> <k_TD> - <value>1.10</value> + <value>1.15</value> </k_TD> + <t_FR> + <value>3</value> + </t_FR> <obstacle_height> <value>15.4</value> </obstacle_height> diff --git a/constraint_analysis/include/constraint_analysis/ca_functions.h b/constraint_analysis/include/constraint_analysis/ca_functions.h index 3c1e611c..0dab1748 100644 --- a/constraint_analysis/include/constraint_analysis/ca_functions.h +++ b/constraint_analysis/include/constraint_analysis/ca_functions.h @@ -184,7 +184,10 @@ namespace Mattingly { */ auto min_speed(double CL_max, double altitude, double Mach, double weight_fraction) -> const double; - auto constraint_analysis::approach_speed(double V_app, double CL_max, double weight_fraction, double s_A, double C_D, double h_obs, double k_TD, double altitude) -> const double; + auto approach_speed(double V_app, double CL_max, double weight_fraction, double s_A, double C_D, double h_obs, double k_TD, double altitude) -> const double; + + auto get_V_stall(double V_app, double k_TD, double CL_max, double CD, double h_obs, double s_A) -> const double; + private: // Membervariables diff --git a/constraint_analysis/src/ca_functions.cpp b/constraint_analysis/src/ca_functions.cpp index a4e9375f..f176ebd0 100644 --- a/constraint_analysis/src/ca_functions.cpp +++ b/constraint_analysis/src/ca_functions.cpp @@ -204,14 +204,28 @@ namespace Mattingly { double b = 0.; double c = pow(V_app, 2.) * CL_max + 2. * h_obs * CL_max - s_A * k_TD; double d = 0.; - double e = -s_A * V_app; + double e = -s_A * V_app * C_D; double del = pow(c, 2.) - 4. * a * e; V_stall = std::max(std::sqrt((-c + sqrt(del)) / (2. * a)), std::sqrt((-c - sqrt(del)) / (2. * a))); - + return pow(V_stall,2.)/(2.*weight_fraction/(atm.getDensity(altitude)*CL_max)); } + auto constraint_analysis::get_V_stall(double V_app, double k_TD, double CL_max, double CD, double h_obs, double s_A) -> const double + { + // this is a 4th order polynomial with coefficients (a*x^4 + b*x^3 + c*x^2 + d*x + e = 0) + double a = -k_TD * CL_max; + double b = 0.; + double c = pow(V_app, 2.) * CL_max + 2. * h_obs * CL_max - s_A * k_TD; + double d = 0.; + double e = -s_A * V_app * CD; + + double del = pow(c, 2.) - 4. * a * e; + + return std::max(std::sqrt((-c + sqrt(del)) / (2. * a)), std::sqrt((-c - sqrt(del)) / (2. * a))); + } + } diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index cbb35926..eb6c05e7 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -340,6 +340,7 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin double k_TD = constraint->at("k_TD/value"); double h_obs = constraint->at("obstacle_height/value"); double M = constraint->at("Mach/value"); + double t_FR = constraint->at("t_FR/value"); double V_app = this->aircraft_xml()->at( "aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/flight_envelope/maximum_approach_speed/value"); double CL_max_L = this->aircraft_xml()->at("aircraft_exchange_file/analysis/aerodynamics/lift_coefficients/C_LmaxLanding/value"); @@ -351,10 +352,13 @@ void EnergyBased::assess_constraints(std::vector<double>& W_over_S_data, Mattin double weight_fraction = max_landing_weight / MTOM; const auto approach = constraint_analysis_tool.approach_speed(V_app, CL_max_L, weight_fraction, s_A, CD_max_L, h_obs, k_TD, 0.0); this->upper_boundaries.push_back(approach); + double V_stall = constraint_analysis_tool.get_V_stall(V_app, k_TD, CL_max_L, CD_max_L, h_obs, s_A); + double s_FR = V_stall * k_TD * t_FR; + /* Landing */ double thrust_lapse = calculate_thrust_lapse(M, 0.0); double my_B = this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/additional_requirements/landing_gear/braking_coefficient/value"); - double s_G_L = 0.6 * this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/landing_field_length/value") - s_A; + double s_G_L = 0.6 * this->aircraft_xml()->at("aircraft_exchange_file/requirements_and_specifications/requirements/top_level_aircraft_requirements/landing_field_length/value") - s_A - s_FR; const auto constraint_border = constraint_analysis_tool.braking_roll(CD_max_L, CL_max_L, weight_fraction, thrust_lapse, M, 0.0, my_B, s_G_L); this->upper_boundaries.push_back(constraint_border); } -- GitLab