.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/mdo/plot_aerostructure.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_mdo_plot_aerostructure.py: MDO formulations for a toy example in aerostructure =================================================== .. GENERATED FROM PYTHON SOURCE LINES 24-49 .. code-block:: default from __future__ import annotations from copy import deepcopy from gemseo.api import configure_logger from gemseo.api import create_discipline from gemseo.api import create_scenario from gemseo.api import generate_n2_plot from gemseo.problems.aerostructure.aerostructure_design_space import ( AerostructureDesignSpace, ) from matplotlib import pyplot as plt configure_logger() algo_options = { "xtol_rel": 1e-8, "xtol_abs": 1e-8, "ftol_rel": 1e-8, "ftol_abs": 1e-8, "ineq_tolerance": 1e-5, "eq_tolerance": 1e-3, } .. GENERATED FROM PYTHON SOURCE LINES 50-54 Create discipline ----------------- First, we create disciplines (aero, structure, mission) with dummy formulas using the :class:`.AnalyticDiscipline` class. .. GENERATED FROM PYTHON SOURCE LINES 54-79 .. code-block:: default aero_formulas = { "drag": "0.1*((sweep/360)**2 + 200 + " + "thick_airfoils**2-thick_airfoils -4*displ)", "forces": "10*sweep + 0.2*thick_airfoils-0.2*displ", "lift": "(sweep + 0.2*thick_airfoils-2.*displ)/3000.", } aerodynamics = create_discipline( "AnalyticDiscipline", name="Aerodynamics", expressions=aero_formulas ) struc_formulas = { "mass": "4000*(sweep/360)**3 + 200000 + " + "100*thick_panels +200.0*forces", "reserve_fact": "-3*sweep " + "-6*thick_panels+0.1*forces+55", "displ": "2*sweep + 3*thick_panels-2.*forces", } structure = create_discipline( "AnalyticDiscipline", name="Structure", expressions=struc_formulas ) mission_formulas = {"range": "8e11*lift/(mass*drag)"} mission = create_discipline( "AnalyticDiscipline", name="Mission", expressions=mission_formulas ) disciplines = [aerodynamics, structure, mission] .. GENERATED FROM PYTHON SOURCE LINES 80-81 We can see that structure and aerodynamics are strongly coupled: .. GENERATED FROM PYTHON SOURCE LINES 81-83 .. code-block:: default generate_n2_plot(disciplines, save=False, show=True) .. image-sg:: /examples/mdo/images/sphx_glr_plot_aerostructure_001.png :alt: plot aerostructure :srcset: /examples/mdo/images/sphx_glr_plot_aerostructure_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 84-87 Create an MDO scenario with MDF formulation ------------------------------------------- Then, we create an MDO scenario based on the MDF formulation .. GENERATED FROM PYTHON SOURCE LINES 87-100 .. code-block:: default design_space = AerostructureDesignSpace() scenario = create_scenario( disciplines=disciplines, formulation="MDF", objective_name="range", design_space=design_space, maximize_objective=True, ) scenario.add_constraint("reserve_fact", "ineq", value=0.5) scenario.add_constraint("lift", "eq", value=0.5) scenario.execute({"algo": "NLOPT_SLSQP", "max_iter": 10, "algo_options": algo_options}) scenario.post_process("OptHistoryView", save=False, show=True) .. rst-class:: sphx-glr-script-out .. code-block:: none /home/docs/checkouts/readthedocs.org/user_builds/gemseo/envs/4.1.0/lib/python3.9/site-packages/gemseo/algos/design_space.py:459: ComplexWarning: Casting complex values to real discards the imaginary part self.__current_value[name] = array_value.astype( INFO - 14:47:20: Variable reserve_fact was removed from the Design Space, it is not an input of any discipline. INFO - 14:47:20: INFO - 14:47:20: *** Start MDOScenario execution *** INFO - 14:47:20: MDOScenario INFO - 14:47:20: Disciplines: Aerodynamics Mission Structure INFO - 14:47:20: MDO formulation: MDF INFO - 14:47:20: Optimization problem: INFO - 14:47:20: minimize -range(thick_airfoils, thick_panels, sweep) INFO - 14:47:20: with respect to sweep, thick_airfoils, thick_panels INFO - 14:47:20: subject to constraints: INFO - 14:47:20: reserve_fact(thick_airfoils, thick_panels, sweep) <= 0.5 INFO - 14:47:20: lift(thick_airfoils, thick_panels, sweep) == 0.5 INFO - 14:47:20: over the design space: INFO - 14:47:20: +----------------+-------------+-------+-------------+-------+ INFO - 14:47:20: | name | lower_bound | value | upper_bound | type | INFO - 14:47:20: +----------------+-------------+-------+-------------+-------+ INFO - 14:47:20: | thick_airfoils | 5 | 15 | 25 | float | INFO - 14:47:20: | thick_panels | 1 | 3 | 20 | float | INFO - 14:47:20: | sweep | 10 | 25 | 35 | float | INFO - 14:47:20: +----------------+-------------+-------+-------------+-------+ INFO - 14:47:20: Solving optimization problem with algorithm NLOPT_SLSQP: INFO - 14:47:20: ... 0%| | 0/10 [00:00 .. GENERATED FROM PYTHON SOURCE LINES 101-104 Create an MDO scenario with bilevel formulation ----------------------------------------------- Then, we create an MDO scenario based on the bilevel formulation .. GENERATED FROM PYTHON SOURCE LINES 104-111 .. code-block:: default sub_scenario_options = { "max_iter": 5, "algo": "NLOPT_SLSQP", "algo_options": algo_options, } design_space_ref = AerostructureDesignSpace() .. rst-class:: sphx-glr-script-out .. code-block:: none /home/docs/checkouts/readthedocs.org/user_builds/gemseo/envs/4.1.0/lib/python3.9/site-packages/gemseo/algos/design_space.py:459: ComplexWarning: Casting complex values to real discards the imaginary part self.__current_value[name] = array_value.astype( .. GENERATED FROM PYTHON SOURCE LINES 112-116 Create the aeronautics sub-scenario ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For this purpose, we create a first sub-scenario to maximize the range with respect to the thick airfoils, based on the aerodynamics discipline. .. GENERATED FROM PYTHON SOURCE LINES 116-126 .. code-block:: default design_space_aero = deepcopy(design_space_ref).filter(["thick_airfoils"]) aero_scenario = create_scenario( disciplines=[aerodynamics, mission], formulation="DisciplinaryOpt", objective_name="range", design_space=design_space_aero, maximize_objective=True, ) aero_scenario.default_inputs = sub_scenario_options .. GENERATED FROM PYTHON SOURCE LINES 127-131 Create the structure sub-scenario ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ We create a second sub-scenario to maximize the range with respect to the thick panels, based on the structure discipline. .. GENERATED FROM PYTHON SOURCE LINES 131-141 .. code-block:: default design_space_struct = deepcopy(design_space_ref).filter(["thick_panels"]) struct_scenario = create_scenario( disciplines=[structure, mission], formulation="DisciplinaryOpt", objective_name="range", design_space=design_space_struct, maximize_objective=True, ) struct_scenario.default_inputs = sub_scenario_options .. GENERATED FROM PYTHON SOURCE LINES 142-146 Create the system scenario ^^^^^^^^^^^^^^^^^^^^^^^^^^ Lastly, we build a system scenario to maximize the range with respect to the sweep, which is a shared variable, based on the previous sub-scenarios. .. GENERATED FROM PYTHON SOURCE LINES 146-164 .. code-block:: default design_space_system = deepcopy(design_space_ref).filter(["sweep"]) system_scenario = create_scenario( disciplines=[aero_scenario, struct_scenario, mission], formulation="BiLevel", objective_name="range", design_space=design_space_system, maximize_objective=True, inner_mda_name="MDAJacobi", tolerance=1e-8, ) system_scenario.add_constraint("reserve_fact", "ineq", value=0.5) system_scenario.add_constraint("lift", "eq", value=0.5) system_scenario.execute( {"algo": "NLOPT_COBYLA", "max_iter": 7, "algo_options": algo_options} ) system_scenario.post_process("OptHistoryView", save=False, show=False) # Workaround for HTML rendering, instead of ``show=True`` plt.show() .. rst-class:: sphx-glr-horizontal * .. image-sg:: /examples/mdo/images/sphx_glr_plot_aerostructure_002.png :alt: Evolution of the optimization variables :srcset: /examples/mdo/images/sphx_glr_plot_aerostructure_002.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_aerostructure_003.png :alt: Evolution of the objective value :srcset: /examples/mdo/images/sphx_glr_plot_aerostructure_003.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_aerostructure_004.png :alt: Distance to the optimum :srcset: /examples/mdo/images/sphx_glr_plot_aerostructure_004.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_aerostructure_005.png :alt: Evolution of the inequality constraints :srcset: /examples/mdo/images/sphx_glr_plot_aerostructure_005.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_aerostructure_006.png :alt: Evolution of the equality constraints :srcset: /examples/mdo/images/sphx_glr_plot_aerostructure_006.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none INFO - 14:47:21: INFO - 14:47:21: *** Start MDOScenario execution *** INFO - 14:47:21: MDOScenario INFO - 14:47:21: Disciplines: MDOScenario MDOScenario Mission INFO - 14:47:21: MDO formulation: BiLevel INFO - 14:47:21: Optimization problem: INFO - 14:47:21: minimize -range(sweep) INFO - 14:47:21: with respect to sweep INFO - 14:47:21: subject to constraints: INFO - 14:47:21: reserve_fact(sweep) <= 0.5 INFO - 14:47:21: lift(sweep) == 0.5 INFO - 14:47:21: over the design space: INFO - 14:47:21: +-------+-------------+-------+-------------+-------+ INFO - 14:47:21: | name | lower_bound | value | upper_bound | type | INFO - 14:47:21: +-------+-------------+-------+-------------+-------+ INFO - 14:47:21: | sweep | 10 | 25 | 35 | float | INFO - 14:47:21: +-------+-------------+-------+-------------+-------+ INFO - 14:47:21: Solving optimization problem with algorithm NLOPT_COBYLA: INFO - 14:47:21: ... 0%| | 0/7 [00:00` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_aerostructure.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_