Scalable problem

We want to solve the Aerostructure MDO problem by means of the MDF formulation with a higher dimension for the sweep parameter. For that, we use the ScalableProblem class.

from __future__ import division, unicode_literals

from gemseo.api import configure_logger, create_discipline, create_scenario
from gemseo.problems.aerostructure.aerostructure_design_space import (
    AerostructureDesignSpace,
)
from gemseo.problems.scalable.data_driven.problem import ScalableProblem

configure_logger()

Out:

<RootLogger root (INFO)>

Define the design problem

In a first step, we define the design problem in terms of objective function (to maximize or minimize), design variables (local and global) and constraints (equality and inequality).

design_variables = ["thick_airfoils", "thick_panels", "sweep"]
objective_function = "range"
eq_constraints = ["c_rf"]
ineq_constraints = ["c_lift"]
maximize_objective = True

Create the disciplinary datasets

Then, we create the disciplinary AbstractFullCache datasets based on a DiagonalDOE.

disciplines = create_discipline(["Aerodynamics", "Structure", "Mission"])
for discipline in disciplines:
    discipline.set_cache_policy(discipline.MEMORY_FULL_CACHE)
    design_space = AerostructureDesignSpace()
    design_space.filter(discipline.get_input_data_names())
    output = next(iter(discipline.get_output_data_names()))
    scenario = create_scenario(
        discipline, "DisciplinaryOpt", output, design_space, scenario_type="DOE"
    )
    scenario.execute({"algo": "DiagonalDOE", "n_samples": 10})

Out:

INFO - 14:42:34:
INFO - 14:42:34: *** Start DOE Scenario execution ***
INFO - 14:42:34: DOEScenario
INFO - 14:42:34:    Disciplines: Aerodynamics
INFO - 14:42:34:    MDOFormulation: DisciplinaryOpt
INFO - 14:42:34:    Algorithm: DiagonalDOE
INFO - 14:42:34: Optimization problem:
INFO - 14:42:34:    Minimize: drag(thick_airfoils, sweep, displ)
INFO - 14:42:34:    With respect to: thick_airfoils, sweep, displ
INFO - 14:42:34: DOE sampling:   0%|          | 0/10 [00:00<?, ?it]
INFO - 14:42:34: DOE sampling: 100%|██████████| 10/10 [00:00<00:00, 548.68 it/sec, obj=-320]
INFO - 14:42:34: Optimization result:
INFO - 14:42:34: Objective value = -319.99905478395067
INFO - 14:42:34: The result is feasible.
INFO - 14:42:34: Status: None
INFO - 14:42:34: Optimizer message: None
INFO - 14:42:34: Number of calls to the objective function by the optimizer: 10
INFO - 14:42:34: Design space:
INFO - 14:42:34: +----------------+-------------+-----------+-------------+-------+
INFO - 14:42:34: | name           | lower_bound |   value   | upper_bound | type  |
INFO - 14:42:34: +----------------+-------------+-----------+-------------+-------+
INFO - 14:42:34: | thick_airfoils |      5      |  (25+0j)  |      25     | float |
INFO - 14:42:34: | sweep          |      10     |  (35+0j)  |      35     | float |
INFO - 14:42:34: | displ          |    -1000    | (1000+0j) |     1000    | float |
INFO - 14:42:34: +----------------+-------------+-----------+-------------+-------+
INFO - 14:42:34: *** DOE Scenario run terminated ***
INFO - 14:42:34:
INFO - 14:42:34: *** Start DOE Scenario execution ***
INFO - 14:42:34: DOEScenario
INFO - 14:42:34:    Disciplines: Structure
INFO - 14:42:34:    MDOFormulation: DisciplinaryOpt
INFO - 14:42:34:    Algorithm: DiagonalDOE
INFO - 14:42:34: Optimization problem:
INFO - 14:42:34:    Minimize: mass(thick_panels, sweep, forces)
INFO - 14:42:34:    With respect to: thick_panels, sweep, forces
INFO - 14:42:34: DOE sampling:   0%|          | 0/10 [00:00<?, ?it]
INFO - 14:42:34: DOE sampling: 100%|██████████| 10/10 [00:00<00:00, 556.94 it/sec, obj=4.02e+5]
INFO - 14:42:34: Optimization result:
INFO - 14:42:34: Objective value = 100.08573388203513
INFO - 14:42:34: The result is feasible.
INFO - 14:42:34: Status: None
INFO - 14:42:34: Optimizer message: None
INFO - 14:42:34: Number of calls to the objective function by the optimizer: 10
INFO - 14:42:34: Design space:
INFO - 14:42:34: +--------------+-------------+------------+-------------+-------+
INFO - 14:42:34: | name         | lower_bound |   value    | upper_bound | type  |
INFO - 14:42:34: +--------------+-------------+------------+-------------+-------+
INFO - 14:42:34: | thick_panels |      1      |   (1+0j)   |      20     | float |
INFO - 14:42:34: | sweep        |      10     |  (10+0j)   |      35     | float |
INFO - 14:42:34: | forces       |    -1000    | (-1000+0j) |     1000    | float |
INFO - 14:42:34: +--------------+-------------+------------+-------------+-------+
INFO - 14:42:34: *** DOE Scenario run terminated ***
INFO - 14:42:34:
INFO - 14:42:34: *** Start DOE Scenario execution ***
INFO - 14:42:34: DOEScenario
INFO - 14:42:34:    Disciplines: Mission
INFO - 14:42:34:    MDOFormulation: DisciplinaryOpt
INFO - 14:42:34:    Algorithm: DiagonalDOE
INFO - 14:42:34: Optimization problem:
INFO - 14:42:34:    Minimize: range(drag, lift, mass, reserve_fact)
INFO - 14:42:34:    With respect to: drag, lift, mass, reserve_fact
INFO - 14:42:34: DOE sampling:   0%|          | 0/10 [00:00<?, ?it]
INFO - 14:42:34: DOE sampling: 100%|██████████| 10/10 [00:00<00:00, 538.35 it/sec, obj=1600.0]
INFO - 14:42:34: Optimization result:
INFO - 14:42:34: Objective value = 1600.0
INFO - 14:42:34: The result is feasible.
INFO - 14:42:34: Status: None
INFO - 14:42:34: Optimizer message: None
INFO - 14:42:34: Number of calls to the objective function by the optimizer: 10
INFO - 14:42:34: Design space:
INFO - 14:42:34: +--------------+-------------+-------------+-------------+-------+
INFO - 14:42:34: | name         | lower_bound |    value    | upper_bound | type  |
INFO - 14:42:34: +--------------+-------------+-------------+-------------+-------+
INFO - 14:42:34: | drag         |     100     |  (1000+0j)  |     1000    | float |
INFO - 14:42:34: | lift         |     0.1     |    (1+0j)   |      1      | float |
INFO - 14:42:34: | mass         |    100000   | (500000+0j) |    500000   | float |
INFO - 14:42:34: | reserve_fact |    -1000    |  (1000+0j)  |     1000    | float |
INFO - 14:42:34: +--------------+-------------+-------------+-------------+-------+
INFO - 14:42:34: *** DOE Scenario run terminated ***

