How to deal with scenarios

1. How is a scenario defined?

1.a. What is a scenario?

A scenario is an interface that:

  • creates an optimization or sampling problem,

  • from a set of disciplines and a multidisciplinary formulation based on a design space and on an objective name,

  • executes it from an optimization or sampling algorithm with mandatory arguments and options and

  • post-process it.

1.b. How does a scenario is implemented in GEMSEO?

Programmatically speaking, scenarios are implemented in GEMSEO through the Scenario abstract class inheriting from the MDODiscipline class and derived classes:

  • The MDOScenario class inheriting from Scenario is dedicated to optimization processes.

  • The DOEScenario class inheriting from Scenario is dedicated to trade-off studies and sampling processes.

A Scenario is defined by four main elements:

  • the disciplines attribute: the list of MDODiscipline,

  • the formulation attribute: the multidisciplinary formulation based on DesignSpace,

  • the optimization_result attribute: the optimization results,

  • the post_factory attribute: the post-processing set of methods.

1.c. What are the API functions in GEMSEO?

After the instantiation of the different MDODiscipline, an instance of this scenario can be created from the create_scenario() API function whose arguments are:

  • disciplines: the list of instantiated MDODiscipline,

  • formulation: the multidisciplinary formulation name (str)

  • objective_name: the objective name (str)

  • design_space: the instantiated DesignSpace,

  • name=None: the optional name of the scenario (str),

  • scenario_type='MDO': the optional type of scenario ('MDO' or 'DOE'),

  • maximize_objective=False: the choice between maximizing or minimizing the objective function (bool),

  • **formulation_options: options passed to the multidisciplinary formulation.

The types of scenarios already implemented in GEMSEO can be obtained by means of the get_available_scenario_types() API function:

from gemseo.api import get_available_scenario_types

get_available_scenario_types():

which results in:

["MDO", "DOE"]

2. How to create a scenario?

We can easily create a MDOScenario or a DOEScenario from the create_scenario() API function.

2.a. Instantiate the disciplines

For that, we first instantiate the different MDODiscipline, e.g.

from gemseo.api import create_discipline

disciplines = create_discipline(['Sellar1', 'Sellar2', 'SellarSystem'])

2.b. Define the design space

Then, we define the design space, either by instantiating a DesignSpace,

from gemseo.problems.sellar.sellar_design_space import SellarDesignSpace

design_space = SellarDesignSpace()

or by means of the file path of the design space:

design_space = 'path_to_sellar_design_space.txt'

2.c. Define the objective function

The objective function should be an output taken among the output list of the different MDODiscipline, e.g.

objective_name = 'obj'

2.d. Define the multidisciplinary formulation

From the design space and the objective name, the Scenario automatically builds an multidisciplinary formulation corresponding to a multidisciplinary formulation name specified by the user, e.g.

formulation = 'MDF'

The list of the different available formulations can be obtained by means of the get_available_formulations() API function:

from gemseo.api import get_available_formulations

get_available_formulations()

which yields:

['BiLevel', 'IDF', 'MDF', 'DisciplinaryOpt']

Note

argument=value formulation options can also be passed to the create_scenario() API function. Available options for the different formulations are presented in MDO formulation options.

2.e. Choose the type of scenario

Just before the Scenario instantiation, the type of scenario must be chosen, e.g.

scenario_type = 'MDO'

Remind that the different types of scenario can be obtained by means of the get_available_scenario_types() API function:

from gemseo.api import get_available_scenario_types

get_available_scenario_types()

which yields:

['MDO', 'DOE']

2.f. Instantiate the scenario

From these different elements, we can instantiate the Scenario by means of the create_scenario() API function:

from gemseo.api import create_scenario

scenario = create_scenario(
    disciplines=disciplines,
    formulation=formulation,
    objective_name=objective_name,
    design_space=design_space,
    scenario_type=scenario_type,
)

2.g. Get the names of design variables

We can use the Scenario.get_optim_variables_names() method of the Scenario to access formulation design variables names in a convenient way:

print(scenario.get_optim_variables_names)

which yields:

['x_local', 'x_shared']

2.g. Get the design space

The design space can be accessed using the Scenario.design_space property of the Scenario:

print(scenario.design_space)

which yields:

+----------+-------------+--------+-------------+-------+
| name     | lower_bound | value  | upper_bound | type  |
+----------+-------------+--------+-------------+-------+
| x_local  |      0      | (1+0j) |      10     | float |
| x_shared |     -10     | (4+0j) |      10     | float |
| x_shared |      0      | (3+0j) |      10     | float |
+----------+-------------+--------+-------------+-------+

2.h. Visualize the scenario before execute it (XDSM graph)

The simplest way to visualize how the Scenario manages the workflow and dataflow before to execute it is to log them in the console or in a file using GEMSEO’s logger.

