From 09cdd2f9c5e4ce34a3c7e2ff8f5385ff0342f6a8 Mon Sep 17 00:00:00 2001 From: Meric Taneri <meric.taneri@tum.de> Date: Fri, 28 Mar 2025 10:15:57 +0100 Subject: [PATCH] bwb integration added --- .../integration/default/default_integration.h | 3 + .../src/integration/default/turbofan.cpp | 119 +++++++++++++++++- propulsion_design/src/propulsion.h | 3 +- 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/propulsion_design/src/integration/default/default_integration.h b/propulsion_design/src/integration/default/default_integration.h index 051b777c..a353d560 100644 --- a/propulsion_design/src/integration/default/default_integration.h +++ b/propulsion_design/src/integration/default/default_integration.h @@ -98,6 +98,9 @@ namespace design template <EnergyCarrier EC> void integrate_into_empennage(Turbofan<EC> &engine); // NOLINT runtime/references + template <EnergyCarrier EC> + void integrate_into_wing_body(Turbofan<EC> &engine); // NOLINT runtime/references + template <EnergyCarrier EC> void guess_position(Turbofan<EC> &engine); // NOLINT runtime/references diff --git a/propulsion_design/src/integration/default/turbofan.cpp b/propulsion_design/src/integration/default/turbofan.cpp index c01bb083..99d14956 100644 --- a/propulsion_design/src/integration/default/turbofan.cpp +++ b/propulsion_design/src/integration/default/turbofan.cpp @@ -44,7 +44,9 @@ namespace design {Parent::Wing, Lateral::Left, Longitudinal::Front, Vertical::Over}, {Parent::Fuselage, Lateral::Right, Longitudinal::Rear, Vertical::Mid}, {Parent::Fuselage, Lateral::Left, Longitudinal::Rear, Vertical::Mid}, - {Parent::Empennage, Lateral::Mid, Longitudinal::Front, Vertical::In}}; + {Parent::Empennage, Lateral::Mid, Longitudinal::Front, Vertical::In}, + {Parent::WingBody, Lateral::Right, Longitudinal::Rear, Vertical::Over}, + {Parent::WingBody, Lateral::Left, Longitudinal::Rear, Vertical::Over} }; } // namespace detail template <EnergyCarrier EC> @@ -74,6 +76,10 @@ namespace design /* Integrate the engine into the empennage */ integrate_into_empennage(engine); break; + case Parent::WingBody: + /* Integrate the engine into the wing-body */ + integrate_into_wing_body(engine); + break; default: throw std::runtime_error("[design::integrator::Default] The parent component of the engine is not supported."); } @@ -275,6 +281,116 @@ namespace design ++this->engines_done.empennage; } + template <EnergyCarrier EC> + void Default::integrate_into_wing_body(Turbofan<EC> &engine) { + + if (std::get<Vertical>(engine.parent_component()) == Vertical::Over) { + /** @todo Add a warning when the aircraft contains more than one wing or fuselage */ + const auto& wing = this->select_wing(); + const double sign_wing_extrusion = std::signbit(wing.sections.back().origin.z()) ? -1.0 : 1.0; + if (wing.normal != geom2::Direction_3{ 0, sign_wing_extrusion * 1, 0 }) + { + throw std::runtime_error("[design::integrator::Default] The wing is not oriented in y-direction. This method is not applicable."); + } + + /* Get the relevant measurements from the aircraft */ + const double span = geom2::measure::span(wing); + const double diameter_max = 1.21 * engine.fan().diameter; // \cite Ata10 p. 45 + + /* Initiate a vector containing locations of wing mounted entities */ + std::vector<double> no_placement = { -span / 2 }; + + /* For each empennage element, get the spanwise boundaries on the xy plane */ + for (std::size_t i = 0; i < this->aircraft()->empennage.size(); i++) { + const auto& empennage = this->aircraft()->empennage[i]; + if (empennage.sections.size() > 1) { + const geom2::Point_3 back_section = geom2::transform::to_parent(empennage, empennage.sections.back().origin); + const geom2::Point_3 front_section = geom2::transform::to_parent(empennage, empennage.sections.front().origin); + double projected_span = std::abs(front_section.y() - back_section.y()); + no_placement.push_back(back_section.y() - projected_span * 0.25); + no_placement.push_back(back_section.y() + 1.5 * projected_span); + }; + }; + no_placement.push_back(span / 2); + std::sort(no_placement.begin(), no_placement.end()); + + /* Check if the wing mounted entities are symmetrical */ + bool is_symmetrical = std::accumulate(no_placement.begin(), no_placement.end(), 0.0) / no_placement.size() < 1; + if (!is_symmetrical) { + throw std::runtime_error("[design::integrator::Default] Non-symmetrical empennage, engine cannot be placed over the wing."); + }; + + switch (this->n_engines_.wing) + { + case 1: { + /* If there is a single engine, place it at the middle of the empennage assembly */ + /* @todo add valid logic for engine placement*/ + std::size_t index = no_placement.size() / 2 - 1; + if (-diameter_max / 2 > no_placement[index] and diameter_max / 2 < no_placement[index + 1]) { + const double span_engine = 0.0; + /* Get the wing spanwise_percentage coordinate at the engine span position */ + const double wing_chord = geom2::measure::chord(wing, span_engine); + const auto wing_quarter = + geom2::measure::offset_LE(wing, span_engine); + + /* Wing local x position of engine */ + const double chord_engine = wing_quarter.x() + 0.10 * wing_chord; + + /* Wing local y position of engine */ + const double height_engine = wing_quarter.y() + + 0.7 * geom2::measure::height_max(engine.nacelle()); + auto position = geom2::Point_3{ chord_engine, height_engine, span_engine }; + engine.set_position(geom2::transform::to_parent(wing, position)); + ++this->engines_done.wing; + } + else { + throw std::runtime_error("[design::integrator::Default] Empennage-engine collision, engine cannot be placed over the wing."); + }; + break; + } + case 2: { + std::size_t index = no_placement.size() / 2 - 1; + double span_engine = 0.0; + /* @todo add valid logic or engine placement*/ + /* If there are two engines, place them symmetrically on the sides of the empennage assembly */ + if (no_placement[index + 1] - no_placement[index] >= 3.4 * diameter_max) { + span_engine = 0.80 * diameter_max; + } + else { + std::size_t i = 0; + int available = 0; + while (i < no_placement.size() / 2 - 1) { + double dist = std::abs(no_placement[i] - no_placement[i + 1]); + if (dist >= diameter_max * 1.5) { available++; }; + i += 2; + } + if (available == 0) { throw std::runtime_error("[design::integrator::Default] No available space, engine cannot be placed over the wing."); }; + span_engine = 0.75 * diameter_max + std::abs(no_placement[2 * available - 1]); + }; + if (this->engines_done.wing > 0) { span_engine = -span_engine; }; + /* Get the wing 80% coordinate at the engine span position */ + const double wing_chord = geom2::measure::chord(wing, span_engine); + const auto wing_quarter = + geom2::measure::offset_LE(wing, span_engine); + + /* Wing local x position of engine */ + const double chord_engine = wing_quarter.x() + 0.10 * wing_chord; + + /* Wing local y position of engine */ + const double height_engine = wing_quarter.y() + + 0.7 * geom2::measure::height_max(engine.nacelle()); + + auto position = geom2::Point_3{ chord_engine, height_engine, span_engine }; + engine.set_position(geom2::transform::to_parent(wing, position)); + ++this->engines_done.wing; + break; + }; + }; + }; + + }; + + template <EnergyCarrier EC> void Default::guess_position(Turbofan<EC> &engine) { @@ -285,6 +401,7 @@ namespace design case Parent::Wing: case Parent::Fuselage: case Parent::Empennage: + case Parent::WingBody: default: /* Fall back to ORIGIN as the default position */ engine.set_position(CGAL::ORIGIN); diff --git a/propulsion_design/src/propulsion.h b/propulsion_design/src/propulsion.h index e03b2590..54e1a5e3 100644 --- a/propulsion_design/src/propulsion.h +++ b/propulsion_design/src/propulsion.h @@ -60,7 +60,8 @@ enum class Parent { Fuselage, Wing, - Empennage + Empennage, + WingBody }; /** -- GitLab