diff --git a/propulsion_design/src/integration/default/default_integration.cpp b/propulsion_design/src/integration/default/default_integration.cpp index 7caf73699772f156159a541e6de15cb97c7ba4e6..9e740e90770e732964b863e5f33c388209b7fac8 100644 --- a/propulsion_design/src/integration/default/default_integration.cpp +++ b/propulsion_design/src/integration/default/default_integration.cpp @@ -56,7 +56,6 @@ namespace design auto Default::select_wing() -> geometry::Wing& { - /** @todo Make it possible to select a wing when there are more than one. */ if (this->aircraft()->wings.size() != 1) { //throw std::runtime_error("[design::integrator::Default::select_wing()] The aircraft does not contain exactly one wing."); diff --git a/propulsion_design/src/integration/default/default_integration.h b/propulsion_design/src/integration/default/default_integration.h index 5bb570bd954942ef96a2e8bc819d45c3992e7f09..89397f9f258d309168506ba6cb2c4f80a16509b1 100644 --- a/propulsion_design/src/integration/default/default_integration.h +++ b/propulsion_design/src/integration/default/default_integration.h @@ -107,9 +107,15 @@ namespace design void turbofan_method(Turbofan<EC>& engine); // NOLINT runtime/references + template <EnergyCarrier EC> + void integrate_over_wing(Openrotorfan<EC> &engine); // NOLINT runtime/references + template <EnergyCarrier EC> void integrate_into_wing(Openrotorfan<EC> &engine); // NOLINT runtime/references + template <EnergyCarrier EC> + void integrate_into_fuselage_top(Openrotorfan<EC> &engine); // NOLINT runtime/references + template <EnergyCarrier EC> void integrate_into_fuselage(Openrotorfan<EC> &engine); // NOLINT runtime/references diff --git a/propulsion_design/src/integration/default/openrotorfan.cpp b/propulsion_design/src/integration/default/openrotorfan.cpp index 8d9993b3f81f375b8055b93a2a0d78b254c36109..98da508224a9015f86bfa9655f72e16fc6b85491 100644 --- a/propulsion_design/src/integration/default/openrotorfan.cpp +++ b/propulsion_design/src/integration/default/openrotorfan.cpp @@ -44,6 +44,8 @@ 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::Fuselage, Lateral::Right, Longitudinal::Rear, Vertical::Over}, + {Parent::Fuselage, Lateral::Left, Longitudinal::Rear, Vertical::Over}, {Parent::Empennage, Lateral::Mid, Longitudinal::Front, Vertical::In}}; } // namespace detail @@ -64,11 +66,26 @@ namespace design { case Parent::Wing: /* Integrate the engine into the wing */ - integrate_into_wing(engine); + if (std::get<Vertical>(engine.parent_component()) != Vertical::Under) + { + integrate_over_wing(engine); + } + else + { + integrate_into_wing(engine); + } break; case Parent::Fuselage: + if (std::get<Vertical>(engine.parent_component()) != Vertical::Over) + { + //throw std::runtime_error("[design::integrator::Default] The engine is not under the wing. This method is not applicable."); + integrate_into_fuselage(engine); + } + else + { /* Integrate the engine into the fuselage */ - integrate_into_fuselage(engine); + integrate_into_fuselage_top(engine); + } break; case Parent::Empennage: /* Integrate the engine into the empennage */ @@ -88,6 +105,96 @@ namespace design this->parents_placed.insert(engine.parent_component()); } + template <EnergyCarrier EC> + void Default::integrate_over_wing(Openrotorfan<EC> &engine) + { + std::cout << "Tobi ist Gott + 1" << std::endl; + /* + * => This method follows the procedure described in \cite Ata10 + * It assumes one main wing which is extruded in global Y direction + */ + /** @fixed Add a warning when the aircraft contains more than one wing or fuselage */ + const auto &wing = this->select_wing(); + const auto &fuselage = this->select_fuselage(); + 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."); + } + if (std::get<Vertical>(engine.parent_component()) != Vertical::Under) + { + //throw std::runtime_error("[design::integrator::Default] The engine is not under the wing. This method is not applicable."); + } + + /* When the current parent position is already placed, we assume this is the outer engine */ + bool is_outer = this->parents_placed.contains(engine.parent_component()); + + /* Check whether there is still space for the engine to be integrated */ + switch (this->n_engines_.wing) + { + case 4: + /* Check whether the outer position is already placed */ + if (is_outer && this->engines_done.wing % 2) + { + break; + } + [[fallthrough]]; + case 2: + /* At this point there does not exist an outer engine position */ + if (is_outer) + { + throw std::runtime_error("[design::integrator::Default] No space on the wing for the engine to be integrated."); + } + break; + default: + throw std::runtime_error("[design::integrator::Default] The number of engines on the wing is not supported."); + } + + /* !!! + * The following assumes the wing local coordinate system: + * - X axis: chord direction + * - Y axis: height direction + * - Z axis: span direction (should be negative coordinates) + * !!! + */ + /* Get the relevant measurements from the aircraft */ + const double span = geom2::measure::span(wing); + const double width_fuselage = geom2::measure::width_max(fuselage); + const double diameter_max = 1.21 * engine.fan().diameter; // \cite Ata10 p. 45 + + /* Wing local z position of engine */ + const double span_engine = 0.7 * sign_wing_extrusion * this->calculate_span_position_openrotor( + width_fuselage, diameter_max, span, is_outer); + + /* Get the wing quarter 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) + + geom2::Vector_3{0.25 * wing_chord, 0, 0}; + + /* Wing local x position of engine */ + const double chord_engine = 0.5 * wing_chord + geom2::measure::offset_LE(wing, span_engine).x(); // \cite Ata10 p. 48f + + /* Wing local y position of engine */ + const double height_engine = wing_quarter.y() + + 2.4 * geom2::measure::height_max(engine.nacelle()); + + /* Adjust whether the engine is left or right */ + auto position = geom2::Point_3{chord_engine, height_engine, span_engine}; + + /* Include user input in there to shift engine in every direction acc to config */ + position = {position.x() + usershift_x, position.y() + usershift_z, position.z() - usershift_y}; + + if (std::get<Lateral>(engine.parent_component()) == Lateral::Left) + { + position = {position.x(), position.y(), -position.z()}; + } + + /* Set the position of the engine in the GLOBAL (!) reference frame */ + engine.set_position(geom2::transform::to_parent(wing, position)); + ++this->engines_done.wing; + } + template <EnergyCarrier EC> void Default::integrate_into_wing(Openrotorfan<EC> &engine) { @@ -105,7 +212,7 @@ namespace design } if (std::get<Vertical>(engine.parent_component()) != Vertical::Under) { - throw std::runtime_error("[design::integrator::Default] The engine is not under the wing. This method is not applicable."); + //throw std::runtime_error("[design::integrator::Default] The engine is not under the wing. This method is not applicable."); } /* When the current parent position is already placed, we assume this is the outer engine */ @@ -178,6 +285,59 @@ namespace design ++this->engines_done.wing; } + template <EnergyCarrier EC> + void Default::integrate_into_fuselage_top(Openrotorfan<EC> &engine) + { + /* + * It assumes one main fuselage which is extruded in global X direction + */ + const auto &fuselage = this->select_fuselage(); + const double sign_extrusion = std::signbit(fuselage.sections.back().origin.z()) ? -1.0 : 1.0; + if (fuselage.normal != geom2::Direction_3{sign_extrusion * 1, 0, 0}) + { + throw std::runtime_error("[design::integrator::Default] The fuselage is not oriented in x-direction. This method is not applicable."); + } + + /* Only two engines on the fuselage are supported right now */ + if (this->n_engines_.fuselage != 2) + { + throw std::runtime_error("[design::integrator::Default] The number of engines on the fuselage is not supported."); + } + + /* Check whether there is still space for the engine to be integrated */ + if (this->parents_placed.contains(engine.parent_component())) + { + throw std::runtime_error("[design::integrator::Default] No space left on the fuselage for the engine to be integrated."); + } + + /* !!! + * The following assumes the fuselage local coordinate system: + * - X axis: width direction + * - Y axis: height direction + * - Z axis: length direction + * !!! + */ + /* Get the engine position in local z direction */ + const double z_engine = sign_extrusion * 0.9 * geom2::measure::length(fuselage); + + /* Get the engine position in local y direction */ + const double y_engine = 1.1 * geom2::measure::height(fuselage, z_engine); + + /* Get the engine position in local x direction */ + const double x_engine = 0.9 * geom2::measure::width_max(engine.nacelle()); + + /* Adjust whether engine is left or right */ + auto position = geom2::Point_3{x_engine, y_engine, z_engine}; + if (std::get<Lateral>(engine.parent_component()) == Lateral::Left) + { + position = {-position.x(), position.y(), position.z()}; + } + + /* Set the position of the engine in the GLOBAL (!) reference frame */ + engine.set_position(geom2::transform::to_parent(fuselage,position)); + ++this->engines_done.fuselage; + } + template <EnergyCarrier EC> void Default::integrate_into_fuselage(Openrotorfan<EC> &engine) { @@ -219,7 +379,7 @@ namespace design const double y_engine = 0.65 * geom2::measure::height(fuselage, z_engine); /* Get the engine position in local x direction */ - const double x_engine = 0.4 * geom2::measure::width(fuselage, z_engine) + + const double x_engine = 0.3 * geom2::measure::width(fuselage, z_engine) + geom2::measure::width_max(engine.nacelle()); /* Adjust whether engine is left or right */ diff --git a/propulsion_design/src/nacelle/default/openrotorfan.cpp b/propulsion_design/src/nacelle/default/openrotorfan.cpp index 3de5c550d26ad0271c2fe8d3cc185e035d531506..1d37cffe446df5d50a814e1d431447e904a92d1c 100644 --- a/propulsion_design/src/nacelle/default/openrotorfan.cpp +++ b/propulsion_design/src/nacelle/default/openrotorfan.cpp @@ -74,14 +74,14 @@ namespace geometry shape_test.set_scale(0.0); builder_test.insert_back(shape_test, {0.0, 0.0, 0}); - shape_test.set_scale(0.0); - builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.401}); + shape_test.set_scale(0.3); + builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.01}); shape_test.set_scale(0.4); - builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.0}); + builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.3}); shape_test.set_scale(0.4); - builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.05}); + builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.3}); shape_test.set_scale(1.0); builder_test.insert_back(shape_test, {0.0, 0.0, 0.0}); @@ -89,11 +89,11 @@ namespace geometry shape_test.set_scale(1.0); builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.01}); - shape_test.set_scale(0.5); - builder_test.insert_back(shape_test, {0.0, 0.0, 0.0}); + shape_test.set_scale(0.4); + builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.0}); - shape_test.set_scale(0.5); - builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.2}); + shape_test.set_scale(0.4); + builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.15}); shape_test.set_scale(1.0); builder_test.insert_back(shape_test, {0.0, 0.0, 0.0}); @@ -101,11 +101,11 @@ namespace geometry shape_test.set_scale(1.0); builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.01}); - shape_test.set_scale(0.4); + shape_test.set_scale(0.3); builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.0}); - shape_test.set_scale(0.4); - builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.3}); + shape_test.set_scale(0.2); + builder_test.insert_back(shape_test, {0.0, 0.0, engine.dimension().length * 0.1}); /* Build the surface and insert it into the engine */ surface_test.name = "nacelle_" + std::to_string(engine.id()); diff --git a/propulsion_design/src/pylon/default/default_pylon.cpp b/propulsion_design/src/pylon/default/default_pylon.cpp index 85f99f629666e8b95814f7a637a817898b089993..583ddd64b854fd2a52c642c94cb621b6d6436633 100644 --- a/propulsion_design/src/pylon/default/default_pylon.cpp +++ b/propulsion_design/src/pylon/default/default_pylon.cpp @@ -47,6 +47,8 @@ namespace geometry {Parent::Wing, Lateral::Right, Longitudinal::Front, Vertical::Over}, {Parent::Wing, Lateral::Left, Longitudinal::Front, Vertical::Over}, {Parent::Fuselage, Lateral::Right, Longitudinal::Rear, Vertical::Mid}, + {Parent::Fuselage, Lateral::Right, Longitudinal::Rear, Vertical::Over}, + {Parent::Fuselage, Lateral::Left, Longitudinal::Rear, Vertical::Over}, {Parent::Fuselage, Lateral::Left, Longitudinal::Rear, Vertical::Mid} }; @@ -179,7 +181,7 @@ namespace geometry switch (std::get<Parent>(parent)) { case Parent::Wing: - return geometry::pylon::detail::get_wing_attachment_points(position, nacelle, this->aircraft()->wings[0]); + return geometry::pylon::detail::get_wing_attachment_points(position, nacelle, this->aircraft()->wings[1]); case Parent::Fuselage: return geometry::pylon::detail::get_fuselage_attachment_points(position, nacelle, this->aircraft()->fuselages[0]); case Parent::Empennage: diff --git a/propulsion_design/src/pylon/default/openrotorfan.cpp b/propulsion_design/src/pylon/default/openrotorfan.cpp index 0b93af2908d3be2d9a3fdddd193c4f6a4671af75..9e8750c5c63c3066a225f5377ac51a0fded3462f 100644 --- a/propulsion_design/src/pylon/default/openrotorfan.cpp +++ b/propulsion_design/src/pylon/default/openrotorfan.cpp @@ -82,12 +82,12 @@ namespace geometry { offsets = computeOffsets(0.6); } - else + else { - offsets = computeOffsets(0.5, geom2::Vector_3(-2.5, engine.position().y() * 0.5, -0.7)); + offsets = computeOffsets(0.3, geom2::Vector_3(-0.5, engine.position().y() * 0.5, -0.7)); } - const auto& offset_start = offsets.first; + const auto& offset_start = offsets.first + geom2::Vector_3(1.5, 0, 0); const auto& offset_end = offsets.second;