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 annotations

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

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 BaseFullCache datasets based on a DiagonalDOE.

disciplines = create_discipline(["Aerodynamics", "Structure", "Mission"])
datasets = []
for discipline in disciplines:
    design_space = AerostructureDesignSpace()
    design_space.filter(discipline.io.input_grammar.names)
    output_names = iter(discipline.io.output_grammar.names)
    scenario = create_scenario(
        discipline,
        next(output_names),
        design_space,
        formulation_name="DisciplinaryOpt",
        scenario_type="DOE",
    )
    for output_name in output_names:
        scenario.add_observable(output_name)
    scenario.execute(algo_name="DiagonalDOE", n_samples=10)
    datasets.append(scenario.to_dataset(name=discipline.name, opt_naming=False))
INFO - 16:21:05: *** Start DOEScenario execution ***
INFO - 16:21:05: DOEScenario
INFO - 16:21:05:    Disciplines: Aerodynamics
INFO - 16:21:05:    MDO formulation: DisciplinaryOpt
INFO - 16:21:05: Optimization problem:
INFO - 16:21:05:    minimize drag(thick_airfoils, sweep, displ)
INFO - 16:21:05:    with respect to displ, sweep, thick_airfoils
INFO - 16:21:05:    over the design space:
INFO - 16:21:05:       +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05:       | Name           | Lower bound | Value | Upper bound | Type  |
INFO - 16:21:05:       +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05:       | thick_airfoils |      5      |   15  |      25     | float |
INFO - 16:21:05:       | sweep          |      10     |   25  |      35     | float |
INFO - 16:21:05:       | displ          |    -1000    |  -700 |     1000    | float |
INFO - 16:21:05:       +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05: Solving optimization problem with algorithm DiagonalDOE:
INFO - 16:21:05:     10%|█         | 1/10 [00:00<00:00, 385.01 it/sec, feas=True, obj=422]
INFO - 16:21:05:     20%|██        | 2/10 [00:00<00:00, 656.44 it/sec, feas=True, obj=336]
INFO - 16:21:05:     30%|███       | 3/10 [00:00<00:00, 875.45 it/sec, feas=True, obj=250]
INFO - 16:21:05:     40%|████      | 4/10 [00:00<00:00, 1059.64 it/sec, feas=True, obj=166]
INFO - 16:21:05:     50%|█████     | 5/10 [00:00<00:00, 1209.64 it/sec, feas=True, obj=82.3]
INFO - 16:21:05:     60%|██████    | 6/10 [00:00<00:00, 1341.82 it/sec, feas=True, obj=-0.0983]
INFO - 16:21:05:     70%|███████   | 7/10 [00:00<00:00, 1454.55 it/sec, feas=True, obj=-81.6]
INFO - 16:21:05:     80%|████████  | 8/10 [00:00<00:00, 1548.36 it/sec, feas=True, obj=-162]
INFO - 16:21:05:     90%|█████████ | 9/10 [00:00<00:00, 1638.12 it/sec, feas=True, obj=-242]
INFO - 16:21:05:    100%|██████████| 10/10 [00:00<00:00, 1694.46 it/sec, feas=True, obj=-320]
INFO - 16:21:05: Optimization result:
INFO - 16:21:05:    Optimizer info:
INFO - 16:21:05:       Status: None
INFO - 16:21:05:       Message: None
INFO - 16:21:05:    Solution:
INFO - 16:21:05:       Objective: -319.99905478395067
INFO - 16:21:05:       Design space:
INFO - 16:21:05:          +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05:          | Name           | Lower bound | Value | Upper bound | Type  |
INFO - 16:21:05:          +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05:          | thick_airfoils |      5      |   25  |      25     | float |
INFO - 16:21:05:          | sweep          |      10     |   35  |      35     | float |
INFO - 16:21:05:          | displ          |    -1000    |  1000 |     1000    | float |
INFO - 16:21:05:          +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05: *** End DOEScenario execution ***
INFO - 16:21:05: *** Start DOEScenario execution ***
INFO - 16:21:05: DOEScenario
INFO - 16:21:05:    Disciplines: Structure
INFO - 16:21:05:    MDO formulation: DisciplinaryOpt
INFO - 16:21:05: Optimization problem:
INFO - 16:21:05:    minimize mass(thick_panels, sweep, forces)
INFO - 16:21:05:    with respect to forces, sweep, thick_panels
INFO - 16:21:05:    over the design space:
INFO - 16:21:05:       +--------------+-------------+-------+-------------+-------+
INFO - 16:21:05:       | Name         | Lower bound | Value | Upper bound | Type  |
INFO - 16:21:05:       +--------------+-------------+-------+-------------+-------+
INFO - 16:21:05:       | thick_panels |      1      |   3   |      20     | float |
INFO - 16:21:05:       | sweep        |      10     |   25  |      35     | float |
INFO - 16:21:05:       | forces       |    -1000    |  400  |     1000    | float |
INFO - 16:21:05:       +--------------+-------------+-------+-------------+-------+
INFO - 16:21:05: Solving optimization problem with algorithm DiagonalDOE:
INFO - 16:21:05:     10%|█         | 1/10 [00:00<00:00, 387.07 it/sec, feas=True, obj=100]
INFO - 16:21:05:     20%|██        | 2/10 [00:00<00:00, 665.29 it/sec, feas=True, obj=4.48e+4]
INFO - 16:21:05:     30%|███       | 3/10 [00:00<00:00, 880.85 it/sec, feas=True, obj=8.94e+4]
INFO - 16:21:05:     40%|████      | 4/10 [00:00<00:00, 1062.45 it/sec, feas=True, obj=1.34e+5]
INFO - 16:21:05:     50%|█████     | 5/10 [00:00<00:00, 1216.59 it/sec, feas=True, obj=1.79e+5]
INFO - 16:21:05:     60%|██████    | 6/10 [00:00<00:00, 1340.60 it/sec, feas=True, obj=2.23e+5]
INFO - 16:21:05:     70%|███████   | 7/10 [00:00<00:00, 1451.53 it/sec, feas=True, obj=2.68e+5]
INFO - 16:21:05:     80%|████████  | 8/10 [00:00<00:00, 1545.93 it/sec, feas=True, obj=3.13e+5]
INFO - 16:21:05:     90%|█████████ | 9/10 [00:00<00:00, 1633.65 it/sec, feas=True, obj=3.57e+5]
INFO - 16:21:05:    100%|██████████| 10/10 [00:00<00:00, 1694.87 it/sec, feas=True, obj=4.02e+5]
INFO - 16:21:05: Optimization result:
INFO - 16:21:05:    Optimizer info:
INFO - 16:21:05:       Status: None
INFO - 16:21:05:       Message: None
INFO - 16:21:05:    Solution:
INFO - 16:21:05:       Objective: 100.08573388203513
INFO - 16:21:05:       Design space:
INFO - 16:21:05:          +--------------+-------------+-------+-------------+-------+
INFO - 16:21:05:          | Name         | Lower bound | Value | Upper bound | Type  |
INFO - 16:21:05:          +--------------+-------------+-------+-------------+-------+
INFO - 16:21:05:          | thick_panels |      1      |   1   |      20     | float |
INFO - 16:21:05:          | sweep        |      10     |   10  |      35     | float |
INFO - 16:21:05:          | forces       |    -1000    | -1000 |     1000    | float |
INFO - 16:21:05:          +--------------+-------------+-------+-------------+-------+
INFO - 16:21:05: *** End DOEScenario execution ***
INFO - 16:21:05: *** Start DOEScenario execution ***
INFO - 16:21:05: DOEScenario
INFO - 16:21:05:    Disciplines: Mission
INFO - 16:21:05:    MDO formulation: DisciplinaryOpt
INFO - 16:21:05: Optimization problem:
INFO - 16:21:05:    minimize range(drag, lift, mass, reserve_fact)
INFO - 16:21:05:    with respect to drag, lift, mass, reserve_fact
INFO - 16:21:05:    over the design space:
INFO - 16:21:05:       +--------------+-------------+--------+-------------+-------+
INFO - 16:21:05:       | Name         | Lower bound | Value  | Upper bound | Type  |
INFO - 16:21:05:       +--------------+-------------+--------+-------------+-------+
INFO - 16:21:05:       | drag         |     100     |  340   |     1000    | float |
INFO - 16:21:05:       | lift         |     0.1     |  0.5   |      1      | float |
INFO - 16:21:05:       | mass         |    100000   | 100000 |    500000   | float |
INFO - 16:21:05:       | reserve_fact |    -1000    |   0    |     1000    | float |
INFO - 16:21:05:       +--------------+-------------+--------+-------------+-------+
INFO - 16:21:05: Solving optimization problem with algorithm DiagonalDOE:
INFO - 16:21:05:     10%|█         | 1/10 [00:00<00:00, 425.60 it/sec, feas=True, obj=8e+3+0j]
INFO - 16:21:05:     20%|██        | 2/10 [00:00<00:00, 711.86 it/sec, feas=True, obj=5.54e+3+0j]
INFO - 16:21:05:     30%|███       | 3/10 [00:00<00:00, 939.02 it/sec, feas=True, obj=4.24e+3+0j]
INFO - 16:21:05:     40%|████      | 4/10 [00:00<00:00, 1122.00 it/sec, feas=True, obj=3.43e+3+0j]
INFO - 16:21:05:     50%|█████     | 5/10 [00:00<00:00, 1267.85 it/sec, feas=True, obj=2.88e+3+0j]
INFO - 16:21:05:     60%|██████    | 6/10 [00:00<00:00, 1398.72 it/sec, feas=True, obj=2.48e+3+0j]
INFO - 16:21:05:     70%|███████   | 7/10 [00:00<00:00, 1509.60 it/sec, feas=True, obj=2.18e+3+0j]
INFO - 16:21:05:     80%|████████  | 8/10 [00:00<00:00, 1597.22 it/sec, feas=True, obj=1.95e+3+0j]
INFO - 16:21:05:     90%|█████████ | 9/10 [00:00<00:00, 1666.24 it/sec, feas=True, obj=1.76e+3+0j]
INFO - 16:21:05:    100%|██████████| 10/10 [00:00<00:00, 1707.29 it/sec, feas=True, obj=(1600+0j)]
INFO - 16:21:05: Optimization result:
INFO - 16:21:05:    Optimizer info:
INFO - 16:21:05:       Status: None
INFO - 16:21:05:       Message: None
INFO - 16:21:05:    Solution:
INFO - 16:21:05:       Objective: (1600+0j)
INFO - 16:21:05:       Design space:
INFO - 16:21:05:          +--------------+-------------+--------+-------------+-------+
INFO - 16:21:05:          | Name         | Lower bound | Value  | Upper bound | Type  |
INFO - 16:21:05:          +--------------+-------------+--------+-------------+-------+
INFO - 16:21:05:          | drag         |     100     |  1000  |     1000    | float |
INFO - 16:21:05:          | lift         |     0.1     |   1    |      1      | float |
INFO - 16:21:05:          | mass         |    100000   | 500000 |    500000   | float |
INFO - 16:21:05:          | reserve_fact |    -1000    |  1000  |     1000    | float |
INFO - 16:21:05:          +--------------+-------------+--------+-------------+-------+
INFO - 16:21:05: *** End DOEScenario execution ***

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.

