diff --git a/aviary/api.py b/aviary/api.py index 3e969c3f6..9bd1e7104 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -30,10 +30,10 @@ from aviary.utils.aviary_values import AviaryValues from aviary.utils.csv_data_file import read_data_file, write_data_file from aviary.utils.data_interpolator_builder import build_data_interpolator -from aviary.variable_info.enums import AlphaModes, AnalysisScheme, ProblemType, SpeedType, GASP_Engine_Type, Flap_Type -from aviary.interface.default_phase_info.gasp import phase_info as default_2DOF_phase_info -from aviary.interface.default_phase_info.flops import phase_info as default_height_energy_phase_info -from aviary.interface.default_phase_info.gasp_fiti import create_gasp_based_ascent_phases, create_gasp_based_descent_phases +from aviary.variable_info.enums import AlphaModes, AnalysisScheme, ProblemType, SpeedType, GASPEngineType, FlapType, EquationsOfMotion, LegacyCode, Verbosity +from aviary.interface.default_phase_info.two_dof import phase_info as default_2DOF_phase_info +from aviary.interface.default_phase_info.height_energy import phase_info as default_height_energy_phase_info +from aviary.interface.default_phase_info.two_dof_fiti import create_2dof_based_ascent_phases, create_2dof_based_descent_phases from aviary.interface.default_phase_info.solved import phase_info as default_solved_phase_info from aviary.interface.default_phase_info.simple import phase_info as default_simple_phase_info from aviary.interface.methods_for_level1 import run_level_1 @@ -46,7 +46,7 @@ from aviary.utils.options import list_options from aviary.constants import GRAV_METRIC_GASP, GRAV_ENGLISH_GASP, GRAV_METRIC_FLOPS, GRAV_ENGLISH_FLOPS, GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH, RHO_SEA_LEVEL_METRIC, MU_TAKEOFF, MU_LANDING, PSLS_PSF, TSLS_DEGR, RADIUS_EARTH_METRIC from aviary.subsystems.test.subsystem_tester import TestSubsystemBuilderBase, skipIfMissingDependencies -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems ################### # Level 3 Imports # diff --git a/aviary/docs/examples/additional_flight_phases.ipynb b/aviary/docs/examples/additional_flight_phases.ipynb index 4d65413f8..a28066d63 100644 --- a/aviary/docs/examples/additional_flight_phases.ipynb +++ b/aviary/docs/examples/additional_flight_phases.ipynb @@ -223,9 +223,8 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info,\n", - " mission_method=\"simple\", mass_method=\"FLOPS\",\n", - " optimizer=\"SLSQP\", make_plots=True)" + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + " phase_info, optimizer=\"SLSQP\", make_plots=True)" ] }, { @@ -277,7 +276,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.18" + "version": "3.10.8" } }, "nbformat": 4, diff --git a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb index 45d9bad73..631f5fe37 100644 --- a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb +++ b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb @@ -155,16 +155,13 @@ "source": [ "import aviary.api as av\n", "\n", - "aircraft_filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", - "mission_method = \"simple\"\n", - "mass_method = \"FLOPS\"\n", + "aircraft_filename = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", "optimizer = \"IPOPT\"\n", "make_plots = True\n", "max_iter = 200\n", "\n", - "prob = av.run_aviary(aircraft_filename, phase_info,\n", - " mission_method=mission_method, mass_method=mass_method,\n", - " optimizer=optimizer, make_plots=make_plots, max_iter=max_iter)" + "prob = av.run_aviary(aircraft_filename, phase_info, optimizer=optimizer,\n", + " make_plots=make_plots, max_iter=max_iter)" ] }, { @@ -212,11 +209,11 @@ "metadata": {}, "outputs": [], "source": [ - "prob = av.AviaryProblem(phase_info, mission_method, mass_method, av.AnalysisScheme.COLLOCATION)\n", + "prob = av.AviaryProblem(av.AnalysisScheme.COLLOCATION)\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(aircraft_filename)\n", + "prob.load_inputs(aircraft_filename, phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -289,9 +286,8 @@ "phase_info['descent_1']['user_options']['optimize_mach'] = True\n", "phase_info['descent_1']['user_options']['optimize_altitude'] = True\n", "\n", - "prob = av.run_aviary(aircraft_filename, phase_info,\n", - " mission_method=mission_method, mass_method=mass_method,\n", - " optimizer=optimizer, make_plots=make_plots, max_iter=max_iter)" + "prob = av.run_aviary(aircraft_filename, phase_info, optimizer=optimizer,\n", + " make_plots=make_plots, max_iter=max_iter)" ] }, { @@ -333,11 +329,11 @@ "metadata": {}, "outputs": [], "source": [ - "prob = av.AviaryProblem(phase_info, mission_method, mass_method, av.AnalysisScheme.COLLOCATION)\n", + "prob = av.AviaryProblem(av.AnalysisScheme.COLLOCATION)\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(aircraft_filename)\n", + "prob.load_inputs(aircraft_filename, phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -440,7 +436,7 @@ "In both cases where the wing aspect ratio is optimized, it moves to the higher bound.\n", "\n", "If we didn't simultaneously design the aircraft and the mission, you would have to manually iterate by first optimizing the aircraft, then the mission, then the aircraft again, etc.\n", - "This cumbersome process is known as sequential optimization and can lead to non-optimal results for coupled systems, as detailed in [Section 13.1 of the free Engineering Design Optimization textbook](https://flowlab.groups.et.byu.net/mdobook.pdf).\n", + "This cumbersome process is known as sequential optimization and can lead to non-optimal results for coupled systems, as detailed in Section 13.1 of the [Engineering Design Optimization textbook](https://flowlab.groups.et.byu.net/mdobook.pdf) (available for free).\n", "\n", "Aviary is unique in its ability to solve these coupled systems using efficient gradient-based optimization.\n", "\n", diff --git a/aviary/docs/examples/intro.md b/aviary/docs/examples/intro.md index 2cf96bcba..2af40c2d9 100644 --- a/aviary/docs/examples/intro.md +++ b/aviary/docs/examples/intro.md @@ -5,7 +5,7 @@ Aviary provides a range of built-in examples that serve as both regression tests and demonstrations of the tool's capabilities. These examples showcase various full mission analysis and optimization problems, incorporating different subsystem analyses from FLOPS and GASP. You can find these examples [here](https://github.com/OpenMDAO/om-Aviary/tree/main/aviary/validation_cases/benchmark_tests), especially the files that start `test_swap`. -These cases highlight the progress and expansion of Aviary's functionality, reflecting the January milestone achieved by the Aviary team that combined basic GASP and FLOPS capabilities. +These cases highlight Aviary's ability to replicate GASP and FLOPS capabilities, as well as use both code's methods in a single analysis. In addition to the examples for core Aviary, we also provide some examples for using external subsystems. These are contained in the `aviary/examples/external_subsystems` folder. diff --git a/aviary/docs/examples/more_advanced_example.ipynb b/aviary/docs/examples/more_advanced_example.ipynb index d66fb836b..ee8e50ece 100644 --- a/aviary/docs/examples/more_advanced_example.ipynb +++ b/aviary/docs/examples/more_advanced_example.ipynb @@ -125,9 +125,8 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info,\n", - " mission_method=\"simple\", mass_method=\"FLOPS\",\n", - " optimizer=\"SLSQP\", make_plots=True)" + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + " phase_info, optimizer=\"SLSQP\", make_plots=True)" ] }, { @@ -189,7 +188,7 @@ "source": [ "import csv\n", "\n", - "filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "filename = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", "filename = av.get_path(filename)\n", "\n", "# Read the file\n", @@ -233,8 +232,7 @@ "outputs": [], "source": [ "prob = av.run_aviary('modified_aircraft.csv', phase_info,\n", - " mission_method=\"simple\", mass_method=\"FLOPS\",\n", - " optimizer=\"SLSQP\", make_plots=True)" + " optimizer=\"SLSQP\", make_plots=True)" ] }, { @@ -281,9 +279,8 @@ "phase_info['cruise']['user_options']['polynomial_control_order'] = 1\n", "phase_info['descent_1']['user_options']['polynomial_control_order'] = 3\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info,\n", - " mission_method=\"simple\", mass_method=\"FLOPS\",\n", - " optimizer=\"IPOPT\", make_plots=True)" + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + " phase_info, optimizer=\"IPOPT\", make_plots=True)" ] }, { diff --git a/aviary/docs/examples/simple_mission_example.ipynb b/aviary/docs/examples/simple_mission_example.ipynb index 681f22980..40556809d 100644 --- a/aviary/docs/examples/simple_mission_example.ipynb +++ b/aviary/docs/examples/simple_mission_example.ipynb @@ -21,7 +21,7 @@ "* value: the user-defined value of the variable\n", "* units: the units of the variable\n", "\n", - "Let's take a look at the first few lines of an example aircraft file, `aircraft_for_bench_FwFm.csv`.\n", + "Let's take a look at the first few lines of an example aircraft file, `aircraft_for_bench_FwFm_simple.csv`.\n", "This aircraft is a commercial single-aisle aircraft with two conventional turbofan engines.\n", "Think of it in the same class as a Boeing 737 or Airbus A320.\n", "\n", @@ -40,7 +40,7 @@ "source": [ "import aviary.api as av\n", "\n", - "filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "filename = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", "filename = av.get_path(filename)\n", "\n", "with open(filename, 'r') as file:\n", @@ -62,7 +62,7 @@ "Please look at relevant examples to see what variables are needed.\n", "```\n", "\n", - "For this example case, we'll be using the `simple` mission method and the `FLOPS`-based mass estimation method.\n", + "For this example case, our model is using the `simple` mission method and `FLOPS`-based mass and aero estimation methods.\n", "We strongly suggest using the `simple` mission method as it is the most robust and easiest to use.\n", "There are relatively few reasons to use a more complex mission method and you should only do so if you have a particular reason to use a more detailed method.\n", "\n", @@ -115,6 +115,8 @@ "Phase info has been saved and formatted in /mnt/c/Users/user/Dropbox/git/Aviary/outputted_phase_info.py\n", "```\n", "\n", + "If you don't have the [black](https://pypi.org/project/black/) python autoformatter installed, your output may look slightly different - as long as you see confirmation that your phase info has been saved, your mission profile was successfully created.\n", + "\n", "The `phase_info` dictionary has been saved to a file called `outputted_phase_info.py` in the current directory.\n", "Let's dig into it.\n", "\n", @@ -277,9 +279,8 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info,\n", - " mission_method=\"simple\", mass_method=\"FLOPS\",\n", - " optimizer=\"SLSQP\", make_plots=True)" + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + " phase_info, optimizer=\"SLSQP\", make_plots=True)" ] }, { diff --git a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb index 245ca7392..c7dea5425 100644 --- a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb +++ b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb @@ -56,11 +56,11 @@ "# Here we just add the simple weight system to only the pre-mission\n", "phase_info['pre_mission']['external_subsystems'] = [WingWeightBuilder(name=\"wing_external\")]\n", "\n", - "prob = av.AviaryProblem(phase_info, mission_method=\"simple\", mass_method=\"FLOPS\")\n", + "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv')\n", + "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -115,11 +115,11 @@ "\n", "# Max iterations set to 1 to reduce runtime of example\n", "max_iter = 1\n", - "prob = av.AviaryProblem(av.default_simple_phase_info, mission_method=\"simple\", mass_method=\"FLOPS\")\n", + "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv')\n", + "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', av.default_simple_phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -229,9 +229,9 @@ "metadata": {}, "outputs": [], "source": [ - "prob = av.AviaryProblem(phase_info, mission_method=\"simple\", mass_method=\"FLOPS\")\n", + "prob = av.AviaryProblem()\n", "\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv')" + "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info)" ] }, { @@ -622,16 +622,14 @@ "metadata": {}, "outputs": [], "source": [ - "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", - "mission_method = 'simple'\n", - "mass_method = 'FLOPS'\n", + "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", "make_plots = False\n", "max_iter = 0\n", "optimizer = 'SNOPT'\n", "\n", - "prob = av.AviaryProblem(phase_info, mission_method=mission_method, mass_method='FLOPS')\n", + "prob = av.AviaryProblem()\n", "\n", - "prob.load_inputs(aircraft_definition_file)\n", + "prob.load_inputs(aircraft_definition_file, phase_info)\n", "prob.check_inputs()\n", "prob.add_pre_mission_systems()\n", "prob.add_phases()\n", @@ -737,7 +735,7 @@ "id": "c04ddce7", "metadata": {}, "source": [ - "The result is comparitable to the output without OpenAeroStruct external subsystem." + "The result is comparable to the output without OpenAeroStruct external subsystem." ] } ], @@ -757,7 +755,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.17" + "version": "3.10.8" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level1.ipynb b/aviary/docs/getting_started/onboarding_level1.ipynb index 84ccc4506..62fff50a8 100644 --- a/aviary/docs/getting_started/onboarding_level1.ipynb +++ b/aviary/docs/getting_started/onboarding_level1.ipynb @@ -46,9 +46,10 @@ " Some variables are only used as initial guesses for the trajectory.\n", " These are displayed separately from the Input Values because they will not be passed directly to components\n", "3. **Unconverted Values:**\n", - " If the fortran_to_aviary converter can't find an Aviary variable with a `historical_name` that matches the FORTRAN variable, it is added to the end of the csv file.\n", + " If the fortran_to_aviary converter can't find an Aviary variable that matches the FORTRAN variable, it is added to the end of the csv file.\n", " We recommend that you check this section after converting a namelist to ensure that there aren't any variables you expected to be converted here.\n", - " Aviary will ignore these variables when loading the csv so you can safely leave them." + " Many of these unconverted variables represent features or options that are not used in Aviary and can be safely ignored. Variables related to mission definition are important, but Aviary defines mission profiles in a significantly different way. Currently, the user must build a new [mission definition file](../examples/simple_mission_example.ipynb) that recreates the mission.\n", + " Aviary will ignore unconverted variables when loading the csv, so you can safely leave them.\n" ] }, { @@ -175,7 +176,7 @@ }, "outputs": [], "source": [ - "!aviary run_mission --max_iter 1 --mass_origin GASP --mission_method GASP --optimizer IPOPT models/test_aircraft/aircraft_for_bench_GwGm.csv" + "!aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --max_iter 1 --optimizer IPOPT" ] }, { @@ -248,15 +249,11 @@ "\n", "- `-o ––outdir`: Use specified directory to write output. The default is the current directory.\n", "\n", - "- `--mass_origin`: Mass estimation origin to use (either “`GASP`” or “`FLOPS`”). The default is `FLOPS`.\n", - "\n", - "- `--mission_method`: Mission origin to use (either “`GASP`”, “`FLOPS`”, or “`simple`”). The default is `simple`.\n", - "\n", "- `--optimizer`: Name of optimizer. Choices are: `SNOPT`, `IPOPT`, `SLSQP`, and `None`. The default is `SNOPT`. If optimizer is `None`, it will be set to `IPOPT` or `SNOPT` depending on the analysis scheme. The optimization objective is fuel burn for level 1 runs. The objective is\n", " - `mission:objectives:fuel` if `mission_method` is `GASP` \n", " - `fuel_burned` if `mission_method` is `FLOPS`.\n", "\n", - "- `--phase_info`: Path to phase info file. If not provided, it is `default_phase_info/gasp.py` if Mission origin is `GASP` and `default_phase_info/flops.py` otherwise.\n", + "- `--phase_info`: Path to phase info file. If not provided, it is `default_phase_info/gasp.py` if Mission origin is `2DOF` and `default_phase_info/flops.py` for `height_energy`.\n", "\n", "- `--n2`: Generate an n2 diagram after the analysis. “[N2](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_basics/n2_basics.html)” diagram is an OpenMDAO helper to visualize the model (see [details](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_details/n2_details.html) too and [tutorial](https://www.youtube.com/watch?v=42VtbX6CX3A)). It is highly recommended that this option is turned on for new users.\n", "\n", @@ -278,84 +275,7 @@ }, "outputs": [], "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1 --mass_origin GASP --mission_method GASP" - ] - }, - { - "cell_type": "markdown", - "id": "183d1ed0", - "metadata": {}, - "source": [ - "## More level 1 runs with other benchmark models\n", - "\n", - "In subdirectory `aviary/models/test_aircraft`, there are four input data files: `aircraft_for_bench_GwFm.csv`, `aircraft_for_bench_GwGm.csv`, `aircraft_for_bench_FwGm.csv`, and `aircraft_for_bench_FwFm.csv`. They are all models of large single aisle aircraft. You can ignore the other files in that directory for now.\n", - "\n", - "Let’s make a few more runs using the above options. Run `aircraft_for_bench_GwFm.csv` data using `FLOPS`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "719136b3", - "metadata": {}, - "outputs": [], - "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_GwFm.csv --mass_origin GASP --mission_method FLOPS --max_iter 1 --optimizer IPOPT" - ] - }, - { - "cell_type": "markdown", - "id": "6be5f00b", - "metadata": {}, - "source": [ - "```{note}\n", - "Not all option combinations will work. For example, the following run results in a runtime error:\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b44d1921", - "metadata": {}, - "outputs": [], - "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_GwFm.csv --mass_origin GASP --mission_method GASP --max_iter 1 --optimizer IPOPT" - ] - }, - { - "cell_type": "markdown", - "id": "4a6b74a6", - "metadata": {}, - "source": [ - "However, the following run is successful:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c5ae353a", - "metadata": {}, - "outputs": [], - "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --mass_origin FLOPS --mission_method FLOPS --max_iter 1 --optimizer IPOPT" - ] - }, - { - "cell_type": "markdown", - "id": "afbd2315", - "metadata": {}, - "source": [ - "This is because these benches were each individually made to test a particular mass/mission/geometry/aerodynamics combination. They may not work with other combinations. The following commands will work:\n", - "\n", - "```\n", - "aviary run_mission models/test_aircraft/aircraft_for_bench_GwFm.csv --mass_origin GASP --mission_method FLOPS\n", - "aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --mass_origin FLOPS --mission_method FLOPS\n", - "aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --mass_origin GASP --mission_method GASP\n", - "aviary run_mission models/test_aircraft/aircraft_for_bench_GwFm.csv --mass_origin GASP --mission_method FLOPS\n", - "```\n", - "\n", - "As you see, we have marked the file name `Gw`for `mass_origin GASP` and `Fw` for `mass_origin FLOPS`. Similarly, `Gm` for `mission_method GASP` and `Fm` for `mission_method FLOPS`." + "!aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1" ] }, { @@ -365,7 +285,7 @@ "source": [ "## Other available input files\n", "\n", - "Other input files reside in aviary/validation_cases. They are:\n", + "Other input files reside in aviary/models. They include:\n", "\n", "```\n", "aviary/models/validation_data/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv\n", @@ -384,7 +304,7 @@ "metadata": {}, "outputs": [], "source": [ - "!aviary run_mission models/large_single_aisle_1/large_single_aisle_1_GwGm.csv --mass_origin GASP --mission_method GASP --max_iter 1 --optimizer IPOPT" + "!aviary run_mission models/large_single_aisle_1/large_single_aisle_1_GwGm.csv --max_iter 1 --optimizer IPOPT" ] }, { @@ -392,7 +312,7 @@ "id": "c64a853c", "metadata": {}, "source": [ - "For FLOPS models, let us run:" + "For FLOPS-derived models, let us run:" ] }, { @@ -402,7 +322,7 @@ "metadata": {}, "outputs": [], "source": [ - "!aviary run_mission --mission_method FLOPS --mass_origin FLOPS --max_iter 1 --optimizer IPOPT models/test_aircraft/aircraft_for_bench_FwFm.csv" + "!aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --max_iter 1 --optimizer IPOPT" ] }, { @@ -418,7 +338,7 @@ "\n", "### Default GASP phases\n", "\n", - "The `default_phase_info/gasp.py` file is shown below:" + "The `default_phase_info/two_dof.py` file is shown below:" ] }, { @@ -435,7 +355,7 @@ "import aviary.api as av\n", "\n", "# Get the path of variables.py within the aviary package\n", - "file_path = av.get_path('interface/default_phase_info/gasp.py')\n", + "file_path = av.get_path('interface/default_phase_info/two_dof.py')\n", "\n", "# Read the file contents\n", "with open(file_path, 'r') as file:\n", @@ -511,7 +431,7 @@ "```\n", "Dynamic.Mission.THROTTLE = 1.0\n", "```\n", - "For the [COLLOCATION](https://openmdao.github.io/dymos/getting_started/collocation.html) setting, there is one [segment](https://openmdao.github.io/dymos/getting_started/intro_to_dymos/intro_segments.html) (`'num_segments': 1`) and polynomial interpolation degree is 3 (`'order': 3`). Increasing the number of segments and/or increasing the degree of polynomial will improve accuracy but will also increase the complexity of computation. For groundroll, it is unnecessary.\n", + "For the [`COLLOCATION`](https://openmdao.github.io/dymos/getting_started/collocation.html) setting, there is one [segment](https://openmdao.github.io/dymos/getting_started/intro_to_dymos/intro_segments.html) (`'num_segments': 1`) and polynomial interpolation degree is 3 (`'order': 3`). Increasing the number of segments and/or increasing the degree of polynomial will improve accuracy but will also increase the complexity of computation. For groundroll, it is unnecessary.\n", "\n", "Since groundroll is the first phase, `connect_initial_mass` is set to `False`. `fix_initial` is set to `True`, but `fix_initial_mass` to `False` because aircraft total mass is a design parameter.\n", "\n", @@ -541,9 +461,7 @@ "\n", "```{note}\n", "File `default_phase_info/flops.py` has a `pre_mission` phase and a `post_mission` phase. In `pre_mission`, `takeoff` is the simplified takeoff and in `post_mission`, `landing` is the simplified landing. For `FLOPS` missions, there are [detailed takeoff and landing](../user_guide/FLOPS_based_detailed_takeoff_and_landing) available. But they are not used in `default_phase_info/flops.py`. The other phases are mission phases.\n", - "```\n", - "\n", - "Also, note that `FLOPS` default `phase_info` has an `core_aerodynamics` key for each of mission phases. If you run with `mission_method FLOPS`, then you need to specify an aero dynamics builder class. On the other hand, for `mission_method GASP`, the aerodynamics class is predefined by the Aviary developers. For example, `ascent` phase uses `LowSpeedAero` and `accel` phase uses `CruiseAero`." + "```" ] }, { @@ -814,7 +732,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.17" + "version": "3.10.8" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index a0db18448..317f42cdd 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -15,8 +15,6 @@ "\n", "- `aircraft_filename`: `aircraft_for_bench_GwGm`\n", "- `phase_info`: `phase_info` (loaded from `aviary/interface/default_phase_info/gasp.py`)\n", - "- `mission_method`: `GASP`\n", - "- `mass_method`: `GASP`\n", "- `optimizer`: `IPOPT` (the default is `None`)\n", "- `analysis_scheme`: `AnalysisScheme.COLLOCATION` (the default)\n", "- `objective_type`: `None` (default)\n", @@ -82,8 +80,6 @@ "\n", "# inputs that run_aviary() requires\n", "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_GwGm.csv\"\n", - "mission_method = \"GASP\"\n", - "mass_method = \"GASP\"\n", "optimizer = \"IPOPT\"\n", "analysis_scheme = av.AnalysisScheme.COLLOCATION\n", "objective_type = None\n", @@ -92,11 +88,11 @@ "max_iter = 0\n", "\n", "# Build problem\n", - "prob = av.AviaryProblem(av.default_2DOF_phase_info, mission_method, mass_method, analysis_scheme)\n", + "prob = av.AviaryProblem(analysis_scheme)\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(aircraft_filename)\n", + "prob.load_inputs(aircraft_filename, av.default_2DOF_phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -156,8 +152,6 @@ "outputs": [], "source": [ "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_GwGm.csv\"\n", - "mission_method = \"GASP\"\n", - "mass_method = \"GASP\"\n", "optimizer = \"IPOPT\"\n", "analysis_scheme = av.AnalysisScheme.COLLOCATION\n", "objective_type = None\n", @@ -165,7 +159,7 @@ "restart_filename = None\n", "max_iter = 1\n", "\n", - "prob = av.AviaryProblem(av.default_2DOF_phase_info, mission_method, mass_method, analysis_scheme)" + "prob = av.AviaryProblem(analysis_scheme)" ] }, { @@ -176,20 +170,18 @@ "Several objects are initialized in this step:\n", "\n", "```\n", - " self.model = om.Group()\n", - " self.pre_mission = PreMissionGroup()\n", - " self.post_mission = PostMissionGroup()\n", - " self.aviary_inputs = None\n", - " self.phase_info = phase_info\n", - " self.traj = None\n", - " self.mission_method = mission_method\n", - " self.mass_method = mass_method\n", - " self.analysis_scheme = analysis_scheme\n", - " self.pre_mission_info = self.phase_info.pop('pre_mission')\n", - " self.post_mission_info = self.phase_info.pop('post_mission')\n", + "self.model = om.Group()\n", + "self.pre_mission = PreMissionGroup()\n", + "self.post_mission = PostMissionGroup()\n", + "self.aviary_inputs = None\n", + "self.phase_info = phase_info\n", + "self.traj = None\n", + "self.analysis_scheme = analysis_scheme\n", + "self.pre_mission_info = self.phase_info.pop('pre_mission')\n", + "self.post_mission_info = self.phase_info.pop('post_mission')\n", "```\n", "\n", - "`phase_info` is a user defined dictionary (in a Python file) that controls the profile of the mission to be simulated (e.g. climb, cruise, descent segments etc). `mission_method` has three options: `GASP`, `FLOPS` and `solved`. The same is true for `mass_method`. \n", + "`phase_info` is a user defined dictionary (in a Python file) that controls the profile of the mission to be simulated (e.g. climb, cruise, descent segments etc).\n", "\n", "For `analysis_scheme`, the two options are: `AnalysisScheme.COLLOCATION` (default) and `AnalysisScheme.SHOOTING` which are defined and described in [variables_info/enums.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/variable_info/enums.py):\n", "- COLLOCATION uses the collocation method to optimize all points simultaneously.\n", @@ -205,7 +197,7 @@ "metadata": {}, "outputs": [], "source": [ - "prob.load_inputs(aircraft_filename)" + "prob.load_inputs(aircraft_filename, av.default_2DOF_phase_info)" ] }, { @@ -216,8 +208,8 @@ "is a function that has a few tasks:\n", "\n", "- read aircraft deck file `aircraft_filename`\n", - "- build engine\n", - "- preprocess propulsion\n", + "- read phase info file `phase_info`\n", + "- build core subsystems, including setting up engines\n", "\n", "We have seen `aircraft_filename` file (a `.csv` file) in our level 1 examples. In [level 1](onboarding_level1), we simply called it input file. Engine is built by using `aircraft:engine:data_file` in the .csv file. For example in `aircraft_for_bench_GwGm.csv` file, we see:\n", "\n", @@ -235,7 +227,9 @@ "| 0.0, | 0.0, | 42.0, | 21214.0, | 0.0, | 5979.1, | 19.8547 |\n", "| 0.0, | 0.0, | 38.0, | 17356.9, | 0.0, | 4795.2, | 17.5877 |\n", "\n", - "The engine builder allows users to provide an `EngineModel` instance of their own to use in Aviary's propulsion systems. In the future this is where people would input NPSS or other engine models. The next task is to update certain parameters with values taken from provided `EngineModels`.\n", + "The engine builder allows users to provide an `EngineModel` instance of their own to use in Aviary's propulsion systems.\n", + "\n", + "Other subsystems, including mass, geometry, and aerodynamics, are set up according to which legacy code options the user has specified in their input file, using `settings:equations_of_motion` and `settings:mass_method`. Aerodynamics is set up to match the selected equations of motion, while geometry will use either GASP, FLOPS, or both methods as required to calculate all values needed by other subsystems.\n", "\n", "Next we check the user-provided inputs:" ] @@ -277,7 +271,7 @@ "source": [ "This call adds a pre-mission group (also called static analysis group) which includes pre-mission propulsion, geometry, pre-mission aerodynamics, and mass subsystems. \n", "\n", - "For `FLOPS` missions, aviary currently models the \"simplified\" takeoff as defined in [mission/flops_based/phases/simplified_takeoff.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_takeoff.py).\n", + "For `height_energy` missions, aviary currently models FLOPS' \"simplified\" takeoff as defined in [mission/flops_based/phases/simplified_takeoff.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_takeoff.py).\n", "\n", "Next is the line" ] @@ -301,7 +295,7 @@ "id": "f9f50477", "metadata": {}, "source": [ - "which adds a sequence of core mission phases. In addition, if `mission_method` is `GASP` and `ascent` is a phase, it adds an equality constraint to the problem to ensure that the TAS at the end of the groundroll phase is equal to the rotation velocity at the start of the rotation phase (`_add_groundroll_eq_constraint(phase)`). If `mission_method` is `FLOPS`, it sets up trajectory parameters by calling `setup_trajectory_params()`. If `mission_method` is `solved`, it has a block of code to make sure that the trajectory is smooth by applying boundary constraints between phases (e.g. fuselage pitch angle or true airspeed).\n", + "which adds a sequence of core mission phases. In addition, if `mission_method` is `2dof` and `ascent` is a phase, it adds an equality constraint to the problem to ensure that the TAS at the end of the groundroll phase is equal to the rotation velocity at the start of the rotation phase (`_add_groundroll_eq_constraint(phase)`). If `mission_method` is `height_energy`, it sets up trajectory parameters by calling `setup_trajectory_params()`. If `mission_method` is `solved`, it has a block of code to make sure that the trajectory is smooth by applying boundary constraints between phases (e.g. fuselage pitch angle or true airspeed).\n", "\n", "It follows by adding post-mission subsystems:" ] @@ -321,7 +315,7 @@ "id": "0c8038df", "metadata": {}, "source": [ - "Similar to pre-mission, it adds a landing phase if `include_landing` key of `post_mission` has value of `True`. If user chooses to define a `post_mission`, it will override the default. For `GASP` missions, landing is defined in [mission/gasp_based/phases/landing_group.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/gasp_based/phases/landing_group.py). For `FLOPS` mission, landing means a [simplified landing](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_landing.py). Note that the `solved` method currently doesn't have any post mission systems.\n", + "Similar to pre-mission, it adds a landing phase if `include_landing` key of `post_mission` has value of `True`. If user chooses to define a `post_mission`, it will override the default. For `2dof` missions, landing is defined in [mission/gasp_based/phases/landing_group.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/gasp_based/phases/landing_group.py). For `height_energy` mission, landing means a [simplified landing](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_landing.py). Note that the `solved` method currently doesn't have any post mission systems.\n", "\n", "The next line is" ] @@ -343,7 +337,7 @@ "source": [ "This is important for allowing each phase of flight to pass to the next without discontinuities in the parameters. Consider Dymos' [Aircraft Balanced Field Length Calculation](https://openmdao.github.io/dymos/examples/balanced_field/balanced_field.html) example. In that example, we see separate nonlinear boundary constraints, nonlinear path constraints, and phase continuity constraints between phases. We don't want to go deeper in this function call, but just point out that each individual link can be set via dymos function `link_phases`. See [dymos API](https://openmdao.github.io/dymos/api/trajectory_api.html) for more details.\n", "\n", - "The code blocks in this function (namely, `link_phases()`) are for `GASP`, `FLOPS`, and `solved` missions. The links are set up based on physical principals (e.g. you can’t have instantaneous changes in mass, velocity, position etc.). Special care is required if the user selects a different or unusual set of phases. \n", + "The code blocks in this function (namely, `link_phases()`) are for `2DOF`, `height_energy`, and `solved` missions. The links are set up based on physical principals (e.g. you can’t have instantaneous changes in mass, velocity, position etc.). Special care is required if the user selects a different or unusual set of phases. \n", "\n", "Now, our aircraft and the mission are fully defined. We are ready to define an optimization problem. This is achieved by adding an optimization driver, adding design variables, and an objective. \n", "\n", @@ -442,7 +436,7 @@ "source": [ "The selection of objective is a little complicated. \n", "\n", - "Earlier in this page, we have discussed the objective when `objective_type=None` and `mission_method` is `GASP`. Let us discuss the other situations.\n", + "Earlier in this page, we have discussed the objective when `objective_type=None` and `mission_method` is `2DOF`. Let us discuss the other situations.\n", "\n", "There are several objective types that users can choose: `mass`, `hybrid_objective`, `fuel_burned`, and `fuel`. \n", "\n", @@ -462,7 +456,7 @@ "```\n", "This is because if we just minimized fuel burn then the optimizer would probably fly the plane slowly to save fuel, but we actually care about some mix of minimizing fuel burn while providing a reasonable travel time for the passengers. This leads to the `hybrid_objective` which seeks to minimize a combination of those two objectives. `final_time` is the duration of the full mission and is usually in the range of hours. So, the denominator `5.` means `5 hours`. That's just a value to scale the final_time variable. Since it's a composite objective we didn't want to have OpenMDAO do the scaling because the two variables in the objective are of a different order of magnitude. We will show an example of this objective type in level 2 discussion.\n", "\n", - "If `objective_type=None` for a `GASP` mission, Aviary will choose the objective based on `mission_method` and `problem_type`. We have discussed this case earlier in this page.\n", + "If `objective_type=None` for a `2DOF` mission, Aviary will choose the objective based on `mission_method` and `problem_type`. We have discussed this case earlier in this page.\n", "\n", "If `objective_type=None` for a `FLOPS` mission method, Aviary adds a `fuel_burned` objective. In fact, this objective is available for `FLOPS` mission only. That number you get is for the actual fuel burned in lbm. You may get something like `fuel_burned` with the scaled value `[3.91228276]`, reference value `1e+04`. It translates to the dimensional physical quantity of `39,122.8276` lbm. To see this in action, check the resulting `reports/opt_report.html` file to see the optimal results.\n", "\n", @@ -471,7 +465,7 @@ "```\n", " reg_objective = overall_fuel/10000 + ascent_duration/30.\n", "```\n", - "where `overall_fuel` has the unit of `lbm` and `ascent_duration` has the unit of seconds. In our case, `mission_method = GASP`, the final value of objective is `[5.5910123]`, with `ref: 1.0` and `units: blank`. The units should be interpreted as `unitless`.\n", + "where `overall_fuel` has the unit of `lbm` and `ascent_duration` has the unit of seconds. In our case, `settings:equations_of_motion = 2DOF`, the final value of objective is `[5.5910123]`, with `ref: 1.0` and `units: blank`. The units should be interpreted as `unitless`.\n", "\n", "Here, `ref` is the reference value. For different objectives, the range may vary significantly different. We want to normalize the value. Ideally, users should choose `ref` such that the objective is in the range of `(0,1)`. This is required by optimizer.\n", "\n", @@ -519,7 +513,7 @@ "id": "57986647", "metadata": {}, "source": [ - "For `FLOPS` and `GASP` missions, this method performs several calls to `set_val` on the trajectory for states and controls to seed the problem with reasonable initial guesses using `initial_guesses` within corresponding phases (e.g. `default_flops_phases.py` and `default_gasp_phases.py`). For `solved` missions, it performs similar tasks but for hard-coded state parameters. This is reasonable because a `solved` mission is actually a level 3 Aviary approach. We will cover it in [level 3 onboarding doc](onboarding_level3.ipynb) in the next page. Note that initial guesses for all phases are especially important for collocation methods.\n", + "For `height_energy` and `2DOF` missions, this method performs several calls to `set_val` on the trajectory for states and controls to seed the problem with reasonable initial guesses using `initial_guesses` within corresponding phases (e.g. `default_flops_phases.py` and `default_gasp_phases.py`). For `solved` missions, it performs similar tasks but for hard-coded state parameters. This is reasonable because a `solved` mission is actually a level 3 Aviary approach. We will cover it in [level 3 onboarding doc](onboarding_level3.ipynb) in the next page. Note that initial guesses for all phases are especially important for collocation methods.\n", "\n", "The last line is to run the problem we just set up:" ] @@ -613,7 +607,7 @@ "metadata": {}, "outputs": [], "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --mission_method FLOPS --mass_origin FLOPS --max_iter 0 --optimizer IPOPT" + "!aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --max_iter 0 --optimizer IPOPT" ] }, { @@ -686,11 +680,11 @@ "restart_filename = None\n", "\n", "# Build problem\n", - "prob = av.AviaryProblem(phase_info, mission_method, mass_method, analysis_scheme)\n", + "prob = av.AviaryProblem(analysis_scheme)\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(aircraft_filename)\n", + "prob.load_inputs(aircraft_filename, phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -775,9 +769,9 @@ "```\n", "validation_cases/benchmark_tests/test_full_mission_solved_level3.py\n", "```\n", - "using `aircraft_for_bench_GwGm.csv` input deck. It is debatable whether it is an example in level 2 or level 3. We are treating it as level 2 because we use standard level 2 API, but as we will show in [level 3](onboarding_level3) onboarding document, `solved` missions are in geneal fall into level 3 category. Let us look at the key differences.\n", + "using the `aircraft_for_bench_GwGm_solved.csv` input deck. It can be run using level 2 or level 3. Here we are using the level 2 API, but as we will show in [level 3](onboarding_level3) onboarding document, `solved` missions generally fall into the level 3 category. Let us look at the key differences.\n", "\n", - "First, it uses `mission_method = \"solved\"` (instead of `GASP`):" + "Note that this input file specifies `solved` instead of `2DOF` under `settings:equations_of_motion`." ] }, { @@ -788,9 +782,7 @@ "outputs": [], "source": [ "# inputs that run_aviary() requires\n", - "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_GwGm.csv\"\n", - "mission_method = \"solved\"\n", - "mass_method = \"GASP\"\n", + "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_GwGm_solved.csv\"\n", "optimizer = \"IPOPT\"\n", "analysis_scheme = av.AnalysisScheme.COLLOCATION" ] @@ -800,7 +792,7 @@ "id": "aab4c294", "metadata": {}, "source": [ - "Second, it provides an objective rather than letting Aviary to choose one:" + "Here, we are specifying an objective rather than letting Aviary to choose one:" ] }, { @@ -832,11 +824,11 @@ "outputs": [], "source": [ "# Build problem\n", - "prob = av.AviaryProblem(av.default_solved_phase_info, mission_method, mass_method, analysis_scheme)\n", + "prob = av.AviaryProblem(analysis_scheme)\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(aircraft_filename)" + "prob.load_inputs(aircraft_filename, av.default_solved_phase_info)" ] }, { @@ -939,7 +931,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.18" + "version": "3.10.8" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb index d59368715..c032c68dd 100644 --- a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb +++ b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb @@ -44,7 +44,7 @@ "# This builder can be used for both takeoff and landing phases\n", "aero_builder = av.CoreAerodynamicsBuilder(\n", " name='low_speed_aero',\n", - " code_origin='FLOPS'\n", + " code_origin=av.LegacyCode.FLOPS\n", ")\n", "\n", "takeoff_subsystem_options = {'low_speed_aero': {\n", @@ -590,7 +590,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/aerodynamics.ipynb b/aviary/docs/user_guide/aerodynamics.ipynb index 5464017e4..8cc0b5929 100644 --- a/aviary/docs/user_guide/aerodynamics.ipynb +++ b/aviary/docs/user_guide/aerodynamics.ipynb @@ -7,7 +7,7 @@ "\n", "# Aerodynamics Subsystem\n", "\n", - "The built-in aerodynamics subsystem in Aviary offers multiple options for computing drag. Users can select from methods based on the FLOPS or GASP legacy codes. Choice of which legacy code's routines to use is determined by the `code_origin` option provided when initializing a `CoreAerodynamicsBuilder`." + "The built-in aerodynamics subsystem in Aviary offers multiple options for computing drag. Users can select from methods based on the FLOPS or GASP legacy codes. Choice of which legacy code's routines to use is determined by the `code_origin` option provided when initializing a `CoreAerodynamicsBuilder`. When using Aviary's [Level 1 interface](../getting_started/onboarding_level1.ipynb), the code origin for aerodynamics is automatically set to match with the mission method (height-energy is paired with FLOPS, and 2-degree-of-freedom is paired with GASP). Future updates to Aviary will allow for the user to specify aerodynamics code origin directly in the input file." ] }, { @@ -16,9 +16,9 @@ "metadata": {}, "outputs": [], "source": [ - "from aviary.api import CoreAerodynamicsBuilder\n", + "from aviary.api import CoreAerodynamicsBuilder, LegacyCode\n", "\n", - "aero_builder = CoreAerodynamicsBuilder(name='aero_example', code_origin='FLOPS')" + "aero_builder = CoreAerodynamicsBuilder(name='aero_example', code_origin=LegacyCode.FLOPS)" ] }, { diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 9dff1ea61..159df792b 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -31,9 +31,9 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', av.default_height_energy_phase_info,\n", - " mission_method=\"FLOPS\", mass_method=\"FLOPS\", max_iter=0,\n", - " optimizer=\"SLSQP\", make_plots=False)" + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " av.default_height_energy_phase_info,\n", + " max_iter=0, optimizer=\"SLSQP\", make_plots=False)" ] }, { @@ -164,11 +164,11 @@ "\n", "csv_path = \"models/test_aircraft/aircraft_for_bench_FwFm.csv\"\n", "\n", - "prob = av.AviaryProblem(phase_info, mission_method=\"FLOPS\", mass_method=\"FLOPS\")\n", + "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(csv_path)\n", + "prob.load_inputs(csv_path, phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "prob.check_inputs()\n", @@ -605,8 +605,7 @@ "\n", "dm.run_problem(prob, simulate=False, make_plots=False, simulate_kwargs={\n", " 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9},\n", - " solution_record_file='large_single_aisle_1_solution.db')\n", - "\n" + " solution_record_file='large_single_aisle_1_solution.db')\n" ] } ], diff --git a/aviary/docs/user_guide/external_aero.ipynb b/aviary/docs/user_guide/external_aero.ipynb index 2f6594da7..ff514ac63 100644 --- a/aviary/docs/user_guide/external_aero.ipynb +++ b/aviary/docs/user_guide/external_aero.ipynb @@ -218,8 +218,8 @@ "input_file = pkg_resources.resource_filename(\n", " \"aviary\", \"models/test_aircraft/aircraft_for_bench_GwFm.csv\")\n", "\n", - "prob = av.AviaryProblem(phase_info, mission_method=\"FLOPS\", mass_method=\"FLOPS\")\n", - "prob.load_inputs(input_file)\n", + "prob = av.AviaryProblem()\n", + "prob.load_inputs(input_file, phase_info)\n", "\n", "# Add correctly-sized polar to aviary_inputs so that input components are sized correctly.\n", "shape = (altitude.size, mach.size, angle_of_attack.size)\n", diff --git a/aviary/docs/user_guide/input_files.ipynb b/aviary/docs/user_guide/input_files.ipynb index 1d9f3356e..39e37182e 100644 --- a/aviary/docs/user_guide/input_files.ipynb +++ b/aviary/docs/user_guide/input_files.ipynb @@ -173,7 +173,7 @@ "source": [ "We can see that only `aircraft:wing:span` was read from file this time, and is the only variable present in the data loaded to memory. Additionally, a warning was created informing us that `Scale Factor` was skipped.\n", "\n", - "A second optional argument is `aliases`. This argument is used to map multiple possible header names to the same openMDAO variable. This is useful if your data files do not have a strict convention for variable names. In this example, our data file has a header labeled `Scale Factor`, but we would like to map it to the more precise `aircraft:wing:mass_scaler`. The allowable header name matching is not case-sensitive and Aviary will treat spaces and underscores as identical, so `scale_factor` will match with `Scale Factor`. This improves ease-of-use. However, the variable name you want headers mapped to are case-sensitive, in case you are connecting to an external component that doesn't follow Aviary's [variable naming standards](../developer_guide/coding_standards.md)." + "A second optional argument is `aliases`. This argument is used to map multiple possible header names to the same openMDAO variable. This is useful if your data files do not use Aviary variable names, or could contain multiple variants of names that all mean the same thing (such as 'height', 'alt', and 'altitude'). In this example, our data file has a header labeled `Scale Factor`, but we would like to map it to the more precise `aircraft:wing:mass_scaler`. The allowable header name matching is not case-sensitive and Aviary will treat spaces and underscores as identical, so `scale_factor` will match with `Scale Factor`. This improves ease-of-use. However, the variable name you want headers mapped to are case-sensitive, in case you are connecting to an external component that doesn't follow Aviary's [variable naming standards](../developer_guide/coding_standards.md). So if your alias dict contains `Final_Name: example_var`, any case combination of `example_var` will always return `Final_Name` capitalized as specified." ] }, { diff --git a/aviary/docs/user_guide/mass.md b/aviary/docs/user_guide/mass.md index ac6526c44..c3da0ade1 100644 --- a/aviary/docs/user_guide/mass.md +++ b/aviary/docs/user_guide/mass.md @@ -33,6 +33,7 @@ Aviary's mass subsystem is designed to accommodate different methodologies, incl ## Using the Mass Subsystem +The choice of which code's methods for mass estimate to use is set using the variable `settings:mass_method`. This variable can be specified in the Aviary input file or can be manually set when using the Level 2 or 3 interface. To effectively use the mass subsystem in Aviary, users need to provide reasonable estimates for mass-related variables in their aircraft .csv file. Which variables are used depends on which mass estimation subsystem you're using, such as `aircraft:crew_and_payload:mass_per_passenger`, `aircraft:engine:additional_mass_fraction`, etc. diff --git a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py index 656ca18ed..9ff7cc2a6 100644 --- a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py +++ b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py @@ -1,6 +1,6 @@ ''' This is a simple test mission to demonstrate the inclusion of a -pre-mission user defined external subsystem. The simple mission +pre-mission user defined external subsystem. The simple mission is based on input data read from the benchmark data file bench_4.csv, which represents a single-aisle commercial transport aircraft. The OpenAeroStruct (OAS) subsystem is used to compute an optimum wing @@ -108,17 +108,15 @@ if use_OAS: phase_info['pre_mission']['external_subsystems'] = [wing_weight_builder] -aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' -mission_method = 'simple' -mass_method = 'FLOPS' +aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv' make_plots = False max_iter = 100 optimizer = 'SNOPT' -prob = av.AviaryProblem(phase_info, mission_method=mission_method, mass_method='FLOPS') +prob = av.AviaryProblem() -prob.load_inputs(aircraft_definition_file) +prob.load_inputs(aircraft_definition_file, phase_info) prob.check_inputs() prob.add_pre_mission_systems() prob.add_phases() diff --git a/aviary/examples/external_subsystems/battery/run_cruise.py b/aviary/examples/external_subsystems/battery/run_cruise.py index b7b804b06..528493120 100644 --- a/aviary/examples/external_subsystems/battery/run_cruise.py +++ b/aviary/examples/external_subsystems/battery/run_cruise.py @@ -12,11 +12,11 @@ phase_info['pre_mission']['external_subsystems'] = [battery_builder] phase_info['climb']['external_subsystems'] = [battery_builder] -prob = av.AviaryProblem(phase_info, mission_method="simple", mass_method="FLOPS") +prob = av.AviaryProblem() # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv') +prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) prob.add_pre_mission_systems() diff --git a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py b/aviary/examples/external_subsystems/battery/run_multiphase_mission.py index 584f75238..1cae165e9 100644 --- a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py +++ b/aviary/examples/external_subsystems/battery/run_multiphase_mission.py @@ -18,11 +18,11 @@ input_file = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_FwFm.csv") -prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") +prob = AviaryProblem() # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs(input_file) +prob.load_inputs(input_file, phase_info) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are diff --git a/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py b/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py index 422617908..225b89b05 100644 --- a/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py +++ b/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py @@ -12,11 +12,11 @@ # Here we just add the simple weight system to only the pre-mission phase_info['pre_mission']['external_subsystems'] = [WingWeightBuilder()] -prob = av.AviaryProblem(phase_info, mission_method="simple", mass_method="FLOPS") +prob = av.AviaryProblem() # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv') +prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info) prob.add_pre_mission_systems() diff --git a/aviary/examples/level2_shooting_traj.py b/aviary/examples/level2_shooting_traj.py index 960db5926..983f42d6f 100644 --- a/aviary/examples/level2_shooting_traj.py +++ b/aviary/examples/level2_shooting_traj.py @@ -8,12 +8,12 @@ from aviary.api import AviaryProblem from aviary.api import AnalysisScheme, SpeedType, AlphaModes from aviary.api import FlexibleTraj -from aviary.api import create_gasp_based_ascent_phases +from aviary.api import create_2dof_based_ascent_phases from aviary.api import SGMCruise, SGMDescent from aviary.api import Dynamic -def run_aviary(aircraft_filename, phase_info, mission_method, mass_method, optimizer=None, analysis_scheme=AnalysisScheme.COLLOCATION, +def run_aviary(aircraft_filename, phase_info, optimizer=None, analysis_scheme=AnalysisScheme.COLLOCATION, objective_type=None, record_filename='dymos_solution.db', restart_filename=None, max_iter=50, run_driver=True, make_plots=True): """ This function runs the aviary optimization problem for the specified aircraft configuration and mission. @@ -30,11 +30,11 @@ def run_aviary(aircraft_filename, phase_info, mission_method, mass_method, optim of the Aviary problem. """ # Build problem - prob = AviaryProblem(phase_info, mission_method, mass_method, analysis_scheme) + prob = AviaryProblem(analysis_scheme) # Load aircraft and options data from user # Allow for user overrides here - prob.load_inputs(aircraft_filename) + prob.load_inputs(aircraft_filename, phase_info) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are @@ -46,7 +46,7 @@ def run_aviary(aircraft_filename, phase_info, mission_method, mass_method, optim # replace the default trajectory with a custom trajectory # This trajectory uses the full GASP based ascent profile, # a Breguet cruise, and a simplified descent - ascent_phases = create_gasp_based_ascent_phases( + ascent_phases = create_2dof_based_ascent_phases( prob.ode_args, cruise_alt=prob.cruise_alt, cruise_mach=prob.cruise_mach) @@ -140,10 +140,7 @@ def run_aviary(aircraft_filename, phase_info, mission_method, mass_method, optim if __name__ == "__main__": - - from aviary.interface.default_phase_info.gasp import phase_info + from aviary.interface.default_phase_info.two_dof import phase_info input_deck = 'models/large_single_aisle_1/large_single_aisle_1_GwGm.csv' run_aviary(input_deck, phase_info, - mission_method="GASP", mass_method="GASP", - analysis_scheme=AnalysisScheme.SHOOTING, run_driver=False, - ) + analysis_scheme=AnalysisScheme.SHOOTING, run_driver=False) diff --git a/aviary/interface/default_phase_info/flops.py b/aviary/interface/default_phase_info/height_energy.py similarity index 97% rename from aviary/interface/default_phase_info/flops.py rename to aviary/interface/default_phase_info/height_energy.py index cb245fb95..66d584192 100644 --- a/aviary/interface/default_phase_info/flops.py +++ b/aviary/interface/default_phase_info/height_energy.py @@ -4,11 +4,15 @@ from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData from aviary.variable_info.variables import Dynamic, Mission +from aviary.variable_info.enums import LegacyCode + +FLOPS = LegacyCode.FLOPS + prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) -mass = CoreMassBuilder('core_mass', BaseMetaData, 'FLOPS') -aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, 'FLOPS') -geom = CoreGeometryBuilder('core_geometry', BaseMetaData, 'FLOPS') +mass = CoreMassBuilder('core_mass', BaseMetaData, FLOPS) +aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) +geom = CoreGeometryBuilder('core_geometry', BaseMetaData, FLOPS) default_premission_subsystems = [prop, geom, mass, aero] default_mission_subsystems = [aero, prop] diff --git a/aviary/interface/default_phase_info/simple.py b/aviary/interface/default_phase_info/simple.py index f62af4ad5..0efd931c3 100644 --- a/aviary/interface/default_phase_info/simple.py +++ b/aviary/interface/default_phase_info/simple.py @@ -3,11 +3,14 @@ from aviary.subsystems.mass.mass_builder import CoreMassBuilder from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.enums import LegacyCode + +FLOPS = LegacyCode.FLOPS prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) -mass = CoreMassBuilder('core_mass', BaseMetaData, 'FLOPS') -aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, 'FLOPS') -geom = CoreGeometryBuilder('core_geometry', BaseMetaData, 'FLOPS') +mass = CoreMassBuilder('core_mass', BaseMetaData, FLOPS) +aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) +geom = CoreGeometryBuilder('core_geometry', BaseMetaData, FLOPS) default_premission_subsystems = [prop, geom, mass, aero] default_mission_subsystems = [aero, prop] diff --git a/aviary/interface/default_phase_info/solved.py b/aviary/interface/default_phase_info/solved.py index f4794458c..a481c42fb 100644 --- a/aviary/interface/default_phase_info/solved.py +++ b/aviary/interface/default_phase_info/solved.py @@ -4,6 +4,10 @@ from aviary.subsystems.mass.mass_builder import CoreMassBuilder from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.enums import LegacyCode + +GASP = LegacyCode.GASP + throttle_max = 1.0 throttle_climb = 0.956 @@ -11,9 +15,9 @@ throttle_idle = 0.0 prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) -mass = CoreMassBuilder('core_mass', BaseMetaData, 'GASP') -aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, 'GASP') -geom = CoreGeometryBuilder('core_geometry', BaseMetaData, 'GASP') +mass = CoreMassBuilder('core_mass', BaseMetaData, GASP) +aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, GASP) +geom = CoreGeometryBuilder('core_geometry', BaseMetaData, GASP) default_premission_subsystems = [prop, geom, aero, mass] default_mission_subsystems = [aero, prop] diff --git a/aviary/interface/default_phase_info/gasp.py b/aviary/interface/default_phase_info/two_dof.py similarity index 98% rename from aviary/interface/default_phase_info/gasp.py rename to aviary/interface/default_phase_info/two_dof.py index a959fbf59..a34a5098d 100644 --- a/aviary/interface/default_phase_info/gasp.py +++ b/aviary/interface/default_phase_info/two_dof.py @@ -6,6 +6,10 @@ from aviary.subsystems.mass.mass_builder import CoreMassBuilder from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData, Mission +from aviary.variable_info.enums import LegacyCode + + +GASP = LegacyCode.GASP throttle_max = 1.0 throttle_climb = 0.956 @@ -13,9 +17,9 @@ throttle_idle = 0.0 prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) -mass = CoreMassBuilder('core_mass', BaseMetaData, 'GASP') -aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, 'GASP') -geom = CoreGeometryBuilder('core_geometry', BaseMetaData, 'GASP') +mass = CoreMassBuilder('core_mass', BaseMetaData, GASP) +aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, GASP) +geom = CoreGeometryBuilder('core_geometry', BaseMetaData, GASP) default_premission_subsystems = [prop, geom, aero, mass] default_mission_subsystems = [aero, prop] diff --git a/aviary/interface/default_phase_info/gasp_fiti.py b/aviary/interface/default_phase_info/two_dof_fiti.py similarity index 97% rename from aviary/interface/default_phase_info/gasp_fiti.py rename to aviary/interface/default_phase_info/two_dof_fiti.py index 88d3a16d6..577bfc20c 100644 --- a/aviary/interface/default_phase_info/gasp_fiti.py +++ b/aviary/interface/default_phase_info/two_dof_fiti.py @@ -5,10 +5,10 @@ SGMRotation, SGMAscentCombined, SGMAccel, SGMClimb, SGMCruise, SGMDescent from aviary.variable_info.variables import Aircraft, Mission, Dynamic -# defaults for GASP based forward in time integeration phases +# defaults for 2DOF based forward in time integeration phases -def create_gasp_based_ascent_phases( +def create_2dof_based_ascent_phases( ode_args, cruise_alt=35e3, cruise_mach=.8, @@ -138,7 +138,7 @@ def create_gasp_based_ascent_phases( return phases -def create_gasp_based_descent_phases( +def create_2dof_based_descent_phases( ode_args, cruise_mach=.8, ): diff --git a/aviary/interface/methods_for_level1.py b/aviary/interface/methods_for_level1.py index dfd9a61e8..0bb4d810c 100644 --- a/aviary/interface/methods_for_level1.py +++ b/aviary/interface/methods_for_level1.py @@ -2,15 +2,13 @@ This file contains functions needed to run Aviary using the Level 1 interface. """ import os -import importlib.util -import sys import openmdao.api as om from aviary.variable_info.enums import AnalysisScheme from aviary.interface.methods_for_level2 import AviaryProblem -def run_aviary(aircraft_filename, phase_info, mission_method, mass_method, optimizer=None, +def run_aviary(aircraft_filename, phase_info, optimizer=None, analysis_scheme=AnalysisScheme.COLLOCATION, objective_type=None, record_filename='dymos_solution.db', restart_filename=None, max_iter=50, run_driver=True, make_plots=True, phase_info_parameterization=None, @@ -29,10 +27,6 @@ def run_aviary(aircraft_filename, phase_info, mission_method, mass_method, optim Filename from which to load the aircraft and options data. phase_info : dict Information about the phases of the mission. - mission_method : str - The method used for defining the mission; can be 'GASP', 'FLOPS', 'solved', or 'simple'. - mass_method : str - The method used for calculating the mass; can be 'GASP' or 'FLOPS'. optimizer : str The optimizer to use. analysis_scheme : AnalysisScheme, optional @@ -63,15 +57,14 @@ def run_aviary(aircraft_filename, phase_info, mission_method, mass_method, optim The function allows for user overrides on aircraft and options data. It raises warnings or errors if there are clashing user inputs. Users can modify or add methods to alter the Aviary problem's behavior. - """ # Build problem - prob = AviaryProblem(phase_info, mission_method, mass_method, analysis_scheme) + prob = AviaryProblem(analysis_scheme) # Load aircraft and options data from user # Allow for user overrides here - prob.load_inputs(aircraft_filename) + prob.load_inputs(aircraft_filename, phase_info) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are @@ -108,8 +101,6 @@ def run_level_1( input_deck, outdir='output', optimizer='SNOPT', - mass_origin='GASP', - mission_method='GASP', phase_info=None, n2=False, max_iter=50, @@ -131,32 +122,7 @@ def run_level_1( # else: kwargs['optimizer'] = optimizer - if phase_info is None: - if mission_method == 'GASP': - from aviary.interface.default_phase_info.gasp import phase_info, phase_info_parameterization - kwargs['phase_info_parameterization'] = phase_info_parameterization - - else: - from aviary.interface.default_phase_info.flops import phase_info, phase_info_parameterization - kwargs['phase_info_parameterization'] = phase_info_parameterization - else: - # Load the phase info dynamically from the current working directory - phase_info_module_path = os.path.join(os.getcwd(), "outputted_phase_info.py") - if not os.path.exists(phase_info_module_path): - raise FileNotFoundError( - "The outputted_phase_info.py file is not in the current working directory. Please run `draw_mission` to generate this file.") - - spec = importlib.util.spec_from_file_location( - "outputted_phase_info", phase_info_module_path) - outputted_phase_info = importlib.util.module_from_spec(spec) - sys.modules["outputted_phase_info"] = outputted_phase_info - spec.loader.exec_module(outputted_phase_info) - - # Access the phase_info variable from the loaded module - phase_info = outputted_phase_info.phase_info - - prob = run_aviary(input_deck, phase_info, mission_method=mission_method, - mass_method=mass_origin, **kwargs) + prob = run_aviary(input_deck, phase_info, **kwargs) if n2: outfile = os.path.join(outdir, "n2.html") @@ -186,20 +152,6 @@ def _setup_level1_parser(parser): help="Name of optimizer", choices=("SNOPT", "IPOPT", "SLSQP", "None") ) - parser.add_argument( - "--mass_origin", - type=str, - default="FLOPS", - help="Mass estimation origin to use", - choices=("GASP", "FLOPS") - ) - parser.add_argument( - "--mission_method", - type=str, - default="simple", - help="Mission origin to use", - choices=("GASP", "FLOPS", "simple") - ) parser.add_argument( "--phase_info", type=str, @@ -237,8 +189,6 @@ def _exec_level1(args, user_args): input_deck=args.input_deck, outdir=args.outdir, optimizer=args.optimizer, - mass_origin=args.mass_origin, - mission_method=args.mission_method, phase_info=args.phase_info, n2=args.n2, max_iter=args.max_iter, diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index f11e27994..9285db939 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -4,6 +4,8 @@ import inspect from pathlib import Path from datetime import datetime +import importlib.util +import sys import numpy as np @@ -46,8 +48,8 @@ from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import setup_trajectory_params, override_aviary_vars -from aviary.variable_info.variables import Aircraft, Mission, Dynamic -from aviary.variable_info.enums import AnalysisScheme, ProblemType, SpeedType, AlphaModes +from aviary.variable_info.variables import Aircraft, Mission, Dynamic, Settings +from aviary.variable_info.enums import AnalysisScheme, ProblemType, SpeedType, AlphaModes, EquationsOfMotion, LegacyCode from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData from aviary.variable_info.variables_in import VariablesIn @@ -58,13 +60,21 @@ from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.merge_variable_metadata import merge_meta_data -from aviary.variable_info.variables import Aircraft, Mission, Dynamic -from aviary.interface.default_phase_info.gasp_fiti import create_gasp_based_ascent_phases, create_gasp_based_descent_phases +from aviary.interface.default_phase_info.two_dof_fiti import create_2dof_based_ascent_phases, create_2dof_based_descent_phases from aviary.mission.gasp_based.idle_descent_estimation import descent_range_and_fuel from aviary.mission.flops_based.phases.phase_utils import get_initial +FLOPS = LegacyCode.FLOPS +GASP = LegacyCode.GASP + +HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY +TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM +SIMPLE = EquationsOfMotion.SIMPLE +SOLVED = EquationsOfMotion.SOLVED + + def wrapped_convert_units(val_unit_tuple, new_units): """ Wrapper for OpenMDAO's convert_units function. @@ -125,7 +135,7 @@ class AviaryProblem(om.Problem): additional methods to help users create and solve Aviary problems. """ - def __init__(self, phase_info, mission_method, mass_method, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): + def __init__(self, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): super().__init__(**kwargs) self.timestamp = datetime.now() @@ -136,8 +146,81 @@ def __init__(self, phase_info, mission_method, mass_method, analysis_scheme=Anal self.aviary_inputs = None + self.traj = None + + self.analysis_scheme = analysis_scheme + + def load_inputs(self, input_filename, phase_info=None, engine_builder=None): + """ + This method loads the aviary_values inputs and options that the + user specifies. They could specify files to load and values to + replace here as well. + Phase info is also loaded if provided by the user. If phase_info is None, + the appropriate default phase_info based on mission analysis method is used. + + This method is not strictly necessary; a user could also supply + an AviaryValues object and/or phase_info dict of their own. + """ + ## LOAD INPUT FILE ### + self.engine_builder = engine_builder + self.aviary_inputs, self.initial_guesses = create_vehicle(input_filename) + + aviary_inputs = self.aviary_inputs + + self.mission_method = mission_method = aviary_inputs.get_val( + Settings.EQUATIONS_OF_MOTION) + self.mass_method = mass_method = aviary_inputs.get_val(Settings.MASS_METHOD) + + if mission_method is TWO_DEGREES_OF_FREEDOM: + aviary_inputs.set_val(Mission.Summary.CRUISE_MASS_FINAL, + val=self.initial_guesses['cruise_mass_final'], units='lbm') + aviary_inputs.set_val(Mission.Summary.GROSS_MASS, + val=self.initial_guesses['actual_takeoff_mass'], units='lbm') + + # Commonly referenced values + self.cruise_alt = aviary_inputs.get_val( + Mission.Design.CRUISE_ALTITUDE, units='ft') + self.problem_type = aviary_inputs.get_val('problem_type') + self.mass_defect = aviary_inputs.get_val('mass_defect', units='lbm') + + self.cruise_mass_final = aviary_inputs.get_val( + Mission.Summary.CRUISE_MASS_FINAL, units='lbm') + self.target_range = aviary_inputs.get_val( + Mission.Design.RANGE, units='NM') + self.cruise_mach = aviary_inputs.get_val(Mission.Design.MACH) + + ## LOAD PHASE_INFO ### + if phase_info is None: + # check if the user generated a phase_info from gui + # Load the phase info dynamically from the current working directory + phase_info_module_path = Path.cwd() / 'outputted_phase_info.py' + + if phase_info_module_path.exists(): + spec = importlib.util.spec_from_file_location( + 'outputted_phase_info', phase_info_module_path) + outputted_phase_info = importlib.util.module_from_spec(spec) + sys.modules['outputted_phase_info'] = outputted_phase_info + spec.loader.exec_module(outputted_phase_info) + + # Access the phase_info variable from the loaded module + phase_info = outputted_phase_info.phase_info + + print('Loaded outputted_phase_info.py generated with GUI') + + else: + # 2dof -> two_dof + method = self.mission_method.value.replace('2DOF', 'two_dof') + + module = importlib.import_module( + self.mission_method.value, 'aviary.interface.default_phase_info') + phase_info = getattr(module, 'phase_info') + + print('Loaded default phase_info for' + f'{self.mission_method.value.lower()} equations of motion') + # create a new dictionary that only contains the phases from phase_info self.phase_info = {} + for phase_name in phase_info: if 'external_subsystems' not in phase_info[phase_name]: phase_info[phase_name]['external_subsystems'] = [] @@ -159,22 +242,17 @@ def __init__(self, phase_info, mission_method, mass_method, analysis_scheme=Anal 'external_subsystems': [], 'constrain_range': False} - self.traj = None - - self.mission_method = mission_method - self.mass_method = mass_method - self.analysis_scheme = analysis_scheme - + ## PROCESSING ## # set up core subsystems - if self.mission_method == "solved": - everything_else_origin = "GASP" - elif self.mission_method == "simple": - everything_else_origin = "FLOPS" + if mission_method in (HEIGHT_ENERGY, SIMPLE): + everything_else_origin = FLOPS + elif mission_method in (TWO_DEGREES_OF_FREEDOM, SOLVED): + everything_else_origin = GASP else: - everything_else_origin = self.mission_method + raise ValueError(f'Unknown mission method {self.mission_method}') prop = CorePropulsionBuilder('core_propulsion') - mass = CoreMassBuilder('core_mass', code_origin=mass_method) + mass = CoreMassBuilder('core_mass', code_origin=self.mass_method) aero = CoreAerodynamicsBuilder( 'core_aerodynamics', code_origin=everything_else_origin) @@ -184,19 +262,19 @@ def __init__(self, phase_info, mission_method, mass_method, analysis_scheme=Anal # which geometry methods should be used, or both? geom_code_origin = None - if (everything_else_origin == 'FLOPS') and (mass_method == 'FLOPS'): - geom_code_origin = 'FLOPS' - elif (everything_else_origin == 'GASP') and (mass_method == 'GASP'): - geom_code_origin = 'GASP' + if (everything_else_origin is FLOPS) and (mass_method is FLOPS): + geom_code_origin = FLOPS + elif (everything_else_origin is GASP) and (mass_method is GASP): + geom_code_origin = GASP else: both_geom = True # which geometry method gets prioritized in case of conflicting outputs if not code_origin_to_prioritize: - if everything_else_origin == 'GASP': - code_origin_to_prioritize = 'GASP' - elif everything_else_origin == 'FLOPS': - code_origin_to_prioritize = 'FLOPS' + if everything_else_origin is GASP: + code_origin_to_prioritize = GASP + elif everything_else_origin is FLOPS: + code_origin_to_prioritize = FLOPS geom = CoreGeometryBuilder('core_geometry', code_origin=geom_code_origin, @@ -208,32 +286,6 @@ def __init__(self, phase_info, mission_method, mass_method, analysis_scheme=Anal 'mass': mass, 'aerodynamics': aero} - def load_inputs(self, input_filename, engine_builder=None): - """ - This method loads the aviary_values inputs and options that the - user specifies. They could specify files to load and values to - replace here as well. - - This method is not strictly necessary; a user could also supply - an AviaryValues object of their own. - """ - self.engine_builder = engine_builder - self.aviary_inputs, self.initial_guesses = create_vehicle(input_filename) - - aviary_inputs = self.aviary_inputs - - if self.mission_method == "GASP": - aviary_inputs.set_val(Mission.Summary.CRUISE_MASS_FINAL, - val=self.initial_guesses['cruise_mass_final'], units='lbm') - aviary_inputs.set_val(Mission.Summary.GROSS_MASS, - val=self.initial_guesses['actual_takeoff_mass'], units='lbm') - - self.cruise_mass_final = aviary_inputs.get_val( - Mission.Summary.CRUISE_MASS_FINAL, units='lbm') - self.target_range = aviary_inputs.get_val( - Mission.Design.RANGE, units='NM') - self.cruise_mach = aviary_inputs.get_val(Mission.Design.MACH) - # TODO optionally accept which subsystems to load from phase_info subsystems = self.core_subsystems default_mission_subsystems = [ @@ -358,12 +410,13 @@ def add_pre_mission_systems(self): if not self.pre_mission_info['include_takeoff']: return - # Check for 'GASP' mission method - if self.mission_method == "GASP": + # Check for 2DOF mission method + # NOTE should solved trigger this as well? + if self.mission_method is TWO_DEGREES_OF_FREEDOM: self._add_gasp_takeoff_systems() - # Check for 'FLOPS' mission method - elif self.mission_method == "FLOPS" or self.mission_method == "simple": + # Check for HE mission method + elif self.mission_method is HEIGHT_ENERGY or self.mission_method is SIMPLE: self._add_flops_takeoff_systems() def _add_flops_takeoff_systems(self): @@ -504,7 +557,7 @@ def _add_premission_external_subsystems(self): promotes_outputs=[ ('subsystem_mass', Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS)]) - def _get_gasp_phase(self, phase_name): + def _get_2dof_phase(self, phase_name): # Get the phase options for the specified phase name phase_options = self.phase_info[phase_name] @@ -643,7 +696,7 @@ def _add_groundroll_eq_constraint(self, phase): promotes_inputs=["t_init_gear", "t_init_flaps"], ) - def _get_flops_phase(self, phase_name, phase_idx): + def _get_height_energy_phase(self, phase_name, phase_idx): base_phase_options = self.phase_info[phase_name] fix_duration = base_phase_options['user_options']['fix_duration'] @@ -665,8 +718,8 @@ def _get_flops_phase(self, phase_name, phase_idx): default_mission_subsystems = [ subsystems['aerodynamics'], subsystems['propulsion']] - if self.mission_method == "FLOPS" or self.mission_method == "simple": - if self.mission_method == "simple": + if self.mission_method is HEIGHT_ENERGY or self.mission_method is SIMPLE: + if self.mission_method is SIMPLE: climb_builder = EnergyPhase cruise_builder = EnergyPhase descent_builder = EnergyPhase @@ -719,7 +772,7 @@ def _get_flops_phase(self, phase_name, phase_idx): fix_initial_time = get_initial(fix_initial, "time", True) input_initial = False - if self.mission_method == "simple": + if self.mission_method is SIMPLE: user_options.set_val('initial_ref', 10., 'min') duration_bounds = user_options.get_val("duration_bounds", 'min') user_options.set_val( @@ -937,12 +990,12 @@ def add_phases(self, phase_info_parameterization=None): elif self.analysis_scheme is AnalysisScheme.SHOOTING: initial_mass = self.aviary_inputs.get_val(Mission.Summary.GROSS_MASS, 'lbm') - ascent_phases = create_gasp_based_ascent_phases( + ascent_phases = create_2dof_based_ascent_phases( self.ode_args, cruise_alt=self.cruise_alt, cruise_mach=self.cruise_mach) - descent_phases = create_gasp_based_descent_phases( + descent_phases = create_2dof_based_descent_phases( self.ode_args, cruise_alt=self.cruise_alt, cruise_mach=self.cruise_mach) @@ -1014,19 +1067,19 @@ def add_subsystem_timeseries_outputs(phase, phase_name): for timeseries in timeseries_to_add: phase.add_timeseries_output(timeseries) - if self.mission_method == "GASP": + if self.mission_method is TWO_DEGREES_OF_FREEDOM: if self.analysis_scheme is AnalysisScheme.COLLOCATION: for idx, phase_name in enumerate(phases): - phase = traj.add_phase(phase_name, self._get_gasp_phase(phase_name)) + phase = traj.add_phase(phase_name, self._get_2dof_phase(phase_name)) add_subsystem_timeseries_outputs(phase, phase_name) if phase_name == 'ascent': self._add_groundroll_eq_constraint(phase) - elif self.mission_method == "FLOPS" or self.mission_method == "simple": + elif self.mission_method is HEIGHT_ENERGY or self.mission_method is SIMPLE: for phase_idx, phase_name in enumerate(phases): phase = traj.add_phase( - phase_name, self._get_flops_phase(phase_name, phase_idx)) + phase_name, self._get_height_energy_phase(phase_name, phase_idx)) add_subsystem_timeseries_outputs(phase, phase_name) # loop through phase_info and external subsystems @@ -1043,7 +1096,7 @@ def add_subsystem_timeseries_outputs(phase, phase_name): traj = setup_trajectory_params( self.model, traj, self.aviary_inputs, phases, meta_data=self.meta_data, external_parameters=external_parameters) - elif self.mission_method == "solved": + elif self.mission_method is SOLVED: target_range = self.aviary_inputs.get_val( Mission.Design.RANGE, units='nmi') takeoff_mass = self.aviary_inputs.get_val( @@ -1145,9 +1198,9 @@ def add_post_mission_systems(self, include_landing=True): """ if include_landing and self.post_mission_info['include_landing']: - if self.mission_method == "FLOPS": + if self.mission_method is HEIGHT_ENERGY: self._add_flops_landing_systems() - elif self.mission_method == "GASP": + elif self.mission_method is TWO_DEGREES_OF_FREEDOM: self._add_gasp_landing_systems() self.model.add_subsystem('post_mission', self.post_mission, @@ -1164,7 +1217,7 @@ def add_post_mission_systems(self, include_landing=True): self.post_mission.add_subsystem(external_subsystem.name, subsystem_postmission) - if self.mission_method == "FLOPS" or self.mission_method == "simple": + if self.mission_method is HEIGHT_ENERGY or self.mission_method is SIMPLE: phases = list(self.phase_info.keys()) ecomp = om.ExecComp('fuel_burned = initial_mass - mass_final', initial_mass={'units': 'lbm'}, @@ -1226,7 +1279,7 @@ def add_post_mission_systems(self, include_landing=True): initial_mass={'units': 'lbm'}, mass_resid={'units': 'lbm'}) - if self.mass_method == "GASP": + if self.mass_method is GASP: payload_mass_src = Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS else: payload_mass_src = Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS @@ -1240,7 +1293,7 @@ def add_post_mission_systems(self, include_landing=True): ('initial_mass', Mission.Design.GROSS_MASS)], promotes_outputs=[("mass_resid", Mission.Constraints.MASS_RESIDUAL)]) - if self.mission_method != "solved": + if self.mission_method is not SOLVED: self.post_mission.add_constraint( Mission.Constraints.MASS_RESIDUAL, equals=0.0, ref=1.e5) @@ -1301,7 +1354,7 @@ def link_phases(self): if len(phases_to_link) > 1: # TODO: hack self.traj.link_phases(phases=phases_to_link, vars=[var], connected=True) - if self.mission_method == "solved": + if self.mission_method is SOLVED: def add_linkage_constraint(self, phase_a, phase_b, var_b): self.traj.add_linkage_constraint(phase_a=phase_a, phase_b=phase_b, @@ -1330,7 +1383,7 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): phases, vars=[Dynamic.Mission.RANGE], units='m', ref=10.e3) self.traj.link_phases(phases[:7], vars=['TAS'], units='kn', ref=200.) - elif self.mission_method == "simple": + elif self.mission_method is SIMPLE: self.traj.link_phases( phases, ["time", Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=True) @@ -1339,14 +1392,14 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): self._link_phases_helper_with_options( phases, 'optimize_mach', Dynamic.Mission.MACH) - elif self.mission_method == "FLOPS": + elif self.mission_method is HEIGHT_ENERGY: self.traj.link_phases( phases, ["time", Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=False, ref=1.e4) self.traj.link_phases( phases, [Dynamic.Mission.VELOCITY], connected=False, ref=250.) - elif self.mission_method == "GASP": + elif self.mission_method is TWO_DEGREES_OF_FREEDOM: if self.analysis_scheme is AnalysisScheme.COLLOCATION: self.traj.link_phases(["groundroll", "rotation", "ascent"], [ "time", "TAS", "mass", "distance"], connected=True) @@ -1598,13 +1651,13 @@ def add_design_variables(self): for dv_name, dv_dict in dv_dict.items(): self.model.add_design_var(dv_name, **dv_dict) - if self.mission_method == "FLOPS" or self.mission_method == "simple": + if self.mission_method is HEIGHT_ENERGY or self.mission_method is SIMPLE: optimize_mass = self.pre_mission_info.get('optimize_mass') if optimize_mass: self.model.add_design_var(Mission.Design.GROSS_MASS, units='lbm', lower=100.e3, upper=200.e3, ref=135.e3) - elif self.mission_method == "GASP": + elif self.mission_method is TWO_DEGREES_OF_FREEDOM: if self.analysis_scheme is AnalysisScheme.COLLOCATION: # problem formulation to make the trajectory work self.model.add_design_var(Mission.Takeoff.ASCENT_T_INTIIAL, @@ -1721,7 +1774,7 @@ def add_objective(self, objective_type=None, ref=None): self.model.add_objective(Mission.Objectives.FUEL, ref=ref) # If 'mission_method' is 'FLOPS', add a 'fuel_burned' objective - elif self.mission_method == "FLOPS" or self.mission_method == "simple": + elif self.mission_method is HEIGHT_ENERGY or self.mission_method is SIMPLE: ref = ref if ref is not None else default_ref_values.get("fuel_burned", 1) self.model.add_objective("fuel_burned", ref=ref) @@ -1859,14 +1912,14 @@ def set_initial_guesses(self): # Loop over each phase and set initial guesses for the state and control variables for idx, (phase_name, phase) in enumerate(phase_items): - if self.mission_method == "solved": + if self.mission_method is SOLVED: # If so, add solved guesses to the problem self._add_solved_guesses(idx, phase_name, phase) else: # If not, fetch the initial guesses specific to the phase guesses = self.phase_info[phase_name]['initial_guesses'] - if 'cruise' in phase_name and self.mission_method == "GASP": + if 'cruise' in phase_name and self.mission_method is TWO_DEGREES_OF_FREEDOM: for guess_key, guess_data in guesses.items(): val, units = guess_data @@ -2006,25 +2059,25 @@ def _add_guesses(self, phase_name, phase, guesses): """ # If using the GASP model, set initial guesses for the rotation mass and flight duration - if self.mission_method == "GASP": + if self.mission_method is TWO_DEGREES_OF_FREEDOM: rotation_mass = self.initial_guesses['rotation_mass'] flight_duration = self.initial_guesses['flight_duration'] - if self.mission_method == "simple": + if self.mission_method is SIMPLE: control_keys = ["mach", "altitude"] state_keys = ["mass", "range"] else: control_keys = ["velocity_rate", "throttle"] state_keys = ["altitude", "velocity", "mass", "range", "TAS", "distance", "flight_path_angle", "alpha"] - if self.mission_method == "GASP" and phase_name == 'ascent': + if self.mission_method is TWO_DEGREES_OF_FREEDOM and phase_name == 'ascent': # Alpha is a control for ascent. control_keys.append('alpha') prob_keys = ["tau_gear", "tau_flaps"] # for the simple mission method, use the provided initial and final mach and altitude values from phase_info - if self.mission_method == "simple": + if self.mission_method is SIMPLE: initial_altitude = self.phase_info[phase_name]['user_options']['initial_altitude'] final_altitude = self.phase_info[phase_name]['user_options']['final_altitude'] initial_mach = self.phase_info[phase_name]['user_options']['initial_mach'] @@ -2081,7 +2134,7 @@ def _add_guesses(self, phase_name, phase, guesses): # that are only available after calling `create_vehicle`. Thus these initial guess # values are not included in the `phase_info` object. if 'mass' not in guesses: - if self.mission_method == "GASP": + if self.mission_method is TWO_DEGREES_OF_FREEDOM: # Determine a mass guess depending on the phase name if phase_name in ["groundroll", "rotation", "ascent", "accel", "climb1"]: mass_guess = rotation_mass @@ -2110,7 +2163,7 @@ def _add_guesses(self, phase_name, phase, guesses): self.set_val(f"traj.{phase_name}.t_duration", t_duration, units='s') - if self.mission_method == "GASP": + if self.mission_method is TWO_DEGREES_OF_FREEDOM: if 'distance' not in guesses: # Determine initial distance guesses depending on the phase name if 'desc1' == phase_name: diff --git a/aviary/interface/test/test_basic_report.py b/aviary/interface/test/test_basic_report.py index 83d0637c8..01b166d9f 100644 --- a/aviary/interface/test/test_basic_report.py +++ b/aviary/interface/test/test_basic_report.py @@ -5,7 +5,7 @@ from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.flops import phase_info +from aviary.interface.default_phase_info.height_energy import phase_info from aviary.interface.methods_for_level1 import run_aviary from openmdao.utils.testing_utils import use_tempdirs diff --git a/aviary/interface/test/test_check_phase_info.py b/aviary/interface/test/test_check_phase_info.py index e0db510e4..cf455372b 100644 --- a/aviary/interface/test/test_check_phase_info.py +++ b/aviary/interface/test/test_check_phase_info.py @@ -1,21 +1,26 @@ import unittest -from aviary.interface.utils.check_phase_info import check_phase_info -from aviary.interface.default_phase_info.flops import phase_info as phase_info_flops -from aviary.interface.default_phase_info.gasp import phase_info as phase_info_gasp import copy +from aviary.interface.utils.check_phase_info import check_phase_info +from aviary.interface.default_phase_info.height_energy import phase_info as phase_info_flops +from aviary.interface.default_phase_info.two_dof import phase_info as phase_info_gasp +from aviary.variable_info.enums import EquationsOfMotion + +HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY +TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM + class TestCheckInputs(unittest.TestCase): def test_correct_input_flops(self): # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info(phase_info_flops, mission_method="FLOPS")) + self.assertTrue(check_phase_info(phase_info_flops, mission_method=HEIGHT_ENERGY)) def test_incorrect_tuple(self): # Let's replace a tuple with a float in the 'climb' phase incorrect_tuple_phase_info = copy.deepcopy(phase_info_flops) incorrect_tuple_phase_info['climb']['user_options']['initial_altitude'] = 10.668e3 with self.assertRaises(ValueError): - check_phase_info(incorrect_tuple_phase_info, mission_method="FLOPS") + check_phase_info(incorrect_tuple_phase_info, mission_method=HEIGHT_ENERGY) def test_incorrect_unit(self): # Let's replace a valid unit with an invalid one in the 'climb' phase @@ -24,14 +29,13 @@ def test_incorrect_unit(self): 10.668e3, 'invalid_unit') with self.assertRaisesRegex(ValueError, "Key initial_altitude in phase climb has an invalid unit invalid_unit."): - check_phase_info(incorrect_unit_phase_info, mission_method="FLOPS") + check_phase_info(incorrect_unit_phase_info, mission_method=HEIGHT_ENERGY) def test_correct_input_gasp(self): # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info(phase_info_gasp, mission_method="GASP")) + self.assertTrue(check_phase_info(phase_info_gasp, + mission_method=TWO_DEGREES_OF_FREEDOM)) if __name__ == '__main__': - # unittest.main() - test = TestCheckInputs() - test.test_incorrect_unit() + unittest.main() diff --git a/aviary/interface/test/test_cmd_entry_points.py b/aviary/interface/test/test_cmd_entry_points.py index cc2a3781b..41da59bd7 100644 --- a/aviary/interface/test/test_cmd_entry_points.py +++ b/aviary/interface/test/test_cmd_entry_points.py @@ -20,12 +20,12 @@ def run_and_test_cmd(self, cmd): @require_pyoptsparse(optimizer="SNOPT") def bench_test_SNOPT_cmd(self): - cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer SNOPT --mass_origin GASP --mission_method GASP --max_iter 1' + cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer SNOPT --max_iter 1' self.run_and_test_cmd(cmd) @require_pyoptsparse(optimizer="IPOPT") def bench_test_IPOPT_cmd(self): - cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --mass_origin GASP --mission_method GASP --max_iter 1' + cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1' self.run_and_test_cmd(cmd) def test_diff_configuration_conversion(self): diff --git a/aviary/interface/test/test_interface_bugs.py b/aviary/interface/test/test_interface_bugs.py index cf60b67f8..59f614e3d 100644 --- a/aviary/interface/test/test_interface_bugs.py +++ b/aviary/interface/test/test_interface_bugs.py @@ -6,7 +6,7 @@ from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.interface.default_phase_info.flops import phase_info as ph_in +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in from aviary.variable_info.variables import Aircraft from openmdao.utils.testing_utils import use_tempdirs @@ -67,12 +67,12 @@ def test_post_mission_promotion(self): WingWeightBuilder(name="wing_external") ] - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index d1691db82..29e32b2ee 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -8,10 +8,10 @@ from openmdao.utils.assert_utils import assert_near_equal -from aviary.interface.default_phase_info.flops import phase_info as ph_in_flops -from aviary.interface.default_phase_info.flops import phase_info_parameterization as phase_info_parameterization_flops -from aviary.interface.default_phase_info.gasp import phase_info as ph_in_gasp -from aviary.interface.default_phase_info.gasp import phase_info_parameterization as phase_info_parameterization_gasp +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in_flops +from aviary.interface.default_phase_info.height_energy import phase_info_parameterization as phase_info_parameterization_flops +from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_gasp +from aviary.interface.default_phase_info.two_dof import phase_info_parameterization as phase_info_parameterization_gasp from aviary.interface.methods_for_level2 import AviaryProblem from aviary.mission.flops_based.phases.phase_builder_base import \ @@ -82,7 +82,7 @@ def _test_phase_info_dict(self, phase_info_dict, name): def test_default_phase_flops(self): """Tests the roundtrip conversion for default_phase_info.flops""" - from aviary.interface.default_phase_info.flops import phase_info + from aviary.interface.default_phase_info.height_energy import phase_info local_phase_info = deepcopy(phase_info) self._test_phase_info_dict(local_phase_info, 'climb') @@ -92,12 +92,12 @@ class TestParameterizePhaseInfo(unittest.TestCase): def test_phase_info_parameterization_gasp(self): phase_info = deepcopy(ph_in_gasp) - prob = AviaryProblem(phase_info, mission_method="GASP", mass_method="GASP") + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "models/small_single_aisle/small_single_aisle_GwGm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) prob.check_inputs() # We can set some crazy vals, since we aren't going to optimize. @@ -129,12 +129,12 @@ def test_phase_info_parameterization_gasp(self): def test_phase_info_parameterization_flops(self): phase_info = deepcopy(ph_in_flops) - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_FwFm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) prob.check_inputs() # We can set some crazy vals, since we aren't going to optimize. diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index b0b3982d8..983bb3e8f 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -6,8 +6,8 @@ from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.interface.default_phase_info.flops import phase_info as ph_in_flops -from aviary.interface.default_phase_info.gasp import phase_info as ph_in_gasp +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in_flops +from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_gasp from aviary.variable_info.variables import Aircraft, Mission @@ -17,12 +17,12 @@ class StaticGroupTest(unittest.TestCase): def test_post_mission_promotion(self): phase_info = deepcopy(ph_in_flops) - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) prob.check_inputs() # TODO: This needs to be converted into a reserve and a scaler so that it can @@ -51,12 +51,12 @@ def test_post_mission_promotion(self): def test_gasp_relative_reserve(self): phase_info = deepcopy(ph_in_gasp) - prob = AviaryProblem(phase_info, mission_method="GASP", mass_method="GASP") + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "models/small_single_aisle/small_single_aisle_GwGm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) prob.check_inputs() prob.aviary_inputs.set_val(Mission.Summary.GROSS_MASS, 140000.0, units='lbm') diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index 1b5762dcb..74ad71aa8 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -1,8 +1,11 @@ import unittest +import subprocess + +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs + from aviary.interface.methods_for_level1 import run_aviary from aviary.subsystems.test.test_dummy_subsystem import ArrayGuessSubsystemBuilder from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -import subprocess @use_tempdirs @@ -91,9 +94,7 @@ def setUp(self): }, } - self.aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' - self.mission_method = "simple" - self.mass_method = "FLOPS" + self.aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv' self.make_plots = False self.max_iter = 100 @@ -110,7 +111,6 @@ def add_external_subsystem(self, phase_info, subsystem_builder): def run_mission(self, phase_info, optimizer): return run_aviary( self.aircraft_definition_file, phase_info, - mission_method=self.mission_method, mass_method=self.mass_method, make_plots=self.make_plots, max_iter=self.max_iter, optimizer=optimizer, optimization_history_filename="driver_test.db") diff --git a/aviary/interface/utils/check_phase_info.py b/aviary/interface/utils/check_phase_info.py index 3379a2f29..1e592be4d 100644 --- a/aviary/interface/utils/check_phase_info.py +++ b/aviary/interface/utils/check_phase_info.py @@ -1,5 +1,10 @@ from openmdao.utils.units import valid_units -from aviary.variable_info.enums import SpeedType +from aviary.variable_info.enums import SpeedType, EquationsOfMotion + +HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY +TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM +SIMPLE = EquationsOfMotion.SIMPLE +SOLVED = EquationsOfMotion.SOLVED def check_phase_info(phase_info, mission_method): @@ -204,21 +209,21 @@ def check_phase_info(phase_info, mission_method): } phase_keys = {} - if mission_method == 'FLOPS': + if mission_method is HEIGHT_ENERGY: for phase in phase_info: if phase != 'pre_mission' and phase != 'post_mission': phase_keys[phase] = {**common_keys, **phase_keys_flops[phase]} else: phase_keys[phase] = phase_keys_flops[phase] - elif mission_method == 'GASP': + elif mission_method is TWO_DEGREES_OF_FREEDOM: for phase in phase_info: if phase != 'pre_mission' and phase != 'post_mission' and phase != 'cruise': phase_keys[phase] = {**common_keys, **phase_keys_gasp[phase]} else: phase_keys[phase] = phase_keys_gasp[phase] - elif mission_method == 'solved': + elif mission_method is SOLVED: return - elif mission_method == 'simple': + elif mission_method is SIMPLE: return else: raise ValueError( diff --git a/aviary/mission/flops_based/ode/test/test_landing_ode.py b/aviary/mission/flops_based/ode/test/test_landing_ode.py index ebe840600..16e34c0f2 100644 --- a/aviary/mission/flops_based/ode/test/test_landing_ode.py +++ b/aviary/mission/flops_based/ode/test/test_landing_ode.py @@ -2,7 +2,7 @@ import openmdao.api as om -from aviary.interface.default_phase_info.flops import default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems from aviary.mission.flops_based.ode.landing_ode import FlareODE from aviary.models.N3CC.N3CC_data import ( detailed_landing_flare, inputs, landing_subsystem_options) diff --git a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py index 8cd5e7e4f..fd39339e5 100644 --- a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py +++ b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py @@ -3,7 +3,7 @@ import openmdao.api as om -from aviary.interface.default_phase_info.flops import default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE from aviary.models.N3CC.N3CC_data import ( detailed_takeoff_climbing, detailed_takeoff_ground, takeoff_subsystem_options, inputs) diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py index 80ba4fb2e..002760085 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py @@ -20,7 +20,7 @@ from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.interface.default_phase_info.flops import prop, aero, geom +from aviary.interface.default_phase_info.height_energy import prop, aero, geom from aviary.subsystems.premission import CorePreMission from aviary.utils.functions import set_aviary_initial_values from aviary.validation_cases.validation_tests import get_flops_inputs diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py index b924184b9..f03466f7f 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py @@ -23,7 +23,7 @@ from aviary.utils.aviary_values import AviaryValues from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.interface.default_phase_info.flops import prop, aero, geom +from aviary.interface.default_phase_info.height_energy import prop, aero, geom from aviary.subsystems.premission import CorePreMission from aviary.utils.functions import set_aviary_initial_values from aviary.validation_cases.validation_tests import get_flops_inputs diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py index b5b42004c..c88f5dd8e 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py @@ -19,7 +19,7 @@ from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.flops import prop, aero, geom +from aviary.interface.default_phase_info.height_energy import prop, aero, geom from aviary.subsystems.premission import CorePreMission from aviary.utils.functions import set_aviary_initial_values from aviary.utils.functions import get_path diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py index c1b907a07..b9925cf5b 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py @@ -23,7 +23,7 @@ from aviary.utils.aviary_values import AviaryValues from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.flops import prop, aero, geom +from aviary.interface.default_phase_info.height_energy import prop, aero, geom from aviary.subsystems.premission import CorePreMission from aviary.utils.functions import set_aviary_initial_values from aviary.utils.functions import get_path diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py index 5990f8164..8e1cfae23 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py @@ -21,7 +21,7 @@ from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.flops import prop, aero, geom +from aviary.interface.default_phase_info.height_energy import prop, aero, geom from aviary.subsystems.premission import CorePreMission from aviary.utils.functions import set_aviary_initial_values from aviary.validation_cases.validation_tests import (get_flops_inputs, diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py index f331ff733..c1dba6168 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py @@ -20,7 +20,7 @@ from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.mission.flops_based.phases.descent_phase import Descent -from aviary.interface.default_phase_info.flops import prop, aero, geom +from aviary.interface.default_phase_info.height_energy import prop, aero, geom from aviary.subsystems.premission import CorePreMission from aviary.utils.functions import set_aviary_initial_values from aviary.utils.functions import get_path diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py index a66015fc7..e6378c4a2 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py @@ -21,7 +21,7 @@ from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.mission.flops_based.phases.descent_phase import Descent -from aviary.interface.default_phase_info.flops import prop, aero, geom +from aviary.interface.default_phase_info.height_energy import prop, aero, geom from aviary.subsystems.premission import CorePreMission from aviary.utils.functions import set_aviary_initial_values from aviary.utils.functions import get_path diff --git a/aviary/mission/gasp_based/idle_descent_estimation.py b/aviary/mission/gasp_based/idle_descent_estimation.py index 744fda46a..0371183fa 100644 --- a/aviary/mission/gasp_based/idle_descent_estimation.py +++ b/aviary/mission/gasp_based/idle_descent_estimation.py @@ -2,7 +2,7 @@ import openmdao.api as om -from aviary.interface.default_phase_info.gasp_fiti import create_gasp_based_descent_phases +from aviary.interface.default_phase_info.two_dof_fiti import create_2dof_based_descent_phases from aviary.mission.gasp_based.phases.time_integration_traj import FlexibleTraj from aviary.variable_info.variables import Aircraft, Mission, Dynamic @@ -27,7 +27,7 @@ def descent_range_and_fuel( prob.driver.opt_settings['print_level'] = 5 if phases is None: - phases = create_gasp_based_descent_phases( + phases = create_2dof_based_descent_phases( ode_args, cruise_mach=cruise_mach, ) diff --git a/aviary/mission/gasp_based/ode/test/test_accel_ode.py b/aviary/mission/gasp_based/ode/test/test_accel_ode.py index c69f50d54..98a613b58 100644 --- a/aviary/mission/gasp_based/ode/test/test_accel_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_accel_ode.py @@ -10,7 +10,7 @@ check_prob_outputs, skipIfMissingXDSM) from aviary.variable_info.variables import Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems class AccelerationODETestCase(unittest.TestCase): diff --git a/aviary/mission/gasp_based/ode/test/test_ascent_ode.py b/aviary/mission/gasp_based/ode/test/test_ascent_ode.py index 192c73459..540899d70 100644 --- a/aviary/mission/gasp_based/ode/test/test_ascent_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_ascent_ode.py @@ -6,7 +6,7 @@ from aviary.mission.gasp_based.ode.ascent_ode import AscentODE from aviary.utils.test_utils.IO_test_util import assert_match_spec, skipIfMissingXDSM -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems from aviary.variable_info.options import get_option_defaults diff --git a/aviary/mission/gasp_based/ode/test/test_climb_ode.py b/aviary/mission/gasp_based/ode/test/test_climb_ode.py index 2e91c0280..9094977a5 100644 --- a/aviary/mission/gasp_based/ode/test/test_climb_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_climb_ode.py @@ -11,7 +11,7 @@ skipIfMissingXDSM) from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems class ClimbODETestCase(unittest.TestCase): diff --git a/aviary/mission/gasp_based/ode/test/test_descent_ode.py b/aviary/mission/gasp_based/ode/test/test_descent_ode.py index 3775882d8..b7a64e408 100644 --- a/aviary/mission/gasp_based/ode/test/test_descent_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_descent_ode.py @@ -14,7 +14,7 @@ skipIfMissingXDSM) from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems class DescentODETestCase(unittest.TestCase): diff --git a/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py b/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py index 49f8cb298..d70a26b4b 100644 --- a/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py @@ -7,7 +7,7 @@ from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE from aviary.utils.test_utils.IO_test_util import assert_match_spec, skipIfMissingXDSM from aviary.variable_info.options import get_option_defaults -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems class GroundrollODETestCase(unittest.TestCase): diff --git a/aviary/mission/gasp_based/ode/test/test_rotation_ode.py b/aviary/mission/gasp_based/ode/test/test_rotation_ode.py index 97e8517cb..891c21b20 100644 --- a/aviary/mission/gasp_based/ode/test/test_rotation_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_rotation_ode.py @@ -8,7 +8,7 @@ from aviary.utils.test_utils.IO_test_util import assert_match_spec, skipIfMissingXDSM from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems class RotationODETestCase(unittest.TestCase): diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py index bfad5f6d2..4aa1f3b9b 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py @@ -5,7 +5,7 @@ from openmdao.utils.assert_utils import assert_near_equal from aviary.constants import GRAV_ENGLISH_LBM -from aviary.interface.default_phase_info.gasp import aero +from aviary.interface.default_phase_info.two_dof import aero from aviary.mission.gasp_based.ode.params import ParamPort from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_control_iter_group import \ UnsteadyControlIterGroup diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py index af251a979..bf1a764d1 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py @@ -11,7 +11,7 @@ from aviary.variable_info.options import get_option_defaults from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems class TestUnsteadySolvedODE(unittest.TestCase): diff --git a/aviary/mission/gasp_based/phases/benchmark/test_accel.py b/aviary/mission/gasp_based/phases/benchmark/test_accel.py index 07cac4119..3ac9323b0 100644 --- a/aviary/mission/gasp_based/phases/benchmark/test_accel.py +++ b/aviary/mission/gasp_based/phases/benchmark/test_accel.py @@ -10,7 +10,7 @@ from aviary.mission.gasp_based.ode.flight_path_ode import FlightPathODE from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems def make_accel_problem( diff --git a/aviary/mission/gasp_based/phases/benchmark/test_bench_new_ascent.py b/aviary/mission/gasp_based/phases/benchmark/test_bench_new_ascent.py index 016711db9..684c88728 100644 --- a/aviary/mission/gasp_based/phases/benchmark/test_bench_new_ascent.py +++ b/aviary/mission/gasp_based/phases/benchmark/test_bench_new_ascent.py @@ -9,7 +9,7 @@ from aviary.mission.gasp_based.ode.flight_path_ode import FlightPathODE from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems def make_ascent_problem(optimizer='IPOPT', print_opt_iters=False): diff --git a/aviary/mission/gasp_based/phases/benchmark/test_bench_new_groundroll.py b/aviary/mission/gasp_based/phases/benchmark/test_bench_new_groundroll.py index 0ebae8c21..7b9feb768 100644 --- a/aviary/mission/gasp_based/phases/benchmark/test_bench_new_groundroll.py +++ b/aviary/mission/gasp_based/phases/benchmark/test_bench_new_groundroll.py @@ -11,7 +11,7 @@ from aviary.mission.gasp_based.phases.v_rotate_comp import VRotateComp from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems def make_groundroll_problem(optimizer='IPOPT', print_opt_iters=False, solve_segments=False): diff --git a/aviary/mission/gasp_based/phases/benchmark/test_bench_new_rotation.py b/aviary/mission/gasp_based/phases/benchmark/test_bench_new_rotation.py index f34a0c055..c26080b6d 100644 --- a/aviary/mission/gasp_based/phases/benchmark/test_bench_new_rotation.py +++ b/aviary/mission/gasp_based/phases/benchmark/test_bench_new_rotation.py @@ -10,7 +10,7 @@ from aviary.mission.gasp_based.ode.flight_path_ode import FlightPathODE from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems def make_rotation_problem(optimizer='IPOPT', print_opt_iters=False): diff --git a/aviary/mission/gasp_based/phases/benchmark/test_climb.py b/aviary/mission/gasp_based/phases/benchmark/test_climb.py index 89a644c98..736d7ff39 100644 --- a/aviary/mission/gasp_based/phases/benchmark/test_climb.py +++ b/aviary/mission/gasp_based/phases/benchmark/test_climb.py @@ -9,7 +9,7 @@ from aviary.mission.gasp_based.ode.flight_path_ode import FlightPathODE from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems def make_climb_problem( diff --git a/aviary/mission/gasp_based/phases/climb_phase.py b/aviary/mission/gasp_based/phases/climb_phase.py index 620137c72..08a28330f 100644 --- a/aviary/mission/gasp_based/phases/climb_phase.py +++ b/aviary/mission/gasp_based/phases/climb_phase.py @@ -2,7 +2,7 @@ from aviary.mission.gasp_based.ode.climb_ode import ClimbODE from aviary.variable_info.variables import Mission, Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems def get_climb( diff --git a/aviary/mission/gasp_based/phases/run_phases/run_accel.py b/aviary/mission/gasp_based/phases/run_phases/run_accel.py index e08a7b2bb..ce26a879e 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_accel.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_accel.py @@ -6,7 +6,7 @@ from aviary.mission.gasp_based.phases.accel_phase import get_accel from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems from packaging import version diff --git a/aviary/mission/gasp_based/phases/run_phases/run_ascent.py b/aviary/mission/gasp_based/phases/run_phases/run_ascent.py index cd8ff39eb..fdd3c0384 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_ascent.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_ascent.py @@ -5,7 +5,7 @@ from aviary.mission.gasp_based.polynomial_fit import PolynomialFit from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.interface.default_phase_info.flops import default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems def run_ascent(make_plots=False): diff --git a/aviary/mission/gasp_based/test/test_idle_descent_estimation.py b/aviary/mission/gasp_based/test/test_idle_descent_estimation.py index e5664d583..8b20a9fd4 100644 --- a/aviary/mission/gasp_based/test/test_idle_descent_estimation.py +++ b/aviary/mission/gasp_based/test/test_idle_descent_estimation.py @@ -2,7 +2,7 @@ from openmdao.utils.assert_utils import assert_near_equal -from aviary.interface.default_phase_info.gasp import default_mission_subsystems +from aviary.interface.default_phase_info.two_dof import default_mission_subsystems from aviary.mission.gasp_based.idle_descent_estimation import descent_range_and_fuel from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.variable_info.variables import Aircraft, Dynamic diff --git a/aviary/models/N3CC/N3CC_data.py b/aviary/models/N3CC/N3CC_data.py index adbd27b82..a163553ea 100644 --- a/aviary/models/N3CC/N3CC_data.py +++ b/aviary/models/N3CC/N3CC_data.py @@ -24,7 +24,9 @@ from aviary.variable_info.variables import Aircraft from aviary.variable_info.variables import Dynamic as _Dynamic from aviary.variable_info.variables import Mission -from aviary.interface.default_phase_info.flops import default_mission_subsystems +from aviary.variable_info.variables import Settings +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems Dynamic = _Dynamic.Mission @@ -311,6 +313,11 @@ inputs.set_val(Mission.Landing.SPOILER_LIFT_COEFFICIENT, -0.810000) inputs.set_val(Mission.Takeoff.THRUST_INCIDENCE, 0., 'deg') +# Settings +# --------------------------- +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) + # --------------------------- # OUTPUTS # --------------------------- diff --git a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv index 1669d212b..81ac1ee35 100644 --- a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv +++ b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv @@ -169,6 +169,8 @@ mission:takeoff:rolling_friction_coefficient,0.0175,unitless mission:takeoff:spoiler_drag_coefficient,0.085,unitless mission:takeoff:spoiler_lift_coefficient,-0.81,unitless mission:takeoff:thrust_incidence,0,deg +settings:equations_of_motion,height_energy +settings:mass_method,FLOPS # Unconverted Values AERIN.clapp,2 diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py b/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py index f65b1e2fc..feeca95a1 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py @@ -4,7 +4,8 @@ from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode +from aviary.variable_info.variables import Aircraft, Mission, Settings LargeSingleAisle1FLOPS = {} inputs = LargeSingleAisle1FLOPS['inputs'] = AviaryValues() @@ -260,6 +261,11 @@ # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 28928.0, 'lbf') +# Settings +# --------------------------- +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) + # --------------------------- # OUTPUTS # --------------------------- diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index 7a69a9942..f2492d9fb 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -142,6 +142,8 @@ mission:summary:fuel_flow_scaler,1,unitless mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.1677,h +settings:equations_of_motion,2DOF +settings:mass_method,GASP # Initial Guesses actual_takeoff_mass,0 diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py index 9f56bb034..37ef21ff0 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py @@ -5,7 +5,8 @@ from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode +from aviary.variable_info.variables import Aircraft, Mission, Settings LargeSingleAisle2FLOPS = {} inputs = LargeSingleAisle2FLOPS['inputs'] = AviaryValues() @@ -260,6 +261,11 @@ # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 27301.0, 'lbf') +# Settings +# --------------------------- +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) + # --------------------------- # OUTPUTS # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py index aeaece188..667b0d72a 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py @@ -5,7 +5,8 @@ from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode +from aviary.variable_info.variables import Aircraft, Mission, Settings LargeSingleAisle2FLOPSalt = {} inputs = LargeSingleAisle2FLOPSalt['inputs'] = AviaryValues() @@ -259,6 +260,11 @@ # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 27301.0, 'lbf') +# Settings +# --------------------------- +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) + # --------------------------- # OUTPUTS # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py index 097dec996..ca02d5832 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py @@ -4,7 +4,8 @@ from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode +from aviary.variable_info.variables import Aircraft, Mission, Settings LargeSingleAisle2FLOPSdw = {} inputs = LargeSingleAisle2FLOPSdw['inputs'] = AviaryValues() @@ -260,6 +261,10 @@ # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 24555.5, 'lbf') +# Settings +# --------------------------- +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- # OUTPUTS diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv index e395cf439..040e2391d 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv @@ -142,6 +142,8 @@ mission:summary:gross_mass,124780 mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.3333,h +settings:equations_of_motion,2DOF +settings:mass_method,GASP # Initial Guesses actual_takeoff_mass,0 diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index 0c2985b9e..2d4ea4703 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -154,4 +154,6 @@ mission:summary:fuel_flow_scaler,1.0,unitless mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless -mission:takeoff:rolling_friction_coefficient,0.0175,unitless \ No newline at end of file +mission:takeoff:rolling_friction_coefficient,0.0175,unitless +settings:equations_of_motion,height_energy +settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv new file mode 100644 index 000000000..abdddb634 --- /dev/null +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv @@ -0,0 +1,159 @@ +aircraft:air_conditioning:mass_scaler,1.0,unitless +aircraft:anti_icing:mass_scaler,1.0,unitless +aircraft:apu:mass_scaler,1.1,unitless +aircraft:avionics:mass_scaler,1.2,unitless +aircraft:canard:area,0.0,ft**2 +aircraft:canard:aspect_ratio,0.0,unitless +aircraft:canard:thickness_to_chord,0.0,unitless +aircraft:crew_and_payload:baggage_mass_per_passenger,45.0,lbm +aircraft:crew_and_payload:cargo_container_mass_scaler,1.0,unitless +aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless +aircraft:crew_and_payload:mass_per_passenger,180.0,lbm +aircraft:crew_and_payload:misc_cargo,0.0,lbm +aircraft:crew_and_payload:non_flight_crew_mass_scaler,1.0,unitless +aircraft:crew_and_payload:num_business_class,0,unitless +aircraft:crew_and_payload:num_first_class,11,unitless +aircraft:crew_and_payload:num_flight_attendants,3,unitless +aircraft:crew_and_payload:num_flight_crew,2,unitless +aircraft:crew_and_payload:num_galley_crew,0,unitless +aircraft:crew_and_payload:num_non_flight_crew,3,unitless +aircraft:crew_and_payload:num_passengers,169,unitless +aircraft:crew_and_payload:num_tourist_class,158,unitless +aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless +aircraft:crew_and_payload:wing_cargo,0.0,lbm +aircraft:design:base_area,0.0,ft**2 +aircraft:design:empty_mass_margin_scaler,0.0,unitless +aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless +aircraft:design:touchdown_mass,152800.0,lbm +aircraft:design:reserves,3000.,unitless +aircraft:design:subsonic_drag_coeff_factor,1.0,unitless +aircraft:design:supersonic_drag_coeff_factor,1.0,unitless +aircraft:design:use_alt_mass,False,unitless +aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless +aircraft:electrical:mass_scaler,1.25,unitless +aircraft:engine:additional_mass_fraction,0.,unitless +aircraft:engine:constant_fuel_consumption,0.,lbm/h +aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless +aircraft:engine:flight_idle_thrust_fraction,0.0,unitless +aircraft:engine:flight_idle_max_fraction,1.0,unitless +aircraft:engine:flight_idle_min_fraction,0.08,unitless +aircraft:engine:fuel_flow_scaler_constant_term,0.,unitless +aircraft:engine:fuel_flow_scaler_linear_term,0.,unitless +aircraft:engine:generate_flight_idle,True,unitless +aircraft:engine:geopotential_alt,False,unitless +aircraft:engine:ignore_negative_thrust,False,unitless +aircraft:engine:interpolation_method,slinear,unitless +aircraft:engine:mass_scaler,1.15,unitless +aircraft:engine:mass,7400,lbm +aircraft:engine:num_engines,2,unitless +aircraft:engine:num_fuselage_engines,0,unitless +aircraft:engine:num_wing_engines,2,unitless +aircraft:engine:reference_mass,7400,lbm +aircraft:engine:reference_sls_thrust,28928.1,lbf +aircraft:engine:scale_mass,True,unitless +aircraft:engine:scale_performance,True,unitless +aircraft:engine:scaled_sls_thrust,28928.1,lbf +aircraft:engine:subsonic_fuel_flow_scaler,1.,unitless +aircraft:engine:supersonic_fuel_flow_scaler,1.,unitless +aircraft:engine:thrust_reversers_mass_scaler,0.0,unitless +aircraft:engine:wing_locations,[0.26869218],unitless +aircraft:fins:area,0.0,ft**2 +aircraft:fins:mass_scaler,1.0,unitless +aircraft:fins:mass,0.0,lbm +aircraft:fins:num_fins,0,unitless +aircraft:fins:taper_ratio,10.0,unitless +aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm +aircraft:fuel:density_ratio,1.0,unitless +aircraft:fuel:fuel_system_mass_scaler,1.0,unitless +aircraft:fuel:fuselage_fuel_capacity,0.0,lbm +aircraft:fuel:num_tanks,7,unitless +aircraft:fuel:total_capacity,45694.0,lbm +aircraft:fuel:unusable_fuel_mass_scaler,1.0,unitless +aircraft:furnishings:mass_scaler,1.1,unitless +aircraft:fuselage:length,128.0,ft +aircraft:fuselage:mass_scaler,1.05,unitless +aircraft:fuselage:max_height,13.17,ft +aircraft:fuselage:max_width,12.33,ft +aircraft:fuselage:military_cargo_floor,False,unitless +aircraft:fuselage:num_fuselages,1,unitless +aircraft:fuselage:passenger_compartment_length,85.5,ft +aircraft:fuselage:planform_area,1578.24,ft**2 +aircraft:fuselage:wetted_area_scaler,1.0,unitless +aircraft:fuselage:wetted_area,4158.62,ft**2 +aircraft:horizontal_tail:area,355.0,ft**2 +aircraft:horizontal_tail:aspect_ratio,6.0,unitless +aircraft:horizontal_tail:mass_scaler,1.2,unitless +aircraft:horizontal_tail:taper_ratio,0.22,unitless +aircraft:horizontal_tail:thickness_to_chord,0.125,unitless +aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless +aircraft:horizontal_tail:wetted_area_scaler,1.0,unitless +aircraft:horizontal_tail:wetted_area,592.65,ft**2 +aircraft:hydraulics:mass_scaler,1.0,unitless +aircraft:hydraulics:system_pressure,3000.0,lbf/ft**2 +aircraft:instruments:mass_scaler,1.25,unitless +aircraft:landing_gear:carrier_based,False,unitless +aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless +aircraft:landing_gear:main_gear_oleo_length,102.0,inch +aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless +aircraft:landing_gear:nose_gear_oleo_length,67.0,inch +aircraft:nacelle:avg_diameter,7.94,ft +aircraft:nacelle:avg_length,12.3,ft +aircraft:nacelle:count_factor,2,unitless +aircraft:nacelle:mass_scaler,1.0,unitless +aircraft:nacelle:wetted_area_scaler,1.0,unitless +aircraft:paint:mass_per_unit_area,0.037,lbm/ft**2 +aircraft:propulsion:engine_oil_mass_scaler,1.0,unitless +aircraft:propulsion:misc_mass_scaler,1.0,unitless +aircraft:vertical_tail:area,284.0,ft**2 +aircraft:vertical_tail:aspect_ratio,1.75,unitless +aircraft:vertical_tail:mass_scaler,1.0,unitless +aircraft:vertical_tail:num_tails,1,unitless +aircraft:vertical_tail:taper_ratio,0.33,unitless +aircraft:vertical_tail:thickness_to_chord,0.1195,unitless +aircraft:vertical_tail:wetted_area_scaler,1.0,unitless +aircraft:vertical_tail:wetted_area,581.13,ft**2 +aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless +aircraft:wing:airfoil_technology,1.92669766647637,unitless +aircraft:wing:area,1370.0,ft**2 +aircraft:wing:aspect_ratio,11.22091,unitless +aircraft:wing:bending_mass_scaler,1.0,unitless +aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless +aircraft:wing:composite_fraction,0.2,unitless +aircraft:wing:control_surface_area,137,ft**2 +aircraft:wing:control_surface_area_ratio,0.1,unitless +aircraft:wing:glove_and_bat,134.0,ft**2 +aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless +aircraft:wing:load_distribution_control,2.0,unitless +aircraft:wing:load_fraction,1.0,unitless +aircraft:wing:load_path_sweep_dist,0.,22.,deg +aircraft:wing:mass_scaler,1.23,unitless +aircraft:wing:max_camber_at_70_semispan,0.0,unitless +aircraft:wing:misc_mass_scaler,1.0,unitless +aircraft:wing:num_integration_stations,50,unitless +aircraft:wing:shear_control_mass_scaler,1.0,unitless +aircraft:wing:span_efficiency_reduction,False,unitless +aircraft:wing:span,117.83,ft +aircraft:wing:strut_bracing_factor,0.0,unitless +aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless +aircraft:wing:sweep,25.0,deg +aircraft:wing:taper_ratio,0.278,unitless +aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless +aircraft:wing:thickness_to_chord,0.13,unitless +aircraft:wing:ultimate_load_factor,3.75,unitless +aircraft:wing:var_sweep_mass_penalty,0.0,unitless +aircraft:wing:wetted_area_scaler,1.0,unitless +aircraft:wing:wetted_area,2396.56,ft**2 +mission:constraints:max_mach,0.785,unitless +mission:design:cruise_altitude,35000,ft +mission:design:gross_mass,175400.0,lbm +mission:design:range,3500,NM +mission:design:thrust_takeoff_per_eng,28928.1,lbf +mission:landing:lift_coefficient_max,2.0,unitless +mission:summary:cruise_mach,0.785,unitless +mission:summary:fuel_flow_scaler,1.0,unitless +mission:takeoff:fuel_simple,577,lbm +mission:takeoff:lift_coefficient_max,3.0,unitless +mission:takeoff:lift_over_drag,17.354,unitless +mission:takeoff:rolling_friction_coefficient,0.0175,unitless +settings:equations_of_motion,simple +settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv index d8128ce1e..0d54c3528 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv @@ -266,6 +266,8 @@ mission:takeoff:lift_coefficient,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless aircraft:fuel:burn_per_passenger_mile,0.1 +settings:equations_of_motion,2DOF +settings:mass_method,FLOPS # Initial Guesses actual_takeoff_mass,0 diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 58caba631..5c0d0b8a0 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -268,4 +268,6 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless -mission:takeoff:rolling_friction_coefficient,0.0175,unitless \ No newline at end of file +mission:takeoff:rolling_friction_coefficient,0.0175,unitless +settings:equations_of_motion,height_energy +settings:mass_method,GASP \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index 70c78f420..a71a6e26f 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -141,6 +141,8 @@ mission:summary:fuel_flow_scaler,1,unitless mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.1677,h +settings:equations_of_motion,2DOF +settings:mass_method,GASP # Initial Guesses actual_takeoff_mass,0 diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv new file mode 100644 index 000000000..720764ca5 --- /dev/null +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv @@ -0,0 +1,214 @@ +debug_mode,False + +aircraft:controls:cockpit_control_mass_scaler,1,unitless +aircraft:controls:control_mass_increment,0,lbm +aircraft:controls:stability_augmentation_system_mass,0,lbm +aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless +aircraft:crew_and_payload:cargo_mass,10040,lbm +aircraft:crew_and_payload:num_passengers,180,unitless +aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm +aircraft:design:cg_delta,0.25,unitless +aircraft:design:cockpit_control_mass_coefficient,16.5,unitless +aircraft:design:drag_increment,0.00175,unitless +aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless +aircraft:design:max_structural_speed,402.5,mi/h +aircraft:design:part25_structural_category,3,unitless +aircraft:design:reserves,4998,unitless +aircraft:design:static_margin,0.03,unitless +aircraft:design:structural_mass_increment,0,lbm +aircraft:design:supercritical_drag_shift,0.033,unitless +aircraft:engine:additional_mass_fraction,0.135,unitless +aircraft:engine:data_file,models/engines/turbofan_23k_1.deck,unitless +aircraft:engine:mass_scaler,1,unitless +aircraft:engine:mass_specific,0.21366,lbm/lbf +aircraft:engine:mass_scaler,1,unitless +aircraft:engine:num_engines,2,unitless +aircraft:engine:pod_mass_scaler,1,unitless +aircraft:engine:pylon_factor,1.25,unitless +aircraft:engine:reference_diameter,5.8,ft +aircraft:engine:reference_sls_thrust,28690,lbf +aircraft:engine:scale_factor,1.0,unitless +aircraft:engine:scaled_sls_thrust,28690,lbf +aircraft:engine:type,7,unitless +aircraft:engine:wing_locations,0.35,unitless +aircraft:fuel:density,6.687,lbm/galUS +aircraft:fuel:fuel_margin,0,unitless +aircraft:fuel:fuel_system_mass_coefficient,0.041,unitless +aircraft:fuel:fuel_system_mass_scaler,1,unitless +aircraft:fuel:wing_fuel_fraction,0.6,unitless +aircraft:fuselage:aisle_width,24,inch +aircraft:fuselage:delta_diameter,4.5,ft +aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 +aircraft:fuselage:form_factor,1.25,unitless +aircraft:fuselage:mass_coefficient,128,unitless +aircraft:fuselage:nose_fineness,1,unitless +aircraft:fuselage:num_aisles,1,unitless +aircraft:fuselage:num_seats_abreast,6,unitless +aircraft:fuselage:pilot_compartment_length,9.5,ft +aircraft:fuselage:pressure_differential,7.5,psi +aircraft:fuselage:seat_pitch,29,inch +aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:tail_fineness,3,unitless +aircraft:fuselage:wetted_area_factor,4000,unitless +aircraft:horizontal_tail:area,0,ft**2 +aircraft:horizontal_tail:aspect_ratio,4.75,unitless +aircraft:horizontal_tail:form_factor,1.25,unitless +aircraft:horizontal_tail:mass_coefficient,0.232,unitless +aircraft:horizontal_tail:moment_ratio,0.2307,unitless +aircraft:horizontal_tail:sweep,25,deg +aircraft:horizontal_tail:taper_ratio,0.352,unitless +aircraft:horizontal_tail:thickness_to_chord,0.12,unitless +aircraft:horizontal_tail:vertical_tail_fraction,0,unitless +aircraft:horizontal_tail:volume_coefficient,1.189,unitless +aircraft:landing_gear:fixed_gear,False,unitless +aircraft:landing_gear:main_gear_location,0.15,unitless +aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless +aircraft:landing_gear:mass_coefficient,0.04,unitless +aircraft:landing_gear:tail_hook_mass_scaler,1,unitless +aircraft:landing_gear:total_mass_scaler,1,unitless +aircraft:nacelle:clearance_ratio,0.2,unitless +aircraft:nacelle:core_diameter_ratio,1.25,unitless +aircraft:nacelle:fineness,2,unitless +aircraft:nacelle:form_factor,1.5,unitless +aircraft:nacelle:mass_specific,3,lbm/ft**2 +aircraft:strut:area_ratio,0,unitless +aircraft:strut:attachment_location,0,ft +aircraft:strut:attachment_location_dimensionless,0,unitless +aircraft:strut:dimensional_location_specified,False,unitless +aircraft:strut:fuselage_interference_factor,0,unitless +aircraft:strut:mass_coefficient,0,unitless +aircraft:strut:thickness_to_chord,0,unitless +aircraft:vertical_tail:area,0,ft**2 +aircraft:vertical_tail:aspect_ratio,1.67,unitless +aircraft:vertical_tail:form_factor,1.25,unitless +aircraft:vertical_tail:mass_coefficient,0.289,unitless +aircraft:vertical_tail:moment_ratio,2.362,unitless +aircraft:vertical_tail:sweep,35,deg +aircraft:vertical_tail:taper_ratio,0.801,unitless +aircraft:vertical_tail:thickness_to_chord,0.12,unitless +aircraft:vertical_tail:volume_coefficient,0.145,unitless +aircraft:wing:aspect_ratio,10.13,unitless +aircraft:wing:center_distance,0.463,unitless +aircraft:wing:choose_fold_location,True,unitless +aircraft:wing:flap_chord_ratio,0.3,unitless +aircraft:wing:flap_deflection_landing,40,deg +aircraft:wing:flap_deflection_takeoff,10,deg +aircraft:wing:flap_drag_increment_optimum,0.1,unitless +aircraft:wing:flap_lift_increment_optimum,1.5,unitless +aircraft:wing:flap_span_ratio,0.65,unitless +aircraft:wing:flap_type,double_slotted,unitless +aircraft:wing:fold_dimensional_location_specified,False,unitless +aircraft:wing:fold_mass_coefficient,0,unitless +aircraft:wing:folded_span,0,ft +aircraft:wing:form_factor,1.25,unitless +aircraft:wing:fuselage_interference_factor,1.1,unitless +aircraft:wing:has_fold,False,unitless +aircraft:wing:has_strut,False,unitless +aircraft:wing:height,8,ft +aircraft:wing:high_lift_mass_coefficient,1.9,unitless +aircraft:wing:incidence,1.5,deg +aircraft:wing:loading,128,lbf/ft**2 +aircraft:wing:mass_coefficient,102.5,unitless +aircraft:wing:max_lift_ref,1.15,unitless +aircraft:wing:max_slat_deflection_landing,10,deg +aircraft:wing:max_slat_deflection_takeoff,10,deg +aircraft:wing:max_thickness_location,0.4,unitless +aircraft:wing:min_pressure_location,0.3,unitless +aircraft:wing:mounting_type,0,unitless +aircraft:wing:num_flap_segments,2,unitless +aircraft:wing:optimum_flap_deflection,55,deg +aircraft:wing:optimum_slat_deflection,20,deg +aircraft:wing:slat_chord_ratio,0.15,unitless +aircraft:wing:slat_lift_increment_optimum,0.93,unitless +aircraft:wing:surface_ctrl_mass_coefficient,0.95,unitless +aircraft:wing:sweep,25,deg +aircraft:wing:taper_ratio,0.33,unitless +aircraft:wing:thickness_to_chord_root,0.15,unitless +aircraft:wing:thickness_to_chord_tip,0.12,unitless +aircraft:wing:zero_lift_angle,-1.2,deg +mission:design:cruise_altitude,37500,ft +mission:design:gross_mass,175400,lbm +mission:design:mach,0.8,unitless +mission:design:range,3675,NM +mission:landing:airport_altitude_landing,0,ft +mission:landing:braking_delay,1,s +mission:landing:glide_to_stall_ratio,1.3,unitless +mission:landing:maximum_flare_load_factor,1.15,unitless +mission:landing:maximum_sink_rate,900,ft/min +mission:landing:obstacle_height,50,ft +mission:landing:touchdown_sink_rate,5,ft/s +mission:summary:fuel_flow_scaler,1,unitless +mission:takeoff:decision_speed_increment,10,kn +mission:takeoff:rotation_speed_increment,5,kn +mission:taxi:duration,0.1677,h +settings:equations_of_motion,solved +settings:mass_method,GASP + +# Initial Guesses +actual_takeoff_mass,0 +climb_range,0 +cruise_mass_final,0 +flight_duration,0 +fuel_burn_per_passenger_mile,0.1 +reserves,0 +rotation_mass,0.99 +time_to_climb,0 + +INGASP.ALR,1.11 +INGASP.BENGOB,0.05 +INGASP.CINP,0.11 +INGASP.CK10,1 +INGASP.CK11,1 +INGASP.CK18,1 +INGASP.CK7,1 +INGASP.CK8,1 +INGASP.CK9,1 +INGASP.CLIAB,1984 +INGASP.CMF,15 +INGASP.CMV,0.15 +INGASP.CRWOH,15 +INGASP.DCDSE,-1 +INGASP.DYR,12 +INGASP.EMCRU,0.8 +INGASP.FCSF,2.5 +INGASP.FPYLND,1 +INGASP.HBTP,0.333 +INGASP.HIR,0.015 +INGASP.HNCRU,37500 +INGASP.HPORT,0 +INGASP.HRI,2500 +INGASP.HSCREQ,20000 +INGASP.ICLM,3 +INGASP.ICRUS,0 +INGASP.IWLD,2 +INGASP.JENGSZ,4 +INGASP.KNAC,1 +INGASP.KODEAC,7 +INGASP.KODECL,7 +INGASP.KODETO,5 +INGASP.KODETR,6 +INGASP.MX,0 +INGASP.NFAIL,0 +INGASP.OFALT,0 +INGASP.OFEM,0.78 +INGASP.OHR,350 +INGASP.PRV,0.15 +INGASP.RELP,0 +INGASP.RELR,0.4524 +INGASP.RF,0.05,125,20000,25000 +INGASP.RI,0.8 +INGASP.ROCTOC,300 +INGASP.ROSCAB,9999 +INGASP.RWCRTX,0.985 +INGASP.SKPES,0.258 +INGASP.SM1D,0.625 +INGASP.SRPM,18000 +INGASP.TBO,3500 +INGASP.TR,1 +INGASP.VCLMB,270 +INGASP.WENG,6130 +INGASP.WLPCT,0.9423 +INGASP.WNAC,0 +INGASP.WPLX,0 +INGASP.WPYLON,0 +INGASP.XTORQ,8000 diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv index a52b15fb7..94de39b61 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv @@ -141,6 +141,8 @@ mission:summary:fuel_flow_scaler,1,unitless mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.1677,h +settings:equations_of_motion,2DOF +settings:mass_method,GASP # Initial Guesses actual_takeoff_mass,0 diff --git a/aviary/subsystems/aerodynamics/aerodynamics_builder.py b/aviary/subsystems/aerodynamics/aerodynamics_builder.py index ac4b0d7c0..959b8f009 100644 --- a/aviary/subsystems/aerodynamics/aerodynamics_builder.py +++ b/aviary/subsystems/aerodynamics/aerodynamics_builder.py @@ -27,6 +27,11 @@ SolvedAlphaGroup from aviary.subsystems.aerodynamics.flops_based.tabular_aero_group import \ TabularAeroGroup +from aviary.variable_info.enums import LegacyCode + + +GASP = LegacyCode.GASP +FLOPS = LegacyCode.FLOPS _default_name = 'aerodynamics' @@ -50,7 +55,7 @@ def __init__(self, name=None, meta_data=None, code_origin=None): if name is None: name = 'core_aerodynamics' - if code_origin not in ('FLOPS', 'GASP'): + if code_origin not in (FLOPS, GASP): raise ValueError('Code origin is not one of the following: (FLOPS, GASP)') self.code_origin = code_origin @@ -60,10 +65,10 @@ def __init__(self, name=None, meta_data=None, code_origin=None): def build_pre_mission(self, aviary_inputs): code_origin = self.code_origin - if code_origin == 'GASP': + if code_origin is GASP: aero_group = PreMissionAero(aviary_options=aviary_inputs) - elif code_origin == 'FLOPS': + elif code_origin is FLOPS: aero_group = om.Group() aero_group.add_subsystem( 'design', Design(aviary_options=aviary_inputs), @@ -82,7 +87,7 @@ def build_mission(self, num_nodes, aviary_inputs, **kwargs): method = kwargs.pop('method') except KeyError: method = None - if self.code_origin == 'FLOPS': + if self.code_origin is FLOPS: if method is None: aero_group = ComputedAeroGroup(num_nodes=num_nodes, aviary_options=aviary_inputs) @@ -115,7 +120,7 @@ def build_mission(self, num_nodes, aviary_inputs, **kwargs): raise ValueError('FLOPS-based aero method is not one of the following: ' '(computed, low_speed, solved_alpha, tabular)') - elif self.code_origin == 'GASP': + elif self.code_origin is GASP: if method is None: aero_group = CruiseAero(num_nodes=num_nodes) @@ -155,7 +160,7 @@ def mission_inputs(self, **kwargs): method = kwargs['method'] promotes = ['*'] - if self.code_origin == 'FLOPS': + if self.code_origin is FLOPS: if method == 'computed': promotes = [Dynamic.Mission.STATIC_PRESSURE, Dynamic.Mission.MACH, @@ -193,7 +198,7 @@ def mission_inputs(self, **kwargs): raise ValueError('FLOPS-based aero method is not one of the following: ' '(computed, low_speed, solved_alpha, tabular)') - elif self.code_origin == 'GASP': + elif self.code_origin is GASP: if method == 'low_speed': promotes = ['*', ("airport_alt", Mission.Takeoff.AIRPORT_ALTITUDE), @@ -217,12 +222,12 @@ def mission_outputs(self, **kwargs): method = kwargs['method'] promotes = ['*'] - if self.code_origin == 'FLOPS': + if self.code_origin is FLOPS: promotes = [Dynamic.Mission.DRAG] if method == 'low_speed': promotes.append(Dynamic.Mission.LIFT) - elif self.code_origin == 'GASP': + elif self.code_origin is GASP: if method == 'low_speed': promotes = [Dynamic.Mission.DRAG, Dynamic.Mission.LIFT, @@ -256,9 +261,9 @@ def report(self, prob, reports_folder, **kwargs): reports_folder : Path Location of the subsystems_report folder this report will be placed in """ - if self.code_origin == 'FLOPS': + if self.code_origin is FLOPS: # FLOPS aero report goes here return - elif self.code_origin == 'GASP': + elif self.code_origin is GASP: # GASP aero report goes here return diff --git a/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv b/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv index 1da0f0791..356ddc757 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv +++ b/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv @@ -136,4 +136,6 @@ mission:summary:fuel_flow_scaler,1.01,unitless #check mission:takeoff:fuel_simple,400,lbm mission:takeoff:lift_coefficient_max,2.55,unitless mission:takeoff:lift_over_drag,25,unitless -mission:takeoff:rolling_friction_coefficient,0.0175,unitless \ No newline at end of file +mission:takeoff:rolling_friction_coefficient,0.0175,unitless +settings:equations_of_motion,height_energy +settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py index ee1cb68be..3788620b8 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py @@ -5,7 +5,7 @@ from openmdao.utils.assert_utils import assert_near_equal from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.flops import aero, prop, geom +from aviary.interface.default_phase_info.height_energy import aero, prop, geom from aviary.utils.aviary_values import get_items from aviary.utils.functions import set_aviary_initial_values from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py index 74fce7f6d..4293d3063 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py @@ -14,7 +14,7 @@ from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.csv_data_file import read_data_file from aviary.utils.named_values import NamedValues -from aviary.interface.default_phase_info.flops import phase_info +from aviary.interface.default_phase_info.height_energy import phase_info from aviary.variable_info.variables import Aircraft from copy import deepcopy @@ -47,13 +47,13 @@ class TestSolvedAero(unittest.TestCase): def test_solved_aero_pass_polar(self): # Test that passing training data provides the same results local_phase_info = deepcopy(phase_info) - prob = AviaryProblem( - local_phase_info, mission_method="FLOPS", mass_method="FLOPS") + + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, local_phase_info) prob.add_pre_mission_systems() prob.add_phases() prob.add_post_mission_systems() @@ -89,9 +89,9 @@ def test_solved_aero_pass_polar(self): ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} - prob = AviaryProblem(ph_in, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem() - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, ph_in) prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, np.zeros_like(CL), units='unitless') diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py index a23d9d263..897caf9a5 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py @@ -8,7 +8,7 @@ from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.flops import aero, prop, geom +from aviary.interface.default_phase_info.height_energy import aero, prop, geom from aviary.utils.aviary_values import AviaryValues, get_items from aviary.utils.functions import set_aviary_initial_values from aviary.utils.named_values import NamedValues @@ -17,6 +17,10 @@ print_case) from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.variables_in import VariablesIn +from aviary.variable_info.enums import LegacyCode + +FLOPS = LegacyCode.FLOPS +GASP = LegacyCode.GASP class TabularAeroGroupFileTest(unittest.TestCase): @@ -31,7 +35,7 @@ def setUp(self): kwargs = {'method': 'tabular', 'CDI_data': CDI_table, 'CD0_data': CD0_table} - aero_builder = CoreAerodynamicsBuilder(code_origin='FLOPS') + aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) self.prob.model.add_subsystem( "aero", @@ -105,7 +109,7 @@ def setUp(self): kwargs = {'method': 'tabular', 'CDI_data': CDI_table, 'CD0_data': CD0_table, } # 'training_data': True} - aero_builder = CoreAerodynamicsBuilder(code_origin='FLOPS') + aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) self.prob.model.add_subsystem( "aero", @@ -224,7 +228,7 @@ def test_case(self, case_name): kwargs = {'method': 'tabular', 'CDI_data': CDI_data, 'CD0_data': CD0_data} - aero_builder = CoreAerodynamicsBuilder(code_origin='FLOPS') + aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) prob.model.add_subsystem( "aero", @@ -593,7 +597,7 @@ def setup(self): kwargs = {'method': 'computed', 'gamma': gamma} - aero_builder = CoreAerodynamicsBuilder(code_origin='FLOPS') + aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) self.add_subsystem( "aero", diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py index d64e2487b..e16c92fe4 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py @@ -12,6 +12,7 @@ from aviary.variable_info.variables import Aircraft from aviary.variable_info.variables import Dynamic as _Dynamic from aviary.variable_info.variables import Mission +from aviary.variable_info.enums import LegacyCode Dynamic = _Dynamic.Mission @@ -92,7 +93,7 @@ def make_problem(subsystem_options={}): "rho", ("sos", Dynamic.SPEED_OF_SOUND), ("temp", Dynamic.TEMPERATURE), ("pres", Dynamic.STATIC_PRESSURE), "viscosity"]) - aero_builder = CoreAerodynamicsBuilder(code_origin='FLOPS') + aero_builder = CoreAerodynamicsBuilder(code_origin=LegacyCode.FLOPS) prob.model.add_subsystem( name='core_aerodynamics', diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py index fe1e25bdf..54c842073 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py @@ -9,7 +9,7 @@ from aviary.subsystems.aerodynamics.gasp_based.flaps_model.meta_model import \ MetaModelGroup from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import Flap_Type +from aviary.variable_info.enums import FlapType from aviary.variable_info.variables import Aircraft, Dynamic @@ -26,13 +26,13 @@ def initialize(self): # optimum trailing edge flap deflection angle defaults (ADELTO table in GASP) self.optimum_flap_defls = { - Flap_Type.PLAIN: 60.0, - Flap_Type.SPLIT: 60.0, - Flap_Type.SINGLE_SLOTTED: 40.0, - Flap_Type.DOUBLE_SLOTTED: 55.0, - Flap_Type.TRIPLE_SLOTTED: 55.0, - Flap_Type.FOWLER: 30.0, - Flap_Type.DOUBLE_SLOTTED_FOWLER: 30.0, + FlapType.PLAIN: 60.0, + FlapType.SPLIT: 60.0, + FlapType.SINGLE_SLOTTED: 40.0, + FlapType.DOUBLE_SLOTTED: 55.0, + FlapType.TRIPLE_SLOTTED: 55.0, + FlapType.FOWLER: 30.0, + FlapType.DOUBLE_SLOTTED_FOWLER: 30.0, } def setup(self): diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py index fc711963d..84e4cf277 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py @@ -2,7 +2,7 @@ import openmdao.api as om from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import Flap_Type +from aviary.variable_info.enums import FlapType from aviary.variable_info.variables import Aircraft, Dynamic @@ -38,7 +38,7 @@ def setup(self): desc="ratio of flap chord to wing chord", ) - if flap_type is Flap_Type.PLAIN or flap_type is Flap_Type.SPLIT: + if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: VDEL1_interp.add_output( "VDEL1", @@ -373,7 +373,7 @@ def setup(self): desc="average wing thickness to chord ratio", ) - if flap_type is Flap_Type.PLAIN or flap_type is Flap_Type.SPLIT: + if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: VLAM4_interp.add_output( "VLAM4", @@ -445,7 +445,7 @@ def setup(self): desc="ratio of flap chord to wing chord", ) - if flap_type is Flap_Type.PLAIN or flap_type is Flap_Type.SPLIT: + if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: VLAM5_interp.add_output( "VLAM5", @@ -456,9 +456,9 @@ def setup(self): ) elif ( - flap_type is Flap_Type.SINGLE_SLOTTED - or flap_type is Flap_Type.DOUBLE_SLOTTED - or flap_type is Flap_Type.TRIPLE_SLOTTED + flap_type is FlapType.SINGLE_SLOTTED + or flap_type is FlapType.DOUBLE_SLOTTED + or flap_type is FlapType.TRIPLE_SLOTTED ): VLAM5_interp.add_output( @@ -515,7 +515,7 @@ def setup(self): desc="flap deflection", ) - if flap_type is Flap_Type.PLAIN or flap_type is Flap_Type.SPLIT: + if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: VLAM6_interp.add_output( "VLAM6", @@ -542,9 +542,9 @@ def setup(self): ) elif ( - flap_type is Flap_Type.SINGLE_SLOTTED - or flap_type is Flap_Type.DOUBLE_SLOTTED - or flap_type is Flap_Type.TRIPLE_SLOTTED + flap_type is FlapType.SINGLE_SLOTTED + or flap_type is FlapType.DOUBLE_SLOTTED + or flap_type is FlapType.TRIPLE_SLOTTED ): VLAM6_interp.add_output( @@ -571,7 +571,7 @@ def setup(self): desc="sensitivity of flap clean wing maximum lift coefficient to wing flap deflection", ) - elif (flap_type is Flap_Type.FOWLER or flap_type is Flap_Type.DOUBLE_SLOTTED_FOWLER): + elif (flap_type is FlapType.FOWLER or flap_type is FlapType.DOUBLE_SLOTTED_FOWLER): VLAM6_interp.add_output( "VLAM6", diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py index 7caf94667..0bf9cb917 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py @@ -6,7 +6,7 @@ from aviary.subsystems.aerodynamics.gasp_based.flaps_model.flaps_model import \ FlapsGroup from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.enums import Flap_Type +from aviary.variable_info.enums import FlapType from aviary.variable_info.variables import Aircraft, Dynamic """ @@ -21,7 +21,7 @@ def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.FLAP_TYPE, - val=Flap_Type.TRIPLE_SLOTTED, units='unitless') + val=FlapType.TRIPLE_SLOTTED, units='unitless') self.prob.model = FCC = FlapsGroup(aviary_options=options) @@ -123,7 +123,7 @@ def setUp(self): self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, val=Flap_Type.SPLIT, units='unitless') + options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.SPLIT, units='unitless') self.prob.model = FCC = FlapsGroup(aviary_options=options) @@ -226,7 +226,7 @@ def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.FLAP_TYPE, - val=Flap_Type.SINGLE_SLOTTED, units='unitless') + val=FlapType.SINGLE_SLOTTED, units='unitless') self.prob.model = FCC = FlapsGroup(aviary_options=options) @@ -329,7 +329,7 @@ def setUp(self): self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, val=Flap_Type.PLAIN, units='unitless') + options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.PLAIN, units='unitless') self.prob.model = FCC = FlapsGroup(aviary_options=options) @@ -431,7 +431,7 @@ def setUp(self): self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, val=Flap_Type.FOWLER, units='unitless') + options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.FOWLER, units='unitless') self.prob.model = FCC = FlapsGroup(aviary_options=options) @@ -534,7 +534,7 @@ def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.FLAP_TYPE, - val=Flap_Type.DOUBLE_SLOTTED_FOWLER, units='unitless') + val=FlapType.DOUBLE_SLOTTED_FOWLER, units='unitless') self.prob.model = FCC = FlapsGroup(aviary_options=options) diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py index af6c5de39..725b5ae60 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py @@ -8,7 +8,7 @@ from aviary.subsystems.aerodynamics.gasp_based.flaps_model.meta_model import \ MetaModelGroup from aviary.utils.test_utils.IO_test_util import assert_match_spec, skipIfMissingXDSM -from aviary.variable_info.enums import Flap_Type +from aviary.variable_info.enums import FlapType from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic @@ -22,7 +22,7 @@ def setUp(self): self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, val=Flap_Type.PLAIN, units='unitless') + options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.PLAIN, units='unitless') self.prob.model = LuTMMa = MetaModelGroup(aviary_options=options) self.prob.setup() @@ -123,7 +123,7 @@ def setUp(self): self.prob = om.Problem() options = get_option_defaults() options.set_val(Aircraft.Wing.FLAP_TYPE, - val=Flap_Type.SINGLE_SLOTTED, units='unitless') + val=FlapType.SINGLE_SLOTTED, units='unitless') self.prob.model = LuTMMb = MetaModelGroup(aviary_options=options) self.prob.setup() @@ -168,7 +168,7 @@ def setUp(self): self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, val=Flap_Type.FOWLER, units='unitless') + options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.FOWLER, units='unitless') self.prob.model = LuTMMc = MetaModelGroup(aviary_options=options) self.prob.setup() diff --git a/aviary/subsystems/geometry/combined_geometry.py b/aviary/subsystems/geometry/combined_geometry.py index 1065a15ac..655f0ae93 100644 --- a/aviary/subsystems/geometry/combined_geometry.py +++ b/aviary/subsystems/geometry/combined_geometry.py @@ -5,6 +5,10 @@ from aviary.utils.aviary_values import AviaryValues from aviary.subsystems.geometry.flops_based.prep_geom import PrepGeom from aviary.subsystems.geometry.gasp_based.size_group import SizeGroup +from aviary.variable_info.enums import LegacyCode + +FLOPS = LegacyCode.FLOPS +GASP = LegacyCode.GASP class CombinedGeometry(om.Group): @@ -15,7 +19,7 @@ def initialize(self): ) self.options.declare('code_origin_to_prioritize', - values=['GASP', 'FLOPS', None], + values=[GASP, FLOPS, None], default=None, desc='sets which code origin to prioritize if there are' ' conflicting outputs.' @@ -53,7 +57,7 @@ def configure(self): gasp_fus_diam_path = gasp_geom_pathname + \ '.fuselage.parameters.' + Aircraft.Fuselage.AVG_DIAMETER - if prioritize_origin == 'GASP': + if prioritize_origin is GASP: override = [flops_fus_area_path, flops_fus_diam_path] name = Aircraft.Fuselage.WETTED_AREA @@ -64,7 +68,7 @@ def configure(self): outs = [(name, f"MANUAL_OVERRIDE:{name}")] self.flops_based_geom.promotes('fuselage_prelim', outputs=outs) - elif prioritize_origin == 'FLOPS': + elif prioritize_origin is FLOPS: override = [gasp_fus_area_path, gasp_fus_diam_path] name = Aircraft.Fuselage.WETTED_AREA diff --git a/aviary/subsystems/geometry/geometry_builder.py b/aviary/subsystems/geometry/geometry_builder.py index 9a9520816..16cbefd34 100644 --- a/aviary/subsystems/geometry/geometry_builder.py +++ b/aviary/subsystems/geometry/geometry_builder.py @@ -14,8 +14,12 @@ from aviary.subsystems.geometry.flops_based.prep_geom import PrepGeom from aviary.subsystems.geometry.gasp_based.size_group import SizeGroup from aviary.variable_info.variables import Aircraft +from aviary.variable_info.enums import LegacyCode +GASP = LegacyCode.GASP +FLOPS = LegacyCode.FLOPS + _default_name = 'geometry' @@ -39,7 +43,7 @@ def __init__(self, name=None, meta_data=None, code_origin=None, if name is None: name = 'core_geometry' - if code_origin not in ('FLOPS', 'GASP') and not use_both_geometries: + if code_origin not in (FLOPS, GASP) and not use_both_geometries: raise ValueError('Code origin is not one of the following: (FLOPS, GASP)') self.code_origin = code_origin @@ -59,11 +63,11 @@ def build_pre_mission(self, aviary_inputs): geom_group = CombinedGeometry(aviary_options=aviary_inputs, code_origin_to_prioritize=code_origin_to_prioritize) - elif code_origin == 'GASP': + elif code_origin is GASP: geom_group = SizeGroup(aviary_options=aviary_inputs) geom_group.manual_overrides = None - elif code_origin == 'FLOPS': + elif code_origin is FLOPS: geom_group = PrepGeom(aviary_options=aviary_inputs) geom_group.manual_overrides = None diff --git a/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py b/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py index 5d5af368b..b57d7c9d7 100644 --- a/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py +++ b/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py @@ -3,7 +3,7 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import GASP_Engine_Type +from aviary.variable_info.enums import GASPEngineType from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission @@ -92,7 +92,7 @@ def compute(self, inputs, outputs): num_pilots = 1.0 if PAX > 9.0: num_pilots = 2.0 - if engine_type is GASP_Engine_Type.TURBOJET and PAX > 5.0: + if engine_type is GASPEngineType.TURBOJET and PAX > 5.0: num_pilots = 2.0 if PAX >= 251.0: num_pilots = 3.0 @@ -285,9 +285,9 @@ def compute(self, inputs, outputs): 20.0 * (num_flight_attendants + num_pilots) + 25.0 * num_pilots ) - if engine_type is GASP_Engine_Type.TURBOJET: + if engine_type is GASPEngineType.TURBOJET: oil_per_eng_wt = 0.0054 * Fn_SLS + 12.0 - # elif engine_type is GASP_Engine_Type.TURBOSHAFT or engine_type is GASP_Engine_Type.TURBOPROP: + # elif engine_type is GASPEngineType.TURBOSHAFT or engine_type is GASPEngineType.TURBOPROP: # oil_per_eng_wt = 0.0124 * Fn_SLS + 14 # else: # oil_per_eng_wt = 0.062 * (Fn_SLS - 100) + 11 @@ -392,7 +392,7 @@ def compute_partials(self, inputs, partials): num_pilots = 1.0 if PAX > 9.0: num_pilots = 2.0 - if engine_type is GASP_Engine_Type.TURBOJET and PAX > 5.0: + if engine_type is GASPEngineType.TURBOJET and PAX > 5.0: num_pilots = 2.0 if PAX >= 251.0: num_pilots = 3.0 @@ -677,9 +677,9 @@ def compute_partials(self, inputs, partials): if PAX >= 251.0: num_flight_attendants = 6.0 - if engine_type is GASP_Engine_Type.TURBOJET: + if engine_type is GASPEngineType.TURBOJET: doil_per_eng_wt_dFn_SLS = 0.0054 - # elif engine_type is GASP_Engine_Type.TURBOSHAFT or engine_type is GASP_Engine_Type.TURBOPROP: + # elif engine_type is GASPEngineType.TURBOSHAFT or engine_type is GASPEngineType.TURBOPROP: # doil_per_eng_wt_dFn_SLS = 0.0124 # else: # doil_per_eng_wt_dFn_SLS = 0.062 diff --git a/aviary/subsystems/mass/gasp_based/fixed.py b/aviary/subsystems/mass/gasp_based/fixed.py index e0090774c..7dd72d03b 100644 --- a/aviary/subsystems/mass/gasp_based/fixed.py +++ b/aviary/subsystems/mass/gasp_based/fixed.py @@ -3,7 +3,7 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import Flap_Type +from aviary.variable_info.enums import FlapType from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission @@ -1637,10 +1637,10 @@ def compute(self, inputs, outputs): outputs['slat_mass'] = WLED / GRAV_ENGLISH_LBM # Flap Mass - if flap_type is Flap_Type.PLAIN: + if flap_type is FlapType.PLAIN: outputs["flap_mass"] = c_mass_trend_high_lift * \ (VFLAP/100.)**2*SFLAP*num_flaps**(-.5) / GRAV_ENGLISH_LBM - elif flap_type is Flap_Type.SPLIT: + elif flap_type is FlapType.SPLIT: if VFLAP > 160: outputs["flap_mass"] = c_mass_trend_high_lift*SFLAP * \ (VFLAP**2.195)/45180. / GRAV_ENGLISH_LBM @@ -1649,12 +1649,12 @@ def compute(self, inputs, outputs): 0.369*VFLAP**0.2733 / GRAV_ENGLISH_LBM elif ( - flap_type is Flap_Type.SINGLE_SLOTTED or flap_type is Flap_Type.DOUBLE_SLOTTED - or flap_type is Flap_Type.TRIPLE_SLOTTED + flap_type is FlapType.SINGLE_SLOTTED or flap_type is FlapType.DOUBLE_SLOTTED + or flap_type is FlapType.TRIPLE_SLOTTED ): outputs["flap_mass"] = c_mass_trend_high_lift * \ (VFLAP/100.)**2*SFLAP*num_flaps**.5 / GRAV_ENGLISH_LBM - elif flap_type is Flap_Type.FOWLER or flap_type is Flap_Type.DOUBLE_SLOTTED_FOWLER: + elif flap_type is FlapType.FOWLER or flap_type is FlapType.DOUBLE_SLOTTED_FOWLER: outputs["flap_mass"] = c_mass_trend_high_lift * \ (VFLAP/100.)**2.38*SFLAP**1.19 / \ (num_flaps**.595) / GRAV_ENGLISH_LBM @@ -1762,7 +1762,7 @@ def compute_partials(self, inputs, J): 1.13*(SLE**.13)*dSLE_dBTSR*dBTSR_dCW / GRAV_ENGLISH_LBM # Flap Mass - if flap_type is Flap_Type.PLAIN: + if flap_type is FlapType.PLAIN: # c_wt_trend_high_lift * (VFLAP/100.)**2*SFLAP*num_flaps**(-.5) J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( VFLAP/100)**2 * SFLAP * num_flaps**(-.5) / GRAV_ENGLISH_LBM @@ -1799,7 +1799,7 @@ def compute_partials(self, inputs, J): J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] = c_mass_trend_high_lift * \ (VFLAP/100)**2 * dSFLAP_dBTSR * dBTSR_dCW * \ num_flaps**(-.5) / GRAV_ENGLISH_LBM - elif flap_type is Flap_Type.SPLIT: + elif flap_type is FlapType.SPLIT: if VFLAP > 160: # c_wt_trend_high_lift*SFLAP*(VFLAP**2.195)/45180. J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = SFLAP * \ @@ -1886,8 +1886,8 @@ def compute_partials(self, inputs, J): * VFLAP**0.2733 / GRAV_ENGLISH_LBM) elif ( - flap_type is Flap_Type.SINGLE_SLOTTED or flap_type is Flap_Type.DOUBLE_SLOTTED - or flap_type is Flap_Type.TRIPLE_SLOTTED + flap_type is FlapType.SINGLE_SLOTTED or flap_type is FlapType.DOUBLE_SLOTTED + or flap_type is FlapType.TRIPLE_SLOTTED ): # c_wt_trend_high_lift*(VFLAP/100.)**2*SFLAP*num_flaps**.5 J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( @@ -1923,7 +1923,7 @@ def compute_partials(self, inputs, J): J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] = c_mass_trend_high_lift * \ (VFLAP/100.)**2*dSFLAP_dBTSR*dBTSR_dCW * \ num_flaps**.5 / GRAV_ENGLISH_LBM - elif flap_type is Flap_Type.FOWLER or flap_type is Flap_Type.DOUBLE_SLOTTED_FOWLER: + elif flap_type is FlapType.FOWLER or flap_type is FlapType.DOUBLE_SLOTTED_FOWLER: # c_wt_trend_high_lift * (VFLAP/100.)**2.38*SFLAP**1.19/(num_flaps**.595) J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( VFLAP/100.)**2.38*SFLAP**1.19/(num_flaps**.595) / GRAV_ENGLISH_LBM diff --git a/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py b/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py index 1c41fe540..0762fe771 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py +++ b/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py @@ -8,7 +8,7 @@ EquipAndUsefulLoadMass from aviary.variable_info.options import get_option_defaults from aviary.utils.test_utils.IO_test_util import assert_match_spec, skipIfMissingXDSM -from aviary.variable_info.enums import GASP_Engine_Type +from aviary.variable_info.enums import GASPEngineType from aviary.variable_info.variables import Aircraft, Mission @@ -181,7 +181,7 @@ def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Engine.TYPE, - val=[GASP_Engine_Type.RECIP_CARB], units='unitless') + val=[GASPEngineType.RECIP_CARB], units='unitless') options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') @@ -439,7 +439,7 @@ def setUp(self): options = get_option_defaults() options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=5, units='unitless') options.set_val(Aircraft.Engine.TYPE, - val=[GASP_Engine_Type.RECIP_CARB], units='unitless') + val=[GASPEngineType.RECIP_CARB], units='unitless') options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, diff --git a/aviary/subsystems/mass/mass_builder.py b/aviary/subsystems/mass/mass_builder.py index f491c7231..3574eda1b 100644 --- a/aviary/subsystems/mass/mass_builder.py +++ b/aviary/subsystems/mass/mass_builder.py @@ -12,6 +12,11 @@ from aviary.subsystems.mass.flops_based.mass_premission import MassPremission as MassPremissionFLOPS from aviary.subsystems.mass.gasp_based.mass_premission import MassPremission as MassPremissionGASP from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.enums import LegacyCode + + +GASP = LegacyCode.GASP +FLOPS = LegacyCode.FLOPS _default_name = 'mass' @@ -35,7 +40,7 @@ def __init__(self, name=None, meta_data=None, code_origin=None): if name is None: name = 'core_mass' - if code_origin not in ('FLOPS', 'GASP'): + if code_origin not in (FLOPS, GASP): raise ValueError('Code origin is not one of the following: (FLOPS, GASP)') self.code_origin = code_origin @@ -45,10 +50,10 @@ def __init__(self, name=None, meta_data=None, code_origin=None): def build_pre_mission(self, aviary_inputs): code_origin = self.code_origin - if code_origin == 'GASP': + if code_origin is GASP: mass_premission = MassPremissionGASP(aviary_options=aviary_inputs,) - elif code_origin == 'FLOPS': + elif code_origin is FLOPS: mass_premission = MassPremissionFLOPS(aviary_options=aviary_inputs) return mass_premission diff --git a/aviary/subsystems/propulsion/test/test_custom_engine_model.py b/aviary/subsystems/propulsion/test/test_custom_engine_model.py index 0619d5ff3..7dace05cf 100644 --- a/aviary/subsystems/propulsion/test/test_custom_engine_model.py +++ b/aviary/subsystems/propulsion/test/test_custom_engine_model.py @@ -182,12 +182,11 @@ def test_custom_engine(self): csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - prob = AviaryProblem(phase_info, mission_method="FLOPS", - mass_method="FLOPS", reports=False) + prob = AviaryProblem(reports=False) # Load aircraft and options data from user # Allow for user overrides here - prob.load_inputs(csv_path, engine_builder=SimpleTestEngine()) + prob.load_inputs(csv_path, phase_info, engine_builder=SimpleTestEngine()) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are diff --git a/aviary/subsystems/test/test_external_subsystem_bus.py b/aviary/subsystems/test/test_external_subsystem_bus.py index f8257a1b5..92b8756c0 100644 --- a/aviary/subsystems/test/test_external_subsystem_bus.py +++ b/aviary/subsystems/test/test_external_subsystem_bus.py @@ -11,7 +11,7 @@ from openmdao.utils.assert_utils import assert_near_equal import aviary.api as av -from aviary.interface.default_phase_info.flops import phase_info as ph_in +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase @@ -90,11 +90,11 @@ def test_external_subsystem_bus(self): phase_info['cruise']['external_subsystems'] = [CustomBuilder(name='test')] phase_info['descent']['external_subsystems'] = [CustomBuilder(name='test')] - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_FwFm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) prob.check_inputs() prob.add_pre_mission_systems() diff --git a/aviary/subsystems/test/test_flops_based_premission.py b/aviary/subsystems/test/test_flops_based_premission.py index 43454f1a1..87a2251e1 100644 --- a/aviary/subsystems/test/test_flops_based_premission.py +++ b/aviary/subsystems/test/test_flops_based_premission.py @@ -13,7 +13,7 @@ from aviary.variable_info.variables import Aircraft, Mission from aviary.variable_info.variables_in import VariablesIn from aviary.utils.functions import set_aviary_initial_values -from aviary.interface.default_phase_info.flops import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload diff --git a/aviary/subsystems/test/test_premission.py b/aviary/subsystems/test/test_premission.py index 5f71412cd..8378ffe96 100644 --- a/aviary/subsystems/test/test_premission.py +++ b/aviary/subsystems/test/test_premission.py @@ -1,6 +1,4 @@ -import warnings import unittest -from parameterized import parameterized import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials @@ -10,7 +8,7 @@ from aviary.subsystems.mass.mass_builder import CoreMassBuilder from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.premission import CorePreMission -from aviary.utils.aviary_values import AviaryValues, get_items, get_keys +from aviary.utils.aviary_values import get_items, get_keys from aviary.validation_cases.validation_tests import ( get_flops_case_names, get_flops_inputs, get_flops_outputs ) @@ -19,6 +17,11 @@ from aviary.models.large_single_aisle_1.V3_bug_fixed_IO import V3_bug_fixed_options, V3_bug_fixed_non_metadata from aviary.utils.functions import set_aviary_initial_values from aviary.variable_info.variables_in import VariablesIn +from aviary.variable_info.enums import LegacyCode + + +FLOPS = LegacyCode.FLOPS +GASP = LegacyCode.GASP data_sets = get_flops_case_names() @@ -65,12 +68,12 @@ def setUp(self): input_options.delete(Aircraft.Nacelle.AVG_LENGTH) prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) - mass = CoreMassBuilder('core_mass', BaseMetaData, 'GASP') - aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, 'FLOPS') + mass = CoreMassBuilder('core_mass', BaseMetaData, GASP) + aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) geom = CoreGeometryBuilder('core_geometry', BaseMetaData, use_both_geometries=True, - code_origin_to_prioritize='GASP') + code_origin_to_prioritize=GASP) core_subsystems = [prop, geom, mass, aero] @@ -273,12 +276,12 @@ def test_manual_override(self): model = prob.model prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) - mass = CoreMassBuilder('core_mass', BaseMetaData, 'GASP') - aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, 'FLOPS') + mass = CoreMassBuilder('core_mass', BaseMetaData, GASP) + aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) geom = CoreGeometryBuilder('core_geometry', BaseMetaData, use_both_geometries=True, - code_origin_to_prioritize='FLOPS') + code_origin_to_prioritize=FLOPS) core_subsystems = [prop, geom, mass, aero] diff --git a/aviary/utils/Fortran_to_Aviary.py b/aviary/utils/Fortran_to_Aviary.py index 63a035830..3273f0ee5 100644 --- a/aviary/utils/Fortran_to_Aviary.py +++ b/aviary/utils/Fortran_to_Aviary.py @@ -29,18 +29,11 @@ from aviary.utils.named_values import NamedValues, get_items from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.enums import LegacyCode from aviary.utils.functions import get_path from aviary.utils.legacy_code_data.deprecated_vars import flops_deprecated_vars, gasp_deprecated_vars -class LegacyCode(Enum): - FLOPS = 'FLOPS' - GASP = 'GASP' - - def __str__(self): - return self.value - - FLOPS = LegacyCode.FLOPS GASP = LegacyCode.GASP @@ -114,6 +107,14 @@ def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, writer.writerow(['# Input Values']) for var, (val, units) in sorted(vehicle_data['input_values']): writer.writerow([var] + val + [units]) + if legacy_code is FLOPS: + EOM = 'height_energy' + mass = 'FLOPS' + if legacy_code is GASP: + EOM = '2DOF' + mass = 'GASP' + writer.writerow(['settings:equations_of_motion'] + [EOM]) + writer.writerow(['settings:mass_method'] + [mass]) if legacy_code is GASP: # Values used in initial guessing of the trajectory @@ -313,10 +314,12 @@ def generate_aviary_names(code_bases): for code_base in code_bases: alternate_names[code_base] = {} for key in _MetaData.keys(): - alt_name = _MetaData[key]['historical_name'][code_base] - if isinstance(alt_name, str): - alt_name = [alt_name] - alternate_names[code_base][key] = alt_name + historical_dict = _MetaData[key]['historical_name'] + if historical_dict and code_base in historical_dict: + alt_name = _MetaData[key]['historical_name'][code_base] + if isinstance(alt_name, str): + alt_name = [alt_name] + alternate_names[code_base][key] = alt_name return alternate_names diff --git a/aviary/utils/aviary_values.py b/aviary/utils/aviary_values.py index 3f5a97004..6357cd79b 100644 --- a/aviary/utils/aviary_values.py +++ b/aviary/utils/aviary_values.py @@ -123,6 +123,11 @@ def _is_iterable(self, val): def _convert_to_enum(self, val, enum_type): if isinstance(val, str): - return enum_type[val.upper()] + try: + # see if str maps to ENUM value + return enum_type(val) + except ValueError: + # str instead maps to ENUM name + return enum_type[val.upper()] else: return enum_type(val) diff --git a/aviary/utils/functions.py b/aviary/utils/functions.py index b78868935..4b5292455 100644 --- a/aviary/utils/functions.py +++ b/aviary/utils/functions.py @@ -6,13 +6,10 @@ import os from aviary.utils.aviary_values import AviaryValues, get_keys -from aviary.variable_info.enums import ProblemType +from aviary.variable_info.enums import ProblemType, EquationsOfMotion, LegacyCode from aviary.variable_info.functions import add_aviary_output, add_aviary_input from aviary.variable_info.variable_meta_data import _MetaData -problem_types = {'sizing': ProblemType.SIZING, - 'alternate': ProblemType.ALTERNATE, 'fallout': ProblemType.FALLOUT} - class Null: ''' @@ -111,8 +108,13 @@ def set_value(var_name, var_value, aviary_values: AviaryValues, units=None, is_a # if only a single value is provided, don't store it as a list var_value = var_value[0] + # TODO handle enums in an automated method via checking metadata for enum type if var_name == 'problem_type': - var_values = problem_types[var_values] + var_values = ProblemType[var_value] + if var_name == 'settings:equations_of_motion': + var_values = EquationsOfMotion(var_value) + if var_name == 'settings:mass_method': + var_values = LegacyCode(var_value) aviary_values.set_val(var_name, val=var_value, units=units, meta_data=meta_data) return aviary_values diff --git a/aviary/utils/test/test_aviary_values.py b/aviary/utils/test/test_aviary_values.py index 923b82741..1694f5202 100644 --- a/aviary/utils/test/test_aviary_values.py +++ b/aviary/utils/test/test_aviary_values.py @@ -7,7 +7,7 @@ from aviary.examples.variables_extension import Aircraft as ExtendedAircraft from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import get_path -from aviary.variable_info.enums import Flap_Type, GASP_Engine_Type +from aviary.variable_info.enums import FlapType, GASPEngineType from aviary.variable_info.variables import Aircraft, Mission @@ -78,38 +78,38 @@ def test_aircraft(self): self.fail('Expecting TypeError.') try: - vals.set_val(Aircraft.Engine.TYPE, GASP_Engine_Type.TURBOJET) + vals.set_val(Aircraft.Engine.TYPE, GASPEngineType.TURBOJET) self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASP_Engine_Type.TURBOJET) + is GASPEngineType.TURBOJET) except: self.fail('Expecting to be able to set the value of an Enum.') try: vals.set_val(Aircraft.Engine.TYPE, 'turbojet') self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASP_Engine_Type.TURBOJET) + is GASPEngineType.TURBOJET) except: self.fail('Expecting to be able to set the value of an Enum from a string.') try: vals.set_val(Aircraft.Engine.TYPE, 'TURBOJET') self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASP_Engine_Type.TURBOJET) + is GASPEngineType.TURBOJET) except: self.fail('Expecting to be able to set the value of an Enum from a string.') try: vals.set_val(Aircraft.Engine.TYPE, 7) self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASP_Engine_Type.TURBOJET) + is GASPEngineType.TURBOJET) except: self.fail('Expecting to be able to set the value of an Enum from an int.') try: - vals.set_val(Aircraft.Engine.TYPE, Flap_Type.DOUBLE_SLOTTED) + vals.set_val(Aircraft.Engine.TYPE, FlapType.DOUBLE_SLOTTED) except ValueError as err: self.assertEqual(str(err), - " is not a valid GASP_Engine_Type") + " is not a valid GASPEngineType") else: self.fail("Expecting ValueError.") diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 0cfcbf173..eaf0fcf0c 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -4,20 +4,19 @@ from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.interface.default_phase_info.gasp import phase_info as gasp_phase_info -from aviary.interface.default_phase_info.flops import phase_info as flops_phase_info +from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info +from aviary.interface.default_phase_info.height_energy import phase_info as height_energy_phase_info from aviary.interface.default_phase_info.solved import phase_info as solved_phase_info +from aviary.variable_info.enums import EquationsOfMotion class BaseProblemPhaseTestCase(unittest.TestCase): - def build_and_run_problem(self, phase_info, mission_method, mass_method, input_filename, - objective_type=None): + def build_and_run_problem(self, input_filename, phase_info, objective_type=None): # Build problem - prob = AviaryProblem( - phase_info, mission_method=mission_method, mass_method=mass_method) + prob = AviaryProblem() - prob.load_inputs(input_filename) + prob.load_inputs(input_filename, phase_info) prob.check_inputs() prob.add_pre_mission_systems() @@ -33,23 +32,23 @@ def build_and_run_problem(self, phase_info, mission_method, mass_method, input_f @use_tempdirs -class GASPZeroItersTestCase(BaseProblemPhaseTestCase): +class TwoDOFZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_gasp_zero_iters(self): - local_phase_info = deepcopy(gasp_phase_info) - self.build_and_run_problem(local_phase_info, "GASP", - "GASP", 'models/test_aircraft/aircraft_for_bench_GwGm.csv') + local_phase_info = deepcopy(two_dof_phase_info) + self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_GwGm.csv', + local_phase_info) @use_tempdirs -class FLOPSZeroItersTestCase(BaseProblemPhaseTestCase): +class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") - def test_flops_zero_iters(self): - local_phase_info = deepcopy(flops_phase_info) - self.build_and_run_problem(local_phase_info, "FLOPS", - "FLOPS", 'models/test_aircraft/aircraft_for_bench_FwFm.csv') + def test_height_energy_zero_iters(self): + local_phase_info = deepcopy(height_energy_phase_info) + self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_FwFm.csv', + local_phase_info) @use_tempdirs @@ -59,12 +58,11 @@ class SolvedProblemTestCase(BaseProblemPhaseTestCase): def test_zero_iters_solved(self): # Modify Aviary inputs before running the common operations local_phase_info = deepcopy(solved_phase_info) - self.build_and_run_problem(local_phase_info, "solved", - "GASP", 'models/test_aircraft/aircraft_for_bench_GwGm.csv', - objective_type="hybrid_objective") + self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_GwGm_solved.csv', + local_phase_info, objective_type="hybrid_objective") if __name__ == "__main__": # unittest.main() - test = FLOPSZeroItersTestCase() - test.test_flops_zero_iters() + test = SolvedProblemTestCase() + test.test_zero_iters_solved() diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py index 57d05bcbe..aff3bb72c 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py @@ -20,7 +20,7 @@ inputs as _inputs from aviary.variable_info.variables import Dynamic as _Dynamic from aviary.variable_info.variables_in import VariablesIn -from aviary.interface.default_phase_info.flops import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.subsystems.premission import CorePreMission Dynamic = _Dynamic.Mission diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py index 090a26b9f..7041b7cb8 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py @@ -31,7 +31,7 @@ from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.variables_in import VariablesIn from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.utils.aviary_values import AviaryValues diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py index 44bf01c3f..55bfd2fbd 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py @@ -31,7 +31,7 @@ from aviary.utils.preprocessors import preprocess_options from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.variables_in import VariablesIn -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems try: import pyoptsparse diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py index 124c64e5b..7a8c71ba1 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py @@ -29,7 +29,7 @@ from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.variables_in import VariablesIn from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems from aviary.utils.preprocessors import preprocess_options try: diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index 69600d000..ef2a355a1 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -29,7 +29,7 @@ from aviary.variable_info.variables import Aircraft, Mission from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload try: diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py index 7ac6494da..512b710d8 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py @@ -18,7 +18,7 @@ landing_fullstop_user_options as _landing_fullstop_user_options) from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.interface.default_phase_info.flops import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py index 354ed2b2e..bc403ccbf 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py @@ -18,7 +18,7 @@ takeoff_liftoff_user_options as _takeoff_liftoff_user_options) from aviary.variable_info.variables import Aircraft, Dynamic as _Dynamic -from aviary.interface.default_phase_info.flops import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 3d623bfb3..ef9c25759 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -5,7 +5,7 @@ import numpy as np from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.flops import phase_info +from aviary.interface.default_phase_info.height_energy import phase_info from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values @@ -16,8 +16,7 @@ class ProblemPhaseTestCase(unittest.TestCase): def bench_test_swap_4_FwFm(self): local_phase_info = deepcopy(phase_info) prob = run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', - local_phase_info, - mission_method="FLOPS", mass_method="FLOPS") + local_phase_info) expected_dict = {} diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py index 72ed35f6a..29dacddbf 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py @@ -5,7 +5,7 @@ from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.interface.default_phase_info.gasp import phase_info +from aviary.interface.default_phase_info.two_dof import phase_info from aviary.interface.methods_for_level1 import run_aviary from aviary.variable_info.variables import Aircraft, Mission @@ -17,8 +17,7 @@ class ProblemPhaseTestCase(unittest.TestCase): def bench_test_swap_3_FwGm(self): local_phase_info = deepcopy(phase_info) prob = run_aviary('models/test_aircraft/aircraft_for_bench_FwGm.csv', - local_phase_info, - mission_method="GASP", mass_method="FLOPS") + local_phase_info) rtol = 1e-2 diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 9dff40469..a6748628f 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -12,7 +12,7 @@ import numpy as np from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.flops import phase_info +from aviary.interface.default_phase_info.height_energy import phase_info from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values @@ -23,8 +23,7 @@ class ProblemPhaseTestCase(unittest.TestCase): def bench_test_swap_1_GwFm(self): local_phase_info = deepcopy(phase_info) prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', - local_phase_info, - mission_method="FLOPS", mass_method="GASP") + local_phase_info) expected_dict = {} expected_dict['times'] = np.array([[120.], diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index 98058f548..d87013d8d 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -5,7 +5,7 @@ from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.interface.default_phase_info.gasp import phase_info +from aviary.interface.default_phase_info.two_dof import phase_info from aviary.interface.methods_for_level1 import run_aviary from aviary.variable_info.variables import Aircraft, Mission @@ -17,8 +17,7 @@ class ProblemPhaseTestCase(unittest.TestCase): def bench_test_swap_2_GwGm(self): local_phase_info = deepcopy(phase_info) prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwGm.csv', - local_phase_info, - mission_method="GASP", mass_method="GASP") + local_phase_info) rtol = 0.01 diff --git a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py index 3cdf771e0..a479d8077 100644 --- a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py +++ b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py @@ -9,6 +9,7 @@ from aviary.api import Mission from aviary.interface.default_phase_info.solved import phase_info from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.variable_info.enums import EquationsOfMotion @unittest.skipIf(version.parse(dymos.__version__) <= version.parse("1.8.0"), @@ -19,12 +20,10 @@ class ProblemPhaseTestCase(unittest.TestCase): def bench_test_solved_full_mission(self): # Build problem local_phase_info = deepcopy(phase_info) - prob = AviaryProblem(local_phase_info, mission_method="solved", - mass_method="GASP", reports='subsystems') - - input_file = 'models/test_aircraft/aircraft_for_bench_GwGm.csv' - prob.load_inputs(input_file) + prob = AviaryProblem() + input_file = 'models/test_aircraft/aircraft_for_bench_GwGm_solved.csv' + prob.load_inputs(input_file, local_phase_info) prob.aviary_inputs.set_val(Mission.Design.RANGE, 2000.0, units="NM") # Have checks for clashing user inputs diff --git a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py index 795424041..d6c841e19 100644 --- a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py @@ -67,13 +67,12 @@ def setUp(self): def test_subsystems_in_a_mission(self): phase_info = self.phase_info.copy() - prob = AviaryProblem( - phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem() csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are @@ -118,13 +117,12 @@ def test_bad_initial_guess_key(self): phase_info = self.phase_info.copy() phase_info['cruise']['initial_guesses']['bad_guess_name'] = ([10., 100.], 'm') - prob = AviaryProblem(phase_info, mission_method="FLOPS", - mass_method="FLOPS", reports=False) + prob = AviaryProblem(reports=False) csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - prob.load_inputs(csv_path) + prob.load_inputs(csv_path, phase_info) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index 912283e50..949253944 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -53,131 +53,131 @@ class AnalysisScheme(Enum): SHOOTING = auto() -class ProblemType(Enum): +class EquationsOfMotion(Enum): """ - ProblemType is used to switch between different combinations of - design variables and constraints. - - SIZING: Varies the design gross weight and actual gross weight to - close to design range. This causes the empty weight and the fuel - weight to change. - - ALTERNATE: Requires a pre-sized aircraft. It holds the design gross - weight and empty weight constant. It then varies the fuel weight - and actual gross weight until the range closes to the off-design - range. - - FALLOUT: Requires a pre-sized aircraft. It holds the design gross - weight and empty weight constant. Using the specified actual - gross weight, it will then find the maximum distance the off-design - aircraft can fly. + Available equations of motion for use during mission analysis """ - SIZING = auto() - ALTERNATE = auto() - FALLOUT = auto() - - -class SpeedType(Enum): - ''' - SpeedType is used to specify the type of speed being used. - EAS is equivalent airspeed. - TAS is true airspeed. - MACH is mach - ''' - EAS = auto() - TAS = auto() - MACH = auto() + HEIGHT_ENERGY = 'height_energy' + TWO_DEGREES_OF_FREEDOM = '2DOF' + # TODO these are a little out of place atm + SIMPLE = 'simple' + SOLVED = 'solved' @unique -class GASP_Engine_Type(Enum): +class GASPEngineType(Enum): """ Defines the type of engine to use in GASP-based mass calculations. Note that only the value for the first engine model will be used. Currenly only the TURBOJET option is implemented, but other types of engines will be added in the future. """ - + # Reciprocating engine with carburator RECIP_CARB = 1 - """ - Reciprocating engine with carburator - """ + + # Reciprocating engine with fuel injection RECIP_FUEL_INJECT = 2 - """ - Reciprocating engine with fuel injection - """ + + # Reciprocating engine with fuel injection and geared RECIP_FUEL_INJECT_GEARED = 3 - """ - Reciprocating engine with fuel injection and geared - """ + + # Rotary-combustion engine ROTARY = 4 - """ - Rotary-combustion engine - """ + + # Turboshaft engine TURBOSHAFT = 5 - """ - Turboshaft engine - """ + + # Turboprop engine TURBOPROP = 6 - """ - Turboprop engine - """ + + # Turbojet or turbofan engine TURBOJET = 7 - """ - Turbojet or turbofan engine - """ + + # Reciprocating engine with carburator; use HOPWSZ (horizontally-opposed piston + # weight and size) methodology for geometry and mass RECIP_CARB_HOPWSZ = 11 - """ - Reciprocating engine with carburator; use HOPWSZ (horizontally-opposed piston weight and size) - methodology for geometry and mass - """ + + # Reciprocating engine with fuel injection; use HOPWSZ (horizontally-opposed piston + # weight and size) methodology for geometry and mass RECIP_FUEL_INJECT_HOPWSZ = 12 - """ - Reciprocating engine with fuel injection; use HOPWSZ (horizontally-opposed piston weight and size) - methodology for geometry and mass - """ + + # Reciprocating engine with fuel injection and geared; use HOPWSZ (horizontally- + # opposed piston weight and size) methodology for geometry and mass RECIP_FUEL_INJECT_GEARED_HOPWSZ = 13 - """ - Reciprocating engine with fuel injection and geared; use HOPWSZ (horizontally-opposed piston weight and size) - methodology for geometry and mass - """ + + # Rotary-combustion engine; use RCWSZ (rotary combustion weight and size) methodology + # for geometry and mass ROTARY_RCWSZ = 14 - """ - Rotary-combustion engine; use RCWSZ (rotary combustion weight and size) - methodology for geometry and mass - """ @unique -class Flap_Type(Enum): +class FlapType(Enum): """ Defines the type of flap used on the wing. Used in GASP-based aerodynamics and mass calculations. """ - PLAIN = 1 - """ - Plain flaps - """ SPLIT = 2 - """ - Split flaps - """ SINGLE_SLOTTED = 3 - """ - Single-slotted flaps - """ DOUBLE_SLOTTED = 4 - """ - Double-slotted flaps - """ TRIPLE_SLOTTED = 5 + FOWLER = 6 + DOUBLE_SLOTTED_FOWLER = 7 + + +class LegacyCode(Enum): """ - Triple-slotted flaps + Flag for legacy codebases """ - FOWLER = 6 + FLOPS = 'FLOPS' + GASP = 'GASP' + + def __str__(self): + return self.value + + +class ProblemType(Enum): """ - Fowler flaps + ProblemType is used to switch between different combinations of + design variables and constraints. + + SIZING: Varies the design gross weight and actual gross weight to + close to design range. This causes the empty weight and the fuel + weight to change. + + ALTERNATE: Requires a pre-sized aircraft. It holds the design gross + weight and empty weight constant. It then varies the fuel weight + and actual gross weight until the range closes to the off-design + range. + + FALLOUT: Requires a pre-sized aircraft. It holds the design gross + weight and empty weight constant. Using the specified actual + gross weight, it will then find the maximum distance the off-design + aircraft can fly. """ - DOUBLE_SLOTTED_FOWLER = 7 + SIZING = 'sizing' + ALTERNATE = 'alternate' + FALLOUT = 'fallout' + + +class SpeedType(Enum): + ''' + SpeedType is used to specify the type of speed being used. + EAS is equivalent airspeed. + TAS is true airspeed. + MACH is mach + ''' + EAS = auto() + TAS = auto() + MACH = auto() + + +class Verbosity(Enum): """ - Double-slotted Fowler flaps + Sets how much information Aviary outputs when run + + Verbosity levels are based on ubuntu's standard: + https://discourse.ubuntu.com/t/cli-verbosity-levels/26973 """ + QUIET = 0 + BRIEF = 1 + VERBOSE = 2 + DEBUG = 3 diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index bd44af54c..94d66ccdc 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -4,11 +4,9 @@ from copy import deepcopy from pathlib import Path -import numpy as np - from aviary.utils.develop_metadata import add_meta_data -from aviary.variable_info.enums import Flap_Type, GASP_Engine_Type -from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.variable_info.enums import EquationsOfMotion, FlapType, GASPEngineType, LegacyCode, Verbosity +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings # --------------------------- # Meta data associated with variables in the aircraft data hierarchy. @@ -2038,8 +2036,8 @@ "LEAPS1": None }, option=True, - default_value=GASP_Engine_Type.TURBOJET, - types=GASP_Engine_Type, + default_value=GASPEngineType.TURBOJET, + types=GASPEngineType, units="unitless", desc='specifies engine type used for engine mass calculation', ) @@ -4886,8 +4884,8 @@ "LEAPS1": None }, units="unitless", - default_value=Flap_Type.DOUBLE_SLOTTED, - types=Flap_Type, + default_value=FlapType.DOUBLE_SLOTTED, + types=FlapType, option=True, desc='Set the flap type. Available choices are: plain, split, single_slotted, ' 'double_slotted, triple_slotted, fowler, and double_slotted_fowler. ' @@ -7287,6 +7285,60 @@ default_value=0.0001, ) +# .----------------. .----------------. .----------------. .----------------. .----------------. .-----------------. .----------------. .----------------. +# | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | +# | | _______ | || | _________ | || | _________ | || | _________ | || | _____ | || | ____ _____ | || | ______ | || | _______ | | +# | | / ___ | | || | |_ ___ | | || | | _ _ | | || | | _ _ | | || | |_ _| | || ||_ \|_ _| | || | .' ___ | | || | / ___ | | | +# | | | (__ \_| | || | | |_ \_| | || | |_/ | | \_| | || | |_/ | | \_| | || | | | | || | | \ | | | || | / .' \_| | || | | (__ \_| | | +# | | '.___`-. | || | | _| _ | || | | | | || | | | | || | | | | || | | |\ \| | | || | | | ____ | || | '.___`-. | | +# | | |`\____) | | || | _| |___/ | | || | _| |_ | || | _| |_ | || | _| |_ | || | _| |_\ |_ | || | \ `.___] _| | || | |`\____) | | | +# | | |_______.' | || | |_________| | || | |_____| | || | |_____| | || | |_____| | || ||_____|\____| | || | `._____.' | || | |_______.' | | +# | | | || | | || | | || | | || | | || | | || | | || | | | +# | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | +# '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' + +add_meta_data( + Settings.EQUATIONS_OF_MOTION, + meta_data=_MetaData, + historical_name={"GASP": None, + "FLOPS": None, + "LEAPS1": None + }, + desc='Sets which equations of motion Aviary will use in mission analysis', + option=True, + types=EquationsOfMotion, + default_value=None, +) + +add_meta_data( + Settings.MASS_METHOD, + meta_data=_MetaData, + historical_name={"GASP": None, + "FLOPS": None, + "LEAPS1": None + }, + desc="Sets which legacy code's methods will be used for mass estimation", + option=True, + types=LegacyCode, + default_value=None +) + +add_meta_data( + Settings.VERBOSITY, + meta_data=_MetaData, + historical_name={"GASP": None, + "FLOPS": None, + "LEAPS1": None + }, + desc='Sets how much information Aviary outputs when run. Options include:' + '0. QUIET: All output except errors are suppressed' + '1. BRIEF: Only important information is output, in human-readable format' + '2. VERBOSE: All avaliable informating is output, in human-readable format' + '3. DEBUG: Intermediate status and calculation outputs, no formatting requirement', + option=True, + types=Verbosity, + default_value=Verbosity.BRIEF +) # here we create a copy of the Aviary-core metadata. The reason for this copy is that if we simply imported the Aviary _MetaData in all the external subsystem extensions, we would be modifying the original and the original _MetaData in the core of Aviary could get altered in undesirable ways. By importing this copy to the API the user modifies a new MetaData designed just for their purposes. CoreMetaData = deepcopy(_MetaData) diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index 51d5df4c6..a64d774f4 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -730,3 +730,9 @@ class Takeoff: class Taxi: DURATION = 'mission:taxi:duration' MACH = 'mission:taxi:mach' + + +class Settings: + EQUATIONS_OF_MOTION = 'settings:equations_of_motion' + MASS_METHOD = 'settings:mass_method' + VERBOSITY = 'settings:verbosity'