FAST-PEDAGO 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fast_pedago-1.1.0/PKG-INFO +68 -0
- fast_pedago-1.1.0/README.md +30 -0
- fast_pedago-1.1.0/fast_pedago/__init__.py +0 -0
- fast_pedago-1.1.0/fast_pedago/app.py +122 -0
- fast_pedago-1.1.0/fast_pedago/configuration/__init__.py +0 -0
- fast_pedago-1.1.0/fast_pedago/configuration/oad_optim_sensitivity_analysis.yml +63 -0
- fast_pedago-1.1.0/fast_pedago/configuration/oad_sizing_sensitivity_analysis.yml +61 -0
- fast_pedago-1.1.0/fast_pedago/gui/__init__.py +3 -0
- fast_pedago-1.1.0/fast_pedago/gui/app_interface.py +345 -0
- fast_pedago-1.1.0/fast_pedago/gui/components/__init__.py +33 -0
- fast_pedago-1.1.0/fast_pedago/gui/components/app_layout.py +275 -0
- fast_pedago-1.1.0/fast_pedago/gui/components/input_widgets.py +508 -0
- fast_pedago-1.1.0/fast_pedago/gui/components/inputs_container.py +612 -0
- fast_pedago-1.1.0/fast_pedago/gui/components/output_figures_container.py +159 -0
- fast_pedago-1.1.0/fast_pedago/gui/components/process_figures_container.py +209 -0
- fast_pedago-1.1.0/fast_pedago/gui/components/tutorial_container.py +324 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/__init__.py +3 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/background.jpg +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/logo_airbus.png +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/logo_fast_oad_main_menu.jpg +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/logo_fast_oad_top_layer.jpg +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/logo_supaero.png +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/tutorial/MDA.png +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/tutorial/__init__.py +3 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/tutorial/inputs.gif +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/tutorial/launch.gif +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/tutorial/n2.gif +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/tutorial/outputs.gif +0 -0
- fast_pedago-1.1.0/fast_pedago/gui/resources/tutorial/text.py +93 -0
- fast_pedago-1.1.0/fast_pedago/notebook/FAST_OAD_app.ipynb +37 -0
- fast_pedago-1.1.0/fast_pedago/notebook/__init__.py +0 -0
- fast_pedago-1.1.0/fast_pedago/notebook/data/__init__.py +0 -0
- fast_pedago-1.1.0/fast_pedago/notebook/data/n2.html +14769 -0
- fast_pedago-1.1.0/fast_pedago/notebook/data/n2.png +0 -0
- fast_pedago-1.1.0/fast_pedago/notebook/data/oad_optim_sensitivity_analysis.yml +63 -0
- fast_pedago-1.1.0/fast_pedago/notebook/data/oad_sizing_sensitivity_analysis.yml +61 -0
- fast_pedago-1.1.0/fast_pedago/notebook/data/xdsm.html +407 -0
- fast_pedago-1.1.0/fast_pedago/notebook/data/xdsm.png +0 -0
- fast_pedago-1.1.0/fast_pedago/notebook/workdir/inputs/reference_aircraft_input_file.xml +553 -0
- fast_pedago-1.1.0/fast_pedago/notebook/workdir/outputs/reference_aircraft_cases.sql +0 -0
- fast_pedago-1.1.0/fast_pedago/notebook/workdir/outputs/reference_aircraft_flight_points.csv +14 -0
- fast_pedago-1.1.0/fast_pedago/notebook/workdir/outputs/reference_aircraft_output_file.xml +1096 -0
- fast_pedago-1.1.0/fast_pedago/plots/__init__.py +44 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/__init__.py +27 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/aircraft_front_view.py +354 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/aircraft_side_view.py +401 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/aircraft_top_view.py +511 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/better_mission_viewer.py +52 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/flaps_and_slats.py +304 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/objectives_viewer.py +104 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/polar_with_lift_to_drag_ratio.py +91 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/residuals_viewer.py +98 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/simplified_payload_range.py +149 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/stability_diagram.py +260 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/static_margin.py +175 -0
- fast_pedago-1.1.0/fast_pedago/plots/functions/wing.py +716 -0
- fast_pedago-1.1.0/fast_pedago/plots/output_graphs_plotter.py +302 -0
- fast_pedago-1.1.0/fast_pedago/plots/plot_constants.py +42 -0
- fast_pedago-1.1.0/fast_pedago/plots/plot_signatures.py +180 -0
- fast_pedago-1.1.0/fast_pedago/processes/__init__.py +3 -0
- fast_pedago-1.1.0/fast_pedago/processes/process_launcher.py +415 -0
- fast_pedago-1.1.0/fast_pedago/source_data_files/A321_like_source_data_file.xml +554 -0
- fast_pedago-1.1.0/fast_pedago/source_data_files/A350_like_source_data_file.xml +553 -0
- fast_pedago-1.1.0/fast_pedago/source_data_files/CeRAS01_source_data_file.xml +1023 -0
- fast_pedago-1.1.0/fast_pedago/source_data_files/__init__.py +0 -0
- fast_pedago-1.1.0/fast_pedago/source_data_files/reference_aircraft_source_data_file.xml +552 -0
- fast_pedago-1.1.0/fast_pedago/utils/__init__.py +53 -0
- fast_pedago-1.1.0/fast_pedago/utils/functions.py +66 -0
- fast_pedago-1.1.0/fast_pedago/utils/path_manager.py +274 -0
- fast_pedago-1.1.0/fast_pedago/utils/paths.py +36 -0
- fast_pedago-1.1.0/pyproject.toml +101 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: FAST-PEDAGO
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Lightweight interface to perform simplified OAD analysis using FAST-OAD
|
|
5
|
+
License-Expression: GPL-3.0-only
|
|
6
|
+
Keywords: aircraft,design,multi-disciplinary,teaching,educational
|
|
7
|
+
Author: Ousmane SY
|
|
8
|
+
Author-email: Ousmane.SY@isae-supaero.fr
|
|
9
|
+
Maintainer: Florent LUTZ
|
|
10
|
+
Maintainer-email: Florent.LUTZ2@isae-supaero.fr
|
|
11
|
+
Requires-Python: >=3.10,<3.15
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
17
|
+
Classifier: Natural Language :: English
|
|
18
|
+
Classifier: Operating System :: MacOS
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
27
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
28
|
+
Requires-Dist: appmode (>=0.9.0)
|
|
29
|
+
Requires-Dist: click (>=8.0.3)
|
|
30
|
+
Requires-Dist: fast-oad-core (>=1.10.0)
|
|
31
|
+
Requires-Dist: fast-oad-cs25 (>=0.9.1)
|
|
32
|
+
Requires-Dist: ipyvuetify (>=3.0.0)
|
|
33
|
+
Requires-Dist: ipywidgets (>=7.7.2)
|
|
34
|
+
Requires-Dist: lxml_html_clean
|
|
35
|
+
Requires-Dist: voila (>=0.3.7)
|
|
36
|
+
Project-URL: Homepage, https://github.com/supaero-aircraft-design/FAST-PEDAGO
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# FAST-OAD TRAINING AND INCREMENTAL DEVELOPMENT BRANCH
|
|
40
|
+
|
|
41
|
+
[](https://mybinder.org/v2/gh/supaero-aircraft-design/FAST-PEDAGO/HEAD?labpath=fast_pedago%2Fnotebook%2FFAST_OAD_app.ipynb)
|
|
42
|
+
|
|
43
|
+
This package offers a lightweight interface to perform simplified OAD analysis using FAST-OAD (https://github.com/fast-aircraft-design/FAST-OAD).
|
|
44
|
+
|
|
45
|
+
Want to try quickly ?
|
|
46
|
+
-------
|
|
47
|
+
|
|
48
|
+
You can open the app on a [Binder-hosted Jupyter notebook](https://mybinder.org/v2/gh/supaero-aircraft-design/FAST-PEDAGO/HEAD?labpath=fast_pedago%2Fnotebook%2FFAST_OAD_app.ipynb)
|
|
49
|
+
|
|
50
|
+
Install
|
|
51
|
+
-------
|
|
52
|
+
|
|
53
|
+
**Prerequisite**: FAST-PEDAGO needs at least **Python 3.7.0**.
|
|
54
|
+
|
|
55
|
+
It is recommended (but not required) to install FAST-PEDAGO in a virtual
|
|
56
|
+
environment ([conda](https://docs.conda.io/en/latest/),
|
|
57
|
+
[venv](https://docs.python.org/3.7/library/venv.html), ...).
|
|
58
|
+
|
|
59
|
+
Once Python is installed, FAST-PEDAGO can be installed using pip, by doing the following:
|
|
60
|
+
|
|
61
|
+
``` {.bash}
|
|
62
|
+
$ pip install fast-pedago
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Once installed the cde can be run by doing the following:
|
|
66
|
+
``` {.bash}
|
|
67
|
+
$ fast-pedago run
|
|
68
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# FAST-OAD TRAINING AND INCREMENTAL DEVELOPMENT BRANCH
|
|
2
|
+
|
|
3
|
+
[](https://mybinder.org/v2/gh/supaero-aircraft-design/FAST-PEDAGO/HEAD?labpath=fast_pedago%2Fnotebook%2FFAST_OAD_app.ipynb)
|
|
4
|
+
|
|
5
|
+
This package offers a lightweight interface to perform simplified OAD analysis using FAST-OAD (https://github.com/fast-aircraft-design/FAST-OAD).
|
|
6
|
+
|
|
7
|
+
Want to try quickly ?
|
|
8
|
+
-------
|
|
9
|
+
|
|
10
|
+
You can open the app on a [Binder-hosted Jupyter notebook](https://mybinder.org/v2/gh/supaero-aircraft-design/FAST-PEDAGO/HEAD?labpath=fast_pedago%2Fnotebook%2FFAST_OAD_app.ipynb)
|
|
11
|
+
|
|
12
|
+
Install
|
|
13
|
+
-------
|
|
14
|
+
|
|
15
|
+
**Prerequisite**: FAST-PEDAGO needs at least **Python 3.7.0**.
|
|
16
|
+
|
|
17
|
+
It is recommended (but not required) to install FAST-PEDAGO in a virtual
|
|
18
|
+
environment ([conda](https://docs.conda.io/en/latest/),
|
|
19
|
+
[venv](https://docs.python.org/3.7/library/venv.html), ...).
|
|
20
|
+
|
|
21
|
+
Once Python is installed, FAST-PEDAGO can be installed using pip, by doing the following:
|
|
22
|
+
|
|
23
|
+
``` {.bash}
|
|
24
|
+
$ pip install fast-pedago
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Once installed the cde can be run by doing the following:
|
|
28
|
+
``` {.bash}
|
|
29
|
+
$ fast-pedago run
|
|
30
|
+
```
|
|
File without changes
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import sys
|
|
5
|
+
from argparse import (
|
|
6
|
+
ArgumentDefaultsHelpFormatter,
|
|
7
|
+
ArgumentParser,
|
|
8
|
+
RawDescriptionHelpFormatter,
|
|
9
|
+
)
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
MAIN_NOTEBOOK_NAME = "FAST_OAD_app.ipynb"
|
|
13
|
+
MAIN_NOTEBOOK_PATH = Path(__file__).parent / "notebook" / MAIN_NOTEBOOK_NAME
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Main:
|
|
17
|
+
"""
|
|
18
|
+
Class for managing command line and doing associated actions
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
class _CustomFormatter(RawDescriptionHelpFormatter, ArgumentDefaultsHelpFormatter):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
self.parser = ArgumentParser(
|
|
26
|
+
description="FAST pedagogical branch main program",
|
|
27
|
+
formatter_class=_CustomFormatter,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def _run(args):
|
|
32
|
+
"""Run FAST pedagogical branch locally or with server configuration."""
|
|
33
|
+
machine = "server" if args.server else "local"
|
|
34
|
+
print(MAIN_NOTEBOOK_PATH)
|
|
35
|
+
if machine == "server":
|
|
36
|
+
command = (
|
|
37
|
+
"voila "
|
|
38
|
+
"--port=8080 "
|
|
39
|
+
"--no-browser "
|
|
40
|
+
"--MappingKernelManager.cull_idle_timeout=7200 "
|
|
41
|
+
r"""--VoilaConfiguration.file_whitelist="['.*\."""
|
|
42
|
+
"""(png|jpg|gif|xlsx|ico|pdf|json)']" """
|
|
43
|
+
)
|
|
44
|
+
else:
|
|
45
|
+
command = (
|
|
46
|
+
"voila "
|
|
47
|
+
r"""--VoilaConfiguration.file_whitelist="['.*\."""
|
|
48
|
+
"""s(png|jpg|gif|xlsx|ico|pdf|json)']" """
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# To not get an ugly error message when you ctrl+c
|
|
52
|
+
try:
|
|
53
|
+
os.system(command + str(MAIN_NOTEBOOK_PATH)) # noqa: S605 this is a literal string, it can be considered safe.
|
|
54
|
+
except KeyboardInterrupt:
|
|
55
|
+
sys.exit()
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def _copy_notebook(args):
|
|
59
|
+
# Should be a pathlib Path already
|
|
60
|
+
requested_destination = args.destination
|
|
61
|
+
if requested_destination.exists() and not requested_destination.is_dir():
|
|
62
|
+
print("Input path should be the path to a directory. Exiting")
|
|
63
|
+
raise SystemExit(1)
|
|
64
|
+
|
|
65
|
+
requested_destination.mkdir(parents=True, exist_ok=True)
|
|
66
|
+
|
|
67
|
+
shutil.copy(MAIN_NOTEBOOK_PATH, args.destination)
|
|
68
|
+
print("You may now run Jupyter with:")
|
|
69
|
+
print(f' jupyter lab "{MAIN_NOTEBOOK_NAME}"')
|
|
70
|
+
return 0
|
|
71
|
+
|
|
72
|
+
# ENTRY POINT ============================================================
|
|
73
|
+
def run(self):
|
|
74
|
+
"""Main function."""
|
|
75
|
+
subparsers = self.parser.add_subparsers(title="sub-commands")
|
|
76
|
+
|
|
77
|
+
# sub-command for running FAST-PEDAGO -----------------------------------
|
|
78
|
+
parser_run = subparsers.add_parser(
|
|
79
|
+
"run",
|
|
80
|
+
help="run FAST-OAD pedagogical branch",
|
|
81
|
+
description="run FAST-OAD pedagogical branch",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
parser_run.add_argument(
|
|
85
|
+
"--server",
|
|
86
|
+
action="store_true",
|
|
87
|
+
help="to be used if ran on server",
|
|
88
|
+
)
|
|
89
|
+
parser_run.set_defaults(func=self._run)
|
|
90
|
+
|
|
91
|
+
# subcommand for copying the notebook ----------------------------------
|
|
92
|
+
parser_copy = subparsers.add_parser(
|
|
93
|
+
"copy_notebook",
|
|
94
|
+
help="copy notebook to target directory to run without voila",
|
|
95
|
+
description="copy notebook to target directory to run without voila",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
parser_copy.add_argument(
|
|
99
|
+
"-d",
|
|
100
|
+
"--destination",
|
|
101
|
+
type=Path,
|
|
102
|
+
required=True,
|
|
103
|
+
help="Location in which to copy the notebook.",
|
|
104
|
+
)
|
|
105
|
+
parser_copy.set_defaults(func=self._copy_notebook)
|
|
106
|
+
|
|
107
|
+
# Parse --------------------------------------------------------------
|
|
108
|
+
args = self.parser.parse_args()
|
|
109
|
+
try:
|
|
110
|
+
args.func(args)
|
|
111
|
+
except AttributeError:
|
|
112
|
+
self.parser.print_help()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def main():
|
|
116
|
+
log_format = "%(levelname)-8s: %(message)s"
|
|
117
|
+
logging.basicConfig(level=logging.INFO, format=log_format)
|
|
118
|
+
Main().run()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
title: Sample OAD Process
|
|
2
|
+
|
|
3
|
+
input_file: ../workdir/inputs/reference_aircraft_input_file.xml
|
|
4
|
+
output_file: ../workdir/outputs/reference_aircraft_output_file.xml
|
|
5
|
+
|
|
6
|
+
driver: om.ScipyOptimizeDriver(tol=1e-2, optimizer='COBYLA')
|
|
7
|
+
|
|
8
|
+
model:
|
|
9
|
+
|
|
10
|
+
# Solvers are defined assuming the OpenMDAO convention "import openmdao.api as om"
|
|
11
|
+
nonlinear_solver: om.NonlinearBlockGS(maxiter=100, rtol=1e-2)
|
|
12
|
+
linear_solver: om.DirectSolver()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Components can be put in sub-groups
|
|
16
|
+
subgroup:
|
|
17
|
+
|
|
18
|
+
# A group can be set with its own solvers.
|
|
19
|
+
# Uncomment the 2 next lines for using the performance module with "mission_file_path: ::sizing_mission"
|
|
20
|
+
# nonlinear_solver: om.NonlinearBlockGS(maxiter=100, atol=1e-2, iprint=0)
|
|
21
|
+
# linear_solver: om.DirectSolver()
|
|
22
|
+
|
|
23
|
+
geometry:
|
|
24
|
+
# An OpenMDAO component is identified by its "id"
|
|
25
|
+
id: fastoad.geometry.legacy
|
|
26
|
+
weight:
|
|
27
|
+
id: fastoad.weight.legacy
|
|
28
|
+
payload_from_npax: false
|
|
29
|
+
loads:
|
|
30
|
+
id: fastoad.loads.legacy
|
|
31
|
+
mtow:
|
|
32
|
+
id: fastoad.mass_performances.compute_MTOW
|
|
33
|
+
hq_tail_sizing:
|
|
34
|
+
id: fastoad.handling_qualities.tail_sizing
|
|
35
|
+
hq_static_margin:
|
|
36
|
+
id: fastoad.handling_qualities.static_margin
|
|
37
|
+
wing_position:
|
|
38
|
+
id: fastoad.loop.wing_position
|
|
39
|
+
aerodynamics_highspeed:
|
|
40
|
+
id: fastoad.aerodynamics.highspeed.legacy
|
|
41
|
+
aerodynamics_lowspeed:
|
|
42
|
+
id: fastoad.aerodynamics.lowspeed.legacy
|
|
43
|
+
aerodynamics_takeoff:
|
|
44
|
+
id: fastoad.aerodynamics.takeoff.legacy
|
|
45
|
+
aerodynamics_landing:
|
|
46
|
+
id: fastoad.aerodynamics.landing.legacy
|
|
47
|
+
use_xfoil: false
|
|
48
|
+
performance:
|
|
49
|
+
id: fastoad.performances.mission
|
|
50
|
+
propulsion_id: fastoad.wrapper.propulsion.rubber_engine
|
|
51
|
+
mission_file_path: ::sizing_breguet
|
|
52
|
+
out_file: ../workdir/outputs/flight_points.csv
|
|
53
|
+
adjust_fuel: true
|
|
54
|
+
is_sizing: true
|
|
55
|
+
wing_area:
|
|
56
|
+
id: fastoad.loop.wing_area
|
|
57
|
+
|
|
58
|
+
model_options:
|
|
59
|
+
"*":
|
|
60
|
+
use_inner_solvers: false
|
|
61
|
+
|
|
62
|
+
submodels:
|
|
63
|
+
service.aerodynamics.oswald_coefficient: null
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
title: Sample OAD Process
|
|
2
|
+
|
|
3
|
+
input_file: ../workdir/inputs/reference_aircraft_input_file.xml
|
|
4
|
+
output_file: ../workdir/outputs/reference_aircraft_output_file.xml
|
|
5
|
+
|
|
6
|
+
model:
|
|
7
|
+
|
|
8
|
+
# Solvers are defined assuming the OpenMDAO convention "import openmdao.api as om"
|
|
9
|
+
nonlinear_solver: om.NonlinearBlockGS(maxiter=100, rtol=1e-5)
|
|
10
|
+
linear_solver: om.DirectSolver()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Components can be put in sub-groups
|
|
14
|
+
subgroup:
|
|
15
|
+
|
|
16
|
+
# A group can be set with its own solvers.
|
|
17
|
+
# Uncomment the 2 next lines for using the performance module with "mission_file_path: ::sizing_mission"
|
|
18
|
+
# nonlinear_solver: om.NonlinearBlockGS(maxiter=100, atol=1e-2, iprint=0)
|
|
19
|
+
# linear_solver: om.DirectSolver()
|
|
20
|
+
|
|
21
|
+
geometry:
|
|
22
|
+
# An OpenMDAO component is identified by its "id"
|
|
23
|
+
id: fastoad.geometry.legacy
|
|
24
|
+
weight:
|
|
25
|
+
id: fastoad.weight.legacy
|
|
26
|
+
payload_from_npax: false
|
|
27
|
+
loads:
|
|
28
|
+
id: fastoad.loads.legacy
|
|
29
|
+
mtow:
|
|
30
|
+
id: fastoad.mass_performances.compute_MTOW
|
|
31
|
+
hq_tail_sizing:
|
|
32
|
+
id: fastoad.handling_qualities.tail_sizing
|
|
33
|
+
hq_static_margin:
|
|
34
|
+
id: fastoad.handling_qualities.static_margin
|
|
35
|
+
wing_position:
|
|
36
|
+
id: fastoad.loop.wing_position
|
|
37
|
+
aerodynamics_highspeed:
|
|
38
|
+
id: fastoad.aerodynamics.highspeed.legacy
|
|
39
|
+
aerodynamics_lowspeed:
|
|
40
|
+
id: fastoad.aerodynamics.lowspeed.legacy
|
|
41
|
+
aerodynamics_takeoff:
|
|
42
|
+
id: fastoad.aerodynamics.takeoff.legacy
|
|
43
|
+
aerodynamics_landing:
|
|
44
|
+
id: fastoad.aerodynamics.landing.legacy
|
|
45
|
+
use_xfoil: false
|
|
46
|
+
performance:
|
|
47
|
+
id: fastoad.performances.mission
|
|
48
|
+
propulsion_id: fastoad.wrapper.propulsion.rubber_engine
|
|
49
|
+
mission_file_path: ::sizing_breguet
|
|
50
|
+
out_file: ../workdir/outputs/flight_points.csv
|
|
51
|
+
adjust_fuel: true
|
|
52
|
+
is_sizing: true
|
|
53
|
+
wing_area:
|
|
54
|
+
id: fastoad.loop.wing_area
|
|
55
|
+
|
|
56
|
+
model_options:
|
|
57
|
+
"*":
|
|
58
|
+
use_inner_solvers: false
|
|
59
|
+
|
|
60
|
+
submodels:
|
|
61
|
+
service.aerodynamics.oswald_coefficient: null
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import ipyvuetify as v
|
|
4
|
+
|
|
5
|
+
from fast_pedago.processes import (
|
|
6
|
+
ProcessLauncher,
|
|
7
|
+
)
|
|
8
|
+
from fast_pedago.utils import PathManager
|
|
9
|
+
|
|
10
|
+
from .components import (
|
|
11
|
+
Drawer,
|
|
12
|
+
Footer,
|
|
13
|
+
Header,
|
|
14
|
+
InputsContainer,
|
|
15
|
+
OutputFiguresContainer,
|
|
16
|
+
ProcessFiguresContainer,
|
|
17
|
+
TutorialContainer,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
_LOGGER = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
# As there are margins and padding in the voila template,
|
|
23
|
+
# I have to adjust the padding considering both the spacings
|
|
24
|
+
# in the voila template and the other components sizes.
|
|
25
|
+
TOP_PADDING = "76px"
|
|
26
|
+
LEFT_PADDING = "426px"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AppInterface(v.App):
|
|
30
|
+
def __init__(self, **kwargs):
|
|
31
|
+
super().__init__(**kwargs)
|
|
32
|
+
|
|
33
|
+
PathManager.build_paths()
|
|
34
|
+
|
|
35
|
+
# The process toggle starts on MDA and only reports later changes
|
|
36
|
+
self.is_MDO = False
|
|
37
|
+
|
|
38
|
+
# Sets MDA/MDO launcher to run MDA/MDO.
|
|
39
|
+
self.process_launcher = ProcessLauncher()
|
|
40
|
+
|
|
41
|
+
self._build_layout()
|
|
42
|
+
self._to_tutorial()
|
|
43
|
+
|
|
44
|
+
def _to_tutorial(self):
|
|
45
|
+
"""
|
|
46
|
+
Displays tutorial.
|
|
47
|
+
"""
|
|
48
|
+
self.footer.start_button.show()
|
|
49
|
+
self.drawer.hide()
|
|
50
|
+
self.header.open_drawer_button.hide()
|
|
51
|
+
self.padding_column.hide()
|
|
52
|
+
self.main_content.children = [self.tutorial]
|
|
53
|
+
self.output_figures.hide_graphs()
|
|
54
|
+
|
|
55
|
+
def _to_main(self):
|
|
56
|
+
"""
|
|
57
|
+
Displays main window, with input drawer and tabs to change
|
|
58
|
+
between residuals/objectives graph and output figures.
|
|
59
|
+
"""
|
|
60
|
+
self.footer.start_button.hide()
|
|
61
|
+
self.drawer.show()
|
|
62
|
+
self.header.open_drawer_button.show()
|
|
63
|
+
self.padding_column.show()
|
|
64
|
+
self.drawer.content.children = [self.inputs]
|
|
65
|
+
self.main_content.children = [self.graphs]
|
|
66
|
+
|
|
67
|
+
def _switch_tab(self, change):
|
|
68
|
+
"""
|
|
69
|
+
Hides the drawer when on outputs tabs, and show it when on
|
|
70
|
+
inputs tab.
|
|
71
|
+
|
|
72
|
+
To be called with "observe" method of a widget.
|
|
73
|
+
"""
|
|
74
|
+
data = change["new"]
|
|
75
|
+
|
|
76
|
+
if data == "outputs":
|
|
77
|
+
self.drawer.hide()
|
|
78
|
+
self.header.open_drawer_button.hide()
|
|
79
|
+
self.padding_column.hide()
|
|
80
|
+
else:
|
|
81
|
+
self.drawer.show()
|
|
82
|
+
self.header.open_drawer_button.show()
|
|
83
|
+
self.padding_column.show()
|
|
84
|
+
|
|
85
|
+
self.graphs_window.v_model = data
|
|
86
|
+
|
|
87
|
+
def _build_layout(self):
|
|
88
|
+
"""
|
|
89
|
+
Builds the layout of the app: all the app components (drawer,
|
|
90
|
+
input/output tabs, header, footer, tutorial).
|
|
91
|
+
"""
|
|
92
|
+
# tutorial widgets
|
|
93
|
+
self.tutorial = TutorialContainer()
|
|
94
|
+
|
|
95
|
+
# Inputs + process graph widgets
|
|
96
|
+
self.process_figures = ProcessFiguresContainer()
|
|
97
|
+
|
|
98
|
+
self.inputs = InputsContainer(self.process_launcher)
|
|
99
|
+
|
|
100
|
+
self.inputs.source_data_file_selector.observe(
|
|
101
|
+
self._set_source_data_file,
|
|
102
|
+
names="v_model",
|
|
103
|
+
)
|
|
104
|
+
self.inputs.process_selection_switch.observe(
|
|
105
|
+
self._switch_process,
|
|
106
|
+
names="v_model",
|
|
107
|
+
)
|
|
108
|
+
self.inputs.launch_button.on_event("click", self._launch_process)
|
|
109
|
+
|
|
110
|
+
self.output_figures = OutputFiguresContainer()
|
|
111
|
+
|
|
112
|
+
self.main_content = v.Container(
|
|
113
|
+
class_="pt-0",
|
|
114
|
+
fluid=True,
|
|
115
|
+
fill_height=True,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
self.graphs_tabs = v.Tabs(
|
|
119
|
+
v_model="inputs",
|
|
120
|
+
align_tabs="center",
|
|
121
|
+
grow=True,
|
|
122
|
+
hide_slider=True,
|
|
123
|
+
children=[
|
|
124
|
+
v.Tab(
|
|
125
|
+
value="inputs",
|
|
126
|
+
children=["Inputs"],
|
|
127
|
+
),
|
|
128
|
+
v.Tab(
|
|
129
|
+
value="outputs",
|
|
130
|
+
children=["Outputs"],
|
|
131
|
+
),
|
|
132
|
+
],
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
self.graphs_window = v.Window(
|
|
136
|
+
v_model="inputs",
|
|
137
|
+
children=[
|
|
138
|
+
v.WindowItem(
|
|
139
|
+
value="inputs",
|
|
140
|
+
children=[
|
|
141
|
+
v.Divider(),
|
|
142
|
+
v.Spacer(),
|
|
143
|
+
self.process_figures,
|
|
144
|
+
],
|
|
145
|
+
),
|
|
146
|
+
v.WindowItem(
|
|
147
|
+
value="outputs",
|
|
148
|
+
children=[
|
|
149
|
+
v.Divider(),
|
|
150
|
+
v.Spacer(),
|
|
151
|
+
self.output_figures,
|
|
152
|
+
],
|
|
153
|
+
),
|
|
154
|
+
],
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
self.graphs = v.Container(
|
|
158
|
+
fluid=True,
|
|
159
|
+
children=[
|
|
160
|
+
self.graphs_tabs,
|
|
161
|
+
self.graphs_window,
|
|
162
|
+
],
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
self.graphs_tabs.observe(
|
|
166
|
+
self._switch_tab,
|
|
167
|
+
names="v_model",
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
self.header = Header()
|
|
171
|
+
self.header.fast_oad_logo.on_event("click", lambda *args: self._to_tutorial())
|
|
172
|
+
self.header.open_drawer_button.on_event(
|
|
173
|
+
"click",
|
|
174
|
+
self._open_or_close_drawer,
|
|
175
|
+
)
|
|
176
|
+
self.header.clear_all_button.button.on_event(
|
|
177
|
+
"click",
|
|
178
|
+
self._clear_all_files,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
self.drawer = Drawer()
|
|
182
|
+
self.drawer.close_drawer_button.on_event(
|
|
183
|
+
"click",
|
|
184
|
+
self._open_or_close_drawer,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
self.footer = Footer()
|
|
188
|
+
self.footer.start_button.on_event("click", lambda *args: self._to_main())
|
|
189
|
+
|
|
190
|
+
self.to_outputs_button = v.Btn(
|
|
191
|
+
color="primary",
|
|
192
|
+
children=[
|
|
193
|
+
"Outputs",
|
|
194
|
+
v.Icon(class_="ps-2", children=["mdi-angle-right"]),
|
|
195
|
+
],
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
self.to_inputs_button = v.Btn(
|
|
199
|
+
color="primary",
|
|
200
|
+
children=[
|
|
201
|
+
v.Icon(class_="pe-2", children=["mdi-angle-left"]),
|
|
202
|
+
"Inputs",
|
|
203
|
+
],
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
self.navigation_buttons = v.Row(
|
|
207
|
+
class_="mx-6 mt-5",
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# Padding column to avoid having the main content behind
|
|
211
|
+
# the drawer when expanded
|
|
212
|
+
self.padding_column = v.Col(
|
|
213
|
+
cols="1",
|
|
214
|
+
style_="padding: 100px 0 0 " + LEFT_PADDING + ";",
|
|
215
|
+
class_="hidden-md-and-down",
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
self.children = [
|
|
219
|
+
self.header,
|
|
220
|
+
self.drawer,
|
|
221
|
+
# Main content : to display graphs
|
|
222
|
+
v.Html(
|
|
223
|
+
tag="main",
|
|
224
|
+
class_="v-main",
|
|
225
|
+
children=[
|
|
226
|
+
v.Row(
|
|
227
|
+
style_="padding: " + TOP_PADDING + " 0 0 0;",
|
|
228
|
+
),
|
|
229
|
+
v.Row(
|
|
230
|
+
no_gutters=True,
|
|
231
|
+
children=[
|
|
232
|
+
self.padding_column,
|
|
233
|
+
v.Col(
|
|
234
|
+
children=[
|
|
235
|
+
v.Row(
|
|
236
|
+
children=[
|
|
237
|
+
self.main_content,
|
|
238
|
+
],
|
|
239
|
+
),
|
|
240
|
+
],
|
|
241
|
+
),
|
|
242
|
+
],
|
|
243
|
+
),
|
|
244
|
+
],
|
|
245
|
+
),
|
|
246
|
+
self.footer,
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
def _switch_process(self, change):
|
|
250
|
+
"""
|
|
251
|
+
Switch display between MDA and MDO depending on process selection
|
|
252
|
+
button state.
|
|
253
|
+
|
|
254
|
+
To be called with "observe" method of a widget.
|
|
255
|
+
"""
|
|
256
|
+
data = change["new"]
|
|
257
|
+
|
|
258
|
+
# If the button toggle is on 1, switch to MDO
|
|
259
|
+
if data == "MDO":
|
|
260
|
+
self.is_MDO = True
|
|
261
|
+
self.inputs.to_mdo()
|
|
262
|
+
self.process_figures.to_mdo()
|
|
263
|
+
|
|
264
|
+
else:
|
|
265
|
+
self.is_MDO = False
|
|
266
|
+
self.inputs.to_mda()
|
|
267
|
+
self.process_figures.to_mda()
|
|
268
|
+
|
|
269
|
+
def _to_process_computation(self):
|
|
270
|
+
"""
|
|
271
|
+
When a process is on-going, blocks the inputs and set a loading screen.
|
|
272
|
+
"""
|
|
273
|
+
self.inputs.disable()
|
|
274
|
+
for tab in self.graphs_tabs.children:
|
|
275
|
+
tab.disabled = True
|
|
276
|
+
|
|
277
|
+
# Show a loading widget to make it apparent that a computation is
|
|
278
|
+
# underway.
|
|
279
|
+
self.process_figures.set_loading("Setting up and running")
|
|
280
|
+
|
|
281
|
+
def _to_process_results(self):
|
|
282
|
+
"""
|
|
283
|
+
Re-enables input widgets after the end of a MDA/MDO process.
|
|
284
|
+
"""
|
|
285
|
+
self.inputs.enable()
|
|
286
|
+
for tab in self.graphs_tabs.children:
|
|
287
|
+
tab.disabled = False
|
|
288
|
+
if self.is_MDO:
|
|
289
|
+
snackbar_to_open = self.process_figures.mdo_end_snackbar
|
|
290
|
+
elif self.process_launcher.get_mda_success():
|
|
291
|
+
snackbar_to_open = self.process_figures.mda_success_snackbar
|
|
292
|
+
else:
|
|
293
|
+
snackbar_to_open = self.process_figures.mda_failure_snackbar
|
|
294
|
+
self.process_figures.open_snackbar(snackbar_to_open)
|
|
295
|
+
# This resets the view to what was displayed before the run was launched.
|
|
296
|
+
self.process_figures._change_display(
|
|
297
|
+
{"new": self.process_figures._display_selection_buttons.v_model}
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
def _launch_process(self, widget, event, data):
|
|
301
|
+
"""
|
|
302
|
+
Retrieves the user inputs from the drawer and launch the selected
|
|
303
|
+
process.
|
|
304
|
+
|
|
305
|
+
To be called with "on_event" method of a widget.
|
|
306
|
+
"""
|
|
307
|
+
self._to_process_computation()
|
|
308
|
+
if self.is_MDO:
|
|
309
|
+
self.inputs.retrieve_mdo_inputs()
|
|
310
|
+
else:
|
|
311
|
+
self.inputs.retrieve_mda_inputs()
|
|
312
|
+
self.process_launcher.launch_processes(is_mdo=self.is_MDO)
|
|
313
|
+
self._to_process_results()
|
|
314
|
+
|
|
315
|
+
def _set_source_data_file(self, change):
|
|
316
|
+
"""
|
|
317
|
+
Sets the reference file name to use
|
|
318
|
+
|
|
319
|
+
To be called with "observe" method of a widget.
|
|
320
|
+
"""
|
|
321
|
+
self.inputs.set_initial_value_mda(change["new"])
|
|
322
|
+
|
|
323
|
+
def _open_or_close_drawer(self, widget, event, data):
|
|
324
|
+
"""
|
|
325
|
+
Opens or closes the input drawer depending on its actual state.
|
|
326
|
+
|
|
327
|
+
To be called with "on_event" method of a widget.
|
|
328
|
+
"""
|
|
329
|
+
self.drawer.v_model = not self.drawer.v_model
|
|
330
|
+
|
|
331
|
+
def _clear_all_files(self, widget, event, data):
|
|
332
|
+
"""
|
|
333
|
+
Clear all files contained in "workdir", in subdirectories "inputs"
|
|
334
|
+
and "outputs", that are not the files of the reference aircraft.
|
|
335
|
+
Also makes the user come back to source selection.
|
|
336
|
+
|
|
337
|
+
The subdirectories of workdir are not deleted in the process.
|
|
338
|
+
"""
|
|
339
|
+
# Gets back to source file selection
|
|
340
|
+
self._to_tutorial()
|
|
341
|
+
# Clears the output selection
|
|
342
|
+
self.output_figures.output_selection.v_model = []
|
|
343
|
+
self.output_figures.hide_graphs()
|
|
344
|
+
|
|
345
|
+
PathManager.clear_all_files()
|