Instantiate a scalable problem

In a third stage, we instantiate a ScalableProblem from these disciplinary datasets and from the definition of the MDO problem. We also increase the dimension of the sweep parameter.

datasets = [discipline.cache.export_to_dataset() for discipline in disciplines]
problem = ScalableProblem(
    datasets,
    design_variables,
    objective_function,
    eq_constraints,
    ineq_constraints,
    maximize_objective,
    sizes={"sweep": 2},
)
print(problem)

Out:

/home/docs/checkouts/readthedocs.org/user_builds/gemseo/conda/stable/lib/python3.8/site-packages/gemseo/problems/scalable/data_driven/model.py:150: ComplexWarning: Casting complex values to real discards the imaginary part
  data[:, indices] = (value - lower_bound) / (upper_bound - lower_bound)
MDO problem
   Disciplines: Aerodynamics, Structure, Mission
   Design variables: thick_airfoils, thick_panels, sweep
   Objective function: range (to maximize)
   Inequality constraints: c_lift
   Equality constraints: c_rf
   Sizes: sweep (2), thick_airfoils (1), displ (1), drag (1), forces (1), lift (1), thick_panels (1), mass (1), reserve_fact (1), range (1), c_lift (1), c_rf (1)

Note

We could also provide options to the ScalableModel objects by means of the constructor of ScalableProblem, e.g. fill_factor in the frame of the ScalableDiagonalModel. In this example, we use the standard ones.

Visualize the N2 chart

We can see the coupling between disciplines through this N2 chart:

problem.plot_n2_chart(save=False, show=True)
plot problem

Create an MDO scenario

Lastly, we create a MDOScenario with the MDF formulation and start the optimization at equilibrium, thus ensuring the feasibility of the first iterate.

scenario = problem.create_scenario("MDF", start_at_equilibrium=True)

Out:

INFO - 14:42:34: Build a preliminary MDA to start at equilibrium

