diff --git a/aviary/docs/_toc.yml b/aviary/docs/_toc.yml index 1142073d7a..3ed81bd706 100644 --- a/aviary/docs/_toc.yml +++ b/aviary/docs/_toc.yml @@ -54,7 +54,8 @@ parts: - file: user_guide/multi_mission - file: user_guide/off_design_missions - file: user_guide/payload_range_functionality - - file: user_guide/features/blended_wing_body + - file: user_guide/features/blended_wing_body_GASP + - file: user_guide/features/blended_wing_body_FLOPS - file: user_guide/troubleshooting - caption: Examples diff --git a/aviary/docs/theory_guide/gasp_based_bwb.ipynb b/aviary/docs/theory_guide/gasp_based_bwb.ipynb index f7274a2b66..8367626c09 100644 --- a/aviary/docs/theory_guide/gasp_based_bwb.ipynb +++ b/aviary/docs/theory_guide/gasp_based_bwb.ipynb @@ -48,7 +48,7 @@ "source": [ "# GASP based BWB model implementation\n", "\n", - "Modeling of GASP based blended wing body (BWB) aircraft is similar to that of the conventional aircraft but with several key differences. This page is a record of the development. For users, please read [Blended Wing Body Modeling](../user_guide/features/blended_wing_body) in the user guide.\n", + "Modeling of GASP based blended wing body (BWB) aircraft is similar to that of the conventional aircraft but with several key differences. This page is a record of the development. For users, please read [Blended Wing Body Modeling](../user_guide/features/blended_wing_body_GASP) in the user guide.\n", "\n", "## BWB geometry subsystem\n", "\n", @@ -456,7 +456,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "base", "language": "python", "name": "python3" }, @@ -470,7 +470,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/features/blended_wing_body_FLOPS.ipynb b/aviary/docs/user_guide/features/blended_wing_body_FLOPS.ipynb new file mode 100644 index 0000000000..db11f2d24c --- /dev/null +++ b/aviary/docs/user_guide/features/blended_wing_body_FLOPS.ipynb @@ -0,0 +1,399 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a63bd94a", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.geometry.flops_based.fuselage import (\n", + " SimpleCabinLayout,\n", + " DetailedCabinLayout,\n", + " BWBSimpleCabinLayout,\n", + " BWBDetailedCabinLayout,\n", + " FuselagePrelim,\n", + " BWBFuselagePrelim,\n", + ")\n", + "from aviary.subsystems.geometry.flops_based.wing_detailed_bwb import (\n", + " BWBUpdateDetailedWingDist,\n", + " BWBComputeDetailedWingDist,\n", + " BWBWingPrelim,\n", + ")\n", + "from aviary.subsystems.geometry.flops_based.prep_geom import (\n", + " _Prelim,\n", + " _BWBFuselage,\n", + " _BWBWing,\n", + " _Tail,\n", + " _Fuselage,\n", + " _FuselageRatios,\n", + " _Wing,\n", + ")\n", + "from aviary.subsystems.geometry.flops_based.nacelle import Nacelles\n", + "from aviary.subsystems.geometry.flops_based.canard import Canard\n", + "from aviary.subsystems.geometry.flops_based.characteristic_lengths import (\n", + " BWBWingCharacteristicLength,\n", + " NacelleCharacteristicLength,\n", + " OtherCharacteristicLengths,\n", + " WingCharacteristicLength,\n", + ")\n", + "from aviary.subsystems.geometry.flops_based.wetted_area_total import TotalWettedArea\n", + "from aviary.subsystems.geometry.flops_based.wing import WingPrelim\n", + "\n", + "glue_variable(get_variable_name(SimpleCabinLayout), md_code=True)\n", + "glue_variable(get_variable_name(DetailedCabinLayout), md_code=True)\n", + "glue_variable(get_variable_name(BWBSimpleCabinLayout), md_code=True)\n", + "glue_variable(get_variable_name(BWBDetailedCabinLayout), md_code=True)\n", + "glue_variable(get_variable_name(FuselagePrelim), md_code=True)\n", + "glue_variable(get_variable_name(BWBFuselagePrelim), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(BWBUpdateDetailedWingDist), md_code=True)\n", + "glue_variable(get_variable_name(BWBComputeDetailedWingDist), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingPrelim), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(_Prelim), md_code=True)\n", + "glue_variable(get_variable_name(_BWBWing), md_code=True)\n", + "glue_variable(get_variable_name(_Tail), md_code=True)\n", + "glue_variable(get_variable_name(_Fuselage), md_code=True)\n", + "glue_variable(get_variable_name(_FuselageRatios), md_code=True)\n", + "glue_variable(get_variable_name(_Wing), md_code=True)\n", + "glue_variable(get_variable_name(_BWBFuselage), md_code=True)\n", + "glue_variable(get_variable_name(Nacelles), md_code=True)\n", + "glue_variable(get_variable_name(Canard), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(BWBWingCharacteristicLength), md_code=True)\n", + "glue_variable(get_variable_name(NacelleCharacteristicLength), md_code=True)\n", + "glue_variable(get_variable_name(OtherCharacteristicLengths), md_code=True)\n", + "glue_variable(get_variable_name(WingCharacteristicLength), md_code=True)\n", + "glue_variable(get_variable_name(TotalWettedArea), md_code=True)\n", + "glue_variable(get_variable_name(WingPrelim), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "928acf60", + "metadata": {}, + "source": [ + "# FLOPS Based Blended Wing Body Modeling\n", + "\n", + "The blended wing body aircraft is modeled following the FLOPS implementation. It is important to point out that the Aviary implementation is limited to certain assumptions. To model a special model, the user must read this document carefully to see it is within the scope of the Aviary implementation.\n", + "\n", + "## FLOPS Based Geometry\n", + "\n", + "The FLOPS based geometry subsystems are shown in the following table. The left column is for the conventional aircraft and the right column is for BWB aircraft. In both case, users can choose a simple layout or a detailed layout.\n", + "\n", + "**Comparision of Conventional Aircraft and BWB Aircraft**\n", + "\n", + "| Tube+Wing | BWB |\n", + "| --------- | ----- |\n", + "| {glue:md}`SimpleCabinLayout` or {glue:md}`DetailedCabinLayout` | {glue:md}`BWBSimpleCabinLayout` or `{glue:md}BWBDetailedCabinLayout` |\n", + "| | {glue:md}`BWBUpdateDetailedWingDist` or {glue:md}`BWBComputeDetailedWingDist` |\n", + "| {glue:md}`FuselagePrelim` | {glue:md}`BWBFuselagePrelim` |\n", + "| {glue:md}`WingPrelim` | {glue:md}`BWBWingPrelim` |\n", + "| {glue:md}`_Prelim` | {glue:md}`_Prelim` |\n", + "| {glue:md}`_Wing` | {glue:md}`_BWBWing` |\n", + "| {glue:md}`_Tail` | {glue:md}`_Tail` |\n", + "| {glue:md}`_Fuselage` | {glue:md}`_BWBFuselage` |\n", + "| {glue:md}`_FuselageRatios` | {glue:md}`_FuselageRatios` |\n", + "| {glue:md}`Nacelles` | {glue:md}`Nacelles` |\n", + "| {glue:md}`Canard` | {glue:md}`Canard` |\n", + "| {glue:md}`WingCharacteristicLength` | {glue:md}`BWBWingCharacteristicLength` |\n", + "| {glue:md}`NacelleCharacteristicLength` | {glue:md}`NacelleCharacteristicLength` |\n", + "| {glue:md}`OtherCharacteristicLengths` | {glue:md}`OtherCharacteristicLengths` |\n", + "| {glue:md}`TotalWettedArea` | {glue:md}`TotalWettedArea` |\n", + "\n", + "As we see in the above table, some geometrical components have no special code in the BWB case (e.g. {glue:md}`Nacelles` and {glue:md}`_Tail`). So, the new implementation of BWB geometry uses the same components in conventional aircraft.\n", + "\n", + "Comparing to traditional tube and wing model, Blended wing body (BWB) modeling has two major new changes in geometry subsystems:\n", + "\n", + "- Wings always have detailed wing data,\n", + "- Fuselage layout is computed using a special algorithm.\n", + "\n", + "We will explain some details of each feature in this document." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b19c227", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_all_non_aviary_names, get_variable_name, glue_variable\n", + "\n", + "# new variables added for FLOPS based BWB geometry\n", + "glue_variable(\n", + " get_variable_name(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS), md_code=True\n", + ")\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST), md_code=True)\n", + "glue_variable(\n", + " get_variable_name(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY), md_code=True\n", + ")\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.BWB.NUM_BAYS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.SIMPLE_LAYOUT), md_code=True)\n", + "\n", + "Rear_spar_percent_chord = get_all_non_aviary_names(BWBFuselagePrelim, include_in_out='in')[0]\n", + "glue_variable('Rear_spar_percent_chord', Rear_spar_percent_chord, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "e8a87f60", + "metadata": {}, + "source": [ + "### Fuselage Layout\n", + "\n", + "There are two options: simple layout and detailed layout. For simple layout, you are given fuselage length, width and leading edge angle (as well as the rear spar percent chord at fuselage centerline, default to 70%), Aviary computes passenger compartment length, wing root chord, cabin area. This is shown in the following image:\n", + "\n", + "![Fuselage size](../images/BWB_FLOPS_Fuselage_Simple_Geom.png)\n", + "\n", + "Variable {glue:md}`Rear_spar_percent_chord` serves as the ratio of fuselage length and compartment length. It says that the rear spar is mounted at the side of fuselage which is 70% (default) of fuselage length from the leading edge. {glue:md}`Rear_spar_percent_chord` is hard coded for now, but can be easily converted to an Aviary variable.\n", + "\n", + "The detailed layout involves more details like the number of passengers, seat pitch and seat abreast. Fuselage length and width are no longer inputs but outputs. If you have those data, it is a better choice.\n", + "\n", + "For BWB, there is a new concept: the number of passenger cabin bays (or {glue:md}`Aircraft.BWB.NUM_BAYS`). It is a discrete, pressurized structural compartment within the BWB center body that contains passenger seating and is bounded by primary load-carrying frames, ribs, and pressure bulkheads. In Aviary, we determine the number of bays as how many blocks can be fit within the fuselage cabin width, assuming each block has a 12-foot width (hard coded). Note that it is not a layout term and bays are not separated by aisles even though the number of bays is computed here in fuselage layout components. The following is an example of six bays.\n", + "\n", + "![Fuselage size](../images/BWB_FLOPS_fuselage_3_Bays.png)\n", + "\n", + "Finally, fuselage height is computed from the width and height-to-width ratio.\n", + "\n", + "To choose detailed layout or simple layout, the user can set up a flag {glue:md}`Aircraft.Fuselage.SIMPLE_LAYOUT`. If it is true, Aviary assumes a simple layout. Otherwise, it is a detailed layout." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "71e99c67", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_all_non_aviary_names, get_variable_name, glue_variable\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.INPUT_STATION_DIST), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.CHORD_PER_SEMISPAN_DIST), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.THICKNESS_TO_CHORD_DIST), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.LOAD_PATH_SWEEP_DIST), md_code=True)\n", + "\n", + "BWB_CHORD_PER_SEMISPAN_DIST = get_all_non_aviary_names(\n", + " BWBUpdateDetailedWingDist, include_in_out='out'\n", + ")[0]\n", + "glue_variable('BWB_CHORD_PER_SEMISPAN_DIST', BWB_CHORD_PER_SEMISPAN_DIST, md_code=True)\n", + "BWB_THICKNESS_TO_CHORD_DIST = get_all_non_aviary_names(\n", + " BWBUpdateDetailedWingDist, include_in_out='out'\n", + ")[1]\n", + "glue_variable('BWB_THICKNESS_TO_CHORD_DIST', BWB_THICKNESS_TO_CHORD_DIST, md_code=True)\n", + "BWB_LOAD_PATH_SWEEP_DIST = get_all_non_aviary_names(\n", + " BWBUpdateDetailedWingDist, include_in_out='out'\n", + ")[2]\n", + "glue_variable('BWB_LOAD_PATH_SWEEP_DIST', BWB_LOAD_PATH_SWEEP_DIST, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "da48ab2d", + "metadata": {}, + "source": [ + "### Wings\n", + "\n", + "#### Detailed Wings\n", + "\n", + "For the BWB, the wing weight is always calculated with detailed wing geometry. The wing station distribution is either given ({glue:md}`BWBUpdateDetailedWingDist`) or created ({glue:md}`BWBComputeDetailedWingDist`). This means that number of input wing stations is always positive. If input wing stations are not provided, FLOPS adds three points. We call this case the simple wing case. Otherwise, we say that we have a detailed wing case.\n", + "\n", + "Let's assume the detailed wing data is given. That means we are given the following arrays:\n", + "\n", + "- {glue:md}`Aircraft.Wing.INPUT_STATION_DIST`\n", + "- {glue:md}`Aircraft.Wing.CHORD_PER_SEMISPAN_DIST`\n", + "- {glue:md}`Aircraft.Wing.THICKNESS_TO_CHORD_DIST`\n", + "- {glue:md}`Aircraft.Wing.LOAD_PATH_SWEEP_DIST`\n", + "\n", + "These data are used to define an outboard wing panel to be added to the side of the cabin. In FLOPS, data start from the wing root to the wing tip. For transporter aircraft, it is good enough. But for BWB aircraft, we need to add one additional wing station at the body centerline. So, if you obtain the data from a FLOPS data set. You need to add one entry at the beginning of the lists. \n", + "\n", + "{glue:md}`Aircraft.Wing.INPUT_STATION_DIST` is the input station distribution (an Aviary option). Each entry is a location of an input station, either as a fraction from wing root to wing tip (when value < 1.0), or the absolute location. If you obtain the data from a FLOPS input data, add a 0.0 at the beginning.\n", + "\n", + "{glue:md}`Aircraft.Wing.CHORD_PER_SEMISPAN_DIST` is the chord length, either as a fraction of semispan or actual chord. If you obtain the data from a FLOPS input data, add a -1.0 at the beginning. It will be updated during the run.\n", + "\n", + "{glue:md}`Aircraft.Wing.THICKNESS_TO_CHORD_DIST` is the thickness to chord ratios at the input station distribution. If you obtain the data from a FLOPS input data, add a -1.0 at the beginning. It will be updated during the run.\n", + "\n", + "{glue:md}`Aircraft.Wing.LOAD_PATH_SWEEP_DIST` is the load path sweep angle between two adjacent input station. f you obtain the data from a FLOPS input data, add a 0.0 at the beginning. Note that this list should have one fewer entry than the other three lists.\n", + "\n", + "When Aviary runs, {glue:md}`Aircraft.Wing.CHORD_PER_SEMISPAN_DIST`, {glue:md}`Aircraft.Wing.THICKNESS_TO_CHORD_DIST`, and {glue:md}`Aircraft.Wing.LOAD_PATH_SWEEP_DIST` are updated and output to local variabls {glue:md}`BWB_THICKNESS_TO_CHORD_DIST`, {glue:md}`BWB_THICKNESS_TO_CHORD_DIST`, and {glue:md}`BWB_LOAD_PATH_SWEEP_DIST`.\n", + "\n", + "#### Simple Wings\n", + "\n", + "Keep in mind that the BWB aircraft always have detailed wings, but users do not have to provide the data as above. In this case, the user should provide (0.0, 0.5, 1.0) as {glue:md}`Aircraft.Wing.INPUT_STATION_DIST`. Here, `Aircraft.Wing.INPUT_STATION_DIST[0] = 0.0` means that the first station is at the fuselage center line (at 0.0%). `Aircraft.Wing.INPUT_STATION_DIST[2] = 1.0` means that the last station is at the tip (namely 100% place). `Aircraft.Wing.INPUT_STATION_DIST[1] = 0.5` is a temporary place holder. When Aviary runs, `Aircraft.Wing.INPUT_STATION_DIST[1]` is updated to the location of root chord (note that this is the actual location, not the percentage). The same three local variables `BWB_THICKNESS_TO_CHORD_DIST` (dimension 3), {glue:md}`BWB_THICKNESS_TO_CHORD_DIST` (dimension 3), and {glue:md}`BWB_LOAD_PATH_SWEEP_DIST` (dimension 2) are updated accordingly. See {glue:md}`BWBComputeDetailedWingDist` component for details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06c717a3", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.geometry.flops_based.characteristic_lengths import (\n", + " HorizontalTailCharacteristicLength,\n", + " VerticalTailCharacteristicLength,\n", + ")\n", + "\n", + "glue_variable(get_variable_name(Aircraft.BWB.DETAILED_WING_PROVIDED), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.CROSS_SECTION), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.WETTED_AREA), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.VerticalTail.CHARACTERISTIC_LENGTH), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(HorizontalTailCharacteristicLength), md_code=True)\n", + "glue_variable(get_variable_name(VerticalTailCharacteristicLength), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "dd29fbb6", + "metadata": {}, + "source": [ + "### Fuselage and Wing\n", + "\n", + "As summary, the geometry subsystem for BWB aircraft is very similar to that of transporter aircraft. See the diagram below:\n", + "\n", + "![Fuselage size](../images/BWB_FLOPS_geom.png)\n", + "\n", + "To choose between simple fuselage layout or detailed fuselage layout, the user sets {glue:md}`Aircraft.Fuselage.SIMPLE_LAYOUT` to True or False. For BWB, to choose between providing detailed wing or letting Aviary to create a detailed wing, the user sets {glue:md}`Aircraft.BWB.DETAILED_WING_PROVIDED` to True or False.\n", + "\n", + "Comparing the two cases (transporter and BWB), we see that {glue:md}`BWBComputeDetailedWingDist` and {glue:md}`BWBUpdateDetailedWingDist` are new. This is because we must update {glue:md}`Aircraft.Wing.CHORD_PER_SEMISPAN_DIST`, {glue:md}`Aircraft.Wing.THICKNESS_TO_CHORD_DIST`, and {glue:md}`Aircraft.Wing.LOAD_PATH_SWEEP_DIST` in the case of BWB.\n", + "\n", + "This feature is explained in the following diagram (in the case of detailed wing provided):\n", + "\n", + "![Fuselage size](../images/BWB_FLOPS_Geom_fus_wing.png)\n", + "\n", + "### Fuselage Cross Section and Wetted Area\n", + "\n", + "Because of the nature of blended wing body, we ignore the fuselage wetted area. There, both {glue:md}`Aircraft.Fuselage.CROSS_SECTION` and {glue:md}`Aircraft.Fuselage.WETTED_AREA` are set to 0.0.\n", + "\n", + "This is implemented in {glue:md}`_BWBFuselage`.\n", + "\n", + "### Characteristics\n", + "\n", + "The FLOPS based BWB aircraft does not have horizontal and vertical tails. Once again ,we simply set both {glue:md}`Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH` and {glue:md}`Aircraft.VerticalTail.CHARACTERISTIC_LENGTH` to 0.0.\n", + "\n", + "This is because the FLOPS algorithm does not apply to non-horizontal and non-vertical tails scenarios. If users want to add them, their mass equations must be provided separately. See {glue:md}`HorizontalTailCharacteristicLength` and {glue:md}`VerticalTailCharacteristicLength` classes for details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "98b57d80", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.mass.flops_based.furnishings import BWBFurnishingsGroupMass\n", + "from aviary.subsystems.mass.flops_based.fuselage import BWBFuselageMass, BWBAftBodyMass\n", + "from aviary.subsystems.mass.flops_based.wing_common import BWBWingMiscMass\n", + "from aviary.subsystems.mass.flops_based.wing_detailed import BWBDetailedWingBendingFact\n", + "\n", + "glue_variable(get_variable_name(BWBFurnishingsGroupMass), md_code=True)\n", + "glue_variable(get_variable_name(BWBFuselageMass), md_code=True)\n", + "glue_variable(get_variable_name(BWBAftBodyMass), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingMiscMass), md_code=True)\n", + "glue_variable(get_variable_name(BWBDetailedWingBendingFact), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Furnishings.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.BWB_AFTBODY_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.MISC_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.BENDING_MATERIAL_FACTOR), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "c08b6066", + "metadata": {}, + "source": [ + "## FLOPS Based Mass\n", + "\n", + "Aviary computes masses of indiviual components and then sum them up. For BWB aircrafts, most of them share the same code with transporters. There are a few exceptions, however. They are:\n", + "\n", + "- {glue:md}`BWBFurnishingsGroupMass` (computation of {glue:md}`Aircraft.Furnishings.MASS`)\n", + "- {glue:md}`BWBFuselageMass` (computation of {glue:md}`Aircraft.Fuselage.MASS`)\n", + "- {glue:md}`BWBAftBodyMass` (computation of {glue:md}`Aircraft.Wing.BWB_AFTBODY_MASS`)\n", + "- {glue:md}`BWBWingMiscMass` (computation of {glue:md}`Aircraft.Wing.MISC_MASS`)\n", + "- {glue:md}`BWBDetailedWingBendingFact` (computation of {glue:md}`Aircraft.Wing.BENDING_MATERIAL_FACTOR`)\n", + "\n", + "Here, {glue:md}`BWBAftBodyMass` is a new component for BWB. This area starts from the rear span and backward.\n", + "\n", + "Because the wing is always a detailed wing for BWB aircraft, we must compute the wing bending material factor with sweep adjustment. This is done in {glue:md}`BWBDetailedWingBendingFact`." + ] + }, + { + "cell_type": "markdown", + "id": "bfdebb5d", + "metadata": {}, + "source": [ + "## FLOPS Based Aerodynamics\n", + "\n", + "There is no special implementation of aerodynamics subsystem in FLOPS. It is likely that users need to provide their own aero tables for their design." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/aviary/docs/user_guide/features/blended_wing_body.ipynb b/aviary/docs/user_guide/features/blended_wing_body_GASP.ipynb similarity index 99% rename from aviary/docs/user_guide/features/blended_wing_body.ipynb rename to aviary/docs/user_guide/features/blended_wing_body_GASP.ipynb index e8460f0e69..cda9a6441d 100644 --- a/aviary/docs/user_guide/features/blended_wing_body.ipynb +++ b/aviary/docs/user_guide/features/blended_wing_body_GASP.ipynb @@ -19,7 +19,7 @@ "id": "267d6a8d", "metadata": {}, "source": [ - "# Blended Wing Body Modeling\n", + "# GASP Based Blended Wing Body Modeling\n", "\n", "The blended wing body aircraft is modeled following GASP implementation. It is important to point out the the Aviary implementation is limited to certain assumptions. To model a special model, the user must read this document carefully to see it is within the scope of the Aviary implementation.\n", "\n", diff --git a/aviary/docs/user_guide/images/BWB_FLOPS_Fuselage_Simple_Geom.png b/aviary/docs/user_guide/images/BWB_FLOPS_Fuselage_Simple_Geom.png new file mode 100644 index 0000000000..b4712f5aa2 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_FLOPS_Fuselage_Simple_Geom.png differ diff --git a/aviary/docs/user_guide/images/BWB_FLOPS_Geom_fus_wing.png b/aviary/docs/user_guide/images/BWB_FLOPS_Geom_fus_wing.png new file mode 100644 index 0000000000..e14bad1b9b Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_FLOPS_Geom_fus_wing.png differ diff --git a/aviary/docs/user_guide/images/BWB_FLOPS_fuselage_3_Bays.png b/aviary/docs/user_guide/images/BWB_FLOPS_fuselage_3_Bays.png new file mode 100644 index 0000000000..1f22f8b260 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_FLOPS_fuselage_3_Bays.png differ diff --git a/aviary/docs/user_guide/images/BWB_FLOPS_geom.png b/aviary/docs/user_guide/images/BWB_FLOPS_geom.png new file mode 100644 index 0000000000..6786c2c337 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_FLOPS_geom.png differ diff --git a/aviary/mission/height_energy_problem_configurator.py b/aviary/mission/height_energy_problem_configurator.py index 4e836111a3..d8de503c0d 100644 --- a/aviary/mission/height_energy_problem_configurator.py +++ b/aviary/mission/height_energy_problem_configurator.py @@ -394,7 +394,11 @@ def add_post_mission_systems(self, aviary_group): ) if aviary_group.post_mission_info['include_landing']: - self._add_landing_systems(aviary_group) + if 'aircraft:wing:area' in aviary_group.aviary_inputs: + self._add_landing_systems(aviary_group) + else: + print('Aircraft.Wing.AREA is not given. Set include_landing = False') + aviary_group.post_mission_info['include_landing'] = False aviary_group.add_subsystem( 'range_constraint', diff --git a/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS.csv b/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS.csv index a31df113e3..858e7d8865 100644 --- a/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS.csv +++ b/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS.csv @@ -27,11 +27,11 @@ aircraft:crew_and_payload:design:seat_pitch_economy,32,inch aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless aircraft:crew_and_payload:misc_cargo,0.0,lbm aircraft:crew_and_payload:mass_per_passenger,165.0,lbm -aircraft:crew_and_payload:num_business_class,100,unitless -aircraft:crew_and_payload:num_first_class,28,unitless aircraft:crew_and_payload:num_flight_attendants,22,unitless aircraft:crew_and_payload:num_flight_crew,2,unitless aircraft:crew_and_payload:num_galley_crew,2,unitless +aircraft:crew_and_payload:num_business_class,100,unitless +aircraft:crew_and_payload:num_first_class,28,unitless aircraft:crew_and_payload:num_passengers,468,unitless aircraft:crew_and_payload:num_economy_class,340,unitless aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless @@ -98,8 +98,8 @@ aircraft:horizontal_tail:taper_ratio,0.0,unitless aircraft:horizontal_tail:thickness_to_chord,0.11,unitless aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless aircraft:horizontal_tail:wetted_area_scaler,1.0,unitless -aircraft:hydraulics:system_pressure,3000.0,psi aircraft:hydraulics:mass_scaler,1.0,unitless +aircraft:hydraulics:system_pressure,3000.0,psi aircraft:instruments:mass_scaler,1.0,unitless aircraft:landing_gear:main_gear_oleo_length,85.0,inch aircraft:landing_gear:main_gear_mass_scaler,1.0,unitless @@ -152,7 +152,6 @@ aircraft:wing:var_sweep_mass_penalty,0.0,unitless aircraft:wing:wetted_area_scaler,1.0,unitless mission:constraints:max_mach,0.85,unitless mission:design:gross_mass,874099,lbm -mission:design:lift_coefficient,-1.0,unitless mission:design:range,7750,NM mission:design:thrust_takeoff_per_eng,0.25,lbf mission:landing:initial_velocity,140,ft/s @@ -164,6 +163,7 @@ mission:summary:fuel_flow_scaler,1.0,unitless settings:aerodynamics_method,FLOPS,unitless settings:equations_of_motion,height_energy,unitless settings:mass_method,FLOPS,unitless +settings:verbosity,1,unitless # Unconverted Values AERIN.FLLDG,11000 diff --git a/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS.in b/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS.in new file mode 100644 index 0000000000..9d689af69c --- /dev/null +++ b/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS.in @@ -0,0 +1,190 @@ +468 passenger BWB + + $OPTION +MPRINT=1, +IOPT=1, +IANAL=3, +INENG=1, +ICOST=0, +ITAKOF=0, +ILAND=0, +NOPRO=0, +NOISE=0, +IFITE=3, +IXFL=1, +IPOLP=0, +IPLTTH=0, + $END + + $WTIN +DGW=874099, +VMMO=0.85, +DIH=3, +FLAPR=0.333, +GLOV=121.05, +VARSWP=0, +FCOMP=1, +FAERT=0, +FSTRT=0, +NETAW=14, +ETAW=0.35,0.4,0.45,0.5,0.55,0.6,0.6499,0.7,0.75,0.8,0.85,0.8999,0.95,1, +CHD=58.03,0.4491,0.3884,0.3317,0.2886,0.2537,0.2269,0.2121,0.1983,0.1843,0.1704,0.1565,0.1426,0.1287, +TOC=0.15,0.1132,0.0928,0.0822,0.0764,0.0742,0.0746,0.0758,0.0758,0.0756,0.0756,0.0758,0.076,0.076, +SWL=0,0,0,0,0,0,0,42.9,42.9,42.9,42.9,42.9,42.9,42.9,0,0,0,0,0,0, +SHT=0, +SWPHT=0, +ARHT=0, +TRHT=0, +TCHT=0, +NVERT=0, +NFIN=2, +SFIN=184.89, +ARFIN=1.952, +TRFIN=0.464, +SWPFIN=39.42, +TCFIN=0.08, +NFUSE=1, +XL=0, ! XL=137.5 for fixed geom. +WF=0, ! WF=64.58 +DF=0, ! DF=17 +XLP=0, ! XLP=40 +XMLG=85, +XNLG=87, +CARBAS=0, +NEW=0, +NEF=3, +THRSO=86459.2, +WENG=22017, +EEXP=1, +WINL=0, +XNAC=17.433, +DNAC=12.608, +NPF=28, +NPB=100, +NPT=340, +NSTU=22, +NFLCR=2, +CARGF=0, +FRWI=1, +FRHT=1, +FRVT=1, +FRFU=1, +FRNA=0, +WTHR=0, +WPMSC=0, +WHYD=1, +WAVONC=1, +WFURN=1, +ISPOWE=0, + $END + + $FUSEIN +ACABIN=0, +FPITCH=61, +NFABR=4, +BPITCH=39, +NBABR=4, +TPITCH=32, +NTABR=6, +OSSPAN=86.75, + $END + $CONFIN +DESRNG=7750, +OFG=1, +OFF=0, +GW=874099, +AR=7.557,0, +THRUST=70000,1,0,0,0,0, +SW=7621.66,1, +TR=0.311, +SWEEP=35.7, +TCA=0.11, +VCMN=0.85, +CH=39000, + $END + + $AERIN +MYAERO=0, +ITPAER=2, +CAM=2, +AITEK=2, +XLLAM=0, +E=0, +WRATIO=0.8, +VAPPR=140, +FLTO=11000, +FLLDG=11000, +THROFF=0.25, + $END + + $ENGDIN +IGENEN=-1, +EIFILE='ENGDEK', +IDLE=1, +MAXCR=1, +NOX=1, + $END + + $MISSIN +FCDO=1, +FCDI=1, +ISKAL=1, +IFLAG=2, +MSUMPT=1, +IRW=2, +IATA=0, +NPCON=1, +TAKOTM=2, +TAXOTM=9, +APPRTM=4, +TAXITM=5, +ITTFF=1, +NCLIMB=1, +CLAMIN=0, +FWF=-0.001, +NCRUSE=3, +IOC=1,4,4, +CRMACH=0.85,0.6,0, +CRALT=45000,25000,1500, +RCIN=300, +IVS=1, +DEAMIN=0, +IRS=1, +RESTRP=0.05, +TIMMAP=2, +ALTRAN=200, +NCLRES=1, +NCRRES=2, +HOLDTM=30, +NCRHOL=3, +IHOPOS=1, +THOLD=0.1, +NCRTH=1, + $END +START +CLIMB +CRUISE +DESCENT +END + + $PCONIN +CONALT=35000, +CONMCH=0.85, +CONPC=1, +ICONSG=2, +CONLIM=300, +ICONTP=5, + $END + + $RERUN + $END + + $MISSIN +IRW=1, +NPCON=0, + $END +START +CLIMB +CRUISE +DESCENT +END diff --git a/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS_data.py b/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS_data.py index 7fc28bc94b..e443a52ed1 100644 --- a/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS_data.py +++ b/aviary/models/aircraft/blended_wing_body/bwb_detailed_FLOPS_data.py @@ -20,7 +20,6 @@ inputs.set_val(Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, 1.0) # FCDSUP inputs.set_val(Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, 1.0) # FCDO inputs.set_val(Aircraft.Design.TYPE, AircraftTypes.BLENDED_WING_BODY) -inputs.set_val(Mission.Design.LIFT_COEFFICIENT, -1.0) # FCLDES inputs.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, False) inputs.set_val(Aircraft.BWB.DETAILED_WING_PROVIDED, True) @@ -89,13 +88,13 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') # FULAUX -inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') # FULDEN inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0) # WFSYS inputs.set_val(Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0, 'lbm') # FULFMX inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) # NTANK inputs.set_val(Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, 1.0) # WUF inputs.set_val(Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT, False) # IFUFU inputs.set_val(Aircraft.Fuel.WING_FUEL_FRACTION, 0.68835495693, 'unitless') +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') # Furnishings # --------------------------- @@ -114,11 +113,11 @@ # Horizontal Tail # --------------------------- inputs.set_val(Aircraft.HorizontalTail.AREA, 0.0, 'ft**2') # SHT -inputs.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, 0.1) # SHT +inputs.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, 0.1) # ARHT inputs.set_val(Aircraft.HorizontalTail.TAPER_RATIO, 0.0) # TRHT inputs.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.11) # TCHT # inputs.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0.0) # HHT -inputs.set_val(Aircraft.HorizontalTail.MASS_SCALER, 1.0) # SHT +inputs.set_val(Aircraft.HorizontalTail.MASS_SCALER, 1.0) # FRHT inputs.set_val(Aircraft.HorizontalTail.WETTED_AREA_SCALER, 1.0) # SWETH # inputs.set_val(Aircraft.HorizontalTail.SWEEP, 0.0) # SWPHT diff --git a/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS.csv b/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS.csv index 4ca45ca361..3969d7aa4d 100644 --- a/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS.csv +++ b/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS.csv @@ -15,7 +15,7 @@ aircraft:crew_and_payload:baggage_mass_per_passenger,44.0,lbm aircraft:crew_and_payload:cargo_container_mass_scaler,1.0,unitless aircraft:crew_and_payload:design:num_business_class,100,unitless aircraft:crew_and_payload:design:num_first_class,28,unitless -aircraft:crew_and_payload:design:num_passengers,468,unitless +# aircraft:crew_and_payload:design:num_passengers,468,unitless aircraft:crew_and_payload:design:num_economy_class,340,unitless aircraft:crew_and_payload:design:num_seats_abreast_business,4,unitless aircraft:crew_and_payload:design:num_seats_abreast_first,4,unitless @@ -27,12 +27,12 @@ aircraft:crew_and_payload:design:seat_pitch_economy,32,inch aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless aircraft:crew_and_payload:misc_cargo,0.0,lbm aircraft:crew_and_payload:mass_per_passenger,165.0,lbm -aircraft:crew_and_payload:num_business_class,100,unitless -aircraft:crew_and_payload:num_first_class,28,unitless aircraft:crew_and_payload:num_flight_attendants,22,unitless aircraft:crew_and_payload:num_flight_crew,2,unitless aircraft:crew_and_payload:num_galley_crew,2,unitless -aircraft:crew_and_payload:num_passengers,468,unitless +# aircraft:crew_and_payload:num_passengers,468,unitless +aircraft:crew_and_payload:num_business_class,100,unitless +aircraft:crew_and_payload:num_first_class,28,unitless aircraft:crew_and_payload:num_economy_class,340,unitless aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless aircraft:crew_and_payload:wing_cargo,0.0,lbm @@ -100,8 +100,8 @@ aircraft:horizontal_tail:taper_ratio,0.0,unitless aircraft:horizontal_tail:thickness_to_chord,0.11,unitless aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless aircraft:horizontal_tail:wetted_area_scaler,1.0,unitless -aircraft:hydraulics:system_pressure,3000.0,psi aircraft:hydraulics:mass_scaler,1.0,unitless +aircraft:hydraulics:system_pressure,3000.0,psi aircraft:instruments:mass_scaler,1.0,unitless aircraft:landing_gear:main_gear_oleo_length,85.0,inch aircraft:landing_gear:main_gear_mass_scaler,1.0,unitless @@ -151,7 +151,6 @@ aircraft:wing:var_sweep_mass_penalty,0.0,unitless aircraft:wing:wetted_area_scaler,1.0,unitless mission:constraints:max_mach,0.85,unitless mission:design:gross_mass,874099,lbm -mission:design:lift_coefficient,-1.0,unitless mission:design:range,7750,NM mission:design:thrust_takeoff_per_eng,0.25,lbf mission:landing:initial_velocity,140,ft/s @@ -163,6 +162,7 @@ mission:summary:fuel_flow_scaler,1.0,unitless settings:aerodynamics_method,FLOPS,unitless settings:equations_of_motion,height_energy,unitless settings:mass_method,FLOPS,unitless +settings:verbosity,1,unitless # Unconverted Values AERIN.FLLDG,11000 diff --git a/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS.in b/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS.in new file mode 100644 index 0000000000..486763ab81 --- /dev/null +++ b/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS.in @@ -0,0 +1,186 @@ +468 passenger BWB + + $OPTION +MPRINT=1, +IOPT=1, +IANAL=3, +INENG=1, +ICOST=0, +ITAKOF=0, +ILAND=0, +NOPRO=0, +NOISE=0, +IFITE=3, +IXFL=1, +IPOLP=0, +IPLTTH=0, + $END + + $WTIN +DGW=874099, +VMMO=0.85, +DIH=3, +FLAPR=0.333, +GLOV=121.05, +VARSWP=0, +FCOMP=1, +FAERT=0, +FSTRT=0, +NETAW=0, +SHT=0, +SWPHT=0, +ARHT=0, +TRHT=0, +TCHT=0, +NVERT=0, +NFIN=2, +SFIN=184.89, +ARFIN=1.952, +TRFIN=0.464, +SWPFIN=39.42, +TCFIN=0.08, +NFUSE=1, +XL=137.5, ! XL=137.5 for fixed geom. +WF=64.58 +DF=0, ! DL=17 +XLP=0, ! XLP=40 +XMLG=85, +XNLG=87, +CARBAS=0, +NEW=0, +NEF=3, +THRSO=86459.2, +WENG=22017, +EEXP=1, +WINL=0, +XNAC=17.433, +DNAC=12.608, +NPF=28, +NPB=100, +NPT=340, +NSTU=22, +NFLCR=2, +CARGF=0, +FRWI=1, +FRHT=1, +FRVT=1, +FRFU=1, +FRNA=0, +WTHR=0, +WPMSC=0, +WHYD=1, +WAVONC=1, +WFURN=1, +ISPOWE=0, + $END + + $FUSEIN +ACABIN=0, +FPITCH=61, +NFABR=4, +BPITCH=39, +NBABR=4, +TPITCH=32, +NTABR=6, +OSSPAN=86.75, + $END + $CONFIN +DESRNG=7750, +OFG=1, +OFF=0, +GW=874099, +AR=7.557,0, +THRUST=70000,1,0,0,0,0, +SW=7621.66,1, +TR=0.311, +SWEEP=35.7, +TCA=0.11, +VCMN=0.85, +CH=39000, + $END + + $AERIN +MYAERO=0, +ITPAER=2, +CAM=2, +AITEK=2, +XLLAM=0, +E=0, +WRATIO=0.8, +VAPPR=140, +FLTO=11000, +FLLDG=11000, +THROFF=0.25, + $END + + $ENGDIN +IGENEN=-1, +EIFILE='ENGDEK', +IDLE=1, +MAXCR=1, +NOX=1, + $END + + $MISSIN +FCDO=1, +FCDI=1, +ISKAL=1, +IFLAG=2, +MSUMPT=1, +IRW=2, +IATA=0, +NPCON=1, +TAKOTM=2, +TAXOTM=9, +APPRTM=4, +TAXITM=5, +ITTFF=1, +NCLIMB=1, +CLAMIN=0, +FWF=-0.001, +NCRUSE=3, +IOC=1,4,4, +CRMACH=0.85,0.6,0, +CRALT=45000,25000,1500, +RCIN=300, +IVS=1, +DEAMIN=0, +IRS=1, +RESTRP=0.05, +TIMMAP=2, +ALTRAN=200, +NCLRES=1, +NCRRES=2, +HOLDTM=30, +NCRHOL=3, +IHOPOS=1, +THOLD=0.1, +NCRTH=1, + $END +START +CLIMB +CRUISE +DESCENT +END + + $PCONIN +CONALT=35000, +CONMCH=0.85, +CONPC=1, +ICONSG=2, +CONLIM=300, +ICONTP=5, + $END + + $RERUN + $END + + $MISSIN +IRW=1, +NPCON=0, + $END +START +CLIMB +CRUISE +DESCENT +END diff --git a/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS_data.py b/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS_data.py index 2cb2018976..adbbb34150 100644 --- a/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS_data.py +++ b/aviary/models/aircraft/blended_wing_body/bwb_simple_FLOPS_data.py @@ -20,7 +20,6 @@ inputs.set_val(Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, 1.0) # FCDSUP inputs.set_val(Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, 1.0) # FCDO inputs.set_val(Aircraft.Design.TYPE, AircraftTypes.BLENDED_WING_BODY) -inputs.set_val(Mission.Design.LIFT_COEFFICIENT, -1.0) # FCLDES inputs.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, True) inputs.set_val(Aircraft.BWB.DETAILED_WING_PROVIDED, False) @@ -89,13 +88,13 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') # FULAUX -inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') # FULDEN inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0) # WFSYS inputs.set_val(Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0, 'lbm') # FULFMX inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) # NTANK inputs.set_val(Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, 1.0) # WUF inputs.set_val(Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT, False) # IFUFU inputs.set_val(Aircraft.Fuel.WING_FUEL_FRACTION, 0.68835495693, 'unitless') +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') # Furnishings # --------------------------- @@ -116,11 +115,11 @@ # Horizontal Tail # --------------------------- inputs.set_val(Aircraft.HorizontalTail.AREA, 0.0, 'ft**2') # SHT -inputs.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, 0.1) # SHT +inputs.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, 0.1) # ARHT inputs.set_val(Aircraft.HorizontalTail.TAPER_RATIO, 0.0) # TRHT inputs.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.11) # TCHT # inputs.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0.0) # HHT -inputs.set_val(Aircraft.HorizontalTail.MASS_SCALER, 1.0) # SHT +inputs.set_val(Aircraft.HorizontalTail.MASS_SCALER, 1.0) # FRHT inputs.set_val(Aircraft.HorizontalTail.WETTED_AREA_SCALER, 1.0) # SWETH # inputs.set_val(Aircraft.HorizontalTail.SWEEP, 0.0) # SWPHT diff --git a/aviary/subsystems/aerodynamics/flops_based/skin_friction.py b/aviary/subsystems/aerodynamics/flops_based/skin_friction.py index 502378cf3f..0cf9fb870b 100644 --- a/aviary/subsystems/aerodynamics/flops_based/skin_friction.py +++ b/aviary/subsystems/aerodynamics/flops_based/skin_friction.py @@ -1,6 +1,7 @@ import numpy as np import openmdao.api as om +from aviary.variable_info.enums import AircraftTypes from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic @@ -36,17 +37,23 @@ def initialize(self): desc='The number of points at which the cross product is computed.', ) + add_aviary_option(self, Aircraft.Design.TYPE) add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) add_aviary_option(self, Aircraft.VerticalTail.NUM_TAILS) def setup(self): nn = self.options['num_nodes'] + design_type = self.options[Aircraft.Design.TYPE] num_engines = self.options[Aircraft.Engine.NUM_ENGINES] num_fuselages = self.options[Aircraft.Fuselage.NUM_FUSELAGES] num_tails = self.options[Aircraft.VerticalTail.NUM_TAILS] - self.nc = nc = 2 + num_tails + num_fuselages + int(sum(num_engines)) + if design_type is AircraftTypes.BLENDED_WING_BODY: + # No horizontal tail for BWB + self.nc = nc = 1 + num_tails + num_fuselages + int(sum(num_engines)) + else: + self.nc = nc = 2 + num_tails + num_fuselages + int(sum(num_engines)) # Simulation inputs add_aviary_input(self, Dynamic.Atmosphere.TEMPERATURE, shape=nn, units='degR') diff --git a/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py b/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py index 2324ecee40..284cc12e4b 100644 --- a/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py @@ -1,6 +1,7 @@ import numpy as np import openmdao.api as om +from aviary.variable_info.enums import AircraftTypes from aviary.variable_info.functions import add_aviary_input, add_aviary_option, get_units from aviary.variable_info.variables import Aircraft @@ -33,6 +34,7 @@ def initialize(self): desc='The number of points at which the cross product is computed.', ) + add_aviary_option(self, Aircraft.Design.TYPE) add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) add_aviary_option(self, Aircraft.VerticalTail.NUM_TAILS) @@ -47,12 +49,17 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] + design_type = self.options[Aircraft.Design.TYPE] nvtail = self.options[Aircraft.VerticalTail.NUM_TAILS] nfuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] num_engines = self.options[Aircraft.Engine.NUM_ENGINES] - self.nc = nc = 2 + nvtail + nfuse + int(sum(num_engines)) + if design_type is AircraftTypes.BLENDED_WING_BODY: + # No horizontal tail for BWB + self.nc = nc = 1 + nvtail + nfuse + int(sum(num_engines)) + else: + self.nc = nc = 2 + nvtail + nfuse + int(sum(num_engines)) # Computed by other components in drag group. self.add_input('skin_friction_coeff', np.zeros((nn, nc)), units='unitless') diff --git a/aviary/subsystems/geometry/flops_based/fuselage.py b/aviary/subsystems/geometry/flops_based/fuselage.py index 35c4cfaf1e..82198e496f 100644 --- a/aviary/subsystems/geometry/flops_based/fuselage.py +++ b/aviary/subsystems/geometry/flops_based/fuselage.py @@ -70,7 +70,9 @@ def setup(self): 'Rear_spar_percent_chord', 0.7, units='unitless', - desc='RSPSOB: Rear spar percent chord for BWB at side of body', + desc='RSPSOB: Rear spar percent chord for BWB at side of body, ' + ' or more precisely, the passenger compartment ends at the ' + ' 70% of fuselage length from the leading edge.', ) add_aviary_output(self, Aircraft.Fuselage.REF_DIAMETER, units='ft') diff --git a/aviary/subsystems/mass/flops_based/mass_premission.py b/aviary/subsystems/mass/flops_based/mass_premission.py index 5c51b1fb1e..c09e1d1411 100644 --- a/aviary/subsystems/mass/flops_based/mass_premission.py +++ b/aviary/subsystems/mass/flops_based/mass_premission.py @@ -173,6 +173,36 @@ def setup(self): 'electrical', AltElectricalMass(), promotes_inputs=['*'], promotes_outputs=['*'] ) + self.add_subsystem( + 'surf_ctrl', AltSurfaceControlMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + + if design_type == AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'fuselage', + BWBFuselageMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'fuselage', + AltFuselageMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'htail', + AltHorizontalTailMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'vert_tail', AltVerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + else: self.add_subsystem( 'fuel_system', @@ -232,6 +262,36 @@ def setup(self): 'electrical', ElectricalMass(), promotes_inputs=['*'], promotes_outputs=['*'] ) + self.add_subsystem( + 'surf_ctrl', SurfaceControlMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + + if design_type == AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'fuselage', + BWBFuselageMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'fuselage', + TransportFuselageMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'htail', + HorizontalTailMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'vert_tail', VerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + self.add_subsystem( 'starter', TransportStarterMass(), promotes_inputs=['*'], promotes_outputs=['*'] ) @@ -270,68 +330,6 @@ def setup(self): 'landing_group', LandingMassGroup(), promotes_inputs=['*'], promotes_outputs=['*'] ) - if alt_mass: - self.add_subsystem( - 'surf_ctrl', AltSurfaceControlMass(), promotes_inputs=['*'], promotes_outputs=['*'] - ) - - if design_type == AircraftTypes.BLENDED_WING_BODY: - self.add_subsystem( - 'fuselage', - BWBFuselageMass(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - else: - self.add_subsystem( - 'fuselage', - AltFuselageMass(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - self.add_subsystem( - 'htail', - AltHorizontalTailMass(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - self.add_subsystem( - 'vert_tail', AltVerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'] - ) - - else: - self.add_subsystem( - 'surf_ctrl', SurfaceControlMass(), promotes_inputs=['*'], promotes_outputs=['*'] - ) - - if design_type == AircraftTypes.BLENDED_WING_BODY: - self.add_subsystem( - 'fuselage', - BWBFuselageMass(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - else: - self.add_subsystem( - 'fuselage', - TransportFuselageMass(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - self.add_subsystem( - 'htail', - HorizontalTailMass(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - self.add_subsystem( - 'vert_tail', VerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'] - ) - self.add_subsystem('canard', CanardMass(), promotes_inputs=['*'], promotes_outputs=['*']) self.add_subsystem('fin', FinMass(), promotes_inputs=['*'], promotes_outputs=['*']) diff --git a/aviary/subsystems/test/test_flops_based_premission.py b/aviary/subsystems/test/test_flops_based_premission.py index 2ef158f33a..451b2d6930 100644 --- a/aviary/subsystems/test/test_flops_based_premission.py +++ b/aviary/subsystems/test/test_flops_based_premission.py @@ -1223,3 +1223,9 @@ def test_case_all_subsystems(self): if __name__ == '__main__': unittest.main() + import numpy as np + + np.seterr(divide='raise') + test = BWBPreMissionGroupCSVTest1() + test.setUp() + # test.test_case_geom_mass() diff --git a/aviary/utils/fortran_to_aviary.py b/aviary/utils/fortran_to_aviary.py index 757a89e226..307ec45545 100644 --- a/aviary/utils/fortran_to_aviary.py +++ b/aviary/utils/fortran_to_aviary.py @@ -904,7 +904,10 @@ def update_flops_options(vehicle_data): if input_values.get_val(Aircraft.Fuel.WING_FUEL_CAPACITY, 'lbm')[0] < 50: # Interpret value equivalently to FWMAX = wing_fuel_fraction * fuel_density * 2/3 FWMAX = input_values.get_val(Aircraft.Fuel.WING_FUEL_CAPACITY, 'lbm')[0] - FULDEN = input_values.get_val(Aircraft.Fuel.DENSITY, 'lbm/ft**3')[0] + if Aircraft.Fuel.DENSITY in input_values: + FULDEN = input_values.get_val(Aircraft.Fuel.DENSITY, 'lbm/ft**3')[0] + else: + FULDEN = 50.12 # 50.12 lbm/ft**3 = 6.7 lbm/galUS input_values.set_val( Aircraft.Fuel.WING_FUEL_FRACTION, [FWMAX / (FULDEN * (2 / 3))], 'unitless' ) @@ -914,6 +917,146 @@ def update_flops_options(vehicle_data): if Aircraft.Wing.INPUT_STATION_DIST in input_values: input_values.set_val(Aircraft.Wing.DETAILED_WING, [True]) + if not Mission.Landing.LIFT_COEFFICIENT_MAX in input_values: + unused_values = vehicle_data['unused_values'] + try: + CLAPP = unused_values.get_item('TOLIN.CLAPP')[0][0] + CLLDM = 1.69 * CLAPP + except: + CLLDM = 3.0 + input_values.set_val(Mission.Landing.LIFT_COEFFICIENT_MAX, [CLLDM]) + + design_type, design_units = input_values.get_item(Aircraft.Design.TYPE) + if design_type[0] == 0: + input_values.set_val(Aircraft.Design.TYPE, ['transport'], design_units) + + if Aircraft.Fuselage.LENGTH in input_values: + input_values.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, [True], 'unitless') + else: + input_values.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, [False], 'unitless') + elif design_type[0] == 3: + input_values.set_val(Aircraft.Design.TYPE, ['BWB'], design_units) + + # BWB always have detailed wing. + input_values.set_val(Aircraft.Wing.DETAILED_WING, [True]) + if Aircraft.Wing.INPUT_STATION_DIST in input_values: + input_station_dist = input_values.get_val(Aircraft.Wing.INPUT_STATION_DIST) + input_station_dist = [0.0] + input_station_dist + input_values.set_val(Aircraft.Wing.INPUT_STATION_DIST, input_station_dist) + n_dist = len(input_station_dist) + chord_per_semispan_dist = input_values.get_val(Aircraft.Wing.CHORD_PER_SEMISPAN_DIST) + chord_per_semispan_dist = [-1.0] + chord_per_semispan_dist[0 : n_dist - 1] + input_values.set_val(Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, chord_per_semispan_dist) + load_path_sweep_dist = input_values.get_val(Aircraft.Wing.LOAD_PATH_SWEEP_DIST, 'deg') + load_path_sweep_dist = [0.0] + load_path_sweep_dist[0 : n_dist - 2] + input_values.set_val(Aircraft.Wing.LOAD_PATH_SWEEP_DIST, load_path_sweep_dist, 'deg') + thickness_to_chord_dist = input_values.get_val(Aircraft.Wing.THICKNESS_TO_CHORD_DIST) + thickness_to_chord_dist = [-1.0] + thickness_to_chord_dist[0 : n_dist - 1] + input_values.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_DIST, thickness_to_chord_dist) + input_values.set_val(Aircraft.BWB.DETAILED_WING_PROVIDED, [True]) + else: + # For BWB, if detail wing is not provided, initialize it to [0, 0.5, 1]. See doc page for detail. + input_values.set_val(Aircraft.BWB.DETAILED_WING_PROVIDED, [False]) + input_values.set_val(Aircraft.Wing.INPUT_STATION_DIST, [0.0, 0.5, 1.0]) + + if ( + Aircraft.Fuselage.LENGTH in input_values + and Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP in input_values + ): + if ( + input_values.get_val(Aircraft.Fuselage.LENGTH, 'ft')[0] > 0.0 + and input_values.get_val(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 'deg')[0] > 0.0 + ): + input_values.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, [True], 'unitless') + else: + input_values.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, [False], 'unitless') + else: + input_values.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, [False], 'unitless') + + if Aircraft.Engine.SCALED_SLS_THRUST in input_values: + # This is a design variable. So, first entry is the initial value + thrust = input_values.get_val(Aircraft.Engine.SCALED_SLS_THRUST, 'lbf')[0] + input_values.set_val(Aircraft.Engine.SCALED_SLS_THRUST, [thrust], 'lbf') + + if not Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO in input_values: + if Aircraft.Wing.THICKNESS_TO_CHORD in input_values: + wing_tc = input_values.get_val(Aircraft.Wing.THICKNESS_TO_CHORD, 'unitless')[0] + input_values.set_val(Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, [wing_tc], 'unitless') + + if not Aircraft.Fuel.WING_FUEL_FRACTION in input_values: + # Interpret value equivalently to FWMAX = wing_fuel_fraction * fuel_density * 2/3 + FWMAX = 23 # the default + if Aircraft.Fuel.DENSITY in input_values: + FULDEN = input_values.get_val(Aircraft.Fuel.DENSITY, 'lbm/ft**3')[0] + else: + FULDEN = 50.1194909 # lbm/ft**3 or 6.7 lbm/galUS + input_values.set_val(Aircraft.Fuel.DENSITY, [6.7], 'lbm/galUS') + input_values.set_val( + Aircraft.Fuel.WING_FUEL_FRACTION, [FWMAX / (FULDEN * (2 / 3))], 'unitless' + ) + + # For BWB, wing area is always computed + if Aircraft.Wing.AREA in input_values: + input_values.delete(Aircraft.Wing.AREA) + if Aircraft.Wing.ASPECT_RATIO in input_values: + input_values.delete(Aircraft.Wing.ASPECT_RATIO) + + if ( + Aircraft.Engine.SCALED_SLS_THRUST in input_values + and Aircraft.Engine.REFERENCE_SLS_THRUST in input_values + ): + ref_thrust = input_values.get_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 'lbf')[0] + scaled_thrust = input_values.get_val(Aircraft.Engine.SCALED_SLS_THRUST, 'lbf')[0] + if scaled_thrust <= 0: + print( + 'Aircraft.Engine.REFERENCE_SLS_THRUST must be positive ' + f'but you have {scaled_thrust}' + ) + else: + engine_scale_factor = scaled_thrust / ref_thrust + input_values.set_val( + Aircraft.Engine.SCALE_FACTOR, [engine_scale_factor], 'unitless' + ) + else: + raise RuntimeError( + f'Currently, Aircraft.Design.TYPE must be either 0 or 3 not {design_type[0]}.' + ) + + if ( + not Aircraft.HorizontalTail.THICKNESS_TO_CHORD in input_values + or input_values.get_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 'unitless')[0] == 0 + ): + if Aircraft.Wing.THICKNESS_TO_CHORD in input_values: + wing_tc = input_values.get_val(Aircraft.Wing.THICKNESS_TO_CHORD, 'unitless')[0] + input_values.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, [wing_tc], 'unitless') + + if (not Aircraft.VerticalTail.THICKNESS_TO_CHORD in input_values) or ( + input_values.get_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, 'unitless')[0] == 0 + ): + if Aircraft.Wing.THICKNESS_TO_CHORD in input_values: + wing_tc = input_values.get_val(Aircraft.Wing.THICKNESS_TO_CHORD, 'unitless')[0] + input_values.set_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, [wing_tc], 'unitless') + + # These variables should be removed if they are zero. + rem_list = [ + (Aircraft.Fuselage.CABIN_AREA, 'ft**2'), + (Aircraft.Fuselage.MAX_HEIGHT, 'ft'), + (Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, 'ft'), + (Aircraft.Fuselage.LENGTH, 'ft'), + (Aircraft.Fuselage.MAX_WIDTH, 'ft'), + (Aircraft.HorizontalTail.SWEEP, 'deg'), + ] + for var in rem_list: + try: + val = input_values.get_val(var[0], var[1])[0] + if val == 0.0: + input_values.delete(var[0]) + except: + pass + + if design_type[0] != 3: + input_values.delete(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP) + vehicle_data['input_values'] = input_values return vehicle_data @@ -922,7 +1065,6 @@ def update_aviary_options(vehicle_data): """Special handling for variables that occurs for either legacy code.""" input_values: NamedValues = vehicle_data['input_values'] - # if reference + scaled thrust both provided, set scale factor try: ref_thrust = input_values.get_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 'lbf')[0] ref_thrust = float(ref_thrust) diff --git a/aviary/utils/legacy_code_data/flops_defaults.py b/aviary/utils/legacy_code_data/flops_defaults.py index 98f796401d..1bef060d1e 100644 --- a/aviary/utils/legacy_code_data/flops_defaults.py +++ b/aviary/utils/legacy_code_data/flops_defaults.py @@ -7,12 +7,16 @@ 'WTIN.IALTWT': (False, 'unitless'), 'WTIN.CARGF': (False, 'unitless'), 'WTIN.IFUFU': (False, 'unitless'), + 'WTIN.HYDPR': (3000.0, 'psi'), + 'WTIN.ULF': (3.75, 'unitless'), + 'WTIN.WPPASS': (165.0, 'lbm'), 'ENGDIN.IDLE': (False, 'unitless'), 'ENGDIN.IGEO': (False, 'unitless'), 'ENGDIN.NONEG': (False, 'unitless'), 'AERIN.MIKE': (False, 'unitless'), 'AERIN.SWETF': (1, 'unitless'), 'AERIN.SWETV': (1, 'unitless'), + 'FUSEIN.SWPLE': (45.0, 'deg'), } ) diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 32a44e1aaf..caa6af385f 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -45,11 +45,13 @@ def preprocess_options(aviary_options: AviaryValues, meta_data=_MetaData, verbos preprocess_crewpayload(aviary_options, meta_data, verbosity) preprocess_fuel_capacities(aviary_options, verbosity) + preprocess_Engines(aviary_options, verbosity) if engine_models is not None: preprocess_propulsion(aviary_options, engine_models, meta_data, verbosity) +# this function is not used def remove_preprocessed_options(aviary_options): """ Remove options whose values will be computed in the preprocessors. @@ -550,6 +552,63 @@ def preprocess_fuel_capacities(aviary_options: AviaryValues, verbosity=None): return aviary_options +def preprocess_Engines(aviary_options: AviaryValues, verbosity=None): + """ + Preprocesses the AviaryValues object to ensure the number of engines is + the sum of wing engines and body engines. + + Parameters + ---------- + aviary_options : AviaryValues + Options to be updated + + """ + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + + if Aircraft.Engine.NUM_FUSELAGE_ENGINES in aviary_options: + num_fuselage_engines = aviary_options.get_val( + Aircraft.Engine.NUM_FUSELAGE_ENGINES, 'unitless' + ) + if isinstance(num_fuselage_engines, np.ndarray) or isinstance(num_fuselage_engines, list): + num_fuselage_engines = num_fuselage_engines[0] + else: + num_fuselage_engines = int(num_fuselage_engines) + else: + num_fuselage_engines = 0 + + if Aircraft.Engine.NUM_WING_ENGINES in aviary_options: + num_wing_engines = aviary_options.get_val(Aircraft.Engine.NUM_WING_ENGINES, 'unitless') + if isinstance(num_wing_engines, np.ndarray) or isinstance(num_wing_engines, list): + num_wing_engines = num_wing_engines[0] + else: + num_wing_engines = int(num_wing_engines) + else: + num_wing_engines = 0 + sum_engines = num_fuselage_engines + num_wing_engines + + if Aircraft.Engine.NUM_ENGINES in aviary_options: + num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + if isinstance(num_engines, np.ndarray) or isinstance(num_engines, list): + num_engines = num_engines[0] + else: + num_engines = int(num_engines) + if num_engines != sum_engines: + if verbosity >= Verbosity.BRIEF: + print( + 'Your total number of engines is not the same as ' + 'the sum of wing engines and fuselage engines.' + ) + else: + num_engines = sum_engines + aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, [num_engines]) + + return aviary_options + + def preprocess_propulsion( aviary_options: AviaryValues, engine_models: list = None, diff --git a/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv b/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv index ec3b79b50d..d4a0c6ff1f 100644 --- a/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv +++ b/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv @@ -28,6 +28,7 @@ aircraft:design:lift_dependent_drag_coeff_factor,0.93,unitless aircraft:design:subsonic_drag_coeff_factor,0.95,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:touchdown_mass,0.0,lbm +aircraft:design:type,transport,unitless aircraft:design:use_alt_mass,False,unitless aircraft:design:zero_lift_drag_coeff_factor,0.96,unitless aircraft:electrical:mass_scaler,1.1976,unitless @@ -72,6 +73,7 @@ aircraft:fuselage:max_width,12.3,ft aircraft:fuselage:military_cargo_floor,False,unitless aircraft:fuselage:num_fuselages,1,unitless aircraft:fuselage:passenger_compartment_length,97.5,ft +aircraft:fuselage:simple_layout,True,unitless aircraft:fuselage:wetted_area,4235.082096,ft**2 aircraft:horizontal_tail:area,349.522730527158,ft**2 aircraft:horizontal_tail:aspect_ratio,5.22699386503068,unitless @@ -288,7 +290,6 @@ MISSIN.txfufl,0 MISSIN.vqlm,260.0,320.0 OPTION.ianal,3 OPTION.icost,0 -OPTION.ifite,0 OPTION.iland,1 OPTION.ineng,0 OPTION.iplths,0 diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 1e516e96aa..1f90e65f29 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1752,7 +1752,7 @@ add_meta_data( Aircraft.Design.TYPE, meta_data=_MetaData, - historical_name={'GASP': ['INGASP.IHWB'], 'FLOPS': None, 'LEAPS1': None}, + historical_name={'GASP': ['INGASP.IHWB'], 'FLOPS': ['OPTION.IFITE'], 'LEAPS1': None}, units='unitless', types=AircraftTypes, option=True,