diff --git a/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.cpp b/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.cpp index df6195460ee3f3863c3c8deae92c16e5f62b9eb6..65de7d509ef03d95c0de0b917d489c24cbc900b4 100644 --- a/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.cpp +++ b/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.cpp @@ -16,6 +16,8 @@ #include <aircraftGeometry2/processing/transform.h> #include <atmosphere/atmosphere.h> #include <unitConversion/unitConversion.h> +#include <CGAL/Simple_cartesian.h> +#include <CGAL/Surface_mesh.h> #include <algorithm> #include <cmath> @@ -34,22 +36,25 @@ #include "lib/general_methods/icao_faa_codes.h" #include "lib/general_methods/newtonAlgorithm.h" + geom2::AirfoilSection get_rescaled_airfoil_geometry(const std::string& airfoildatadir, - std::tuple<double, double, std::string> wing_profile_and_thickness); + std::tuple<double, double, std::string> wing_profile_and_thickness); namespace tandem { namespace cantilever { Wing::Wing(const std::shared_ptr<RuntimeIO>& rtIO) : rtIO(rtIO), - config(std::make_shared<tandem::cantilever::WingDesignConfig>()), //front back TODO kayra + config(std::make_shared<tandem::cantilever::WingDesignConfig>()), data(std::make_shared<tandem::cantilever::WingDesignData>()), reporter(rtIO) { /* Setup design modes */ design_mode_runner["mode_0"] = [this]() { standard_design(); }; /* Setup mass modes */ - mass_mode_runner["mode_0"] = [this]() { flops_mass(); }; + mass_mode_runner["mode_0"] = [this]() { flops_mass(); }; //TODO kayra: buradan ayari mass_mode_runner["mode_1"] = [this]() { chiozzotto_wer_mass(); }; + back_mass_mode_runner["mode_0"] = [this]() { back_flops_mass(); }; //TODO kayra: buradan ayari + back_mass_mode_runner["mode_1"] = [this]() { back_chiozzotto_wer_mass(); }; } void Wing::initialize() { @@ -70,6 +75,8 @@ void Wing::initialize() { /* Store method to variable */ selected_design_mode = config->wing_design_mode.value(); selected_mass_mode = config->wing_mass_mode.value(); + selected_back_mass_mode = config->back_wing_mass_mode.value(); //TODO kayra :altta sikintisi var:bunlardan biri gerekmeyebilir + airfoils_library = std::make_shared<Airfoils>(static_cast<std::filesystem::path>(config->common_airfoil_data_path.value())); airfoils_library->add_directory_airfoils(rtIO->getAirfoilDataDir()); @@ -84,7 +91,8 @@ void Wing::run() { myRuntimeInfo->out << "Selected design method ... [FINISHED]" << std::endl; myRuntimeInfo->out << "Selected mass method ... [START]" << std::endl; - mass_mode_runner[selected_mass_mode](); + mass_mode_runner[selected_mass_mode](); //TODO kayra: burada bir eksik var back mass mode runner, + back_mass_mode_runner[selected_back_mass_mode](); //belki ikisi icin ortak mass mode daha mantikli myRuntimeInfo->out << "Selected mass method ... [FINISHED]" << std::endl; myRuntimeInfo->out << "Run wing design ... [FINISHED]" << std::endl; @@ -103,7 +111,11 @@ void Wing::report() { reporter.generateReports(); /* Generate wing stl */ geom2::Mesh wing_mesh = geom2::transform::to_mesh(data->wing); - CGAL::IO::write_STL("wing_left.stl", wing_mesh); + CGAL::IO::write_STL("front_wing_left.stl", wing_mesh); + geom2::Mesh back_wing_mesh = geom2::transform::to_mesh(data->back_wing); + CGAL::IO::write_STL("back_wing_left.stl", back_wing_mesh); + geom2::Mesh combined_mesh = combine_meshes(wing_mesh, back_wing_mesh); + CGAL::IO::write_STL("front_and_back_wing_left.stl", combined_mesh); myRuntimeInfo->out << "Report designed wing ... [FINISHED]" << std::endl; } void Wing::save() { @@ -117,126 +129,251 @@ void Wing::standard_design() { /* Run standard method */ myRuntimeInfo->out << "Wing Design ... [Start]" << std::endl; - /* check if wing is kinked */ + double f_L = geom2::measure::length(data->fuselage); + myRuntimeInfo->out << "fuselage length: " << f_L << std::endl; + + myRuntimeInfo->out << "relative longitudinal position of tandem wing set and front wing: " << data->specification_longitudinal_position.value() << " of fuselage length" << std::endl; + myRuntimeInfo->out << "relative LE stagger: " << config->user_relative_LE_stagger.value() << " of fuselage length" << std::endl; + myRuntimeInfo->out << "relative position of rear wing: " << data->specification_longitudinal_position.value() + config->user_relative_LE_stagger.value() << " of fuselage length" << std::endl; + + //TODO kayra: bunu dah altta chord length ile birlikte cagirsam mantikli olabilir. ama wing gemometry calculationa da dikkat ederek cagirmak lazim olur. + if (data->specification_longitudinal_position.value() + config->user_relative_LE_stagger.value() > 1) { + throwError(__FILE__,__func__,__LINE__,"Error - Position of rear wing exceeds fuselage length. Please decrease your tandem wing set position value or your stagger value"); + } + + /* check seperately if wings are kinked */ //TODO kayra: kink olayini user defined yapabilirsin tamamen. bool is_wing_kinked = is_wing_kinked_check(); + bool is_back_wing_kinked = is_back_wing_kinked_check(); - /* get maximum thickness to chord ratio */ + /* get maximum thickness to chord ratios of wings */ double max_thickness_to_chord_ratio = get_max_thickness_to_chord_ratio(); + myRuntimeInfo->out << "max_thickness_to_chord_ratio: " << max_thickness_to_chord_ratio << std::endl; + double back_max_thickness_to_chord_ratio = get_back_max_thickness_to_chord_ratio(); + myRuntimeInfo->out << "back_max_thickness_to_chord_ratio: " << back_max_thickness_to_chord_ratio << std::endl; + /* get mtom */ double maximum_takeoff_mass = get_maximum_takeoff_mass(); + myRuntimeInfo->out << "MTOM: " << maximum_takeoff_mass << std::endl; - // Compute wing quarter chord based on selected mode - const double installed_quarter_chord_sweep = get_wing_quarter_chord_sweep( - config->sweep_calculation_mode.value(), config->user_sweep_angle_at_quarter_chord.value(), - data->specification_design_mach.value(), data->sizing_point_wing_loading.value(), - data->specification_design_altitude.value(), max_thickness_to_chord_ratio, - config->delta_drag_divergence_to_mach_design.value(), config->korn_technology_factor.value()); - - // Compute wing area based on selected mode - myRuntimeInfo->out << "Calculated wing area is the TOTAL WING AREA of both wings." << std::endl; - const double installed_wing_area = + // Compute total wing area based on selected mode + myRuntimeInfo->out << "Calculated wing area is the TOTAL WING AREA of both wings!" << std::endl; + const double installed_total_wing_area = get_design_wing_area(config->total_wing_area_calculation_mode.value(), config->user_total_wing_area.value(), maximum_takeoff_mass, data->sizing_point_wing_loading.value()); - myRuntimeInfo->out <<"Total Wing Area: "<< config->user_total_wing_area.value() << std::endl; + const double wing_area_ratio = config->user_wing_area_ratio.value(); + + myRuntimeInfo->out <<"Wing Area Ratio: "<< wing_area_ratio << std::endl; - //kendi yazdiklarim TODO kayra - myRuntimeInfo->out <<"WAR: "<< config->user_wing_area_ratio.value() << std::endl; - myRuntimeInfo->out <<"WSR: "<< config->user_wing_span_ratio.value() << std::endl; + const double installed_front_wing_area = installed_total_wing_area / (wing_area_ratio + 1); + const double installed_back_wing_area = installed_total_wing_area - installed_front_wing_area; + + myRuntimeInfo->out <<"S_1: "<< installed_front_wing_area << std::endl; + myRuntimeInfo->out <<"S_2: "<< installed_back_wing_area << std::endl; + + + // Compute front wing quarter chord based on selected mode + myRuntimeInfo->out << "1/4 sweep of front Wing: " << std::endl; + const double installed_quarter_chord_sweep = get_wing_quarter_chord_sweep( + config->sweep_calculation_mode.value(), config->user_sweep_angle_at_quarter_chord.value(), + data->specification_design_mach.value(), data->sizing_point_wing_loading.value(), + data->specification_design_altitude.value(), max_thickness_to_chord_ratio, + config->delta_drag_divergence_to_mach_design.value(), config->korn_technology_factor.value()); + + myRuntimeInfo->out << "1/4 sweep of rear Wing: " << std::endl; + // Compute back wing quarter chord based on selected mode + const double installed_back_quarter_chord_sweep = get_wing_quarter_chord_sweep( + config->back_sweep_calculation_mode.value(), config->user_back_sweep_angle_at_quarter_chord.value(), + data->specification_design_mach.value(), data->sizing_point_wing_loading.value(), + data->specification_design_altitude.value(), back_max_thickness_to_chord_ratio, + config->back_delta_drag_divergence_to_mach_design.value(), config->back_korn_technology_factor.value()); - // Comptue aspect ratio and wing span + // Comptue aspect ratios and wing spans std::map<std::string, std::tuple<double, double>> limits_field_length_and_wing_span = icao_easa_aerodrome_reference_code(data->specification_icao_aerodrome_reference_code.value()); /* Current limits of wing span according to reference code data*/ const auto [lower_wing_span, upper_wing_span] = limits_field_length_and_wing_span["wing_span"]; - /* Compute aspect ratio based on selected mode*/ + /* Compute aspect ratios based on selected modes*/ + //TODO kayra spanden gidip AR bulman gerekebilir. uzun installed tapera kadar.ayrica sadece user a izin verebilirsin biri icin + //TODO kayra ayrica pitch up limit function icin Cop iki kanatta da ileri gidiyor ama bir finetuning gerekli mi bilmiyorum + //TODO kayra: aspect ratiolari da sinirlandiracak bir fkt yazabilirsin user birbirinden alakasiz vermesin diye yada ARR ile yap. + //myRuntimeInfo->out <<"WSR: "<< wing_span_ratio << std::endl;//TODO kayra:suan yanlislik yaratiyor + //TODO kayra: bu design icin gereksiz bir parametre olarak kalabilir eger farkli yapmazsak. + + myRuntimeInfo->out <<"AR_1 of forward wing: "<< std::endl; double aspect_ratio = get_design_aspect_ratio(config->aspect_ratio_calculation_mode.value(), config->user_aspect_ratio.value(), installed_quarter_chord_sweep); - - /* Determine span and possible aspect ratio limits */ - double span = sqrt(aspect_ratio * installed_wing_area); - double maximum_possible_aspect_ratio = pow(upper_wing_span, 2.) / installed_wing_area; - double minimum_possible_aspect_ratio = pow(lower_wing_span, 2.) / installed_wing_area; - - /* if current aspect ratio exceeds maximum possible aspect ratio -> set aspect ratio to maximum possible aspect ratio + + myRuntimeInfo->out <<"AR_2 of rear wing: "<< std::endl; + double back_aspect_ratio = get_design_aspect_ratio(config->back_aspect_ratio_calculation_mode.value(), + config->user_back_aspect_ratio.value(), installed_back_quarter_chord_sweep); + + /* Determine spans and possible aspect ratio limits */ + double span = sqrt(aspect_ratio * installed_front_wing_area); + myRuntimeInfo->out <<"b_1: "<< span << std::endl; + double back_span = sqrt(back_aspect_ratio * installed_back_wing_area); + myRuntimeInfo->out <<"b_2: "<< back_span << std::endl; + + + double maximum_possible_aspect_ratio = pow(upper_wing_span, 2.) / installed_front_wing_area; + double minimum_possible_aspect_ratio = pow(lower_wing_span, 2.) / installed_front_wing_area; + double maximum_possible_back_aspect_ratio = pow(upper_wing_span, 2.) / installed_back_wing_area; + double minimum_possible_back_aspect_ratio = pow(lower_wing_span, 2.) / installed_back_wing_area; + + /* if current aspect ratios exceed maximum possible aspect ratio -> set aspect ratios to maximum possible aspect ratio * and set span to according wing span */ if (aspect_ratio > maximum_possible_aspect_ratio) { - myRuntimeInfo->warn << "Calculated aspect ratio > maximum_possible_aspect_ratio" << std::endl; + myRuntimeInfo->warn << "Calculated aspect ratio for forward wing > maximum_possible_aspect_ratio" << std::endl; myRuntimeInfo->warn << "Switch to maximum possible aspect_ratio" << std::endl; aspect_ratio = maximum_possible_aspect_ratio; span = upper_wing_span; } - // Check if current aspect ratio is below lower span limit -> set aspect ratio to minimum possible aspect ratio and - // set span to according wing span */ + if (back_aspect_ratio > maximum_possible_back_aspect_ratio) { + myRuntimeInfo->warn << "Calculated aspect ratio for rear wing > maximum_possible_back_aspect_ratio" << std::endl; + myRuntimeInfo->warn << "Switch to maximum possible back_aspect_ratio" << std::endl; + back_aspect_ratio = maximum_possible_back_aspect_ratio; + back_span = upper_wing_span; + } + // Check if current aspect ratios are below lower span limits -> set aspect ratios to minimum possible aspect ratios and + // set spans to according wing spans */ if (aspect_ratio < minimum_possible_aspect_ratio) { - myRuntimeInfo->warn << "Current aspect ratio breach lower span limit ..." << std::endl; + myRuntimeInfo->warn << "Current aspect ratio for forward wing breach lower span limit ..." << std::endl; myRuntimeInfo->warn << "Switch to minimum possible aspect_ratio" << std::endl; aspect_ratio = minimum_possible_aspect_ratio; span = lower_wing_span; } + if (back_aspect_ratio < minimum_possible_back_aspect_ratio) { + myRuntimeInfo->warn << "Current aspect ratio for rear wing breach lower span limit ..." << std::endl; + myRuntimeInfo->warn << "Switch to minimum possible back_aspect_ratio" << std::endl; + back_aspect_ratio = minimum_possible_back_aspect_ratio; + back_span = lower_wing_span; + } - /* Freeze aspect ratio and span */ + /* Freeze aspect ratios and spans */ const double installed_aspect_ratio = aspect_ratio; + const double installed_back_aspect_ratio = back_aspect_ratio; const double installed_span = span; - // Compute taper ratio based on selected mode + const double installed_back_span = back_span; + + myRuntimeInfo->out <<"jetzt korrigierte Werte: "<< std::endl; + myRuntimeInfo->out <<"AR_1: "<< installed_aspect_ratio << std::endl; + myRuntimeInfo->out <<"AR_2: "<< installed_back_aspect_ratio << std::endl; + myRuntimeInfo->out <<"b_1: "<< installed_span << std::endl; + myRuntimeInfo->out <<"b_2: "<< installed_back_span << std::endl; + + double wing_span_ratio = installed_back_span / installed_span; //TODO kayra: just to show + myRuntimeInfo->out <<"Wing Span Ratio: "<< wing_span_ratio << std::endl; + + double aspect_ratio_ratio = installed_back_aspect_ratio / installed_aspect_ratio; //TODO kayra: just to show + myRuntimeInfo->out <<"Aspect Ratio Ratio: "<< aspect_ratio_ratio << std::endl; + + // Compute taper ratios based on selected modes + myRuntimeInfo->out <<"Taper Ratio of forward wing: "<< std::endl; const double installed_taper_ratio = get_design_taper_ratio(config->taper_ratio_calculation_mode.value(), config->user_taper_ratio.value(), installed_aspect_ratio, installed_quarter_chord_sweep); - - // Comptue dihedral based on selected mode + myRuntimeInfo->out <<"Taper Ratio of rear wing: "<< std::endl; + const double installed_back_taper_ratio = + get_design_taper_ratio(config->back_taper_ratio_calculation_mode.value(), config->user_back_taper_ratio.value(), + installed_back_aspect_ratio, installed_back_quarter_chord_sweep); + + // Comptue dihedrals based on selected modes + //TODO kayra: iste burada rolling stability acisindan ciddi sikintilar cikabilir. dihedral diff gerekebilir. Paper var + myRuntimeInfo->out <<"Dihedral Angle of forward wing: "<< std::endl; const double installed_dihedral = get_design_dihedral( config->dihedral_calculation_mode.value(), data->specification_wing_mounting.value(), config->user_dihedral.value(), installed_quarter_chord_sweep, data->specification_design_mach.value()); + myRuntimeInfo->out <<"Dihedral Angle of rear wing: "<< std::endl; + const double installed_back_dihedral = get_design_dihedral( + config->back_dihedral_calculation_mode.value(), data->specification_back_wing_mounting.value(), + config->user_back_dihedral.value(), installed_back_quarter_chord_sweep, data->specification_design_mach.value()); - // Generate wing + // Generate wings + myRuntimeInfo->out <<"FORWARD WING PROFILE: "<< std::endl; if (is_wing_kinked) { data->wing = calculate_kinked_wing_geometry(installed_taper_ratio, installed_aspect_ratio, installed_quarter_chord_sweep, - installed_dihedral, installed_wing_area, installed_span); + installed_dihedral, installed_front_wing_area, installed_span); } else { data->wing = calculate_unkinked_wing_geometry(installed_taper_ratio, installed_aspect_ratio, installed_quarter_chord_sweep, - installed_dihedral, installed_wing_area, installed_span); + installed_dihedral, installed_front_wing_area, installed_span); + } + myRuntimeInfo->out <<"REAR WING PROFILE: "<< std::endl; + if (is_back_wing_kinked) { + data->back_wing = + calculate_kinked_back_wing_geometry(installed_back_taper_ratio, installed_back_aspect_ratio, installed_back_quarter_chord_sweep, + installed_back_dihedral, installed_back_wing_area, installed_back_span); + } else { + data->back_wing = + calculate_unkinked_back_wing_geometry(installed_back_taper_ratio, installed_back_aspect_ratio, installed_back_quarter_chord_sweep, + installed_back_dihedral, installed_back_wing_area, installed_back_span); } - // Set wing name to constant name - data->wing.name = "main_wing"; + // Set wing names to constant names + data->wing.name = "FRONT WING"; + data->back_wing.name ="BACK WING"; data->wing_position.set_xyz(calculate_wing_position()); - // Set spar devices + myRuntimeInfo->out << "front wing position" << " X:" <<data->wing_position.x.value()<<" Y:"<<data->wing_position.y.value()<<" Z:"<<data->wing_position.z.value()<< std::endl; + + data->back_wing.origin = calculate_back_wing_position(); + + myRuntimeInfo->out << "back wing position" << " X:" <<data->back_wing.origin.x()+data->wing_position.x.value()<<" Y:"<<data->back_wing.origin.y()+data->wing_position.y.value()<<" Z:"<<data->back_wing.origin.z()+data->wing_position.z.value()<< std::endl; + + + // Set spar devices data->spars = get_spars(config->spars_mode.value(), config->user_defined_spars); + data->back_spars = get_spars(config->back_spars_mode.value(), config->user_defined_back_spars); // Set control devices + double eta_kink = 0.; + double back_eta_kink = 0.; + if (is_wing_kinked_check()) { eta_kink = get_design_relative_kink_position( config->relative_kink_position_calculation_mode.value(), config->user_relative_kink.value(), config->track_based_initial_relative_kink.value(), data->track_based_relative_kink.value()); } + if (is_back_wing_kinked_check()) { + back_eta_kink = get_design_relative_kink_position( + config->back_relative_kink_position_calculation_mode.value(), config->user_back_relative_kink.value(), + config->track_based_back_initial_relative_kink.value(), data->track_based_back_relative_kink.value()); + } + auto [devices, deflections] = get_control_devices(config->control_device_mode.value(), config->user_defined_control_devices, data->spars, data->wing, data->fuselage, is_wing_kinked_check(), eta_kink, config->high_lift_device_type_leading_edge.value(), config->high_lift_device_type_trailing_edge.value()); + + auto [back_devices, back_deflections] = get_control_devices(config->back_control_device_mode.value(), config->user_defined_back_control_devices, + data->back_spars, data->back_wing, data->fuselage, is_back_wing_kinked_check(), back_eta_kink, + config->back_high_lift_device_type_leading_edge.value(), + config->back_high_lift_device_type_trailing_edge.value()); + data->control_devices = devices; data->control_devices_deflections = deflections; + data->back_control_devices = back_devices; + data->back_control_devices_deflections = back_deflections; /* Check control device boundaries - if inside fuselage */ if ((config->control_device_mode.value() == "mode_0") && - (rtIO->aircraft_configuration_type() == "tube_and_wing")) { - double eta_fuselage_max = geom2::measure::width_max(data->fuselage) / geom2::measure::span(data->wing); + (rtIO->aircraft_configuration_type() == "tandem")) { + double eta_fuselage_max = geom2::measure::width_max(data->fuselage) / geom2::measure::span(data->wing); //TODO kayra: ok olabilir bu hesap devices uzak olsun for (auto& device : data->control_devices) { size_t sec_id = 0; for (auto& section : device.sections) { if (section.origin.z() < eta_fuselage_max * 1.1) { myRuntimeInfo->warn << std::format( - "User defined control device {} (section {}) inside fuselage width - set to span position to 1.1 " + "User defined control device for forward wing {} (section {}) inside fuselage width - set to span position to 1.1 " "fuselage width\n", device.name, sec_id); section.origin = geom2::Point_3(section.origin.x(), section.origin.y(), eta_fuselage_max * 1.1); @@ -245,18 +382,49 @@ void Wing::standard_design() { } } } + if ((config->back_control_device_mode.value() == "mode_0") && + (rtIO->aircraft_configuration_type() == "tandem")) { + double back_eta_fuselage_max = geom2::measure::width_max(data->fuselage) / geom2::measure::span(data->back_wing); + for (auto& device : data->back_control_devices) { + size_t sec_id = 0; + for (auto& section : device.sections) { + if (section.origin.z() < back_eta_fuselage_max * 1.1) { + myRuntimeInfo->warn << std::format( + "User defined control device for rear wing {} (section {}) inside fuselage width - set to span position to 1.1 " + "fuselage width\n", + device.name, sec_id); + section.origin = geom2::Point_3(section.origin.x(), section.origin.y(), back_eta_fuselage_max * 1.1); + } + sec_id++; + } + } + } } bool Wing::is_wing_kinked_check() { - myRuntimeInfo->out << "Wing kink check ..." << std::endl; + myRuntimeInfo->out << "Front Wing kink check ..." << std::endl; - /* Check if mounting is low & landing gear mounted on wing */ + /* Check if front wing mounting is low & landing gear mounted on front wing */ if (data->specification_wing_mounting.value()== "low" && data->specification_landing_gear_mounting.value() == "wing_mounted") { - myRuntimeInfo->out << "Wing is kinked ... [TRUE]" << std::endl; + myRuntimeInfo->out << "Front Wing is kinked ... [TRUE]" << std::endl; + return true; + } else { + myRuntimeInfo->out << "Front Wing is kinked ... [FALSE]" << std::endl; + return false; + } +} + +bool Wing::is_back_wing_kinked_check() { + myRuntimeInfo->out << "Back Wing kink check ..." << std::endl; + + /* Check if back wing mounting is low & landing gear mounted on back wing */ + if (data->specification_back_wing_mounting.value()== "low" && + data->specification_landing_gear_mounting.value() == "tandem_back_wing_mounted") { + myRuntimeInfo->out << "Back Wing is kinked ... [TRUE]" << std::endl; return true; } else { - myRuntimeInfo->out << "Wing is kinked ... [FALSE]" << std::endl; + myRuntimeInfo->out << "Back Wing is kinked ... [FALSE]" << std::endl; return false; } } @@ -276,10 +444,27 @@ double Wing::get_max_thickness_to_chord_ratio() { } } +double Wing::get_back_max_thickness_to_chord_ratio() { + // Get maximum thickness to chord ratio based on back wing profile and thickness mode + // If user - get maximum thickness from elements + // Else use max_thickness to chord ratio from sweep calculation method + if (config->back_wing_profile_and_thickness_calculation_mode.value() == "mode_0") { + std::vector<double> to_check; + for (auto item : config->user_back_thickness_to_chord) { + to_check.push_back(item.value()); + } + return *std::max_element(to_check.begin(), to_check.end()); + } else { + return config->back_max_thickness_to_chord_ratio.value(); + } +} + double Wing::get_maximum_takeoff_mass() { return data->mtom_mass_properties.data["mass"].value(); } +//TODO kayra: buralarda cok fazla ayarlama yapman lazim simdiden. gereksizleri de silmen lazim. eger arka taraf pos ayarlamasi yaparsan wing geometri hesabina da eklemen lazim.ayrica mass lere de + geom2::Point_3 Wing::calculate_wing_position() { // Get cg position - if overall not exists -> use fuselage cg double x_wing_apex, x_cg, y; @@ -292,7 +477,7 @@ geom2::Point_3 Wing::calculate_wing_position() { const double fuselage_length = geom2::measure::length(data->fuselage); const double fuselage_maximum_width = geom2::measure::width_max(data->fuselage); - const double fuselage_maximum_height = geom2::measure::height_max(data->fuselage); + const double fuselage_maximum_height = geom2::measure::height_max(data->fuselage); //TODO kayra:daha ayarini yapmamisim. keal beam de karisiklik yaratabilir. double fuselage_upper_z; double fuselage_lower_z; @@ -320,9 +505,54 @@ geom2::Point_3 Wing::calculate_wing_position() { } auto const [lim_low, lim_up] = z_limits; double z_position = lim_low + 0.5 * (lim_up - lim_low); - return geom2::Point_3(x_cg - x_mac_position_quarter_chord_referred_to_centerline, 0., z_position); + return geom2::Point_3(data->specification_longitudinal_position.value()*fuselage_length, 0., z_position); } +geom2::Point_3 Wing::calculate_back_wing_position() { + // Get cg position - if overall not exists -> use fuselage cg + double x_wing_apex, x_cg, y; + std::tuple<double, double> z_limits; + + double y_mac_position = geom2::measure::mean_aerodynamic_chord_position(data->back_wing); + double x_mac_position_quarter_chord_referred_to_centerline = + geom2::measure::offset_LE(data->back_wing, y_mac_position).x() + + 0.25 * geom2::measure::chord(data->back_wing, y_mac_position); + + const double fuselage_length = geom2::measure::length(data->fuselage); + const double fuselage_maximum_width = geom2::measure::width_max(data->fuselage); + const double fuselage_maximum_height = geom2::measure::height_max(data->fuselage); //TODO kayra:daha ayarini yapmamisim. keal beam de karisiklik yaratabilir. + + double fuselage_upper_z; + double fuselage_lower_z; + + /* Keel beam height as fraction of fuselage height*/ + double keel_beam_height = 0.005 * fuselage_maximum_height; // Assumed 0.5% of fuselage height + + /* Define wing position limits */ + if (data->specification_back_wing_mounting.value() == "low") { + fuselage_upper_z = data->fuselage.origin.z(); + fuselage_lower_z = data->fuselage.origin.z() - fuselage_maximum_height * 0.5; + keel_beam_height = 0.005 * (fuselage_upper_z - fuselage_lower_z); + z_limits = {fuselage_lower_z + keel_beam_height, fuselage_upper_z}; + } else if (data->specification_back_wing_mounting.value() == "high") { + z_limits = {fuselage_lower_z, fuselage_upper_z - keel_beam_height}; + } else { + z_limits = {fuselage_lower_z, fuselage_upper_z}; + } + + // Assume center position + if (data->mtom_mass_properties.data["x"].value() < 0.01 && !data->fuselage.sections.empty()) { + x_cg = fuselage_length * 0.45; + } else { + x_cg = data->mtom_mass_properties.data["x"].value(); + } + auto const [lim_low, lim_up] = z_limits; + double z_position = lim_low + 0.5 * (lim_up - lim_low); + + return geom2::Point_3(config->user_relative_LE_stagger.value()*fuselage_length, 0., z_position - data->wing_position.z.value()); +} + + geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_kinked_wing_geometry( const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, const double wing_area, const double span) { @@ -336,8 +566,8 @@ geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_kinked_wing_ge // Get normalized half span values - eta const double half_span = 0.5 * span; - const double half_fuselage_width = geom2::measure::width_max(data->fuselage) * 0.5; - + const double half_fuselage_width = + geom2::measure::width(data->fuselage, geom2::measure::length(data->fuselage) * data->specification_longitudinal_position.value()) * 0.5; //TODO kayra: max olmasi kesin degil wingin. ondan böyle yaptim const double eta_fuselage = half_fuselage_width / half_span; double eta_centerline = 0. / half_span; double eta_tip = half_span / half_span; @@ -415,19 +645,19 @@ geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_kinked_wing_ge // Condition 2: trailing edge inner wing <= trailing edge outer wing // K_eta * (1-taper_ratio_2) >= taper_ratio_2 - taper_ratio -> OK const double K_eta = (eta_tip - eta_kink) / (eta_kink - eta_fuselage); - std::cout << "Leading edge check ... "; + std::cout << "Leading edge of front wing check ... "; if ((K_eta * (1 - taper_ratio_inner)) >= (taper_ratio_inner - taper_ratio)) { std::cout << "[OK]" << std::endl; // Check if trailing edge is none negative // s*(eta_kink-eta_fuselage)*tan(sweep_leading_edge_inner) >= 1 - taper_ratio_2 -> ok - std::cout << "Trailing edge check ... "; + std::cout << "Trailing edge of front wing check ... "; if ((half_span * (eta_kink - eta_fuselage) * tan_inner_wing_leading_edge_sweep) >= (1 - taper_ratio_inner)) { std::cout << "[OK]" << std::endl; } else { - throwError(__FILE__,__func__,__LINE__,"Error - trailing edge condition not fulfilled (TE Sweep < 0)"); + throwError(__FILE__,__func__,__LINE__,"Error - trailing edge condition of front wing not fulfilled (TE Sweep < 0)"); } } else { - throwError(__FILE__,__func__,__LINE__,"Error - leading edge condition not fulfilled (LE Sweep inner < LE Sweep outer)."); + throwError(__FILE__,__func__,__LINE__,"Error - leading edge condition of front wing not fulfilled (LE Sweep inner < LE Sweep outer)."); } /* Create Sections */ @@ -478,6 +708,163 @@ geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_kinked_wing_ge return wing; } +geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_kinked_back_wing_geometry( + const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, + const double wing_area, const double span) { + double maximum_inner_trailing_edge_sweep = get_design_maximum_inner_trailing_edge_sweep( + config->back_relative_kink_position_calculation_mode.value(), + config->user_back_max_inner_trailing_edge_sweep.value(), // old converted to radians + config->track_based_back_max_inner_trailing_edge_sweep.value()); // old converted to radians + + const double max_thickness_to_chord_ratio = get_back_max_thickness_to_chord_ratio(); + + // Get normalized half span values - eta + const double half_span = 0.5 * span; + + const double half_fuselage_width = + geom2::measure::width(data->fuselage, geom2::measure::length(data->fuselage) * (data->specification_longitudinal_position.value()+config->user_relative_LE_stagger.value())) * 0.5; //TODO kayra + + const double eta_fuselage = half_fuselage_width / half_span; + double eta_centerline = 0. / half_span; + double eta_tip = half_span / half_span; + std::vector<double> eta_values = {eta_centerline, eta_fuselage, eta_tip}; + + double eta_kink = get_design_relative_kink_position( + config->back_relative_kink_position_calculation_mode.value(), config->user_back_relative_kink.value(), + config->track_based_back_initial_relative_kink.value(), data->track_based_back_relative_kink.value()); + eta_values.push_back(eta_kink); + + std::vector<std::tuple<double, double, std::string>> wing_profile_and_thickness_vector = + get_wing_profile_and_thickness(config->back_wing_profile_and_thickness_calculation_mode.value(), + config->user_back_wing_profiles_and_thickness_vector, + config->back_torenbeek_jenkinson_wing_profile.value(), max_thickness_to_chord_ratio, + config->back_airfoil_critical_factor.value(), data->specification_design_mach.value(), + data->specification_design_altitude.value(), quarter_chord_sweep, + config->back_delta_drag_divergence_to_mach_design.value(), + data->sizing_point_wing_loading.value(), eta_fuselage, eta_values); + + // Geometry computation functions + auto condition_trailing_edge_max = [=](const double inner_taper_ratio) { + return (4. / 3. * (tan(quarter_chord_sweep) - tan(maximum_inner_trailing_edge_sweep)) * half_span * + (eta_kink - eta_fuselage) / (1 - inner_taper_ratio)); + }; + + auto root_chord_function = [=](const double inner_taper_ratio) { + return wing_area / (2. * half_span * + (eta_fuselage + (1 + inner_taper_ratio) * 0.5 * (eta_kink - eta_fuselage) + + (inner_taper_ratio + taper_ratio) * 0.5 * (eta_tip - eta_kink))); + }; + + // Maximum possible taper ratio + const double eta_ratio = (eta_tip - eta_kink) / (eta_kink - eta_fuselage); + const double taper_ratio_inner_max = (eta_ratio + taper_ratio) / (1 + eta_ratio); + auto taper_ratio_inner_searcher = [=](const double inner_taper_ratio) { + return root_chord_function(inner_taper_ratio) - condition_trailing_edge_max(inner_taper_ratio); + }; + // Find root_chord which fulfills - half_wing_area = half_inner_wing_area + half_outer_wing_area + + // half_fuselage_area + double taper_ratio_inner = newton_algorithm(taper_ratio_inner_searcher, taper_ratio_inner_max); + if (taper_ratio_inner > taper_ratio_inner_max) { + taper_ratio_inner = taper_ratio_inner_max; + } + const double taper_ratio_outer = taper_ratio / taper_ratio_inner; + const double root_chord = root_chord_function(taper_ratio_inner); + + // Compute values for wing geometry + const double kink_chord = root_chord * taper_ratio_inner; + const double tip_chord = root_chord * taper_ratio; + const double fuselage_area = 2. * eta_fuselage * half_span * root_chord; + const double inner_wing_area = (eta_kink - eta_fuselage) * (1 + taper_ratio_inner) * half_span * root_chord; + const double outer_wing_area = (eta_tip - eta_kink) * (taper_ratio_inner + taper_ratio) * half_span * root_chord; + + // Inner wing + const double tan_inner_wing_quarter_chord_sweep = tan(quarter_chord_sweep); + const double tan_inner_wing_leading_edge_sweep = + tan_inner_wing_quarter_chord_sweep + + 0.25 * root_chord / (half_span * (eta_kink - eta_fuselage)) * (1 - taper_ratio_inner); + const double tan_inner_wing_trailing_edge_sweep = + tan_inner_wing_quarter_chord_sweep - + 0.75 * root_chord / (half_span * (eta_kink - eta_fuselage)) * (1 - taper_ratio_inner); + + // Outer wing + const double tan_outer_wing_quarter_chord_sweep = tan_inner_wing_quarter_chord_sweep; + const double tan_outer_wing_leading_edge_sweep = + tan_outer_wing_quarter_chord_sweep + + 0.25 * (root_chord * taper_ratio_inner) / (half_span * (eta_tip - eta_kink)) * (1 - taper_ratio_outer); + const double tan_outer_wing_trailing_edge_sweep = + tan_inner_wing_quarter_chord_sweep - + 0.75 * root_chord * taper_ratio_inner / (half_span * (eta_tip - eta_kink)) * (1 - taper_ratio_outer); + + // Check different conditions + // Check sweeps leading edge and trailing edge by single equation + // Condition 1: leading edge inner wing >= leading edge outer wing + // Condition 2: trailing edge inner wing <= trailing edge outer wing + // K_eta * (1-taper_ratio_2) >= taper_ratio_2 - taper_ratio -> OK + const double K_eta = (eta_tip - eta_kink) / (eta_kink - eta_fuselage); + std::cout << "Leading edge of rear wing check ... "; + if ((K_eta * (1 - taper_ratio_inner)) >= (taper_ratio_inner - taper_ratio)) { + std::cout << "[OK]" << std::endl; + // Check if trailing edge is none negative + // s*(eta_kink-eta_fuselage)*tan(sweep_leading_edge_inner) >= 1 - taper_ratio_2 -> ok + std::cout << "Trailing edge of rear wing check ... "; + if ((half_span * (eta_kink - eta_fuselage) * tan_inner_wing_leading_edge_sweep) >= (1 - taper_ratio_inner)) { + std::cout << "[OK]" << std::endl; + } else { + throwError(__FILE__,__func__,__LINE__,"Error - trailing edge condition of rear wing not fulfilled (TE Sweep < 0)"); + } + } else { + throwError(__FILE__,__func__,__LINE__,"Error - leading edge condition of rear wing not fulfilled (LE Sweep inner < LE Sweep outer)."); + } + + /* Create Sections */ + std::vector<geom2::AirfoilSection> sections; + geom2::MultisectionSurface<geom2::AirfoilSection> back_wing; + back_wing.is_symmetric = true; + geom2::Vector_3 section_position; + for (auto profile_and_thickness : wing_profile_and_thickness_vector) { + const auto [eta, t_to_c, profile] = profile_and_thickness; + sections.push_back(get_rescaled_airfoil_geometry(profile_and_thickness)); + + // Sections center -> fuselage + if (eta <= eta_fuselage) { + sections.back().origin = geom2::Point_3(0.0, 0.0, -eta * half_span); + sections.back().set_chord_length(root_chord); + } + // Sections fuselage -> kink + else if (eta > eta_fuselage && eta < eta_kink) { + double normalized_eta = (eta - eta_fuselage) / (eta_kink - eta_fuselage); + double x = + std::lerp(0.0, tan_inner_wing_leading_edge_sweep * (eta_kink - eta_fuselage) * half_span, normalized_eta); + double y = std::lerp(0.0, tan(dihedral) * (eta_kink - eta_fuselage) * half_span, normalized_eta); + double z = -eta * half_span; + double section_chord = std::lerp(root_chord, taper_ratio_inner * root_chord, normalized_eta); + sections.back().origin = geom2::Point_3(x, y, z); + sections.back().set_chord_length(section_chord); + } + // Sections kink -> tip + else { + double normalized_eta = (eta - eta_kink) / (eta_tip - eta_kink); + double x = std::lerp(0.0, tan_outer_wing_leading_edge_sweep * (eta_tip - eta_kink) * half_span, normalized_eta) + + tan_inner_wing_leading_edge_sweep * (eta_kink - eta_fuselage) * half_span; + double y = std::lerp(0.0, tan(dihedral) * (eta_tip - eta_kink) * half_span, normalized_eta) + + tan(dihedral) * (eta_kink - eta_fuselage) * half_span; + double z = -eta * half_span; + double section_chord = std::lerp(taper_ratio_inner * root_chord, taper_ratio * root_chord, normalized_eta); + sections.back().origin = geom2::Point_3(x, y, z); + sections.back().set_chord_length(section_chord); + } + sections.back().name = profile; + back_wing.sections.push_back(sections.back()); + back_wing.normal = geom2::Direction_3(0., -1., 0.); + // back_wing.origin = geom2::Point_3(0.45 * 37.5 - 0.5 * root_chord, 0., 0.); + back_wing.origin = geom2::Point_3(0., 0., 0.); //TODO kayra: temporarily + } + // Create Sections + + return back_wing; +} + + geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_unkinked_wing_geometry( const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, const double wing_area, const double span) { @@ -486,7 +873,7 @@ geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_unkinked_wing_ // Get normalized half span values - eta const double half_span = 0.5 * span; const double half_fuselage_width = - geom2::measure::width(data->fuselage, geom2::measure::length(data->fuselage) * 0.5) * 0.5; + geom2::measure::width(data->fuselage, geom2::measure::length(data->fuselage) * data->specification_longitudinal_position.value()) * 0.5; //TODO kayra const double eta_fuselage = half_fuselage_width / half_span; double eta_centerline = 0. / half_span; double eta_tip = half_span / half_span; @@ -547,28 +934,98 @@ geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_unkinked_wing_ return wing; } -void Wing::flops_mass() { - myRuntimeInfo->out << "Wing mass estimation using ... FLOPS" << std::endl; - myRuntimeInfo->out << "Calculating ... " << std::endl; - auto get_max_thickness_to_chord_ratio = [](const geom2::AirfoilSection section) { - std::vector<double> t_to_c; - const double chord = section.get_chord_length(); - const int steps = 50; - const double step_width = chord / steps; - for (size_t i = 0; i < steps; ++i) { - t_to_c.push_back(geom2::measure::thickness(section, i * step_width) / chord); - } - return *std::max_element(t_to_c.begin(), t_to_c.end()); - }; +geom2::MultisectionSurface<geom2::AirfoilSection> Wing::calculate_unkinked_back_wing_geometry( + const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, + const double wing_area, const double span) { + const double max_thickness_to_chord_ratio = get_back_max_thickness_to_chord_ratio(); - myRuntimeInfo->warn << "Following values are Hard coded!" << std::endl; - myRuntimeInfo->warn << "================================" << std::endl; - myRuntimeInfo->warn << "\twing_mounted_engines" << std::endl; - myRuntimeInfo->warn << "================================" << std::endl; - const double to_foot = convertUnit(METER, FOOT, 1.0); - const double to_meter = 1. / to_foot; - const double taper_ratio = geom2::measure::taper_ratio(data->wing); - const double span_ft = geom2::measure::span(data->wing) * to_foot; + // Get normalized half span values - eta + const double half_span = 0.5 * span; + const double half_fuselage_width = + geom2::measure::width(data->fuselage, geom2::measure::length(data->fuselage) * (data->specification_longitudinal_position.value()+config->user_relative_LE_stagger.value())) * 0.5; //TODO kayra + const double eta_fuselage = half_fuselage_width / half_span; + double eta_centerline = 0. / half_span; + double eta_tip = half_span / half_span; + std::vector<double> eta_values = {eta_centerline, eta_fuselage, eta_tip}; + + std::vector<std::tuple<double, double, std::string>> wing_profile_and_thickness_vector = + get_wing_profile_and_thickness(config->back_wing_profile_and_thickness_calculation_mode.value(), + config->user_back_wing_profiles_and_thickness_vector, + config->back_torenbeek_jenkinson_wing_profile.value(), max_thickness_to_chord_ratio, + config->back_airfoil_critical_factor.value(), data->specification_design_mach.value(), + data->specification_design_altitude.value(), quarter_chord_sweep, + config->back_delta_drag_divergence_to_mach_design.value(), + data->sizing_point_wing_loading.value(), eta_fuselage, eta_values); + + // Geometry computation functions + + const double root_chord = wing_area / (half_span * (2 * eta_fuselage + (1 + taper_ratio) * (eta_tip - eta_fuselage))); + // Compute values for wing geometry + + // Outer wing + const double tan_outer_wing_quarter_chord_sweep = tan(quarter_chord_sweep); + const double tan_outer_wing_leading_edge_sweep = + tan_outer_wing_quarter_chord_sweep + + 0.25 * root_chord / (half_span * (eta_tip - eta_fuselage)) * (1 - taper_ratio); + + std::vector<geom2::AirfoilSection> sections; + geom2::MultisectionSurface<geom2::AirfoilSection> back_wing; + back_wing.is_symmetric = true; + geom2::Vector_3 section_position; + for (auto profile_and_thickness : wing_profile_and_thickness_vector) { + const auto [eta, t_to_c, profile] = profile_and_thickness; + sections.push_back(get_rescaled_airfoil_geometry(profile_and_thickness)); + + // Sections center -> fuselage + if (eta <= eta_fuselage) { + sections.back().origin = geom2::Point_3(0.0, 0.0, -eta * half_span); + sections.back().set_chord_length(root_chord); + } + // Sections fuselage -> tip + else { + double normalized_eta = (eta - eta_fuselage) / (eta_tip - eta_fuselage); + double x = + std::lerp(0.0, tan_outer_wing_leading_edge_sweep * (eta_tip - eta_fuselage) * half_span, normalized_eta); + double y = std::lerp(0.0, tan(dihedral) * (eta_tip - eta_fuselage) * half_span, normalized_eta); + double z = -eta * half_span; + double section_chord = std::lerp(root_chord, taper_ratio * root_chord, normalized_eta); + sections.back().origin = geom2::Point_3(x, y, z); + sections.back().set_chord_length(section_chord); + } + + sections.back().name = profile; + back_wing.sections.push_back(sections.back()); + back_wing.normal = geom2::Direction_3(0., -1., 0.); + back_wing.origin = geom2::Point_3(0., 0., 0.); + } + + // Create Sections + return back_wing; +} + + +void Wing::flops_mass() { + myRuntimeInfo->out << "Front Wing mass estimation using ... FLOPS" << std::endl; + myRuntimeInfo->out << "Calculating ... " << std::endl; + auto get_max_thickness_to_chord_ratio = [](const geom2::AirfoilSection section) { + std::vector<double> t_to_c; + const double chord = section.get_chord_length(); + const int steps = 50; + const double step_width = chord / steps; + for (size_t i = 0; i < steps; ++i) { + t_to_c.push_back(geom2::measure::thickness(section, i * step_width) / chord); + } + return *std::max_element(t_to_c.begin(), t_to_c.end()); + }; + + myRuntimeInfo->warn << "Following values are Hard coded!" << std::endl; + myRuntimeInfo->warn << "================================" << std::endl; + myRuntimeInfo->warn << "\twing_mounted_engines" << std::endl; + myRuntimeInfo->warn << "================================" << std::endl; + const double to_foot = convertUnit(METER, FOOT, 1.0); + const double to_meter = 1. / to_foot; + const double taper_ratio = geom2::measure::taper_ratio(data->wing); + const double span_ft = geom2::measure::span(data->wing) * to_foot; const double wing_area_sqrft = geom2::measure::reference_area(data->wing) * to_foot * to_foot; const double aspect_ratio = geom2::measure::aspect_ratio(data->wing); const double t_to_c_root = get_max_thickness_to_chord_ratio(data->wing.sections.front()); @@ -686,12 +1143,152 @@ void Wing::flops_mass() { } +void Wing::back_flops_mass() { + myRuntimeInfo->out << "Back Wing mass estimation using ... FLOPS" << std::endl; + myRuntimeInfo->out << "Calculating ... " << std::endl; + auto get_max_thickness_to_chord_ratio = [](const geom2::AirfoilSection section) { + std::vector<double> t_to_c; + const double chord = section.get_chord_length(); + const int steps = 50; + const double step_width = chord / steps; + for (size_t i = 0; i < steps; ++i) { + t_to_c.push_back(geom2::measure::thickness(section, i * step_width) / chord); + } + return *std::max_element(t_to_c.begin(), t_to_c.end()); + }; + + myRuntimeInfo->warn << "Following values are Hard coded!" << std::endl; + myRuntimeInfo->warn << "================================" << std::endl; + myRuntimeInfo->warn << "\twing_mounted_engines" << std::endl; + myRuntimeInfo->warn << "================================" << std::endl; + const double to_foot = convertUnit(METER, FOOT, 1.0); + const double to_meter = 1. / to_foot; + const double taper_ratio = geom2::measure::taper_ratio(data->back_wing); + const double span_ft = geom2::measure::span(data->back_wing) * to_foot; + const double wing_area_sqrft = geom2::measure::reference_area(data->back_wing) * to_foot * to_foot; + const double aspect_ratio = geom2::measure::aspect_ratio(data->back_wing); + const double t_to_c_root = get_max_thickness_to_chord_ratio(data->back_wing.sections.front()); + const double t_to_c_tip = get_max_thickness_to_chord_ratio(data->back_wing.sections.back()); + const double quarter_chord_sweep = + geom2::measure::sweep(data->back_wing, 0.25 * span_ft * to_meter, 0.25); // measure at 50% half span -> 25% of span + + const double to_lb = convertUnit(KILO, GRAM, NOPREFIX, POUND, 1.0); + const double to_kg = 1 / to_lb; + + const double dg = data->mtom_mass_properties.data["mass"].value() * to_lb; + + // Tangent of 3/4 chord wing sweep + double TLAM = tan(quarter_chord_sweep) - 2.0 * (1.0 - taper_ratio) / (aspect_ratio * (1.0 + taper_ratio)); + // Sine of 3/4 chord wing sweep angle + double SLAM = TLAM / (sqrt(1 + TLAM * TLAM)); + + // Factor Eq. 15 + double C4 = 1.0 - 0.5 * config->back_flops_faert.value(); + + // Factor Eq. 16 + double C6 = 0.5 * config->back_flops_faert.value() - 0.16 * config->back_flops_fstrt.value(); + + // Aspect ratio defined factor Eq. 17 + double CAYA = aspect_ratio > 5. ? aspect_ratio - 5.0 : 0.; + // Wing sweep and aeroelastic factor + double CAYL = (1.0 - SLAM * SLAM) * (1.0 + C6 * SLAM * SLAM + 0.03 * CAYA * C4 * SLAM); + + // Wing strut bracing factor (for cantilever w/o wing strut) + double EMS = 1.0 - 0.25 * config->back_flops_fstrt.value(); + // Weighted average of the wing thickness to chord ratio (Jenkinson 1999 formulation) + double TCA = 0.25 * (3. * t_to_c_tip + t_to_c_root); + // wing equivalent bending material factor Dimension [-] + double BT = 0.215 * (0.37 + 0.7 * taper_ratio) * pow(span_ft * span_ft / wing_area_sqrft, EMS) / (CAYL * TCA); + + // Total wing bending material weight + + // A1 - Table 1 Flops wing weight constants for transport and hwb + const double A1 = 8.80; + + // A2 + const double A2 = 6.25; + + // ULF - Structural Ultimate load factor - default 3.75 + const double ULF = 3.75; + + // CAYF - only single fuselage usage + const double CAYF = 1.0; + + // VARSWP - no variable sweep allowed + const double VARSWP = 0.0; + // VFACT + const double VFACT = 1.0; + // PCTL + const double PCTL = 1.0; + + // Wing bending material weight, not including the effects of inertia [lb] + const double W1NIR = A1 * BT * (1.0 + sqrt(A2 / span_ft)) * ULF * span_ft * + (1.0 - 0.4 * config->back_flops_fcomp.value()) * (1.0 - 0.1 * config->back_flops_faert.value()) * CAYF * + VFACT * PCTL / 1000000.0; + + // Total wing shear material and control surface weight + const double A3 = 0.68; + const double A4 = 0.34; + const double A5 = 0.6; + + // total movable wing surface area including flaps, elevators, spoilers etc [ft^2] + + const double SFLAP = get_back_control_device_area_in_fraction_of_back_wing_area() * + wing_area_sqrft; // set to 20% of wing_area - testing only TODO + + const double W2 = A3 * (1.0 - 0.17 * config->back_flops_fcomp.value()) * pow(SFLAP, A4) * pow(dg, A5); + + // Total wing miscellaneous items weight + const double A6 = 0.035; + const double A7 = 1.50; + + const double W3 = A6 * (1.0 - 0.3 * config->back_flops_fcomp.value()) * pow(wing_area_sqrft, A7); + + // Wing bending material weight intertia relief adjustment + const int NEW = data->specification_number_of_wing_mounted_engines; + const double CAYE = 1.0 - 0.03 * NEW; + + const double W1 = (dg * CAYE * W1NIR + W2 + W3) / (1.0 + W1NIR) - W2 - W3; + + // Total aft body weight for hybrid wing body aircraft - here no HWB + const double W4 = 0.0; + + // Total wing weight + const double wing_mass = config->back_flops_technology_factor.value() * (W1 + W2 + W3 + W4) * to_kg; + + myRuntimeInfo->out << "Calculated wing mass ... " << wing_mass << "[kg]" << std::endl; + myRuntimeInfo->out << "Wing bending material mass ... " << config->back_flops_technology_factor.value() * W1 * to_kg << "[kg]" << std::endl; + myRuntimeInfo->out << "Wing shear material and control surface mass ... " << config->back_flops_technology_factor.value() * W2 * to_kg << "[kg]" << std::endl; + myRuntimeInfo->out << "Wing miscellaneous items mass ... " << config->back_flops_technology_factor.value() * W3 * to_kg << "[kg]" << std::endl; + data->back_wing_mass_properties.data["mass"] = wing_mass; + + // Calculate wing center of gravity according to Howe 2005 page 252 + myRuntimeInfo->out << "Calculate Center of Gravity ..." << std::endl; + const double half_span_mac_position = geom2::measure::mean_aerodynamic_chord_position(data->back_wing); + const double mean_chord = geom2::measure::reference_area(data->back_wing) / geom2::measure::span(data->back_wing); + const double mac = geom2::measure::chord(data->back_wing, half_span_mac_position); + const geom2::Point_3 leading_edge_point = geom2::measure::offset_LE(data->back_wing, half_span_mac_position); + data->back_wing_mass_properties.data["x"].set_value(data->back_wing.origin.x() + leading_edge_point.x() + 0.25 * mac + + 0.1 * mean_chord); + // Transform values into global coordinate system z-> -y z + data->back_wing_mass_properties.data["y"].set_value(data->back_wing.origin.y() + fabs(leading_edge_point.z()) - + fabs(leading_edge_point.z())); + data->back_wing_mass_properties.data["z"].set_value(data->back_wing.origin.z() + leading_edge_point.y()); + + myRuntimeInfo->out << "CG Position..." << std::endl; + myRuntimeInfo->out << "x ... " << data->back_wing_mass_properties.data["x"].value() << std::endl; + myRuntimeInfo->out << "y ... " << data->back_wing_mass_properties.data["y"].value() << std::endl; + myRuntimeInfo->out << "z ... " << data->back_wing_mass_properties.data["z"].value() << std::endl; + +} + /** * \brief Chiozzotto weight estimation relationship mass estimation - assumes symmetric engine distribution on wings * */ +// TODO kayra: bu wing loadingli falan bir garip olabilir tandem icin, mtom da gariplik yaratir. void Wing::chiozzotto_wer_mass() { - myRuntimeInfo->out << "Wing mass estimation using ... CHIOZZOTTO" << std::endl; + myRuntimeInfo->out << "Front Wing mass estimation using ... CHIOZZOTTO" << std::endl; myRuntimeInfo->out << "Calculating ... " << std::endl; @@ -896,6 +1493,213 @@ void Wing::chiozzotto_wer_mass() { myRuntimeInfo->out << "z ... " << data->wing_mass_properties.data["z"].value() << std::endl; } +void Wing::back_chiozzotto_wer_mass() { + myRuntimeInfo->out << "Back Wing mass estimation using ... CHIOZZOTTO" << std::endl; + myRuntimeInfo->out << "Calculating ... " << std::endl; + + + std::map<std::string, std::tuple<double, double>> min_max_mtom = { + {"AL ASW", {20000, 250000}}, {"AL USW", {20000, 250000}}, {"AL FSW", {20000, 250000}}, + {"CFRP ASW", {20000, 250000}}, {"CFRP USW", {20000, 250000}}, {"CFRP FSW", {20000, 250000}}}; + std::map<std::string, std::tuple<double, double>> min_max_w_to_s = { + {"AL ASW", {3000, 8000}}, {"AL USW", {3000, 8000}}, {"AL FSW", {3000, 8000}}, + {"CFRP ASW", {3000, 8000}}, {"CFRP USW", {3000, 8000}}, {"CFRP FSW", {3000, 8000}}}; + std::map<std::string, std::tuple<double, double>> min_max_aspect_ratio = { + {"AL ASW", {10, 20}}, {"AL USW", {10, 20}}, {"AL FSW", {8, 16}}, + {"CFRP ASW", {10, 20}}, {"CFRP USW", {10, 20}}, {"CFRP FSW", {8, 16}}}; + std::map<std::string, std::tuple<double, double>> min_max_sweep = {{"AL ASW", {10, 40}}, {"AL USW", {0, 10}}, + {"AL FSW", {-5, -25}}, {"CFRP ASW", {10, 40}}, + {"CFRP USW", {0, 10}}, {"CFRP FSW", {-5, -25}}}; + std::map<std::string, std::tuple<double, double>> min_max_t_to_c = { + {"AL ASW", {0.08, 0.14}}, {"AL USW", {0.08, 0.18}}, {"AL FSW", {0.08, 0.16}}, + {"CFRP ASW", {0.08, 0.14}}, {"CFRP USW", {0.08, 0.18}}, {"CFRP FSW", {0.08, 0.16}}}; + std::map<std::string, std::tuple<double, double>> min_max_v_eas = { + {"AL ASW", {130, 200}}, {"AL USW", {130, 200}}, {"AL FSW", {130, 200}}, + {"CFRP ASW", {130, 200}}, {"CFRP USW", {130, 200}}, {"CFRP FSW", {130, 200}}}; + std::map<std::string, std::tuple<double, double>> min_max_taper_ratio = { + {"AL ASW", {0.1, 0.5}}, {"AL USW", {0.1, 0.5}}, {"AL FSW", {0.1, 0.5}}, + {"CFRP ASW", {0.1, 0.5}}, {"CFRP USW", {0.1, 0.5}}, {"CFRP FSW", {0.1, 0.5}}}; + + /**< Parameter containing a table of the constants and exponents of conventional Aircraft Covers*/ + std::map<std::string, std::tuple<double, double, double, double, double, double, double, double>> + lookup_table_covers = {{"AL ASW", {2.14e-3, 1.345, -0.623, 1.286, -1.601, -0.830, -0.010, 0.104}}, + {"AL USW", {2.66e-3, 1.320, -0.731, 1.370, 6.733, -0.945, 0.110, 0.305}}, + {"AL FSW", {2.82e-5, 1.373, -1.152, 2.006, -5.507, -1.549, 1.036, 0.698}}, + {"CFRP ASW", {9.47e-4, 1.440, -0.699, 1.233, -1.044, -0.808, 0.017, 0.518}}, + {"CFRP USW", {1.29e-3, 1.396, -0.929, 1.4481, 0.667, -1.051, 0.266, 0.633}}, + {"CFRP FSW", {3.92e-5, 1.401, -1.111, 1.874, -4.084, -1.436, 0.889, 0.751}}}; + + /**< Parameter containing a table of constants and exponents of conventional Aircraft spars and ribs*/ + std::map<std::string, std::tuple<double, double, double, double, double, double, double, double>> + lookup_table_spars_and_ribs = {{"AL ASW", {1.86, 1.384, -0.972, -0.072, -0.072, 0.486, 0.043, -0.126}}, + {"AL USW", {2.99, 1.376, -1.090, 0.008, 5.376, 0.423, 0.112, -0.070}}, + {"AL FSW", {9.82e-2, 1.362, -1.319, 0.598, -3.711, -0.126, 0.673, 0.391}}, + {"CFRP ASW", {1.50e-1, 1.411, -0.832, 0.105, -0.235, 0.301, 0.057, 0.101}}, + {"CFRP USW", {2.85e-1, 1.391, -0.994, 0.210, 5.854, 0.194, 0.164, 0.189}}, + {"CFRP FSW", {2.31e-2, 1.370, -1.174, 0.650, -2.750, -0.204, 0.620, 0.454}}}; + + /**< Parameter containing a table of constants and exponents of conventional Aircraft engine relief*/ + std::map<std::string, std::tuple<double, double, double>> lookup_table_engine_relief = { + {"AL ASW", {8.41, 3.017, 0.817}}, {"AL USW", {12.5, 2.177, 1.011}}, {"AL FSW", {25.4, 1.941, 1.204}}, + {"CFRP ASW", {15.3, 3.104, 0.909}}, {"CFRP USW", {13.6, 2.569, 0.910}}, {"CFRP FSW", {24.7, 2.117, 1.148}}}; + + // Chiozzotto Engine relief factor k_e (5.5 - Page 116) + // IF NUMBER OF ENGINES ON WING > 2 -> + // double engine_relative_spanwise_position = 0.3; // BOOKMARK + // Vector with data for one half -> + // More than one engine -> k_e = k_e_1 * k_e_2 + + double wing_loading = data->sizing_point_wing_loading.value(); + if (data->sizing_point_wing_loading.unit() == "kg/m^2") { + wing_loading *= G_FORCE; + } + + atmosphere isa; + const double mtom = data->mtom_mass_properties.data["mass"].value(); + const double aspect_ratio = geom2::measure::aspect_ratio(data->back_wing); + const double taper_ratio = geom2::measure::taper_ratio(data->back_wing); + const double half_span = geom2::measure::span(data->back_wing) * 0.5; + const double speed_of_sound_at_zero = isa.getSpeedOfSoundISA(0.0); + const double pressure_at_zero = isa.getPressureISA(0.0); + const double pressure_at_design_altitude = isa.getPressureISA(data->specification_design_altitude.value()); + + std::vector<std::tuple<double, double>> engines_mass_and_eta = data->wing_mounted_engine_data; + + // Calculation of EAS Design + const double v_eas_design = data->specification_design_mach.value() * speed_of_sound_at_zero * + sqrt(pressure_at_design_altitude / pressure_at_zero); + + // No LRA sweep existent - use 1/4 chord sweep (deviation from chiozzotto P.112 -> referred to figure 5.3) + const double quarter_chord_sweep = -geom2::measure::sweep(data->back_wing, 0.5 * half_span, 0.25); + + // Get material selection + std::string material = config->back_chiozzotto_material.value() + " "; + if (quarter_chord_sweep > ACCURACY_LOW) { + material += "ASW"; + } else if (quarter_chord_sweep < -ACCURACY_LOW) { + material += "FSW"; + } else { + material += "USW"; + } + myRuntimeInfo->out << "Wing material used ... " << material << std::endl; + + // Get design relative kink - + double t_to_c_kink = 0.0; + double eta_kink = 0.35; + if (is_back_wing_kinked_check()) { + eta_kink = get_design_relative_kink_position( + config->back_relative_kink_position_calculation_mode.value(), config->user_back_relative_kink.value(), + config->track_based_back_initial_relative_kink.value(), data->track_based_back_relative_kink.value()); + } + + // Find thickness to chord ratio + const double chord_at_kink = geom2::measure::chord(data->back_wing, eta_kink * half_span); + + double eta_position_last = 0.; + double max_thickness_last = 0.0; + double eta_position_next = 0.; + double max_thickness_next = 0.0; + for (size_t idx = 0; idx < data->back_wing.sections.size() - 1; ++idx) { + eta_position_last = fabs(data->back_wing.sections.at(idx).origin.z()) / half_span; + eta_position_next = fabs(data->back_wing.sections.at(idx + 1).origin.z()) / half_span; + // If kink at a specified section + if (fabs(eta_position_last - eta_kink) < ACCURACY_MEDIUM) { + t_to_c_kink = geom2::measure::thickness_max(data->back_wing.sections.at(idx)) / chord_at_kink; + } else if (fabs(eta_position_next - eta_kink) < ACCURACY_MEDIUM) { + t_to_c_kink = geom2::measure::thickness_max(data->back_wing.sections.at(idx)) / chord_at_kink; + } else if (eta_position_last > eta_kink && eta_position_next < eta_kink) { + double max_thickness_last = geom2::measure::thickness_max(data->back_wing.sections.at(idx)); + double max_thickness_next = geom2::measure::thickness_max(data->back_wing.sections.at(idx)); + double dimensionless_position = (eta_kink - eta_position_last) / (eta_position_last - eta_position_next); + t_to_c_kink = std::lerp(max_thickness_last, max_thickness_next, dimensionless_position) / chord_at_kink; + } else { + // Do nothing + } + } + + // Check inputs //TODO kayra: bundan assagida bir seyi ikiyle carpip sonuc alabilirsin sanirim iki wing massi ile + if (!(chiozzotto_wer_check_limits(min_max_mtom.at(material), mtom))) { + myRuntimeInfo->warn << "Chiozzotto limit check out of bounds ... mtom ... " << mtom << std::endl; + } + if (!(chiozzotto_wer_check_limits(min_max_w_to_s.at(material), wing_loading))) { + myRuntimeInfo->warn << "Chiozzotto limit check out of bounds ... wing_loading ... " << wing_loading << std::endl; + } + if (!(chiozzotto_wer_check_limits(min_max_aspect_ratio.at(material), aspect_ratio))) { + myRuntimeInfo->warn << "Chiozzotto limit check out of bounds ... aspect ratio ... " << aspect_ratio << std::endl; + } + if (!(chiozzotto_wer_check_limits(min_max_taper_ratio.at(material), taper_ratio))) { + myRuntimeInfo->warn << "Chiozzotto limit check out of bounds ... taper ratio ... " << taper_ratio << std::endl; + } + if (!(chiozzotto_wer_check_limits(min_max_sweep.at(material), quarter_chord_sweep * geom2::detail::to_degrees))) { + myRuntimeInfo->warn << "Chiozzotto limit check out of bounds ... sweep ... " + << quarter_chord_sweep * geom2::detail::to_degrees << std::endl; + } + if (!(chiozzotto_wer_check_limits(min_max_t_to_c.at(material), t_to_c_kink))) { + myRuntimeInfo->warn << "Chiozzotto limit check out of bounds ... thickness to chord ... " << t_to_c_kink + << std::endl; + } + if (!(chiozzotto_wer_check_limits(min_max_v_eas.at(material), v_eas_design))) { + myRuntimeInfo->warn << "Chiozzotto limit check out of bounds ... equivalent airspeed at design point ... " + << v_eas_design << std::endl; + } + + const auto [C_er, E_eta_er, E_K_er] = lookup_table_engine_relief[material]; + + // Engine relief factor + double k_e = 1.; + for (auto engine : engines_mass_and_eta) { + const auto [engine_mass, engine_spanwise_position] = engine; + /* If engines exist, the spanwise position is absolute, if engines not exist, the default values are in rel. half span */ + double engine_relative_spanwise_position = data->engines_exist ? std::fabs(engine_spanwise_position)/half_span : engine_spanwise_position; + //TODO kayra: engine existin arka kanat icin farkli olmasi gerekebilir + k_e *= (1 - C_er * pow(engine_relative_spanwise_position, E_eta_er) * pow(engine_mass / mtom, E_K_er)); + } + // Secondary structure mass + double mass_secondary_structure = 0.0443 * mtom * config->back_chiozzotto_technology_factor.value(); + + // Mass of covers + const auto [C_cov, mtom_cov, w_to_s_cov, ar_cov, cos_lambda_cov, t_to_c_kink_cov, v_eas_design_cov, + one_plus_taper_cov] = lookup_table_covers[material]; + double mass_covers = (k_e * C_cov * pow(mtom, mtom_cov) * pow(wing_loading, w_to_s_cov) * pow(aspect_ratio, ar_cov) * + pow(cos(quarter_chord_sweep), cos_lambda_cov) * pow(t_to_c_kink, t_to_c_kink_cov) * + pow(v_eas_design, v_eas_design_cov) * pow(1 + taper_ratio, one_plus_taper_cov)) * + config->back_chiozzotto_technology_factor.value(); + + // Mass of spars and ribs + const auto [C_sr, mtom_sr, w_to_s_sr, ar_sr, cos_lambda_sr, t_to_c_kink_sr, v_eas_design_sr, one_plus_taper_sr] = + lookup_table_spars_and_ribs[material]; + double mass_spars_and_ribs = (C_sr * pow(mtom, mtom_sr) * pow(wing_loading, w_to_s_sr) * pow(aspect_ratio, ar_sr) * + pow(cos(quarter_chord_sweep), cos_lambda_sr) * pow(t_to_c_kink, t_to_c_kink_sr) * + pow(v_eas_design, v_eas_design_sr) * pow(1 + taper_ratio, one_plus_taper_sr)) * + config->back_chiozzotto_technology_factor.value(); + + double wing_mass = mass_covers + mass_spars_and_ribs + mass_secondary_structure; + + myRuntimeInfo->out << "Calculated wing mass ... " << wing_mass << "[kg]" << std::endl; + myRuntimeInfo->out << "Wing mass spars and ribs ..." << mass_spars_and_ribs << "[kg]" << std::endl; + myRuntimeInfo->out << "Wing mass covers ..." << mass_covers << "[kg]" << std::endl; + myRuntimeInfo->out << "Wing mass secondary structure ..." << mass_secondary_structure << "[kg]" << std::endl; + data->back_wing_mass_properties.data["mass"] = wing_mass; + + // Calculate wing center of gravity according to Howe 2005 page 252 + myRuntimeInfo->out << "Calculate Center of Gravity ..." << std::endl; + const double half_span_mac_position = geom2::measure::mean_aerodynamic_chord_position(data->back_wing); + const double mean_chord = geom2::measure::reference_area(data->back_wing) / geom2::measure::span(data->back_wing); + const double mac = geom2::measure::chord(data->back_wing, half_span_mac_position); + const geom2::Point_3 leading_edge_point = geom2::measure::offset_LE(data->back_wing, half_span_mac_position); + data->back_wing_mass_properties.data["x"].set_value(data->back_wing.origin.x() + leading_edge_point.x() + 0.25 * mac + + 0.1 * mean_chord); + // Transform values into global coordinate system z-> -y z + data->back_wing_mass_properties.data["y"].set_value(data->back_wing.origin.y() + fabs(leading_edge_point.z()) - + fabs(leading_edge_point.z())); + data->back_wing_mass_properties.data["z"].set_value(data->back_wing.origin.z() + leading_edge_point.y()); + + myRuntimeInfo->out << "CG Position..." << std::endl; + myRuntimeInfo->out << "x ... " << data->back_wing_mass_properties.data["x"].value() << std::endl; + myRuntimeInfo->out << "y ... " << data->back_wing_mass_properties.data["y"].value() << std::endl; + myRuntimeInfo->out << "z ... " << data->back_wing_mass_properties.data["z"].value() << std::endl; +} + bool Wing::chiozzotto_wer_check_limits(std::tuple<double, double>& min_max, double value_to_check) { const auto [min, max] = min_max; if ((value_to_check > min && value_to_check < max) || @@ -915,7 +1719,18 @@ double Wing::get_control_device_area_in_fraction_of_wing_area() { } return overall_control_device_area / wing_area; } - geom2::AirfoilSection Wing::get_rescaled_airfoil_geometry(std::tuple<double, double, std::string> wing_profile_and_thickness) { + +double Wing::get_back_control_device_area_in_fraction_of_back_wing_area() { + double overall_control_device_area = 0.0; + double wing_area = geom2::measure::reference_area(data->back_wing); + for (auto& item : data->back_control_devices) { + auto cd = geom2::transform::to_absolute(item, data->back_wing); + overall_control_device_area += geom2::measure::area(cd); + } + return overall_control_device_area / wing_area; +} + +geom2::AirfoilSection Wing::get_rescaled_airfoil_geometry(std::tuple<double, double, std::string> wing_profile_and_thickness) { const auto [eta, t_to_c, wing_profile] = wing_profile_and_thickness; geom2::Polygon_2 shape = airfoils_library->get_airfoil(wing_profile); airfoils_library->copy_available_airfoil(wing_profile,rtIO->getAirfoilDataDir()); @@ -925,8 +1740,39 @@ double Wing::get_control_device_area_in_fraction_of_wing_area() { return section; } + + geom2::Mesh Wing::combine_meshes(geom2::Mesh mesh1, const geom2::Mesh mesh2) { + + // Define the Surface_mesh as a new type for a 3D point mesh + typedef CGAL::Surface_mesh<CGAL::Simple_cartesian<double>::Point_3> Surface_mesh; + + // Map to store the correspondence between vertices from mesh2 to mesh1 + std::map<Surface_mesh::Vertex_index, Surface_mesh::Vertex_index> vmap; + + // Iterate over vertices of mesh2 and add them to mesh1 + for (const auto& v2 : mesh2.vertices()) { + // Add vertex to mesh1 (this returns a reference to the new vertex) + vmap[v2] = mesh1.add_vertex(mesh2.point(v2)); + } + + // Iterate over faces of mesh2 and add them to mesh1 + for (const auto& f2 : mesh2.faces()) { + // Collect the vertices of the face in mesh2 + std::vector<Surface_mesh::Vertex_index> vertices; + Surface_mesh::Halfedge_index h = mesh2.halfedge(f2); + for (auto h_around = mesh2.halfedges_around_face(h).begin(); h_around != mesh2.halfedges_around_face(h).end(); ++h_around) { + Surface_mesh::Vertex_index v2 = mesh2.source(*h_around); + vertices.push_back(vmap[v2]); + } + // Add face to mesh1 + mesh1.add_face(vertices); + } + + return mesh1; +} + } // namespace cantilever -} // namespace taw +} // namespace tandem // Helper methods diff --git a/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.h b/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.h index 6c2a36a6e8b226a37d0a7c722181026e4a9838d2..c725f6756e431ecbe0c058fd793974018db0647c 100644 --- a/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.h +++ b/wing_design/src/tandem/cantilever/cantileverTandemWingDesign.h @@ -15,6 +15,7 @@ #include <moduleBasics/module.h> #include <moduleBasics/strategySelector.h> #include <moduleBasics/report.h> +#include <aircraftGeometry2/processing/transform.h> #include "src/tandem/tandemWingDesignConfig.h" #include "src/tandem/tandemWingDesignData.h" @@ -64,17 +65,31 @@ class Wing : public Strategy { void standard_design(); /** - * \brief mass method -> flops + * \brief mass method of front wing -> flops * */ void flops_mass(); /** - * \brief mass method -> chiozzotto weight estimation relationship + * \brief mass method of back wing -> flops + * + */ + void back_flops_mass(); + + + /** + * \brief mass method of front wing -> chiozzotto weight estimation relationship * */ void chiozzotto_wer_mass(); + /** + * \brief mass method of back wing -> chiozzotto weight estimation relationship + * + */ + void back_chiozzotto_wer_mass(); + + /** * \brief Chiozzotto utility check function * @@ -86,7 +101,7 @@ class Wing : public Strategy { bool chiozzotto_wer_check_limits(std::tuple<double, double>& min_max, double value_to_check); /** - * \brief Check if designed wing is a kinked or not + * \brief Check if designed front wing is a kinked or not * * \return true if kinked * \return false if not kinked @@ -94,12 +109,27 @@ class Wing : public Strategy { bool is_wing_kinked_check(); /** - * \brief Get the max thickness to chord ratio value + * \brief Check if designed back wing is a kinked or not + * + * \return true if kinked + * \return false if not kinked + */ + bool is_back_wing_kinked_check(); //TODO kayra: burdakiler icin de dokumentation lazim + + /** + * \brief Get the max thickness to chord ratio value for front wing * * \return double */ double get_max_thickness_to_chord_ratio(); + /** + * \brief Get the max thickness to chord ratio value for back wing + * + * \return double + */ + double get_back_max_thickness_to_chord_ratio(); + /** * \brief Get the maximum takeoff mass value * @@ -108,21 +138,37 @@ class Wing : public Strategy { double get_maximum_takeoff_mass(); /** - * \brief Get the control device area in fraction of wing area value + * \brief Get the front wing control device area in fraction of front wing area value * * \return double */ double get_control_device_area_in_fraction_of_wing_area(); /** - * \brief Calculates the wing position based on the fuselage length + * \brief Get the back wing control device area in fraction of back wing area value + * + * \return double + */ + double get_back_control_device_area_in_fraction_of_back_wing_area(); + + + /** + * \brief Calculates the front wing position based on the fuselage length * * \return geom2::Point_3 */ geom2::Point_3 calculate_wing_position(); /** - * \brief Calculation method for kinked wing geometry + * \brief Calculates the back wing position based on the fuselage length + * + * \return geom2::Point_3 + */ + geom2::Point_3 calculate_back_wing_position(); + + + /** + * \brief Calculation method for kinked front wing geometry * * \param taper_ratio * \param aspect_ratio @@ -136,6 +182,21 @@ class Wing : public Strategy { const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, const double wing_area, const double span); + /** + * \brief Calculation method for kinked back wing geometry + * + * \param taper_ratio + * \param aspect_ratio + * \param quarter_chord_sweep + * \param dihedral + * \param wing_area + * \param span + * \return geom2::MultisectionSurface<geom2::AirfoilSection> object + */ + geom2::MultisectionSurface<geom2::AirfoilSection> calculate_kinked_back_wing_geometry( + const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, + const double wing_area, const double span); + /** * \brief Get the rescaled airfoil geometry object * @@ -145,7 +206,7 @@ class Wing : public Strategy { geom2::AirfoilSection get_rescaled_airfoil_geometry(std::tuple<double, double, std::string> wing_profile_and_thickness); /** - * \brief Calculation method for unkinked wing geometry + * \brief Calculation method for unkinkedfront wing geometry * * \param taper_ratio * \param aspect_ratio @@ -159,6 +220,21 @@ class Wing : public Strategy { const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, const double wing_area, const double span); + /** + * \brief Calculation method for unkinked back wing geometry + * + * \param taper_ratio + * \param aspect_ratio + * \param quarter_chord_sweep + * \param dihedral + * \param wing_area + * \param span + * \return geom2::MultisectionSurface<geom2::AirfoilSection> object + */ + geom2::MultisectionSurface<geom2::AirfoilSection> calculate_unkinked_back_wing_geometry( + const double taper_ratio, const double aspect_ratio, const double quarter_chord_sweep, const double dihedral, + const double wing_area, const double span); + /** * \brief Set the html body * @@ -186,14 +262,24 @@ class Wing : public Strategy { */ std::vector<fs::path> plot_airfoils(); + /** + * \brief Method to combine two meshes into one + * + */ + geom2::Mesh combine_meshes(geom2::Mesh mesh1, geom2::Mesh mesh2); + std::string selected_design_mode; std::string selected_mass_mode; + std::string selected_back_mass_mode; + std::map<std::string, std::function<void(void)>> design_mode_runner; std::map<std::string, std::function<void(void)>> mass_mode_runner; + std::map<std::string, std::function<void(void)>> back_mass_mode_runner; + std::shared_ptr<Airfoils> airfoils_library; const std::shared_ptr<RuntimeIO>& rtIO; - const std::shared_ptr<tandem::cantilever::WingDesignData> data; + const std::shared_ptr<tandem::cantilever::WingDesignData> data; const std::shared_ptr<tandem::cantilever::WingDesignConfig> config; Report reporter; }; @@ -201,4 +287,4 @@ class Wing : public Strategy { } // namespace cantilever } // namespace tandem -#endif // LOW_WINGDESIGN_TAW_H_ \ No newline at end of file +#endif // LOW_WINGDESIGN_TANDEM_H_ \ No newline at end of file diff --git a/wing_design/src/tandem/tandemWingDesignConfig.cpp b/wing_design/src/tandem/tandemWingDesignConfig.cpp index 0a12302b8ef6fab8390fce464f15d8710a30e67d..c83c2141abfcbab1af91e8e81dedbc0ccda7b3b3 100644 --- a/wing_design/src/tandem/tandemWingDesignConfig.cpp +++ b/wing_design/src/tandem/tandemWingDesignConfig.cpp @@ -1,11 +1,13 @@ #include "tandemWingDesignConfig.h" -// front back function input TODO kayra + tandem::cantilever::WingDesignConfig::WingDesignConfig() : wing_design_mode(EndnodeReadOnly<std::string>("program_settings/modes/design_mode")), wing_mass_mode( EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/front_wing/mass/method")), + back_wing_mass_mode( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/mass/method")), wing_configuration_mode(EndnodeReadOnly<std::string>("program_settings/tandem/wing_configuration")), total_wing_area_calculation_mode(EndnodeReadOnly<std::string>( "program_settings/tandem/cantilever/calculation_methods/total_wing_area/method")), @@ -15,11 +17,8 @@ tandem::cantilever::WingDesignConfig::WingDesignConfig() //kendi yazdiklarim TODO kayra user_wing_area_ratio(EndnodeReadOnly<double>( "program_settings/tandem/cantilever/calculation_methods/wing_area_ratio/parameters/mode_0/wing_area_ratio")), - user_wing_span_ratio(EndnodeReadOnly<double>( - "program_settings/tandem/cantilever/calculation_methods/wing_span_ratio/parameters/mode_0/wing_span_ratio")), - - - + user_relative_LE_stagger(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/relative_LE_stagger/parameters/mode_0/relative_LE_stagger")), sweep_calculation_mode( EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/front_wing/sweep/method")), @@ -30,14 +29,34 @@ tandem::cantilever::WingDesignConfig::WingDesignConfig() delta_drag_divergence_to_mach_design( EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/front_wing/sweep/parameters/" "mode_1/delta_drag_divergence_to_mach_design")), + back_sweep_calculation_mode( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/sweep/method")), + user_back_sweep_angle_at_quarter_chord(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/sweep/parameters/mode_0/sweep_angle")), + back_korn_technology_factor(EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "sweep/parameters/mode_1/korn_technology_factor")), + back_delta_drag_divergence_to_mach_design( + EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/back_wing/sweep/parameters/" + "mode_1/delta_drag_divergence_to_mach_design")), + taper_ratio_calculation_mode(EndnodeReadOnly<std::string>( "program_settings/tandem/cantilever/calculation_methods/front_wing/taper_ratio/method")), user_taper_ratio(EndnodeReadOnly<double>( "program_settings/tandem/cantilever/calculation_methods/front_wing/taper_ratio/parameters/mode_0/taper_ratio")), + back_taper_ratio_calculation_mode(EndnodeReadOnly<std::string>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/taper_ratio/method")), + user_back_taper_ratio(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/taper_ratio/parameters/mode_0/taper_ratio")), + aspect_ratio_calculation_mode(EndnodeReadOnly<std::string>( "program_settings/tandem/cantilever/calculation_methods/front_wing/aspect_ratio/method")), user_aspect_ratio(EndnodeReadOnly<double>( "program_settings/tandem/cantilever/calculation_methods/front_wing/aspect_ratio/parameters/mode_0/aspect_ratio")), + back_aspect_ratio_calculation_mode(EndnodeReadOnly<std::string>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/aspect_ratio/method")), + user_back_aspect_ratio(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/aspect_ratio/parameters/mode_0/aspect_ratio")), + dihedral_calculation_mode(EndnodeReadOnly<std::string>( "program_settings/tandem/cantilever/calculation_methods/front_wing/dihedral/method")), user_dihedral(EndnodeReadOnly<double>( @@ -45,19 +64,43 @@ tandem::cantilever::WingDesignConfig::WingDesignConfig() dihedral_limitation_mode( EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/front_wing/dihedral/" "parameters/mode_1/dihedral_limitation")), + back_dihedral_calculation_mode(EndnodeReadOnly<std::string>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/dihedral/method")), + user_back_dihedral(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/dihedral/parameters/mode_0/dihedral_angle")), + back_dihedral_limitation_mode( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/dihedral/" + "parameters/mode_1/dihedral_limitation")), + relative_kink_position_calculation_mode(EndnodeReadOnly<std::string>( "program_settings/tandem/cantilever/calculation_methods/front_wing/relative_kink_position/method")), user_relative_kink(EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/front_wing/" "relative_kink_position/parameters/mode_0/relative_kink_position")), + back_relative_kink_position_calculation_mode(EndnodeReadOnly<std::string>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/relative_kink_position/method")), + user_back_relative_kink(EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "relative_kink_position/parameters/mode_0/relative_kink_position")), + user_max_inner_trailing_edge_sweep( EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/front_wing/" "relative_kink_position/parameters/mode_0/maximum_inner_trailing_edge_sweep")), + user_back_max_inner_trailing_edge_sweep( + EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "relative_kink_position/parameters/mode_0/maximum_inner_trailing_edge_sweep")), + track_based_initial_relative_kink( EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/front_wing/" "relative_kink_position/parameters/mode_1/initial_relative_kink_position")), track_based_max_inner_trailing_edge_sweep( EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/front_wing/" "relative_kink_position/parameters/mode_1/maximum_inner_trailing_edge_sweep")), + track_based_back_initial_relative_kink( + EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "relative_kink_position/parameters/mode_1/initial_relative_kink_position")), + track_based_back_max_inner_trailing_edge_sweep( + EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "relative_kink_position/parameters/mode_1/maximum_inner_trailing_edge_sweep")), + wing_profile_and_thickness_calculation_mode( EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/front_wing/" "wing_profile_and_thickness_distribution/method")), @@ -70,6 +113,19 @@ tandem::cantilever::WingDesignConfig::WingDesignConfig() airfoil_critical_factor( EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/front_wing/" "wing_profile_and_thickness_distribution/parameters/mode_1/airfoil_critical_factor")), + back_wing_profile_and_thickness_calculation_mode( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "wing_profile_and_thickness_distribution/method")), + back_torenbeek_jenkinson_wing_profile( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "wing_profile_and_thickness_distribution/parameters/mode_1/wing_profile")), + back_max_thickness_to_chord_ratio(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/wing_profile_and_thickness_distribution/" + "parameters/mode_1/max_thickness_to_chord_ratio")), + back_airfoil_critical_factor( + EndnodeReadOnly<double>("program_settings/tandem/cantilever/calculation_methods/back_wing/" + "wing_profile_and_thickness_distribution/parameters/mode_1/airfoil_critical_factor")), + control_device_mode(EndnodeReadOnly<std::string>( "program_settings/tandem/cantilever/calculation_methods/front_wing/control_devices/method")), high_lift_device_type_leading_edge( @@ -78,8 +134,20 @@ tandem::cantilever::WingDesignConfig::WingDesignConfig() high_lift_device_type_trailing_edge( EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/front_wing/control_devices/" "parameters/mode_1/high_lift_device_type_trailing_edge")), + back_control_device_mode(EndnodeReadOnly<std::string>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/control_devices/method")), + back_high_lift_device_type_leading_edge( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/control_devices/" + "parameters/mode_1/high_lift_device_type_leading_edge")), + back_high_lift_device_type_trailing_edge( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/control_devices/" + "parameters/mode_1/high_lift_device_type_trailing_edge")), + spars_mode( EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/front_wing/spars/method")), + back_spars_mode( + EndnodeReadOnly<std::string>("program_settings/tandem/cantilever/calculation_methods/back_wing/spars/method")), + flops_fstrt(EndnodeReadOnly<double>( "program_settings/tandem/cantilever/calculation_methods/front_wing/mass/parameters/mode_0/fstrt")), flops_faert(EndnodeReadOnly<double>( @@ -88,56 +156,121 @@ tandem::cantilever::WingDesignConfig::WingDesignConfig() "program_settings/tandem/cantilever/calculation_methods/front_wing/mass/parameters/mode_0/fcomp")), flops_technology_factor(EndnodeReadOnly<double>( "program_settings/tandem/cantilever/calculation_methods/front_wing/mass/parameters/mode_0/technology_factor")), + back_flops_fstrt(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/mass/parameters/mode_0/fstrt")), + back_flops_faert(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/mass/parameters/mode_0/faert")), + back_flops_fcomp(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/mass/parameters/mode_0/fcomp")), + back_flops_technology_factor(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/mass/parameters/mode_0/technology_factor")), + chiozzotto_technology_factor(EndnodeReadOnly<double>( "program_settings/tandem/cantilever/calculation_methods/front_wing/mass/parameters/mode_1/technology_factor")), chiozzotto_material(EndnodeReadOnly<std::string>( "program_settings/tandem/cantilever/calculation_methods/front_wing/mass/parameters/mode_1/material")), + back_chiozzotto_technology_factor(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/mass/parameters/mode_1/technology_factor")), + back_chiozzotto_material(EndnodeReadOnly<std::string>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/mass/parameters/mode_1/material")), + common_airfoil_data_path(EndnodeReadOnly<std::string>("module_configuration_file/program_settings/additional_directory_paths/common_airfoil_data_path")) {} + void tandem::cantilever::WingDesignConfig::read(const node& xml) { wing_design_mode.read(xml); wing_mass_mode.read(xml); + back_wing_mass_mode.read(xml); + wing_configuration_mode.read(xml); total_wing_area_calculation_mode.read(xml); user_total_wing_area.read(xml); - //kendi yazdiklarim TODO kayra - //beraber degerleri + //TODO kayra: beraber degerleri ama WSP silinmesi gerekebilir user_wing_area_ratio.read(xml); - user_wing_span_ratio.read(xml); + user_relative_LE_stagger.read(xml); sweep_calculation_mode.read(xml); user_sweep_angle_at_quarter_chord.read(xml); korn_technology_factor.read(xml); delta_drag_divergence_to_mach_design.read(xml); + + back_sweep_calculation_mode.read(xml); + user_back_sweep_angle_at_quarter_chord.read(xml); + back_korn_technology_factor.read(xml); + back_delta_drag_divergence_to_mach_design.read(xml); + taper_ratio_calculation_mode.read(xml); user_taper_ratio.read(xml); + back_taper_ratio_calculation_mode.read(xml); + user_back_taper_ratio.read(xml); + aspect_ratio_calculation_mode.read(xml); user_aspect_ratio.read(xml); + back_aspect_ratio_calculation_mode.read(xml); + user_back_aspect_ratio.read(xml); + dihedral_calculation_mode.read(xml); user_dihedral.read(xml); dihedral_limitation_mode.read(xml); + back_dihedral_calculation_mode.read(xml); + user_back_dihedral.read(xml); + back_dihedral_limitation_mode.read(xml); + relative_kink_position_calculation_mode.read(xml); user_relative_kink.read(xml); + back_relative_kink_position_calculation_mode.read(xml); + user_back_relative_kink.read(xml); + user_max_inner_trailing_edge_sweep.read(xml); + user_back_max_inner_trailing_edge_sweep.read(xml); + track_based_initial_relative_kink.read(xml); track_based_max_inner_trailing_edge_sweep.read(xml); + track_based_back_initial_relative_kink.read(xml); + track_based_back_max_inner_trailing_edge_sweep.read(xml); + wing_profile_and_thickness_calculation_mode.read(xml); torenbeek_jenkinson_wing_profile.read(xml); max_thickness_to_chord_ratio.read(xml); airfoil_critical_factor.read(xml); + control_device_mode.read(xml); + + back_wing_profile_and_thickness_calculation_mode.read(xml); + back_torenbeek_jenkinson_wing_profile.read(xml); + back_max_thickness_to_chord_ratio.read(xml); + back_airfoil_critical_factor.read(xml); + + control_device_mode.read(xml); high_lift_device_type_leading_edge.read(xml); high_lift_device_type_trailing_edge.read(xml); + + back_control_device_mode.read(xml); + back_high_lift_device_type_leading_edge.read(xml); + back_high_lift_device_type_trailing_edge.read(xml); + + spars_mode.read(xml); + back_spars_mode.read(xml); + flops_fstrt.read(xml); flops_faert.read(xml); flops_fcomp.read(xml); + flops_technology_factor.read(xml); + back_flops_fstrt.read(xml); + back_flops_faert.read(xml); + back_flops_fcomp.read(xml); + back_flops_technology_factor.read(xml); + chiozzotto_technology_factor.read(xml); chiozzotto_material.read(xml); + back_chiozzotto_technology_factor.read(xml); + back_chiozzotto_material.read(xml); + common_airfoil_data_path.read(xml); // Read user wing profiles thickness and half span position @@ -174,6 +307,39 @@ void tandem::cantilever::WingDesignConfig::read(const node& xml) { } } + if (user_back_wing_profiles.empty()) { + node* back_result; + int to_count = 0; + do { + back_result = xml.find( + "program_settings/tandem/cantilever/calculation_methods/back_wing/wing_profile_and_thickness_distribution/" + "parameters/mode_0/wing_profile_and_thickness@" + + std::to_string(to_count)); + to_count++; + } while (back_result != nullptr); + to_count--; + for (int i = 0; i < to_count; ++i) { + std::string id = std::to_string(i); + user_back_wing_profiles.push_back(EndnodeReadOnly<std::string>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/wing_profile_and_thickness_distribution/" + "parameters/mode_0/wing_profile_and_thickness@" + + id + "/wing_profile")); + user_back_thickness_to_chord.push_back(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/wing_profile_and_thickness_distribution/" + "parameters/mode_0/wing_profile_and_thickness@" + + id + "/thickness_to_chord/ratio")); + user_back_eta.push_back(EndnodeReadOnly<double>( + "program_settings/tandem/cantilever/calculation_methods/back_wing/wing_profile_and_thickness_distribution/" + "parameters/mode_0/wing_profile_and_thickness@" + + id + "/thickness_to_chord/at_half_span")); + user_back_wing_profiles[i].read(xml); + user_back_thickness_to_chord[i].read(xml); + user_back_eta[i].read(xml); + user_back_wing_profiles_and_thickness_vector.push_back( + {user_back_eta[i].value(), user_back_thickness_to_chord[i].value(), user_back_wing_profiles[i].value()}); + } + } + // read user defined control surfaces if (user_defined_control_devices.empty()) { node* result; @@ -194,6 +360,27 @@ void tandem::cantilever::WingDesignConfig::read(const node& xml) { user_defined_control_devices.back().read(xml); } } + + if (user_defined_back_control_devices.empty()) { + node* back_result; + int to_count = 0; + do { + back_result = xml.find( + "program_settings/tandem/cantilever/calculation_methods/back_wing/control_devices/" + "parameters/mode_0/control_device@" + + std::to_string(to_count)); + to_count++; + } while (back_result != nullptr); + to_count--; + for (int i = 0; i < to_count; ++i) { + user_defined_back_control_devices.push_back( + ControlDevice("program_settings/tandem/cantilever/calculation_methods/back_wing/control_devices/" + "parameters/mode_0/control_device@" + + std::to_string(i) + "/")); + user_defined_back_control_devices.back().read(xml); + } + } + // read user defined spars if (user_defined_spars.empty()) { node* result; @@ -214,4 +401,24 @@ void tandem::cantilever::WingDesignConfig::read(const node& xml) { user_defined_spars.back().read(xml); } } + + if (user_defined_back_spars.empty()) { + node* back_result; + int to_count = 0; + do { + back_result = xml.find( + "program_settings/tandem/cantilever/calculation_methods/back_wing/spars/" + "parameters/mode_0/spar@" + + std::to_string(to_count)); + to_count++; + } while (back_result != nullptr); + to_count--; + for (int i = 0; i < to_count; ++i) { + user_defined_back_spars.push_back( + Spar("program_settings/tandem/cantilever/calculation_methods/back_wing/spars/" + "parameters/mode_0/spar@" + + std::to_string(i) + "/")); + user_defined_back_spars.back().read(xml); + } + } } diff --git a/wing_design/src/tandem/tandemWingDesignConfig.h b/wing_design/src/tandem/tandemWingDesignConfig.h index 9ee7ede7bb91660bf9ec4f12d6cd8c6716bb3f62..9a7910106ab8e1a660ef32dfb1f3a91c7c08bc99 100644 --- a/wing_design/src/tandem/tandemWingDesignConfig.h +++ b/wing_design/src/tandem/tandemWingDesignConfig.h @@ -34,15 +34,17 @@ class WingDesignConfig { EndnodeReadOnly<std::string> wing_design_mode; EndnodeReadOnly<std::string> wing_configuration_mode; EndnodeReadOnly<std::string> wing_mass_mode; + EndnodeReadOnly<std::string> back_wing_mass_mode; + /* Design */ /* Data for method - wing area calculation */ EndnodeReadOnly<std::string> total_wing_area_calculation_mode; EndnodeReadOnly<double> user_total_wing_area; //kendi yazdiklarim TODO kayra - //beraber degerleri + EndnodeReadOnly<double> user_wing_area_ratio; - EndnodeReadOnly<double> user_wing_span_ratio; + EndnodeReadOnly<double> user_relative_LE_stagger; @@ -52,25 +54,49 @@ class WingDesignConfig { EndnodeReadOnly<double> korn_technology_factor; EndnodeReadOnly<double> delta_drag_divergence_to_mach_design; + EndnodeReadOnly<std::string> back_sweep_calculation_mode; + EndnodeReadOnly<double> user_back_sweep_angle_at_quarter_chord; + EndnodeReadOnly<double> back_korn_technology_factor; + EndnodeReadOnly<double> back_delta_drag_divergence_to_mach_design; + /* Data for method - taper ratio calculation */ EndnodeReadOnly<std::string> taper_ratio_calculation_mode; EndnodeReadOnly<double> user_taper_ratio; + EndnodeReadOnly<std::string> back_taper_ratio_calculation_mode; + EndnodeReadOnly<double> user_back_taper_ratio; + /* Data for method - aspect ratio calculation */ EndnodeReadOnly<std::string> aspect_ratio_calculation_mode; EndnodeReadOnly<double> user_aspect_ratio; + EndnodeReadOnly<std::string> back_aspect_ratio_calculation_mode; + EndnodeReadOnly<double> user_back_aspect_ratio; + /* Data for method - dihedral calculation*/ EndnodeReadOnly<std::string> dihedral_calculation_mode; EndnodeReadOnly<std::string> dihedral_limitation_mode; EndnodeReadOnly<double> user_dihedral; + EndnodeReadOnly<std::string> back_dihedral_calculation_mode; + EndnodeReadOnly<std::string> back_dihedral_limitation_mode; + EndnodeReadOnly<double> user_back_dihedral; + EndnodeReadOnly<std::string> relative_kink_position_calculation_mode; EndnodeReadOnly<double> user_relative_kink; + + EndnodeReadOnly<std::string> back_relative_kink_position_calculation_mode; + EndnodeReadOnly<double> user_back_relative_kink; + EndnodeReadOnly<double> user_max_inner_trailing_edge_sweep; + + EndnodeReadOnly<double> user_back_max_inner_trailing_edge_sweep; + EndnodeReadOnly<double> track_based_initial_relative_kink; EndnodeReadOnly<double> track_based_max_inner_trailing_edge_sweep; + EndnodeReadOnly<double> track_based_back_initial_relative_kink; + EndnodeReadOnly<double> track_based_back_max_inner_trailing_edge_sweep; /* Data for method - wing profile and thickness calculation */ EndnodeReadOnly<std::string> wing_profile_and_thickness_calculation_mode; @@ -82,6 +108,15 @@ class WingDesignConfig { EndnodeReadOnly<double> max_thickness_to_chord_ratio; EndnodeReadOnly<double> airfoil_critical_factor; + EndnodeReadOnly<std::string> back_wing_profile_and_thickness_calculation_mode; + std::vector<EndnodeReadOnly<std::string>> user_back_wing_profiles; + std::vector<EndnodeReadOnly<double>> user_back_thickness_to_chord; + std::vector<EndnodeReadOnly<double>> user_back_eta; + std::vector<std::tuple<double, double, std::string>> user_back_wing_profiles_and_thickness_vector; //TODO kayra + EndnodeReadOnly<std::string> back_torenbeek_jenkinson_wing_profile; + EndnodeReadOnly<double> back_max_thickness_to_chord_ratio; + EndnodeReadOnly<double> back_airfoil_critical_factor; + /* Mass */ @@ -91,22 +126,39 @@ class WingDesignConfig { EndnodeReadOnly<double> flops_fcomp; EndnodeReadOnly<double> flops_technology_factor; + EndnodeReadOnly<double> back_flops_fstrt; + EndnodeReadOnly<double> back_flops_faert; + EndnodeReadOnly<double> back_flops_fcomp; + EndnodeReadOnly<double> back_flops_technology_factor; + // chiozzotto wer mass method EndnodeReadOnly<double> chiozzotto_technology_factor; EndnodeReadOnly<std::string> chiozzotto_material; + EndnodeReadOnly<double> back_chiozzotto_technology_factor; + EndnodeReadOnly<std::string> back_chiozzotto_material; + /* Data for method - control devices */ EndnodeReadOnly<std::string> control_device_mode; std::vector<ControlDevice> user_defined_control_devices; EndnodeReadOnly<std::string> high_lift_device_type_leading_edge; EndnodeReadOnly<std::string> high_lift_device_type_trailing_edge; + EndnodeReadOnly<std::string> back_control_device_mode; + std::vector<ControlDevice> user_defined_back_control_devices; + EndnodeReadOnly<std::string> back_high_lift_device_type_leading_edge; + EndnodeReadOnly<std::string> back_high_lift_device_type_trailing_edge; + /* Data for method - spars */ EndnodeReadOnly<std::string> spars_mode; std::vector<Spar> user_defined_spars; + + EndnodeReadOnly<std::string> back_spars_mode; + std::vector<Spar> user_defined_back_spars; /* Additional paths */ EndnodeReadOnly<std::string> common_airfoil_data_path; + }; } // namespace cantilever } // namespace tandem diff --git a/wing_design/src/tandem/tandemWingDesignData.cpp b/wing_design/src/tandem/tandemWingDesignData.cpp index 276e9147645d02b15c897af404444a8a94c483c9..115234e70c7e1ac02d23509cf2e60a535f1560e7 100644 --- a/wing_design/src/tandem/tandemWingDesignData.cpp +++ b/wing_design/src/tandem/tandemWingDesignData.cpp @@ -1,8 +1,8 @@ #include "tandemWingDesignData.h" /** - * \file tawWingDesignData.cpp + * \file tandemWingDesignData.cpp * \author Christopher Ruwisch (christopher.ruwisch@tu-berlin.de) - * \brief Tube and wing wing design data + * \brief Tandem wing wing design data * \version 0.1 * \date 2023-12-20 * @@ -17,9 +17,13 @@ tandem::cantilever::WingDesignData::WingDesignData() EndnodeReadOnly<std::string>("requirements_and_specifications/requirements/top_level_aircraft_requirements/" "icao_aerodrome_reference_code")), specification_wing_mounting( - EndnodeReadOnly<std::string>("requirements_and_specifications/design_specification/configuration/wing_definition/mounting")), - specification_landing_gear_mounting(EndnodeReadOnly<std::string>( - "requirements_and_specifications/design_specification/configuration/undercarriage_definition/main_gear_mounting")), + EndnodeReadOnly<std::string>("requirements_and_specifications/design_specification/configuration/wing_definition/tandem_wing_mounting/front_mounting")), + specification_back_wing_mounting( + EndnodeReadOnly<std::string>("requirements_and_specifications/design_specification/configuration/wing_definition/tandem_wing_mounting/back_mounting")), + specification_landing_gear_mounting( + EndnodeReadOnly<std::string>("requirements_and_specifications/design_specification/configuration/undercarriage_definition/main_gear_mounting")), + specification_longitudinal_position( + EndnodeReadOnly<double>("requirements_and_specifications/design_specification/configuration/wing_definition/tandem_longitudinal_position")), specification_design_mach( EndnodeReadOnly<double>("requirements_and_specifications/requirements/top_level_aircraft_requirements/" "design_mission/initial_cruise_mach_number")), @@ -34,11 +38,15 @@ tandem::cantilever::WingDesignData::WingDesignData() sizing_point_wing_loading(EndnodeReadOnly<double>("sizing_point/wing_loading")), mtom_mass_properties(MassPropertiesIO("analysis/masses_cg_inertia/maximum_takeoff_mass","maximum takeoff mass")), wing_mass_properties(MassPropertiesIO("component_design/wing", "wing")), - wing_position(PositionIO("component_design/wing/position", "wing")) {} + back_wing_mass_properties(MassPropertiesIO("component_design/back_wing", "Back Wing")), + wing_position(PositionIO("component_design/wing/position", "tandem wing set")) {} + void tandem::cantilever::WingDesignData::read(const node& xml) { specification_icao_aerodrome_reference_code.read(xml); specification_wing_mounting.read(xml); + specification_back_wing_mounting.read(xml); + specification_longitudinal_position.read(xml); specification_landing_gear_mounting.read(xml); specification_design_mach.read(xml); specification_design_altitude.read(xml); @@ -46,7 +54,7 @@ void tandem::cantilever::WingDesignData::read(const node& xml) { specification_maximum_load_factor.read(xml); sizing_point_wing_loading.read(xml); mtom_mass_properties.read(xml); - read_wing_mounted_engine_information(xml); + read_wing_mounted_engine_information(xml); //TODO kayra: bununla ilgili seyleri back winge aynen aldim ayarlama lazim olabilir } void tandem::cantilever::WingDesignData::read_wing_mounted_engine_information(const node& xml) { @@ -108,6 +116,14 @@ void tandem::cantilever::WingDesignData::update_wing(node& xml) { io); } +void tandem::cantilever::WingDesignData::update_back_wing(node& xml) { + geom2::io::SurfaceType io = geom2::io::Wing(back_wing); + const std::string path_to_geometry_back = "component_design/wing/specific/geometry"; + std::visit(geom2::io::AixmlConverter(xml[path_to_geometry_back], + {"aerodynamic_surface", "1", back_wing.name}), + io); +} +// TODO KAYRA void tandem::cantilever::WingDesignData::update_spars(node& xml) { for (size_t i = 0; i < spars.size(); ++i) { geom2::io::SurfaceType io_spar = geom2::io::Spar(spars[i]); @@ -118,7 +134,17 @@ void tandem::cantilever::WingDesignData::update_spars(node& xml) { io_spar); } } - +void tandem::cantilever::WingDesignData::update_back_spars(node& xml) { + for (size_t i = 0; i < back_spars.size(); ++i) { + geom2::io::SurfaceType io_spar = geom2::io::Spar(back_spars[i]); + const std::string path_to_spars = "component_design/wing/specific/geometry/aerodynamic_surface@1/parameters/spars"; + std::visit(geom2::io::AixmlConverter( + xml[path_to_spars], + {"spar", std::to_string(i), back_spars[i].name}), + io_spar); + } +} +// TODO kayra void tandem::cantilever::WingDesignData::update_control_devices(node& xml) { for (size_t i = 0; i < control_devices.size(); ++i) { geom2::io::SurfaceType io_control_device = geom2::io::ControlDevice(control_devices[i]); @@ -139,15 +165,67 @@ void tandem::cantilever::WingDesignData::update_control_devices(node& xml) { max_deflection.update(xml); } } +void tandem::cantilever::WingDesignData::update_back_control_devices(node& xml) { + for (size_t i = 0; i < back_control_devices.size(); ++i) { + geom2::io::SurfaceType io_control_device = geom2::io::ControlDevice(back_control_devices[i]); + const std::string path_to_control_devices = "component_design/wing/specific/geometry/aerodynamic_surface@1/parameters/control_devices"; + std::visit(geom2::io::AixmlConverter( + xml[path_to_control_devices], + {"control_device", std::to_string(i), back_control_devices[i].name}), + io_control_device); + Endnode<double> back_min_deflection(path_to_control_devices + "/control_device@" + std::to_string(i) + "/deflection/full_negative_deflection","full negative deflection"); + Endnode<double> back_max_deflection(path_to_control_devices + "/control_device@" + std::to_string(i) + "/deflection/full_positive_deflection","full positive deflection"); + const auto [min, max] = back_control_devices_deflections[i]; + back_min_deflection.set_unit("rad"); + back_max_deflection.set_unit("rad"); + back_min_deflection.set_value(min); + back_max_deflection.set_value(max); + + back_min_deflection.update(xml); + back_max_deflection.update(xml); + } +} void tandem::cantilever::WingDesignData::update(node& xml) { + myRuntimeInfo->out << " [START]" << std::endl; + auto tmp = xml.find("component_design/wing"); if (tmp != nullptr) { tmp->deleteChildren(); } - wing_mass_properties.update(xml); + //tmp = xml.find("component_design/back_wing"); TODO kayra + //if (tmp != nullptr) { + // tmp->deleteChildren(); + //} + + + wing_mass_properties.update(xml); + + + back_wing_mass_properties.update(xml); + + wing_position.update(xml); - update_wing(xml); + + + + update_wing(xml); + + + update_back_wing(xml); + + + update_spars(xml); + + + update_back_spars(xml); + + update_control_devices(xml); + + + update_back_control_devices(xml); + + } diff --git a/wing_design/src/tandem/tandemWingDesignData.h b/wing_design/src/tandem/tandemWingDesignData.h index 64ae7c218339e3a8e161e4e59092407ce90fba64..57baccd4f234f1a2d1b81e6d31b0b861fdf3b4bf 100644 --- a/wing_design/src/tandem/tandemWingDesignData.h +++ b/wing_design/src/tandem/tandemWingDesignData.h @@ -17,7 +17,7 @@ #include <iostream> #include "lib/io_methods/massPropertiesIO.h" -//#include "massPropertiesIOError.h" + #include "lib/io_methods/positionIO.h" namespace tandem { @@ -34,11 +34,18 @@ class WingDesignData { void update(node& xml); void update_wing(node& xml); + void update_back_wing(node& xml); + void update_spars(node& xml); + void update_back_spars(node& xml); + void update_control_devices(node& xml); + void update_back_control_devices(node& xml); EndnodeReadOnly<std::string> specification_icao_aerodrome_reference_code; EndnodeReadOnly<std::string> specification_wing_mounting; + EndnodeReadOnly<std::string> specification_back_wing_mounting; + EndnodeReadOnly<double> specification_longitudinal_position; EndnodeReadOnly<std::string> specification_landing_gear_mounting; EndnodeReadOnly<double> specification_maximum_operating_mach; EndnodeReadOnly<double> specification_design_mach; @@ -46,21 +53,35 @@ class WingDesignData { EndnodeReadOnly<double> specification_maximum_load_factor; EndnodeReadOnly<double> sizing_point_wing_loading; EndnodeReadOnly<double> track_based_relative_kink; + EndnodeReadOnly<double> track_based_back_relative_kink; + Endnode<double> spanwise_kink; - size_t specification_number_of_wing_mounted_engines; + size_t specification_number_of_wing_mounted_engines; //TODO kayra: bununla ilgili seyleri back winge aynen aldim ayarlama lazim olabilir std::vector<std::tuple<double,double>> wing_mounted_engine_data; bool engines_exist = true; MassPropertiesIO mtom_mass_properties; MassPropertiesIO wing_mass_properties; + MassPropertiesIO back_wing_mass_properties; + PositionIO wing_position; + //PositionIO back_wing_position; //TODO kayra: silinecek + + PositionIO center_of_gravity_mtom; geom2::MultisectionSurface<geom2::PolygonSection> fuselage; geom2::MultisectionSurface<geom2::AirfoilSection> wing; + geom2::MultisectionSurface<geom2::AirfoilSection> back_wing; + // todo kayra std::vector<geom2::MultisectionSurface<geom2::PolygonSection>> control_devices; std::vector<std::tuple<double,double>> control_devices_deflections; + std::vector<geom2::MultisectionSurface<geom2::PolygonSection>> back_control_devices; + std::vector<std::tuple<double,double>> back_control_devices_deflections; + std::vector<geom2::MultisectionSurface<geom2::PolygonSection>> spars; + std::vector<geom2::MultisectionSurface<geom2::PolygonSection>> back_spars; + }; } // namespace cantilever } // namespace tandem diff --git a/wing_design/src/taw/tawWingDesignData.h b/wing_design/src/taw/tawWingDesignData.h index fee8ba4151344006f1b9257a8ebd78c0e9998f74..cb9ec1c059d95bb70b9982354c54459b76061c04 100644 --- a/wing_design/src/taw/tawWingDesignData.h +++ b/wing_design/src/taw/tawWingDesignData.h @@ -55,7 +55,7 @@ class WingDesignData { PositionIO center_of_gravity_mtom; geom2::MultisectionSurface<geom2::PolygonSection> fuselage; geom2::MultisectionSurface<geom2::AirfoilSection> wing; - geom2::MultisectionSurface<geom2::AirfoilSection> back_wing; + std::vector<geom2::MultisectionSurface<geom2::PolygonSection>> control_devices; std::vector<std::tuple<double,double>> control_devices_deflections; diff --git a/wing_design/wing_design_conf.xml b/wing_design/wing_design_conf.xml index 32e90ccc8756352afc943e92c86c1704af393860..10c83f691362941a97076c95fc04e58d50884dc2 100644 --- a/wing_design/wing_design_conf.xml +++ b/wing_design/wing_design_conf.xml @@ -747,7 +747,7 @@ </parameters> </total_wing_area> - <wing_area_ratio description="Wing Area Ratio(WAR)"> + <wing_area_ratio description="wing area ratio(WAR = Back Wing Area / Front Wing Area)"> <method description="selector mode_0: user_defined"> <value>mode_0</value> </method> @@ -763,24 +763,23 @@ </parameters> </wing_area_ratio> - <wing_span_ratio description="Wing Span Ratio"> + <relative_LE_stagger description="horizontal distance between leading edges of root chords of forward and rear wings along x-coordinate relative to fuselage length (St,rel=St/l,fuselage)"> <method description="selector mode_0: user_defined"> <value>mode_0</value> </method> <parameters> <mode_0 description="user_defined"> - <wing_span_ratio description="wingspan ratio"> - <value>1</value> + <relative_LE_stagger description="relative leading edge stagger"> + <value>0.5</value> <unit>1</unit> - <lower_boundary>0.9</lower_boundary> - <upper_boundary>1.2</upper_boundary> - </wing_span_ratio> + <lower_boundary>0</lower_boundary> + <upper_boundary>1</upper_boundary> + </relative_LE_stagger> </mode_0> </parameters> - </wing_span_ratio> + </relative_LE_stagger> <front_wing> - <!--delete unnecessary TODO kayra--> <sweep description="sweep calculation method"> <method description="selector mode_0: user_defined, mode_1: drag_divergence"> <value>mode_0</value> @@ -817,7 +816,7 @@ <parameters> <mode_0 description="user_defined"> <taper_ratio description="taper ratio of overall wing"> - <value>0</value> + <value>0.17</value> <unit>1</unit> <lower_boundary>0.0</lower_boundary> <upper_boundary>1.0</upper_boundary> @@ -827,12 +826,12 @@ </taper_ratio> <dihedral description="dihedral calculation method"> <method description="selector mode_0: user_defined, mode_1: by_wing_position_and_quarter_chord_sweep"> - <value>mode_1</value> + <value>mode_0</value> </method> <parameters description="parameters for methods"> <mode_0 description="user_defined"> <dihedral_angle description="dihedral angle"> - <value>4</value> + <value>0</value> <unit>deg</unit> <lower_boundary>-20</lower_boundary> <upper_boundary>20</upper_boundary> @@ -1431,7 +1430,6 @@ </spars> </front_wing> <back_wing> - <!--delete unnecessary TODO kayra--> <sweep description="sweep calculation method"> <method description="selector mode_0: user_defined, mode_1: drag_divergence"> <value>mode_0</value> @@ -1468,7 +1466,7 @@ <parameters> <mode_0 description="user_defined"> <taper_ratio description="taper ratio of overall wing"> - <value>0</value> + <value>0.17</value> <unit>1</unit> <lower_boundary>0.0</lower_boundary> <upper_boundary>1.0</upper_boundary> @@ -1478,7 +1476,7 @@ </taper_ratio> <dihedral description="dihedral calculation method"> <method description="selector mode_0: user_defined, mode_1: by_wing_position_and_quarter_chord_sweep"> - <value>mode_1</value> + <value>mode_0</value> </method> <parameters description="parameters for methods"> <mode_0 description="user_defined">