.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/mdo/plot_sellar.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_mdo_plot_sellar.py: A from scratch example on the Sellar problem ============================================ .. _sellar_from_scratch: .. GENERATED FROM PYTHON SOURCE LINES 27-45 Introduction ------------ In this example, we will create an MDO scenario based on the Sellar's problem from scratch. Contrary to the :ref:`sphx_glr_examples_mdo_plot_gemseo_in_10_minutes.py`, all the disciplines will be implemented from scratch by sub-classing the :class:`.MDODiscipline` class for each discipline of the Sellar problem. The Sellar problem ------------------ We will consider in this example the Sellar problem: .. include:: /problems/sellar_problem_definition.inc Imports ------- All the imports needed for the tutorials are performed here. .. GENERATED FROM PYTHON SOURCE LINES 45-60 .. code-block:: Python from __future__ import annotations from math import exp from numpy import array from numpy import ones from gemseo import configure_logger from gemseo import create_scenario from gemseo.algos.design_space import DesignSpace from gemseo.core.discipline import MDODiscipline configure_logger() .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 61-87 Create the disciplinary classes ------------------------------- In this section, we define the Sellar disciplines by sub-classing the :class:`.MDODiscipline` class. For each class, the constructor and the _run method are overriden: - In the constructor, the input and output grammar are created. They define which inputs and outputs variables are allowed at the discipline execution. The default inputs are also defined, in case of the user does not provide them at the discipline execution. - In the _run method is implemented the concrete computation of the discipline. The inputs data are fetch by using the :meth:`.MDODiscipline.get_inputs_by_name` method. The returned NumPy arrays can then be used to compute the output values. They can then be stored in the :attr:`!MDODiscipline.local_data` dictionary. If the discipline execution is successful. Note that we do not define the Jacobians in the disciplines. In this example, we will approximate the derivatives using the finite differences method. Create the SellarSystem class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. GENERATED FROM PYTHON SOURCE LINES 87-114 .. code-block:: Python class SellarSystem(MDODiscipline): def __init__(self) -> None: super().__init__() # Initialize the grammars to define inputs and outputs self.input_grammar.update_from_names(["x", "z", "y_1", "y_2"]) self.output_grammar.update_from_names(["obj", "c_1", "c_2"]) # Default inputs define what data to use when the inputs are not # provided to the execute method self.default_inputs = { "x": ones(1), "z": array([4.0, 3.0]), "y_1": ones(1), "y_2": ones(1), } def _run(self) -> None: # The run method defines what happens at execution # ie how outputs are computed from inputs x, z, y_1, y_2 = self.get_inputs_by_name(["x", "z", "y_1", "y_2"]) # The ouputs are stored here self.local_data["obj"] = array([x[0] ** 2 + z[1] + y_1[0] ** 2 + exp(-y_2[0])]) self.local_data["c_1"] = array([3.16 - y_1[0] ** 2]) self.local_data["c_2"] = array([y_2[0] - 24.0]) .. GENERATED FROM PYTHON SOURCE LINES 115-117 Create the Sellar1 class ^^^^^^^^^^^^^^^^^^^^^^^^ .. GENERATED FROM PYTHON SOURCE LINES 117-137 .. code-block:: Python class Sellar1(MDODiscipline): def __init__(self) -> None: super().__init__() self.input_grammar.update_from_names(["x", "z", "y_2"]) self.output_grammar.update_from_names(["y_1"]) self.default_inputs = { "x": ones(1), "z": array([4.0, 3.0]), "y_2": ones(1), } def _run(self) -> None: x, z, y_2 = self.get_inputs_by_name(["x", "z", "y_2"]) self.local_data["y_1"] = array([ (z[0] ** 2 + z[1] + x[0] - 0.2 * y_2[0]) ** 0.5 ]) .. GENERATED FROM PYTHON SOURCE LINES 138-140 Create the Sellar2 class ^^^^^^^^^^^^^^^^^^^^^^^^ .. GENERATED FROM PYTHON SOURCE LINES 140-157 .. code-block:: Python class Sellar2(MDODiscipline): def __init__(self) -> None: super().__init__() self.input_grammar.update_from_names(["z", "y_1"]) self.output_grammar.update_from_names(["y_2"]) self.default_inputs = { "z": array([4.0, 3.0]), "y_1": ones(1), } def _run(self) -> None: z, y_1 = self.get_inputs_by_name(["z", "y_1"]) self.local_data["y_2"] = array([abs(y_1[0]) + z[0] + z[1]]) .. GENERATED FROM PYTHON SOURCE LINES 158-165 Create and execute the scenario ------------------------------- Instantiate disciplines ^^^^^^^^^^^^^^^^^^^^^^^ We can now instantiate the disciplines and store the instances in a list which will be used below. .. GENERATED FROM PYTHON SOURCE LINES 165-168 .. code-block:: Python disciplines = [Sellar1(), Sellar2(), SellarSystem()] .. GENERATED FROM PYTHON SOURCE LINES 169-181 Create the design space ^^^^^^^^^^^^^^^^^^^^^^^ In this section, we define the design space which will be used for the creation of the MDOScenario. Note that the coupling variables are defined in the design space. Indeed, as we are going to select the IDF formulation to solve the MDO scenario, the coupling variables will be unknowns of the optimization problem and consequently they have to be included in the design space. Conversely, it would not have been necessary to include them if we aimed to select an MDF formulation. .. GENERATED FROM PYTHON SOURCE LINES 181-190 .. code-block:: Python design_space = DesignSpace() design_space.add_variable("x", l_b=0.0, u_b=10.0, value=ones(1)) design_space.add_variable( "z", 2, l_b=(-10, 0.0), u_b=(10.0, 10.0), value=array([4.0, 3.0]) ) design_space.add_variable("y_1", l_b=-100.0, u_b=100.0, value=ones(1)) design_space.add_variable("y_2", l_b=-100.0, u_b=100.0, value=ones(1)) .. GENERATED FROM PYTHON SOURCE LINES 191-196 Create the scenario ^^^^^^^^^^^^^^^^^^^ In this section, we build the MDO scenario which links the disciplines with the formulation, the design space and the objective function. .. GENERATED FROM PYTHON SOURCE LINES 196-198 .. code-block:: Python scenario = create_scenario(disciplines, "IDF", "obj", design_space) .. GENERATED FROM PYTHON SOURCE LINES 199-203 Add the constraints ^^^^^^^^^^^^^^^^^^^ Then, we have to set the design constraints .. GENERATED FROM PYTHON SOURCE LINES 203-206 .. code-block:: Python scenario.add_constraint("c_1", constraint_type="ineq") scenario.add_constraint("c_2", constraint_type="ineq") .. GENERATED FROM PYTHON SOURCE LINES 207-210 As previously mentioned, we are going to use finite differences to approximate the derivatives since the disciplines do not provide them. .. GENERATED FROM PYTHON SOURCE LINES 210-212 .. code-block:: Python scenario.set_differentiation_method("finite_differences") .. GENERATED FROM PYTHON SOURCE LINES 213-219 Execute the scenario ^^^^^^^^^^^^^^^^^^^^ Then, we execute the MDO scenario with the inputs of the MDO scenario as a dictionary. In this example, the gradient-based `SLSQP` optimizer is selected, with 10 iterations at maximum: .. GENERATED FROM PYTHON SOURCE LINES 219-221 .. code-block:: Python scenario.execute({"max_iter": 10, "algo": "SLSQP"}) .. rst-class:: sphx-glr-script-out .. code-block:: none INFO - 00:11:00: INFO - 00:11:00: *** Start MDOScenario execution *** INFO - 00:11:00: MDOScenario INFO - 00:11:00: Disciplines: Sellar1 Sellar2 SellarSystem INFO - 00:11:00: MDO formulation: IDF INFO - 00:11:00: Optimization problem: INFO - 00:11:00: minimize obj(x, z, y_1, y_2) INFO - 00:11:00: with respect to x, y_1, y_2, z INFO - 00:11:00: subject to constraints: INFO - 00:11:00: c_1(x, z, y_1, y_2) <= 0.0 INFO - 00:11:00: c_2(x, z, y_1, y_2) <= 0.0 INFO - 00:11:00: y_1(x, z, y_2): y_1(x, z, y_2) - y_1 == 0.0 INFO - 00:11:00: y_2(z, y_1): y_2(z, y_1) - y_2 == 0.0 INFO - 00:11:00: over the design space: INFO - 00:11:00: +------+-------------+-------+-------------+-------+ INFO - 00:11:00: | Name | Lower bound | Value | Upper bound | Type | INFO - 00:11:00: +------+-------------+-------+-------------+-------+ INFO - 00:11:00: | x | 0 | 1 | 10 | float | INFO - 00:11:00: | z[0] | -10 | 4 | 10 | float | INFO - 00:11:00: | z[1] | 0 | 3 | 10 | float | INFO - 00:11:00: | y_1 | -100 | 1 | 100 | float | INFO - 00:11:00: | y_2 | -100 | 1 | 100 | float | INFO - 00:11:00: +------+-------------+-------+-------------+-------+ INFO - 00:11:00: Solving optimization problem with algorithm SLSQP: INFO - 00:11:00: 10%|█ | 1/10 [00:00<00:00, 229.86 it/sec, obj=5.37] INFO - 00:11:00: 20%|██ | 2/10 [00:00<00:00, 85.48 it/sec, obj=4.34] INFO - 00:11:00: 30%|███ | 3/10 [00:00<00:00, 83.75 it/sec, obj=3.26] INFO - 00:11:00: 40%|████ | 4/10 [00:00<00:00, 81.90 it/sec, obj=3.18] INFO - 00:11:00: 50%|█████ | 5/10 [00:00<00:00, 80.96 it/sec, obj=3.18] INFO - 00:11:00: 60%|██████ | 6/10 [00:00<00:00, 80.28 it/sec, obj=3.18] INFO - 00:11:00: Optimization result: INFO - 00:11:00: Optimizer info: INFO - 00:11:00: Status: 8 INFO - 00:11:00: Message: Positive directional derivative for linesearch INFO - 00:11:00: Number of calls to the objective function by the optimizer: 7 INFO - 00:11:00: Solution: INFO - 00:11:00: The solution is feasible. INFO - 00:11:00: Objective: 3.1833939516400456 INFO - 00:11:00: Standardized constraints: INFO - 00:11:00: c_1 = 5.764277943853813e-13 INFO - 00:11:00: c_2 = -20.244722233074114 INFO - 00:11:00: y_1 = [2.06834549e-15] INFO - 00:11:00: y_2 = [1.98063788e-15] INFO - 00:11:00: Design space: INFO - 00:11:00: +------+-------------+-------------------+-------------+-------+ INFO - 00:11:00: | Name | Lower bound | Value | Upper bound | Type | INFO - 00:11:00: +------+-------------+-------------------+-------------+-------+ INFO - 00:11:00: | x | 0 | 0 | 10 | float | INFO - 00:11:00: | z[0] | -10 | 1.977638883463326 | 10 | float | INFO - 00:11:00: | z[1] | 0 | 0 | 10 | float | INFO - 00:11:00: | y_1 | -100 | 1.777638883462956 | 100 | float | INFO - 00:11:00: | y_2 | -100 | 3.755277766925886 | 100 | float | INFO - 00:11:00: +------+-------------+-------------------+-------------+-------+ INFO - 00:11:00: *** End MDOScenario execution (time: 0:00:00.114933) *** {'max_iter': 10, 'algo': 'SLSQP'} .. GENERATED FROM PYTHON SOURCE LINES 222-226 Post-process the scenario ^^^^^^^^^^^^^^^^^^^^^^^^^ Finally, we can generate plots of the optimization history: .. GENERATED FROM PYTHON SOURCE LINES 226-227 .. code-block:: Python scenario.post_process("OptHistoryView", save=False, show=True) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /examples/mdo/images/sphx_glr_plot_sellar_001.png :alt: Evolution of the optimization variables :srcset: /examples/mdo/images/sphx_glr_plot_sellar_001.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_sellar_002.png :alt: Evolution of the objective value :srcset: /examples/mdo/images/sphx_glr_plot_sellar_002.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_sellar_003.png :alt: Distance to the optimum :srcset: /examples/mdo/images/sphx_glr_plot_sellar_003.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_sellar_004.png :alt: Hessian diagonal approximation :srcset: /examples/mdo/images/sphx_glr_plot_sellar_004.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_sellar_005.png :alt: Evolution of the inequality constraints :srcset: /examples/mdo/images/sphx_glr_plot_sellar_005.png :class: sphx-glr-multi-img * .. image-sg:: /examples/mdo/images/sphx_glr_plot_sellar_006.png :alt: Evolution of the equality constraints :srcset: /examples/mdo/images/sphx_glr_plot_sellar_006.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.521 seconds) .. _sphx_glr_download_examples_mdo_plot_sellar.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_sellar.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_sellar.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_