Note

We could also provide options for the scalable models to the constructor of ScalableProblem, e.g. fill_factor in the frame of the ScalableDiagonalModel. In this example, we use the standard ones.

Once the scenario is created, we can execute it as any scenario. Here, we use the NLOPT_SLSQP optimization algorithm with no more than 100 iterations.

scenario.execute({"algo": "NLOPT_SLSQP", "max_iter": 100})

Out:

    INFO - 14:42:34:
    INFO - 14:42:34: *** Start MDO Scenario execution ***
    INFO - 14:42:34: MDOScenario
    INFO - 14:42:34:    Disciplines: sdm_Aerodynamics sdm_Structure sdm_Mission
    INFO - 14:42:34:    MDOFormulation: MDF
    INFO - 14:42:34:    Algorithm: NLOPT_SLSQP
    INFO - 14:42:34: Optimization problem:
    INFO - 14:42:34:    Minimize: -range(thick_airfoils, thick_panels, sweep)
    INFO - 14:42:34:    With respect to: thick_airfoils, thick_panels, sweep
    INFO - 14:42:34:    Subject to constraints:
    INFO - 14:42:34:       c_lift(thick_airfoils, thick_panels, sweep) <= [0.74804822]
    INFO - 14:42:34:       c_rf(thick_airfoils, thick_panels, sweep) == 0.4974338463722028
    INFO - 14:42:34: Design space:
    INFO - 14:42:34: +----------------+-------------+-------+-------------+-------+
    INFO - 14:42:34: | name           | lower_bound | value | upper_bound | type  |
    INFO - 14:42:34: +----------------+-------------+-------+-------------+-------+
    INFO - 14:42:34: | thick_airfoils |      0      |  0.5  |      1      | float |
    INFO - 14:42:34: | thick_panels   |      0      |  0.5  |      1      | float |
    INFO - 14:42:34: | sweep          |      0      |  0.5  |      1      | float |
    INFO - 14:42:34: | sweep          |      0      |  0.5  |      1      | float |
    INFO - 14:42:34: +----------------+-------------+-------+-------------+-------+
    INFO - 14:42:34: Optimization:   0%|          | 0/100 [00:00<?, ?it]
    INFO - 14:42:34: Optimization:   3%|▎         | 3/100 [00:00<00:00, 993.12 it/sec]
    INFO - 14:42:35: Optimization:   7%|▋         | 7/100 [00:00<00:00, 460.89 it/sec]
    INFO - 14:42:35: Optimization:   8%|▊         | 8/100 [00:00<00:00, 407.27 it/sec]
    INFO - 14:42:35: Optimization result:
    INFO - 14:42:35: Objective value = 0.2985276625156168
    INFO - 14:42:35: The result is feasible.
    INFO - 14:42:35: Status: None
    INFO - 14:42:35: Optimizer message: Successive iterates of the objective function are closer than ftol_rel or ftol_abs. GEMSEO Stopped the driver
    INFO - 14:42:35: Number of calls to the objective function by the optimizer: 8
    INFO - 14:42:35: Constraints values:
    INFO - 14:42:35:    c_lift + offset = [-0.49234168]
    INFO - 14:42:35:    c_rf - 0.4974338463722028 = -1.6653345369377348e-16
    INFO - 14:42:35: Design space:
    INFO - 14:42:35: +----------------+-------------+--------------------+-------------+-------+
    INFO - 14:42:35: | name           | lower_bound |       value        | upper_bound | type  |
    INFO - 14:42:35: +----------------+-------------+--------------------+-------------+-------+
    INFO - 14:42:35: | thick_airfoils |      0      | 0.9999999999999832 |      1      | float |
    INFO - 14:42:35: | thick_panels   |      0      | 0.5155052311585216 |      1      | float |
    INFO - 14:42:35: | sweep          |      0      | 0.9999999999999821 |      1      | float |
    INFO - 14:42:35: | sweep          |      0      | 0.9999999999999528 |      1      | float |
    INFO - 14:42:35: +----------------+-------------+--------------------+-------------+-------+
    INFO - 14:42:35: *** MDO Scenario run terminated in 0:00:00.254290 ***

{'algo': 'NLOPT_SLSQP', 'max_iter': 100}

We can post-process the results. Here, we use the standard OptHistoryView.

scenario.post_process("OptHistoryView", save=False, show=True)

Out:

<gemseo.post.opt_history_view.OptHistoryView object at 0x7f3b515d4970>

Total running time of the script: ( 0 minutes 0.952 seconds)

Gallery generated by Sphinx-Gallery