The method Scenario.xdsmize() of the Scenario can be used to this aim (monitor=True).

If html_output (default True), will generate a self contained html file, that can be automatically open using the option open_browser=True. If json_output is True, it will generate a XDSMjs input file XDSM visualization,

and print the statuses in the logs (print_statuses=True):

scenario.xdsmize(monitor=True, print_statuses=True, open_browser=False)

which yields:

INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(PENDING), [{MDAJacobi(None), (Sellar1(None), Sellar2(None), ), }, SellarSystem(None), ], }, }
INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(RUNNING), [{MDAJacobi(PENDING), (Sellar1(None), Sellar2(None), ), }, SellarSystem(None), ], }, }
INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(RUNNING), [{MDAJacobi(RUNNING), (Sellar1(PENDING), Sellar2(PENDING), ), }, SellarSystem(None), ], }, }
INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(RUNNING), [{MDAJacobi(RUNNING), (Sellar1(RUNNING), Sellar2(RUNNING), ), }, SellarSystem(None), ], }, }
INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(RUNNING), [{MDAJacobi(RUNNING), (Sellar1(DONE), Sellar2(RUNNING), ), }, SellarSystem(None), ], }, }
INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(RUNNING), [{MDAJacobi(RUNNING), (Sellar1(PENDING), Sellar2(PENDING), ), }, SellarSystem(None), ], }, }
INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(RUNNING), [{MDAJacobi(RUNNING), (Sellar1(PENDING), Sellar2(PENDING), ), }, SellarSystem(None), ], }, }
INFO - 13:21:18 : {MDOScenario(RUNNING), {MDAChain(RUNNING), [{MDAJacobi(RUNNING), (Sellar1(RUNNING), Sellar2(RUNNING), ), }, SellarSystem(None), ], }, }
...

and

../_images/xdsm1.png

Moreover, you can export a static version of the XDSM in both TIKZ, LaTeX and PDF files by means of the latex_output boolean argument of the Scenario.xdsmize() method:

scenario.xdsmize(latex_output=True)

eventually specifying the output directory outdir='SOME_PATH'.

3. How to execute a scenario?

When the Scenario is created, we can execute it to solve the optimization problem, e.g.

scenario.execute({'algo': 'SLSQP', 'max_iter': 100}) # MDO case

or sampling the problem, e.g.

doe_scenario = create_scenario(
    disciplines=disciplines,
    formulation=formulation,
    objective_name=objective_name,
    design_space=design_space,
    scenario_type=scenario_type,
)
doe_scenario.execute({'algo': 'lhs', 'n_samples': 100}) # DOE case

Note

See also

We can print scenario information (disciplines, MDO formulation and algorithm):

repr(scenario)

which yields:

MDOScenario:
Disciplines: Sellar1 Sellar2 SellarSystem
MDOFormulation: MDF
Algorithm: SLSQP

4. How to get the optimum solution?

Once the Scenario is executed, the optimum results can be found in the execution log.

It is also possible to extract them by invoking the Scenario.get_optimum() method of the Scenario class. It returns a dictionary containing the optimum results for the scenario under consideration:

opt_results = scenario.get_optimum()
print("The solution of P is (x*,f(x*)) = ({}, {})".format(
    opt_results.x_opt, opt_results.f_opt
))

which yields:

The solution of P is (x*,f(x*)) = ([  0.00000000e+00   5.81632893e-01   6.38978246e-10], (0.527289923509+0j)).

5. How to log disciplinary and total execution metrics?

The Scenario.print_execution_metrics() method of the Scenario class adds disciplinary and total execution metrics in the logs:

scenario.print_execution_metrics()

which yields:

INFO - 12:50:53 : * Scenario Executions statistics *
INFO - 12:50:53 : * Discipline: Sellar1
INFO - 12:50:53 : Executions number: 128
INFO - 12:50:53 : Execution time:  0.00471186637878 s
INFO - 12:50:53 : Linearizations number: 9
INFO - 12:50:53 : * Discipline: Sellar2
INFO - 12:50:53 : Executions number: 128
INFO - 12:50:53 : Execution time:  0.0041139125824 s
INFO - 12:50:53 : Linearizations number: 9
INFO - 12:50:53 : * Discipline: SellarSystem
INFO - 12:50:53 : Executions number: 15
INFO - 12:50:53 : Execution time:  0.00153756141663 s
INFO - 12:50:53 : Linearizations number: 9
INFO - 12:50:53 : Total number of executions calls 271
INFO - 12:50:53 : Total number of linearizations 27

6. How to visualize the scenario execution and results?

GEMSEO provides many post-processing tools which can be called either by means of the Scenario.post_process() method of the Scenario class or by means of the execute_post() API function. Scenario.post_process() method of the Scenario class returns the list of available post-processing methods. Find more information about post-processing and visualization here: How to deal with post-processing.