From f4357a5eab216c7badc3fdb60e353d12cd761a1b Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 13:45:45 +0100 Subject: [PATCH 1/8] Change copyright year --- constraint_analysis/include/constraint_analysis/ca_functions.h | 2 +- constraint_analysis/include/constraint_analysis/ca_minfinder.h | 2 +- constraint_analysis/include/constraint_analysis/ca_parser.h | 2 +- constraint_analysis/include/constraint_analysis/ca_plotting.h | 2 +- constraint_analysis/src/ca_functions.cpp | 2 +- constraint_analysis/src/ca_parser.cpp | 2 +- constraint_analysis/src/ca_strategy.h | 2 +- constraint_analysis/src/constraint_analysis.cpp | 2 +- constraint_analysis/src/constraint_analysis.h | 2 +- constraint_analysis/src/energy_based/energy_based.cpp | 2 +- constraint_analysis/src/energy_based/energy_based.h | 2 +- .../src/energy_based/energy_based_refactored.cpp | 2 +- constraint_analysis/src/main.cpp | 2 +- constraint_analysis/src/toolinfo.h | 2 +- constraint_analysis/test/test_analysis.cpp | 2 +- constraint_analysis/test/test_constraintAnalysis.cpp | 2 +- constraint_analysis/test/test_parser.cpp | 2 +- constraint_analysis/test/test_plotter.cpp | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/constraint_analysis/include/constraint_analysis/ca_functions.h b/constraint_analysis/include/constraint_analysis/ca_functions.h index 3681889f..a5126853 100644 --- a/constraint_analysis/include/constraint_analysis/ca_functions.h +++ b/constraint_analysis/include/constraint_analysis/ca_functions.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/include/constraint_analysis/ca_minfinder.h b/constraint_analysis/include/constraint_analysis/ca_minfinder.h index c4b3f8a2..67412817 100644 --- a/constraint_analysis/include/constraint_analysis/ca_minfinder.h +++ b/constraint_analysis/include/constraint_analysis/ca_minfinder.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/include/constraint_analysis/ca_parser.h b/constraint_analysis/include/constraint_analysis/ca_parser.h index 55574447..61d0d3c1 100644 --- a/constraint_analysis/include/constraint_analysis/ca_parser.h +++ b/constraint_analysis/include/constraint_analysis/ca_parser.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/include/constraint_analysis/ca_plotting.h b/constraint_analysis/include/constraint_analysis/ca_plotting.h index aaf5a3ff..e04688d0 100644 --- a/constraint_analysis/include/constraint_analysis/ca_plotting.h +++ b/constraint_analysis/include/constraint_analysis/ca_plotting.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/ca_functions.cpp b/constraint_analysis/src/ca_functions.cpp index 0262ec1f..738e8186 100644 --- a/constraint_analysis/src/ca_functions.cpp +++ b/constraint_analysis/src/ca_functions.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/ca_parser.cpp b/constraint_analysis/src/ca_parser.cpp index 54c1729f..a964cacb 100644 --- a/constraint_analysis/src/ca_parser.cpp +++ b/constraint_analysis/src/ca_parser.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/ca_strategy.h b/constraint_analysis/src/ca_strategy.h index 2ff90a3f..435782cb 100644 --- a/constraint_analysis/src/ca_strategy.h +++ b/constraint_analysis/src/ca_strategy.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/constraint_analysis.cpp b/constraint_analysis/src/constraint_analysis.cpp index 7b75ba06..1a491be4 100644 --- a/constraint_analysis/src/constraint_analysis.cpp +++ b/constraint_analysis/src/constraint_analysis.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/constraint_analysis.h b/constraint_analysis/src/constraint_analysis.h index c42fbcaa..b7886be4 100644 --- a/constraint_analysis/src/constraint_analysis.h +++ b/constraint_analysis/src/constraint_analysis.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/energy_based/energy_based.cpp b/constraint_analysis/src/energy_based/energy_based.cpp index 7cc47455..f889393b 100644 --- a/constraint_analysis/src/energy_based/energy_based.cpp +++ b/constraint_analysis/src/energy_based/energy_based.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/energy_based/energy_based.h b/constraint_analysis/src/energy_based/energy_based.h index d027e566..b8c56b24 100644 --- a/constraint_analysis/src/energy_based/energy_based.h +++ b/constraint_analysis/src/energy_based/energy_based.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/energy_based/energy_based_refactored.cpp b/constraint_analysis/src/energy_based/energy_based_refactored.cpp index d7e9e093..ff445762 100644 --- a/constraint_analysis/src/energy_based/energy_based_refactored.cpp +++ b/constraint_analysis/src/energy_based/energy_based_refactored.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/main.cpp b/constraint_analysis/src/main.cpp index 80d5dc5a..944066ec 100644 --- a/constraint_analysis/src/main.cpp +++ b/constraint_analysis/src/main.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/src/toolinfo.h b/constraint_analysis/src/toolinfo.h index 9a4ea25c..848a94dd 100644 --- a/constraint_analysis/src/toolinfo.h +++ b/constraint_analysis/src/toolinfo.h @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/test/test_analysis.cpp b/constraint_analysis/test/test_analysis.cpp index c6719171..f0646090 100644 --- a/constraint_analysis/test/test_analysis.cpp +++ b/constraint_analysis/test/test_analysis.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/test/test_constraintAnalysis.cpp b/constraint_analysis/test/test_constraintAnalysis.cpp index dac75bba..d3c55479 100644 --- a/constraint_analysis/test/test_constraintAnalysis.cpp +++ b/constraint_analysis/test/test_constraintAnalysis.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/test/test_parser.cpp b/constraint_analysis/test/test_parser.cpp index bec5bae2..c3b4dfe2 100644 --- a/constraint_analysis/test/test_parser.cpp +++ b/constraint_analysis/test/test_parser.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 diff --git a/constraint_analysis/test/test_plotter.cpp b/constraint_analysis/test/test_plotter.cpp index e674b0bc..bd24bb04 100644 --- a/constraint_analysis/test/test_plotter.cpp +++ b/constraint_analysis/test/test_plotter.cpp @@ -1,7 +1,7 @@ /* * UNICADO - UNIversity Conceptual Aircraft Design and Optimization * - * Copyright (C) 2024 UNICADO consortium + * Copyright (C) 2025 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 -- GitLab From c876d394c655beb374df1995c79d7af1f8fa73e0 Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 13:48:25 +0100 Subject: [PATCH 2/8] Replace energy based file with the refactored one --- constraint_analysis/CMakeLists.txt | 2 +- .../src/energy_based/energy_based.cpp | 388 ++++++++++-------- .../energy_based/energy_based_refactored.cpp | 347 ---------------- 3 files changed, 208 insertions(+), 529 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 f889393b..ff445762 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,13 @@ 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); - }; - - 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,11 +130,11 @@ 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"); @@ -308,14 +144,204 @@ void EnergyBased::operator()() 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"); + 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 ff445762..00000000 --- a/constraint_analysis/src/energy_based/energy_based_refactored.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* - * UNICADO - UNIversity Conceptual Aircraft Design and Optimization - * - * Copyright (C) 2025 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; - } - } - - 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") { - ConstraintAnalysis_Plot ca_plot; - - ca_plot.fill_infeasible_area(W_over_S_data, min_finder.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 d7df4ab2afb7ee7c9d73abd5183b61da9165b167 Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 14:37:33 +0100 Subject: [PATCH 3/8] Initial running version --- constraint_analysis/CMakeLists.txt | 1 + .../src/constraint_analysis.cpp | 10 ++++ constraint_analysis/src/constraint_analysis.h | 14 +++-- .../src/energy_based/energy_based_report.cpp | 53 +++++++++++++++++++ 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 constraint_analysis/src/energy_based/energy_based_report.cpp diff --git a/constraint_analysis/CMakeLists.txt b/constraint_analysis/CMakeLists.txt index 564eb7d2..2007843e 100644 --- a/constraint_analysis/CMakeLists.txt +++ b/constraint_analysis/CMakeLists.txt @@ -8,6 +8,7 @@ set(MODULE_SOURCES src/ca_parser.cpp src/io/aircraft_xml.cpp src/energy_based/energy_based.cpp + src/energy_based/energy_based_report.cpp ) add_executable(${MODULE_NAME} diff --git a/constraint_analysis/src/constraint_analysis.cpp b/constraint_analysis/src/constraint_analysis.cpp index 1a491be4..4a9343f0 100644 --- a/constraint_analysis/src/constraint_analysis.cpp +++ b/constraint_analysis/src/constraint_analysis.cpp @@ -71,6 +71,16 @@ void DefaultAnalysis::update() { } void DefaultAnalysis::report() { + /* Only when the reports are enabled */ + if (!this->get_RuntimeIO()->reportOn) + { + std::cout << "Skipping the creation of the report." << std::endl; + return; + } + std::cout << "Creating the HTML report." << std::endl; + this->create_html_report(); + + //TODO plots check? } void DefaultAnalysis::save() { diff --git a/constraint_analysis/src/constraint_analysis.h b/constraint_analysis/src/constraint_analysis.h index b7886be4..34f19db6 100644 --- a/constraint_analysis/src/constraint_analysis.h +++ b/constraint_analysis/src/constraint_analysis.h @@ -20,15 +20,17 @@ * This file is part of UNICADO. */ -#include <cmath> +#include "ca_strategy.h" + +#include <moduleBasics/module.h> + + #include <cmath> #include <vector> #include <numbers> #include <memory> -#include <moduleBasics/module.h> #include <string> #include <vector> #include <unordered_map> -#include "ca_strategy.h" #ifndef SRC_CONSTRAINT_ANALYSIS_H_ #define SRC_CONSTRAINT_ANALYSIS_H_ @@ -55,8 +57,14 @@ public: void report() override; void save() override; + private: + /** + * @brief Create the html report for the constraint analysis. + */ + void create_html_report(); + /* === Properties === */ std::unique_ptr<ConstraintAnalysisStrategy> constraint_analyzer; std::shared_ptr<node> configuration_xml; std::shared_ptr<node> aircraft_xml; diff --git a/constraint_analysis/src/energy_based/energy_based_report.cpp b/constraint_analysis/src/energy_based/energy_based_report.cpp new file mode 100644 index 00000000..a2a47992 --- /dev/null +++ b/constraint_analysis/src/energy_based/energy_based_report.cpp @@ -0,0 +1,53 @@ +/* + * UNICADO - UNIversity Conceptual Aircraft Design and Optimization + * + * Copyright (C) 2025 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 "../constraint_analysis.h" +#include <moduleBasics/report.h> +#include <moduleBasics/html.h> + +void DefaultAnalysis::create_html_report() +{ + /* Setup the report */ + Report report(this->get_RuntimeIO()); + auto &html_stream = report.htmlReportStream(); + + /* Get the relative plot directory for the html report */ + std::filesystem::path plot_dir_relative{ + std::filesystem::relative(this->get_RuntimeIO()->getPlotDir(), + this->get_RuntimeIO()->getHtmlDir())}; + + /* Start the data div */ + html_stream << html::div_start("class=\"box data\""); + html_stream << html::h3("List of installed engines:") << "<ul>\n"; + + /* Close the data div */ + html_stream << html::div_end; + + /* Insert the plots for the report if they are enabled */ + if (this->get_RuntimeIO()->plotOn) + { + std::cout << "Inserting plots into the html report..." << std::endl; + } + + /* Finish the html report */ + report.generateHtmlReport(""); +} \ No newline at end of file -- GitLab From 2150381c56ab5922ed1fa3d950d21c96ffff8ad6 Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 14:50:44 +0100 Subject: [PATCH 4/8] Include runtimeinfo & table --- constraint_analysis/src/constraint_analysis.cpp | 4 ++-- .../src/energy_based/energy_based_report.cpp | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/constraint_analysis/src/constraint_analysis.cpp b/constraint_analysis/src/constraint_analysis.cpp index 4a9343f0..6d0c8701 100644 --- a/constraint_analysis/src/constraint_analysis.cpp +++ b/constraint_analysis/src/constraint_analysis.cpp @@ -74,10 +74,10 @@ void DefaultAnalysis::report() { /* Only when the reports are enabled */ if (!this->get_RuntimeIO()->reportOn) { - std::cout << "Skipping the creation of the report." << std::endl; + myRuntimeInfo->out << "Skipping the creation of the report." << std::endl; return; } - std::cout << "Creating the HTML report." << std::endl; + myRuntimeInfo->out << "Creating the HTML report..." << std::endl; this->create_html_report(); //TODO plots check? diff --git a/constraint_analysis/src/energy_based/energy_based_report.cpp b/constraint_analysis/src/energy_based/energy_based_report.cpp index a2a47992..2288e277 100644 --- a/constraint_analysis/src/energy_based/energy_based_report.cpp +++ b/constraint_analysis/src/energy_based/energy_based_report.cpp @@ -37,17 +37,21 @@ void DefaultAnalysis::create_html_report() /* Start the data div */ html_stream << html::div_start("class=\"box data\""); - html_stream << html::h3("List of installed engines:") << "<ul>\n"; - + html_stream << html::h3("Final performance parameter:") << "<ul>\n"; + html_stream << html::table_begin({"Parameter", "Value", "Unit"}); + html_stream << html::table_row("Wing loading", "kg/m2", wing_loading_point); + html_stream << html::table_row("Trust-to-weight-ratio", "-", thrust_to_weight_point); + html_stream << html::table_end; /* Close the data div */ html_stream << html::div_end; /* Insert the plots for the report if they are enabled */ if (this->get_RuntimeIO()->plotOn) { - std::cout << "Inserting plots into the html report..." << std::endl; + myRuntimeInfo->out << "Inserting plots into the html report..." << std::endl; } /* Finish the html report */ report.generateHtmlReport(""); + myRuntimeInfo->out << "HTML report created." << std::endl; } \ No newline at end of file -- GitLab From e1079a0aed6eadffe3a69a789d90522119dec060 Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 15:18:24 +0100 Subject: [PATCH 5/8] Include plot --- .../src/energy_based/energy_based_report.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/constraint_analysis/src/energy_based/energy_based_report.cpp b/constraint_analysis/src/energy_based/energy_based_report.cpp index 2288e277..f6840e3f 100644 --- a/constraint_analysis/src/energy_based/energy_based_report.cpp +++ b/constraint_analysis/src/energy_based/energy_based_report.cpp @@ -48,10 +48,23 @@ void DefaultAnalysis::create_html_report() /* Insert the plots for the report if they are enabled */ if (this->get_RuntimeIO()->plotOn) { - myRuntimeInfo->out << "Inserting plots into the html report..." << std::endl; + // TODO: move plot creation here + /* Get the relative plot directory for the html report */ + std::filesystem::path plot_dir_relative{ + std::filesystem::relative(this->get_RuntimeIO()->getPlotDir(), + this->get_RuntimeIO()->getHtmlDir())}; + std::string plot_path = (plot_dir_relative / "constraint_plot.svg").string(); + html_stream + << html::div_start("class=\"box plot\"") + << html::h2("Design chart") + << html::image(plot_path, "width=\"800px\""); + + /* Close the plots div */ + html_stream << html::div_end; + } /* Finish the html report */ report.generateHtmlReport(""); myRuntimeInfo->out << "HTML report created." << std::endl; -} \ No newline at end of file +} -- GitLab From 011056da2cf129293802919b1e05d12f30fd9375 Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 16:11:45 +0100 Subject: [PATCH 6/8] Includes the csv data --- .../src/energy_based/energy_based_report.cpp | 48 +++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/constraint_analysis/src/energy_based/energy_based_report.cpp b/constraint_analysis/src/energy_based/energy_based_report.cpp index f6840e3f..7e1a9491 100644 --- a/constraint_analysis/src/energy_based/energy_based_report.cpp +++ b/constraint_analysis/src/energy_based/energy_based_report.cpp @@ -30,17 +30,49 @@ void DefaultAnalysis::create_html_report() Report report(this->get_RuntimeIO()); auto &html_stream = report.htmlReportStream(); - /* Get the relative plot directory for the html report */ - std::filesystem::path plot_dir_relative{ - std::filesystem::relative(this->get_RuntimeIO()->getPlotDir(), - this->get_RuntimeIO()->getHtmlDir())}; - + std::filesystem::path csv_dir = this->get_RuntimeIO()->getCsvFilesDir(); /* Start the data div */ html_stream << html::div_start("class=\"box data\""); html_stream << html::h3("Final performance parameter:") << "<ul>\n"; - html_stream << html::table_begin({"Parameter", "Value", "Unit"}); - html_stream << html::table_row("Wing loading", "kg/m2", wing_loading_point); - html_stream << html::table_row("Trust-to-weight-ratio", "-", thrust_to_weight_point); + std::string csv_file_path = (csv_dir / "design_point.csv").string(); + std::ifstream csv_file(csv_file_path); + if (!csv_file.is_open()) + { + throw std::runtime_error("Could not open CSV file: " + csv_file_path); + } + + std::string line; + std::vector<std::vector<std::string>> csv_data; + while (std::getline(csv_file, line)) + { + std::stringstream line_stream(line); + std::string cell; + std::vector<std::string> row; + while (std::getline(line_stream, cell, ',')) + { + row.push_back(cell); + } + csv_data.push_back(row); + } + csv_file.close(); + + if (!csv_data.empty()) + { + std::vector<html::Element> header_row; + for (const auto &cell : csv_data[0]) + { + header_row.push_back(html::Element(cell)); + } + html_stream << html::table_begin(header_row); + csv_data.erase(csv_data.begin()); // Remove the header row + } + for (const auto &row : csv_data) + { + if (row.size() == 3) // Ensure there are exactly 3 columns + { + html_stream << html::table_row(row[0], row[1], row[2]); + } + } html_stream << html::table_end; /* Close the data div */ html_stream << html::div_end; -- GitLab From 8db7f82f1cb357ad509047a5212a9f2fc8defe39 Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 16:52:47 +0100 Subject: [PATCH 7/8] Refactoring --- .../src/energy_based/energy_based_report.cpp | 171 ++++++++++-------- 1 file changed, 91 insertions(+), 80 deletions(-) diff --git a/constraint_analysis/src/energy_based/energy_based_report.cpp b/constraint_analysis/src/energy_based/energy_based_report.cpp index 7e1a9491..ad264244 100644 --- a/constraint_analysis/src/energy_based/energy_based_report.cpp +++ b/constraint_analysis/src/energy_based/energy_based_report.cpp @@ -20,83 +20,94 @@ * This file is part of UNICADO. */ -#include "../constraint_analysis.h" -#include <moduleBasics/report.h> -#include <moduleBasics/html.h> - -void DefaultAnalysis::create_html_report() -{ - /* Setup the report */ - Report report(this->get_RuntimeIO()); - auto &html_stream = report.htmlReportStream(); - - std::filesystem::path csv_dir = this->get_RuntimeIO()->getCsvFilesDir(); - /* Start the data div */ - html_stream << html::div_start("class=\"box data\""); - html_stream << html::h3("Final performance parameter:") << "<ul>\n"; - std::string csv_file_path = (csv_dir / "design_point.csv").string(); - std::ifstream csv_file(csv_file_path); - if (!csv_file.is_open()) - { - throw std::runtime_error("Could not open CSV file: " + csv_file_path); - } - - std::string line; - std::vector<std::vector<std::string>> csv_data; - while (std::getline(csv_file, line)) - { - std::stringstream line_stream(line); - std::string cell; - std::vector<std::string> row; - while (std::getline(line_stream, cell, ',')) - { - row.push_back(cell); - } - csv_data.push_back(row); - } - csv_file.close(); - - if (!csv_data.empty()) - { - std::vector<html::Element> header_row; - for (const auto &cell : csv_data[0]) - { - header_row.push_back(html::Element(cell)); - } - html_stream << html::table_begin(header_row); - csv_data.erase(csv_data.begin()); // Remove the header row - } - for (const auto &row : csv_data) - { - if (row.size() == 3) // Ensure there are exactly 3 columns - { - html_stream << html::table_row(row[0], row[1], row[2]); - } - } - html_stream << html::table_end; - /* Close the data div */ - html_stream << html::div_end; - - /* Insert the plots for the report if they are enabled */ - if (this->get_RuntimeIO()->plotOn) - { - // TODO: move plot creation here - /* Get the relative plot directory for the html report */ - std::filesystem::path plot_dir_relative{ - std::filesystem::relative(this->get_RuntimeIO()->getPlotDir(), - this->get_RuntimeIO()->getHtmlDir())}; - std::string plot_path = (plot_dir_relative / "constraint_plot.svg").string(); - html_stream - << html::div_start("class=\"box plot\"") - << html::h2("Design chart") - << html::image(plot_path, "width=\"800px\""); - - /* Close the plots div */ - html_stream << html::div_end; - - } - - /* Finish the html report */ - report.generateHtmlReport(""); - myRuntimeInfo->out << "HTML report created." << std::endl; -} + #include "../constraint_analysis.h" + #include <moduleBasics/report.h> + #include <moduleBasics/html.h> + #include <fstream> + #include <sstream> + #include <vector> + #include <filesystem> + + std::vector<std::vector<std::string>> read_csv(const std::string& file_path) { + std::ifstream csv_file(file_path); + if (!csv_file.is_open()) { + throw std::runtime_error("Could not open CSV file: " + file_path); + } + + std::vector<std::vector<std::string>> csv_data; + std::string line; + while (std::getline(csv_file, line)) { + std::stringstream line_stream(line); + std::string cell; + std::vector<std::string> row; + while (std::getline(line_stream, cell, ',')) { + row.push_back(cell); + } + csv_data.push_back(row); + } + + return csv_data; + } + + void generate_html_table(std::ostream& html_stream, const std::vector<std::vector<std::string>>& csv_data) { + if (csv_data.empty()) return; + + // Generate table header dynamically based on the first row + std::vector<html::Element> header_row; + for (const auto& cell : csv_data.front()) { + header_row.push_back(html::Element(cell)); + } + html_stream << html::table_begin(header_row); + + // Generate table rows dynamically + for (auto it = std::next(csv_data.begin()); it != csv_data.end(); ++it) { + const auto& row = *it; + + if (!row.empty()) { + html_stream << "<tr>\n"; + for (const auto& cell : row) { + html_stream << html::table_data(cell); + } + html_stream << "</tr>\n"; + } + } + + html_stream << html::table_end; + } + + void DefaultAnalysis::create_html_report() { + try { + Report report(this->get_RuntimeIO()); + std::ostream& html_stream = report.htmlReportStream(); + std::filesystem::path csv_dir = this->get_RuntimeIO()->getCsvFilesDir(); + + html_stream << html::div_start("class=\"box data\"") + << html::h3("Final performance parameter:") + << "<ul>\n"; + + std::string csv_file_path = (csv_dir / "design_point.csv").string(); + auto csv_data = read_csv(csv_file_path); + generate_html_table(html_stream, csv_data); + + html_stream << html::div_end; + + if (this->get_RuntimeIO()->plotOn) { + std::filesystem::path plot_dir_relative = + std::filesystem::relative(this->get_RuntimeIO()->getPlotDir(), + this->get_RuntimeIO()->getHtmlDir()); + std::string plot_path = (plot_dir_relative / "constraint_plot.svg").string(); + + html_stream << html::div_start("class=\"box plot\"") + << html::h2("Design chart") + << html::image(plot_path, "width=\"800px\"") + << html::div_end; + } + + report.generateHtmlReport(""); + myRuntimeInfo->out << "HTML report created." << std::endl; + + } catch (const std::exception& e) { + myRuntimeInfo->out << "Error creating HTML report: " << e.what() << std::endl; + } + } + \ No newline at end of file -- GitLab From 92d1e13d27c438f045e0217aa0eca809ad9cf21a Mon Sep 17 00:00:00 2001 From: Kristina Mazur <kristina.mazur@tum.de> Date: Fri, 21 Feb 2025 16:58:47 +0100 Subject: [PATCH 8/8] Final refactoring --- .../src/energy_based/energy_based_report.cpp | 197 ++++++++++-------- 1 file changed, 106 insertions(+), 91 deletions(-) diff --git a/constraint_analysis/src/energy_based/energy_based_report.cpp b/constraint_analysis/src/energy_based/energy_based_report.cpp index ad264244..5e6d8985 100644 --- a/constraint_analysis/src/energy_based/energy_based_report.cpp +++ b/constraint_analysis/src/energy_based/energy_based_report.cpp @@ -20,94 +20,109 @@ * This file is part of UNICADO. */ - #include "../constraint_analysis.h" - #include <moduleBasics/report.h> - #include <moduleBasics/html.h> - #include <fstream> - #include <sstream> - #include <vector> - #include <filesystem> - - std::vector<std::vector<std::string>> read_csv(const std::string& file_path) { - std::ifstream csv_file(file_path); - if (!csv_file.is_open()) { - throw std::runtime_error("Could not open CSV file: " + file_path); - } - - std::vector<std::vector<std::string>> csv_data; - std::string line; - while (std::getline(csv_file, line)) { - std::stringstream line_stream(line); - std::string cell; - std::vector<std::string> row; - while (std::getline(line_stream, cell, ',')) { - row.push_back(cell); - } - csv_data.push_back(row); - } - - return csv_data; - } - - void generate_html_table(std::ostream& html_stream, const std::vector<std::vector<std::string>>& csv_data) { - if (csv_data.empty()) return; - - // Generate table header dynamically based on the first row - std::vector<html::Element> header_row; - for (const auto& cell : csv_data.front()) { - header_row.push_back(html::Element(cell)); - } - html_stream << html::table_begin(header_row); - - // Generate table rows dynamically - for (auto it = std::next(csv_data.begin()); it != csv_data.end(); ++it) { - const auto& row = *it; - - if (!row.empty()) { - html_stream << "<tr>\n"; - for (const auto& cell : row) { - html_stream << html::table_data(cell); - } - html_stream << "</tr>\n"; - } - } - - html_stream << html::table_end; - } - - void DefaultAnalysis::create_html_report() { - try { - Report report(this->get_RuntimeIO()); - std::ostream& html_stream = report.htmlReportStream(); - std::filesystem::path csv_dir = this->get_RuntimeIO()->getCsvFilesDir(); - - html_stream << html::div_start("class=\"box data\"") - << html::h3("Final performance parameter:") - << "<ul>\n"; - - std::string csv_file_path = (csv_dir / "design_point.csv").string(); - auto csv_data = read_csv(csv_file_path); - generate_html_table(html_stream, csv_data); - - html_stream << html::div_end; - - if (this->get_RuntimeIO()->plotOn) { - std::filesystem::path plot_dir_relative = - std::filesystem::relative(this->get_RuntimeIO()->getPlotDir(), - this->get_RuntimeIO()->getHtmlDir()); - std::string plot_path = (plot_dir_relative / "constraint_plot.svg").string(); - - html_stream << html::div_start("class=\"box plot\"") - << html::h2("Design chart") - << html::image(plot_path, "width=\"800px\"") - << html::div_end; - } - - report.generateHtmlReport(""); - myRuntimeInfo->out << "HTML report created." << std::endl; - - } catch (const std::exception& e) { - myRuntimeInfo->out << "Error creating HTML report: " << e.what() << std::endl; - } - } - \ No newline at end of file +#include "../constraint_analysis.h" +#include <moduleBasics/report.h> +#include <moduleBasics/html.h> +#include <fstream> +#include <sstream> +#include <vector> +#include <filesystem> +#include <iomanip> + +std::vector<std::vector<std::string>> read_csv(const std::string& file_path) { + std::ifstream csv_file(file_path); + if (!csv_file.is_open()) { + throw std::runtime_error("Could not open CSV file: " + file_path); + } + std::vector<std::vector<std::string>> csv_data; + std::string line; + while (std::getline(csv_file, line)) { + std::stringstream line_stream(line); + std::string cell; + std::vector<std::string> row; + while (std::getline(line_stream, cell, ',')) { + row.push_back(cell); + } + csv_data.push_back(row); + } + return csv_data; +} + +std::string format_number(const std::string& value, int precision) { +try { + double num = std::stod(value); + std::ostringstream stream; + stream << std::fixed << std::setprecision(precision) << num; + return stream.str(); +} catch (...) { + return value; +} +} + +void generate_html_table(std::ostream& html_stream, const std::vector<std::vector<std::string>>& csv_data) { + if (csv_data.empty()) return; + + // Generate table header dynamically based on the first row + std::vector<html::Element> header_row; + for (const auto& cell : csv_data.front()) { + header_row.push_back(html::Element(cell)); + } + html_stream << html::table_begin(header_row); + + // Generate table rows dynamically + for (auto it = std::next(csv_data.begin()); it != csv_data.end(); ++it) { + const auto& row = *it; + + if (!row.empty()) { + html_stream << "<tr>\n"; + for (size_t i = 0; i < row.size(); ++i) { + std::string formatted_value = row[i]; + if (i == 1) { // 2nd column (index 1) - 4 decimal places + formatted_value = format_number(row[i], 4); + } else if (i == 2) { // 3rd column (index 2) - 1 decimal place + formatted_value = format_number(row[i], 1); + } + html_stream << html::table_data(formatted_value); + } + html_stream << "</tr>\n"; + } + } + + html_stream << html::table_end; +} + +void DefaultAnalysis::create_html_report() { + try { + Report report(this->get_RuntimeIO()); + std::ostream& html_stream = report.htmlReportStream(); + std::filesystem::path csv_dir = this->get_RuntimeIO()->getCsvFilesDir(); + + html_stream << html::div_start("class=\"box data\"") + << html::h3("Final performance parameter:") + << "<ul>\n"; + + std::string csv_file_path = (csv_dir / "design_point.csv").string(); + auto csv_data = read_csv(csv_file_path); + generate_html_table(html_stream, csv_data); + + html_stream << html::div_end; + + if (this->get_RuntimeIO()->plotOn) { + std::filesystem::path plot_dir_relative = + std::filesystem::relative(this->get_RuntimeIO()->getPlotDir(), + this->get_RuntimeIO()->getHtmlDir()); + std::string plot_path = (plot_dir_relative / "constraint_plot.svg").string(); + + html_stream << html::div_start("class=\"box plot\"") + << html::h2("Design chart") + << html::image(plot_path, "width=\"800px\"") + << html::div_end; + } + + report.generateHtmlReport(""); + myRuntimeInfo->out << "HTML report created." << std::endl; + + } catch (const std::exception& e) { + myRuntimeInfo->out << "Error creating HTML report: " << e.what() << std::endl; + } +} -- GitLab