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 1/4] 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 2/4] 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 3/4] 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 4/4] 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