problem = ScalableProblem(
    datasets,
    design_variables,
    objective_function,
    eq_constraints,
    ineq_constraints,
    maximize_objective,
    sizes={"sweep": 2},
)
print(problem)
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: displ (1), sweep (2), thick_airfoils (1), drag (1), forces (1), lift (1), thick_panels (1), mass (1), reserve_fact (1), c_lift (1), c_rf (1), range (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 an 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)
INFO - 16:21:05: 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_name="NLOPT_SLSQP", max_iter=100)
INFO - 16:21:05: *** Start MDOScenario execution ***
INFO - 16:21:05: MDOScenario
INFO - 16:21:05:    Disciplines: sdm_Aerodynamics sdm_Mission sdm_Structure
INFO - 16:21:05:    MDO formulation: MDF
INFO - 16:21:05: Optimization problem:
INFO - 16:21:05:    minimize -range(thick_airfoils, thick_panels, sweep)
INFO - 16:21:05:    with respect to sweep, thick_airfoils, thick_panels
INFO - 16:21:05:    under the equality constraints
INFO - 16:21:05:       c_rf(thick_airfoils, thick_panels, sweep) = 0.49642016361892943
INFO - 16:21:05:    under the inequality constraints
INFO - 16:21:05:       c_lift(thick_airfoils, thick_panels, sweep) <= [0.74554856]
INFO - 16:21:05:    over the design space:
INFO - 16:21:05:       +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05:       | Name           | Lower bound | Value | Upper bound | Type  |
INFO - 16:21:05:       +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05:       | thick_airfoils |      0      |  0.5  |      1      | float |
INFO - 16:21:05:       | thick_panels   |      0      |  0.5  |      1      | float |
INFO - 16:21:05:       | sweep[0]       |      0      |  0.5  |      1      | float |
INFO - 16:21:05:       | sweep[1]       |      0      |  0.5  |      1      | float |
INFO - 16:21:05:       +----------------+-------------+-------+-------------+-------+
INFO - 16:21:05: Solving optimization problem with algorithm NLOPT_SLSQP:
INFO - 16:21:05:      1%|          | 1/100 [00:00<00:01, 57.41 it/sec, feas=True, obj=-0.168]
INFO - 16:21:05:      2%|▏         | 2/100 [00:00<00:01, 52.80 it/sec, feas=True, obj=-0.172]
INFO - 16:21:05:      3%|▎         | 3/100 [00:00<00:02, 39.75 it/sec, feas=True, obj=-0.2]
INFO - 16:21:05:      4%|▍         | 4/100 [00:00<00:02, 41.24 it/sec, feas=True, obj=-0.302]
INFO - 16:21:05:      5%|▌         | 5/100 [00:00<00:02, 41.57 it/sec, feas=True, obj=-0.302]
INFO - 16:21:05:      6%|▌         | 6/100 [00:00<00:02, 41.00 it/sec, feas=True, obj=-0.303]
INFO - 16:21:05:      7%|▋         | 7/100 [00:00<00:02, 41.45 it/sec, feas=True, obj=-0.304]
INFO - 16:21:05:      8%|▊         | 8/100 [00:00<00:02, 41.39 it/sec, feas=True, obj=-0.309]
INFO - 16:21:05:      9%|▉         | 9/100 [00:00<00:02, 41.71 it/sec, feas=True, obj=-0.309]
INFO - 16:21:05:     10%|█         | 10/100 [00:00<00:02, 42.09 it/sec, feas=True, obj=-0.309]
INFO - 16:21:05:     11%|█         | 11/100 [00:00<00:02, 42.44 it/sec, feas=True, obj=-0.309]
INFO - 16:21:05: Optimization result:
INFO - 16:21:05:    Optimizer info:
INFO - 16:21:05:       Status: None
INFO - 16:21:05:       Message: Successive iterates of the objective function are closer than ftol_rel or ftol_abs. GEMSEO stopped the driver.
INFO - 16:21:05:    Solution:
INFO - 16:21:05:       The solution is feasible.
INFO - 16:21:05:       Objective: -0.3093760989443489
INFO - 16:21:05:       Standardized constraints:
INFO - 16:21:05:          [c_lift+offset] = [-0.42031165]
INFO - 16:21:05:          [c_rf-0.49642016361892943] = 0.0
INFO - 16:21:05:       Design space:
INFO - 16:21:05:          +----------------+-------------+--------------------+-------------+-------+
INFO - 16:21:05:          | Name           | Lower bound |       Value        | Upper bound | Type  |
INFO - 16:21:05:          +----------------+-------------+--------------------+-------------+-------+
INFO - 16:21:05:          | thick_airfoils |      0      | 0.300477022842664  |      1      | float |
INFO - 16:21:05:          | thick_panels   |      0      | 0.9999999999999986 |      1      | float |
INFO - 16:21:05:          | sweep[0]       |      0      |         1          |      1      | float |
INFO - 16:21:05:          | sweep[1]       |      0      | 0.9999999999999999 |      1      | float |
INFO - 16:21:05:          +----------------+-------------+--------------------+-------------+-------+
INFO - 16:21:05: *** End MDOScenario execution ***

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

scenario.post_process(post_name="OptHistoryView", save=False, show=True)
  • Evolution of the optimization variables
  • Evolution of the objective value
  • Evolution of the distance to the optimum
  • Evolution of the inequality constraints
  • Evolution of the equality constraints
<gemseo.post.opt_history_view.OptHistoryView object at 0x7c2f8f67a660>

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

Gallery generated by Sphinx-Gallery