{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# BiLevel-based DOE on the Sobieski SSBJ test case\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from copy import deepcopy\nfrom os import name as os_name\n\nfrom gemseo.api import configure_logger\nfrom gemseo.api import create_discipline\nfrom gemseo.api import create_scenario\nfrom gemseo.problems.sobieski.core.problem import SobieskiProblem\nfrom matplotlib import pyplot as plt\n\nconfigure_logger()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Instantiate the  disciplines\nFirst, we instantiate the four disciplines of the use case:\n:class:`~gemseo.problems.sobieski.disciplines.SobieskiPropulsion`,\n:class:`~gemseo.problems.sobieski.disciplines.SobieskiAerodynamics`,\n:class:`~gemseo.problems.sobieski.disciplines.SobieskiMission`\nand :class:`~gemseo.problems.sobieski.disciplines.SobieskiStructure`.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "propu, aero, mission, struct = create_discipline(\n    [\n        \"SobieskiPropulsion\",\n        \"SobieskiAerodynamics\",\n        \"SobieskiMission\",\n        \"SobieskiStructure\",\n    ]\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Build, execute and post-process the scenario\nThen, we build the scenario which links the disciplines\nwith the formulation and the optimization algorithm. Here, we use the\n:class:`.BiLevel` formulation. We tell the scenario to minimize -y_4\ninstead of minimizing y_4 (range), which is the default option.\n\nWe need to define the design space.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "design_space = SobieskiProblem().design_space"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Then, we build a sub-scenario for each strongly coupled disciplines,\nusing the following algorithm, maximum number of iterations and\nalgorithm options:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "algo_options = {\n    \"xtol_rel\": 1e-7,\n    \"xtol_abs\": 1e-7,\n    \"ftol_rel\": 1e-7,\n    \"ftol_abs\": 1e-7,\n    \"ineq_tolerance\": 1e-4,\n}\nsub_sc_opts = {\"max_iter\": 30, \"algo\": \"SLSQP\", \"algo_options\": algo_options}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Build a sub-scenario for Propulsion\nThis sub-scenario will minimize SFC.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "sc_prop = create_scenario(\n    propu,\n    \"DisciplinaryOpt\",\n    \"y_34\",\n    design_space=deepcopy(design_space).filter(\"x_3\"),\n    name=\"PropulsionScenario\",\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Build a sub-scenario for Aerodynamics\nThis sub-scenario will minimize L/D.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "sc_aero = create_scenario(\n    aero,\n    \"DisciplinaryOpt\",\n    \"y_24\",\n    deepcopy(design_space).filter(\"x_2\"),\n    name=\"AerodynamicsScenario\",\n    maximize_objective=True,\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Build a sub-scenario for Structure\nThis sub-scenario will maximize\nlog(aircraft total weight / (aircraft total weight - fuel weight)).\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "sc_str = create_scenario(\n    struct,\n    \"DisciplinaryOpt\",\n    \"y_11\",\n    deepcopy(design_space).filter(\"x_1\"),\n    name=\"StructureScenario\",\n    maximize_objective=True,\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Build a scenario for Mission\nThis scenario is based on the three previous sub-scenarios and on the\nMission and aims to maximize the range (Breguet).\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "sub_disciplines = [sc_prop, sc_aero, sc_str] + [mission]\ndesign_space = deepcopy(design_space).filter(\"x_shared\")\nsystem_scenario = create_scenario(\n    sub_disciplines,\n    \"BiLevel\",\n    \"y_4\",\n    design_space,\n    parallel_scenarios=False,\n    reset_x0_before_opt=True,\n    scenario_type=\"DOE\",\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-info\"><h4>Note</h4><p>Setting :code:`reset_x0_before_opt=True` is mandatory when doing a DOE\n   in parallel. If we want reproducible results, don't reuse previous xopt.</p></div>\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "system_scenario.formulation.mda1.warm_start = False\nsystem_scenario.formulation.mda2.warm_start = False"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-info\"><h4>Note</h4><p>This is mandatory when doing a DOE in parallel if we want always exactly\n   the same results, don't warm start mda1 to have exactly the same\n   process whatever the execution order and process dispatch.</p></div>\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "for sub_sc in sub_disciplines[0:3]:\n    sub_sc.default_inputs = {\"max_iter\": 20, \"algo\": \"L-BFGS-B\"}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Multiprocessing\nIt is possible to run a DOE in parallel using multiprocessing, in order to do\nthis, we specify the number of processes to be used for the computation of\nthe samples.\n\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-danger\"><h4>Warning</h4><p>The multiprocessing option has some limitations on Windows.\n   Due to problems with sphinx, we disable it in this example.\n   For Python versions < 3.7 and Numpy < 1.20.0, subprocesses may get hung\n   randomly during execution. It is strongly recommended to update your\n   environment to avoid this problem.\n   The features :class:`.MemoryFullCache` and :class:`.HDF5Cache` are not\n   available for multiprocessing on Windows.\n   As an alternative, we recommend the method\n   :meth:`.DOEScenario.set_optimization_history_backup`.</p></div>\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "system_scenario.execute(\n    {\n        \"n_samples\": 30,\n        \"algo\": \"lhs\",\n        \"algo_options\": {\"n_processes\": 1 if os_name == \"nt\" else 4},\n    }\n)\n\nsystem_scenario.print_execution_metrics()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-danger\"><h4>Warning</h4><p>On Windows, the progress bar may show duplicated instances during the\n   initialization of each subprocess. In some cases it may also print the\n   conclusion of an iteration ahead of another one that was concluded first.\n   This is a consequence of the pickling process and does not affect the\n   computations of the scenario.</p></div>\n\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Plot the optimization history view\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "system_scenario.post_process(\"OptHistoryView\", show=False, save=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Plot the scatter matrix\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "system_scenario.post_process(\n    \"ScatterPlotMatrix\", show=False, save=False, variable_names=[\"y_4\", \"x_shared\"]\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Plot parallel coordinates\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "system_scenario.post_process(\"ParallelCoordinates\", show=False, save=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Plot correlations\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "system_scenario.post_process(\"Correlations\", show=False, save=False)\n# Workaround for HTML rendering, instead of ``show=True``\nplt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.9.13"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}