gemseo-multi-fidelity 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gemseo_multi_fidelity/__init__.py +17 -0
- gemseo_multi_fidelity/core/MFMapperAdapter_input.json +22 -0
- gemseo_multi_fidelity/core/MFMapperAdapter_output.json +22 -0
- gemseo_multi_fidelity/core/MFMapperLinker_input.json +22 -0
- gemseo_multi_fidelity/core/MFMapperLinker_output.json +22 -0
- gemseo_multi_fidelity/core/MFScenarioAdapter_input.json +39 -0
- gemseo_multi_fidelity/core/MFScenarioAdapter_output.json +23 -0
- gemseo_multi_fidelity/core/__init__.py +16 -0
- gemseo_multi_fidelity/core/boxed_domain.py +242 -0
- gemseo_multi_fidelity/core/corr_function.py +411 -0
- gemseo_multi_fidelity/core/criticality.py +124 -0
- gemseo_multi_fidelity/core/ds_mapper.py +307 -0
- gemseo_multi_fidelity/core/errors.py +42 -0
- gemseo_multi_fidelity/core/eval_mapper.py +188 -0
- gemseo_multi_fidelity/core/id_mapper_adapter.py +61 -0
- gemseo_multi_fidelity/core/mapper_adapter.py +126 -0
- gemseo_multi_fidelity/core/mapper_linker.py +72 -0
- gemseo_multi_fidelity/core/mf_formulation.py +635 -0
- gemseo_multi_fidelity/core/mf_logger.py +216 -0
- gemseo_multi_fidelity/core/mf_opt_problem.py +480 -0
- gemseo_multi_fidelity/core/mf_scenario.py +205 -0
- gemseo_multi_fidelity/core/noise_criterion.py +94 -0
- gemseo_multi_fidelity/core/projpolytope.out +0 -0
- gemseo_multi_fidelity/core/scenario_adapter.py +568 -0
- gemseo_multi_fidelity/core/stop_criteria.py +201 -0
- gemseo_multi_fidelity/core/strict_chain.py +75 -0
- gemseo_multi_fidelity/core/utils_model_quality.py +74 -0
- gemseo_multi_fidelity/corrections/__init__.py +16 -0
- gemseo_multi_fidelity/corrections/add_corr_function.py +80 -0
- gemseo_multi_fidelity/corrections/correction_factory.py +65 -0
- gemseo_multi_fidelity/corrections/mul_corr_function.py +86 -0
- gemseo_multi_fidelity/drivers/__init__.py +16 -0
- gemseo_multi_fidelity/drivers/mf_algo_factory.py +38 -0
- gemseo_multi_fidelity/drivers/mf_driver_lib.py +462 -0
- gemseo_multi_fidelity/drivers/refinement.py +234 -0
- gemseo_multi_fidelity/drivers/settings/__init__.py +16 -0
- gemseo_multi_fidelity/drivers/settings/base_mf_driver_settings.py +59 -0
- gemseo_multi_fidelity/drivers/settings/mf_refine_settings.py +50 -0
- gemseo_multi_fidelity/formulations/__init__.py +16 -0
- gemseo_multi_fidelity/formulations/refinement.py +144 -0
- gemseo_multi_fidelity/mapping/__init__.py +16 -0
- gemseo_multi_fidelity/mapping/identity_mapper.py +74 -0
- gemseo_multi_fidelity/mapping/interp_mapper.py +422 -0
- gemseo_multi_fidelity/mapping/mapper_factory.py +70 -0
- gemseo_multi_fidelity/mapping/mapping_errors.py +46 -0
- gemseo_multi_fidelity/mapping/subset_mapper.py +122 -0
- gemseo_multi_fidelity/mf_rosenbrock/__init__.py +16 -0
- gemseo_multi_fidelity/mf_rosenbrock/delayed_disc.py +136 -0
- gemseo_multi_fidelity/mf_rosenbrock/refact_rosen_testcase.py +46 -0
- gemseo_multi_fidelity/mf_rosenbrock/rosen_mf_case.py +284 -0
- gemseo_multi_fidelity/mf_rosenbrock/rosen_mf_funcs.py +350 -0
- gemseo_multi_fidelity/models/__init__.py +16 -0
- gemseo_multi_fidelity/models/fake_updater.py +112 -0
- gemseo_multi_fidelity/models/model_updater.py +91 -0
- gemseo_multi_fidelity/models/rbf/__init__.py +16 -0
- gemseo_multi_fidelity/models/rbf/kernel_factory.py +66 -0
- gemseo_multi_fidelity/models/rbf/kernels/__init__.py +16 -0
- gemseo_multi_fidelity/models/rbf/kernels/gaussian.py +93 -0
- gemseo_multi_fidelity/models/rbf/kernels/matern_3_2.py +101 -0
- gemseo_multi_fidelity/models/rbf/kernels/matern_5_2.py +101 -0
- gemseo_multi_fidelity/models/rbf/kernels/rbf_kernel.py +172 -0
- gemseo_multi_fidelity/models/rbf/rbf_model.py +422 -0
- gemseo_multi_fidelity/models/sparse_rbf_updater.py +96 -0
- gemseo_multi_fidelity/models/taylor/__init__.py +16 -0
- gemseo_multi_fidelity/models/taylor/taylor.py +212 -0
- gemseo_multi_fidelity/models/taylor_updater.py +66 -0
- gemseo_multi_fidelity/models/updater_factory.py +62 -0
- gemseo_multi_fidelity/settings/__init__.py +16 -0
- gemseo_multi_fidelity/settings/drivers.py +22 -0
- gemseo_multi_fidelity/settings/formulations.py +16 -0
- gemseo_multi_fidelity-0.0.1.dist-info/METADATA +99 -0
- gemseo_multi_fidelity-0.0.1.dist-info/RECORD +76 -0
- gemseo_multi_fidelity-0.0.1.dist-info/WHEEL +5 -0
- gemseo_multi_fidelity-0.0.1.dist-info/entry_points.txt +2 -0
- gemseo_multi_fidelity-0.0.1.dist-info/licenses/LICENSE.txt +165 -0
- gemseo_multi_fidelity-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 3 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
13
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
14
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
15
|
+
|
|
16
|
+
# Copyright (c) 2019 AIRBUS OPERATIONS
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Contributors:
|
|
20
|
+
# INITIAL AUTHORS - API and implementation and/or documentation
|
|
21
|
+
# :author: Romain Olivanti
|
|
22
|
+
# OTHER AUTHORS - MACROSCOPIC CHANGES
|
|
23
|
+
"""Delayed discipline."""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from time import sleep
|
|
28
|
+
from typing import TYPE_CHECKING
|
|
29
|
+
|
|
30
|
+
from gemseo.core.discipline.discipline import Discipline
|
|
31
|
+
from numpy import atleast_1d
|
|
32
|
+
from numpy import atleast_2d
|
|
33
|
+
from numpy import zeros
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from collections.abc import Callable
|
|
37
|
+
from collections.abc import Iterable
|
|
38
|
+
|
|
39
|
+
from gemseo.typing import StrKeyMapping
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class DelayedFuncDisc(Discipline):
|
|
43
|
+
"""Delayed function discipline.
|
|
44
|
+
|
|
45
|
+
Simple convenience discipline to encapsulate a single function.
|
|
46
|
+
Can add a fake delay for the function evaluation and the jacobian evaluation.
|
|
47
|
+
Delays can be different for the two calls and are added as input of the disciplines.
|
|
48
|
+
They can be adjusted for each call.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
DVS = "x"
|
|
52
|
+
DT_FUNC_SEC = "dt_func_sec"
|
|
53
|
+
DT_JAC_SEC = "dt_jac_sec"
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
name: str,
|
|
58
|
+
func: Callable,
|
|
59
|
+
jac: Callable,
|
|
60
|
+
dimension: int,
|
|
61
|
+
out_name: str | None = None,
|
|
62
|
+
dt_func_sec: float = 0.0,
|
|
63
|
+
dt_jac_sec: float = 0.0,
|
|
64
|
+
) -> None:
|
|
65
|
+
"""Constructor.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
name: The name of the discipline.
|
|
69
|
+
func: The function pointer.
|
|
70
|
+
jac: The jacobian pointer.
|
|
71
|
+
dimension: The dimension of the dvs.
|
|
72
|
+
out_name: The name of the output, name of the discipline if none.
|
|
73
|
+
dt_func_sec: The delay to add for the function evaluation.
|
|
74
|
+
dt_jac_sec: The delay to add for the jacobian evaluation.
|
|
75
|
+
"""
|
|
76
|
+
super().__init__(name=name)
|
|
77
|
+
self._func = func
|
|
78
|
+
self._jac = jac
|
|
79
|
+
|
|
80
|
+
self._check_dt(dt_func_sec)
|
|
81
|
+
self._check_dt(dt_jac_sec)
|
|
82
|
+
|
|
83
|
+
default_inputs = {
|
|
84
|
+
self.DVS: zeros(dimension),
|
|
85
|
+
self.DT_FUNC_SEC: dt_func_sec,
|
|
86
|
+
self.DT_JAC_SEC: dt_jac_sec,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
self._out_name = self.name if out_name is None else out_name
|
|
90
|
+
|
|
91
|
+
self.input_grammar.update_from_data(default_inputs)
|
|
92
|
+
self.output_grammar.update_from_names([self._out_name])
|
|
93
|
+
self.default_input_data = default_inputs
|
|
94
|
+
self.add_differentiated_inputs([self.DVS])
|
|
95
|
+
self.add_differentiated_outputs([self._out_name])
|
|
96
|
+
self._check_funcs()
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def _check_dt(dt_sec: float) -> None:
|
|
100
|
+
if dt_sec < 0.0:
|
|
101
|
+
msg = "dt < 0."
|
|
102
|
+
raise ValueError(msg)
|
|
103
|
+
|
|
104
|
+
def _check_funcs(self) -> None:
|
|
105
|
+
for f_name, f_pointer in zip(
|
|
106
|
+
["func", "jac"], [self._func, self._jac], strict=False
|
|
107
|
+
):
|
|
108
|
+
if not callable(f_pointer):
|
|
109
|
+
msg = f"{f_name} not callable"
|
|
110
|
+
raise TypeError(msg)
|
|
111
|
+
try:
|
|
112
|
+
f_pointer(self.default_input_data[self.DVS])
|
|
113
|
+
except Exception as exc:
|
|
114
|
+
msg = f"{f_name} not callable for the specified dimension"
|
|
115
|
+
raise RuntimeError(msg) from exc
|
|
116
|
+
|
|
117
|
+
def _run(self, input_data: StrKeyMapping) -> None:
|
|
118
|
+
x_vect = self.io.data[self.DVS]
|
|
119
|
+
dt_sec = self.io.data[self.DT_FUNC_SEC]
|
|
120
|
+
self._check_dt(dt_sec)
|
|
121
|
+
|
|
122
|
+
# Compute the value
|
|
123
|
+
sleep(dt_sec)
|
|
124
|
+
self.io.data[self._out_name] = atleast_1d(self._func(x_vect))
|
|
125
|
+
|
|
126
|
+
def _compute_jacobian(
|
|
127
|
+
self, input_names: Iterable[str] = (), output_names: Iterable[str] = ()
|
|
128
|
+
) -> None:
|
|
129
|
+
x_vect = self.io.data[self.DVS]
|
|
130
|
+
dt_sec = self.io.data[self.DT_JAC_SEC]
|
|
131
|
+
self._check_dt(dt_sec)
|
|
132
|
+
|
|
133
|
+
# Compute the jacobian
|
|
134
|
+
sleep(dt_sec)
|
|
135
|
+
self.jac = {}
|
|
136
|
+
self.jac[self._out_name] = {self.DVS: atleast_2d(self._jac(x_vect))}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 3 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
13
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
14
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
15
|
+
|
|
16
|
+
# Copyright (c) 2019 AIRBUS OPERATIONS
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Contributors:
|
|
20
|
+
# INITIAL AUTHORS - API and implementation and/or documentation
|
|
21
|
+
# :author: Romain Olivanti
|
|
22
|
+
# OTHER AUTHORS - MACROSCOPIC CHANGES
|
|
23
|
+
"""Refactoring of Rosenbrock test case."""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from .rosen_mf_case import MFRosenCaseGenerator
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build_scenarios() -> list:
|
|
31
|
+
"""Build the scenarios."""
|
|
32
|
+
coef = 1.0
|
|
33
|
+
fidelities = [
|
|
34
|
+
MFRosenCaseGenerator.HF_ROS,
|
|
35
|
+
MFRosenCaseGenerator.LF_ROS_CUS,
|
|
36
|
+
MFRosenCaseGenerator.LF_ROS_CUS,
|
|
37
|
+
]
|
|
38
|
+
dims = [2, 2, 2]
|
|
39
|
+
opts = [
|
|
40
|
+
{"coef": coef, "dt_func_sec": 0.0, "dt_jac_sec": 0.0},
|
|
41
|
+
{"coef": coef, "x_sol": 0.9, "dt_func_sec": 0.0, "dt_jac_sec": 0.0},
|
|
42
|
+
{"coef": coef, "x_sol": 0.6, "dt_func_sec": 0.0, "dt_jac_sec": 0.0},
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
generator = MFRosenCaseGenerator(fidelities, dimensions=dims, options=opts)
|
|
46
|
+
return generator.build_scenarios(l_b=-2.1, u_b=2.1)
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
5
|
+
# License version 3 as published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
10
|
+
# Lesser General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
13
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
14
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
15
|
+
|
|
16
|
+
# Copyright (c) 2019 AIRBUS OPERATIONS
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Contributors:
|
|
20
|
+
# INITIAL AUTHORS - API and implementation and/or documentation
|
|
21
|
+
# :author: Romain Olivanti
|
|
22
|
+
# OTHER AUTHORS - MACROSCOPIC CHANGES
|
|
23
|
+
# :author: Francois Gallard - portage to GEMSEO 6
|
|
24
|
+
"""Multi-fidelity Rosenbrock Case Generator."""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
from typing import TYPE_CHECKING
|
|
29
|
+
from typing import ClassVar
|
|
30
|
+
|
|
31
|
+
from gemseo import create_scenario
|
|
32
|
+
from gemseo.algos.design_space import DesignSpace
|
|
33
|
+
from gemseo.settings.opt import L_BFGS_B_Settings
|
|
34
|
+
|
|
35
|
+
from gemseo_multi_fidelity.mf_rosenbrock.delayed_disc import DelayedFuncDisc
|
|
36
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen
|
|
37
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen_custom
|
|
38
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen_custom_grad
|
|
39
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen_grad
|
|
40
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen_quartic
|
|
41
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen_quartic_grad
|
|
42
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen_sqr
|
|
43
|
+
from gemseo_multi_fidelity.mf_rosenbrock.rosen_mf_funcs import rosen_sqr_grad
|
|
44
|
+
|
|
45
|
+
if TYPE_CHECKING:
|
|
46
|
+
from gemseo.scenarios.mdo_scenario import MDOScenario
|
|
47
|
+
from numpy.typing import NDArray
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MFRosenCaseGenerator:
|
|
51
|
+
"""Multi-fidelity Rosenbrock Case Generator.
|
|
52
|
+
|
|
53
|
+
Builds scenarios for each fidelity specified.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
HF_ROS = "rosen"
|
|
57
|
+
LF_ROS_CUS = "rosen_lf_cus"
|
|
58
|
+
LF_ROS_QUA = "rosen_lf_qua"
|
|
59
|
+
LF_ROS_SQR = "rosen_lf_sqr"
|
|
60
|
+
|
|
61
|
+
AVAILABLE_FIDS: ClassVar[list] = [HF_ROS, LF_ROS_CUS, LF_ROS_QUA, LF_ROS_SQR]
|
|
62
|
+
"""The list of available fidelities."""
|
|
63
|
+
|
|
64
|
+
OUTPUT_NAME = "rosen"
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
fidelities: list[str],
|
|
69
|
+
dimensions: list[int] = 2,
|
|
70
|
+
options: list[dict] | None = None,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Constructor.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
fidelities: The list of tags, ordered from the highest fidelity to the
|
|
76
|
+
lowest.
|
|
77
|
+
dimensions: The list of dimensions.
|
|
78
|
+
options: The list of options dicts to set up the multi-fidelity functions.
|
|
79
|
+
"""
|
|
80
|
+
self._disciplines = []
|
|
81
|
+
if options is None:
|
|
82
|
+
options = []
|
|
83
|
+
try:
|
|
84
|
+
len(dimensions)
|
|
85
|
+
except TypeError:
|
|
86
|
+
dimensions = [dimensions]
|
|
87
|
+
self._build_disciplines(fidelities, dimensions, options)
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def _process_inputs(
|
|
91
|
+
n_fidelities: int, dimensions: list[int], opt_dicts: list[dict]
|
|
92
|
+
) -> tuple[list[int], list[dict]]:
|
|
93
|
+
n_dim = len(dimensions)
|
|
94
|
+
n_options = len(opt_dicts)
|
|
95
|
+
|
|
96
|
+
if n_dim < n_fidelities:
|
|
97
|
+
# Duplicate the last dimension specified
|
|
98
|
+
dimensions += [dimensions[-1]] * (n_fidelities - n_dim)
|
|
99
|
+
|
|
100
|
+
if n_options < n_fidelities:
|
|
101
|
+
# Append empty dicts
|
|
102
|
+
opt_dicts += [{}] * (n_fidelities - n_options)
|
|
103
|
+
return dimensions, opt_dicts
|
|
104
|
+
|
|
105
|
+
def _get_fidelity_funcs(
|
|
106
|
+
self, fidelity: str, options: dict
|
|
107
|
+
) -> tuple[NDArray, NDArray]:
|
|
108
|
+
# Root tag to funcs
|
|
109
|
+
if fidelity == self.HF_ROS:
|
|
110
|
+
func = rosen
|
|
111
|
+
grad = rosen_grad
|
|
112
|
+
elif fidelity == self.LF_ROS_CUS:
|
|
113
|
+
func = rosen_custom
|
|
114
|
+
grad = rosen_custom_grad
|
|
115
|
+
elif fidelity == self.LF_ROS_QUA:
|
|
116
|
+
func = rosen_quartic
|
|
117
|
+
grad = rosen_quartic_grad
|
|
118
|
+
elif fidelity == self.LF_ROS_SQR:
|
|
119
|
+
func = rosen_sqr
|
|
120
|
+
grad = rosen_sqr_grad
|
|
121
|
+
else:
|
|
122
|
+
msg = f"{fidelity} not in {self.AVAILABLE_FIDS}"
|
|
123
|
+
raise ValueError(msg)
|
|
124
|
+
|
|
125
|
+
# Build callables with unique arg x_vect
|
|
126
|
+
func_opts = options.copy()
|
|
127
|
+
|
|
128
|
+
def wrapped_func(x_vect: NDArray) -> NDArray:
|
|
129
|
+
return func(x_vect, **func_opts)
|
|
130
|
+
|
|
131
|
+
def wrapped_grad(x_vect: NDArray) -> NDArray:
|
|
132
|
+
return grad(x_vect, **func_opts)
|
|
133
|
+
|
|
134
|
+
return wrapped_func, wrapped_grad
|
|
135
|
+
|
|
136
|
+
def _build_disciplines(
|
|
137
|
+
self, fidelities: list[str], dimensions: list[int], opt_dicts: list[dict]
|
|
138
|
+
) -> None:
|
|
139
|
+
"""Build the specified Rosenbrock fidelities as individual disciplines.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
fidelities: The list of fidelity tags.
|
|
143
|
+
dimensions: The list of dimensions.
|
|
144
|
+
opt_dicts: The list of dictionary storing options to configure the different
|
|
145
|
+
fidelities.
|
|
146
|
+
"""
|
|
147
|
+
last_dt_func = None
|
|
148
|
+
last_dt_jac = None
|
|
149
|
+
|
|
150
|
+
dimensions, opt_dicts = self._process_inputs(
|
|
151
|
+
len(fidelities), dimensions, opt_dicts
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
for fidelity, dim, opt_dict in zip(
|
|
155
|
+
fidelities, dimensions, opt_dicts, strict=False
|
|
156
|
+
):
|
|
157
|
+
# Pop delay options, handled at the discipline level
|
|
158
|
+
try:
|
|
159
|
+
dt_func = opt_dict.pop(DelayedFuncDisc.DT_FUNC_SEC)
|
|
160
|
+
except KeyError:
|
|
161
|
+
dt_func = 0.0
|
|
162
|
+
try:
|
|
163
|
+
dt_jac = opt_dict.pop(DelayedFuncDisc.DT_JAC_SEC)
|
|
164
|
+
except KeyError:
|
|
165
|
+
dt_jac = 0.0
|
|
166
|
+
# Perform checks on the delay logic
|
|
167
|
+
# Func
|
|
168
|
+
if last_dt_func is not None and dt_func > last_dt_func:
|
|
169
|
+
msg = (
|
|
170
|
+
f"The evaluation of {fidelity} "
|
|
171
|
+
"takes longer than the previous fidelity"
|
|
172
|
+
)
|
|
173
|
+
raise ValueError(msg)
|
|
174
|
+
last_dt_func = dt_func
|
|
175
|
+
# Jacobian
|
|
176
|
+
if last_dt_jac is not None and dt_jac > last_dt_jac:
|
|
177
|
+
msg = (
|
|
178
|
+
f"The jacobian of {fidelity} "
|
|
179
|
+
"takes longer than the previous fidelity"
|
|
180
|
+
)
|
|
181
|
+
raise ValueError(msg)
|
|
182
|
+
last_dt_jac = dt_jac
|
|
183
|
+
# Build the functions
|
|
184
|
+
func, grad = self._get_fidelity_funcs(fidelity, opt_dict)
|
|
185
|
+
discipline = DelayedFuncDisc(
|
|
186
|
+
fidelity,
|
|
187
|
+
func,
|
|
188
|
+
grad,
|
|
189
|
+
dim,
|
|
190
|
+
out_name=self.OUTPUT_NAME,
|
|
191
|
+
dt_func_sec=dt_func,
|
|
192
|
+
dt_jac_sec=dt_jac,
|
|
193
|
+
)
|
|
194
|
+
self._disciplines.append(discipline)
|
|
195
|
+
|
|
196
|
+
def build_scenarios(self, l_b: float = -2.1, u_b: float = 2.1) -> list[MDOScenario]:
|
|
197
|
+
"""Build scenarios.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
l_b: The lower bound.
|
|
201
|
+
u_b: The upper bound.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
The list of scenarios.
|
|
205
|
+
"""
|
|
206
|
+
# Process design spaces, adapt dim, default inputs if needed
|
|
207
|
+
scenarios = []
|
|
208
|
+
|
|
209
|
+
for i, disc in enumerate(self._disciplines):
|
|
210
|
+
scenario_name = f"rosen_l{i:d}"
|
|
211
|
+
# Build the design space
|
|
212
|
+
design_space = DesignSpace()
|
|
213
|
+
default_dvs = disc.default_input_data[disc.DVS]
|
|
214
|
+
design_space.add_variable(
|
|
215
|
+
disc.DVS,
|
|
216
|
+
len(default_dvs),
|
|
217
|
+
lower_bound=l_b,
|
|
218
|
+
upper_bound=u_b,
|
|
219
|
+
value=default_dvs,
|
|
220
|
+
type_="float",
|
|
221
|
+
)
|
|
222
|
+
# Build the scenario
|
|
223
|
+
scenario = create_scenario(
|
|
224
|
+
[disc],
|
|
225
|
+
self.OUTPUT_NAME,
|
|
226
|
+
design_space,
|
|
227
|
+
formulation_name="DisciplinaryOpt",
|
|
228
|
+
name=scenario_name,
|
|
229
|
+
scenario_type="MDO",
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
scenario.set_algorithm(algo_settings_model=L_BFGS_B_Settings(max_iter=100))
|
|
233
|
+
# search_paths=search_paths)
|
|
234
|
+
scenarios.append(scenario)
|
|
235
|
+
return scenarios
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
if __name__ == "__main__":
|
|
239
|
+
from time import time
|
|
240
|
+
|
|
241
|
+
COEF = 1.0
|
|
242
|
+
FIDS = [
|
|
243
|
+
MFRosenCaseGenerator.HF_ROS,
|
|
244
|
+
MFRosenCaseGenerator.LF_ROS_CUS,
|
|
245
|
+
MFRosenCaseGenerator.LF_ROS_CUS,
|
|
246
|
+
MFRosenCaseGenerator.LF_ROS_QUA,
|
|
247
|
+
]
|
|
248
|
+
DIMS = [4, 4, 3, 2]
|
|
249
|
+
OPTS = [
|
|
250
|
+
{"coef": COEF, "dt_func_sec": 2.0, "dt_jac_sec": 1.5},
|
|
251
|
+
{"coef": COEF, "x_sol": 0.9, "dt_func_sec": 1.0, "dt_jac_sec": 1.0},
|
|
252
|
+
{"coef": COEF, "x_sol": 0.7, "dt_func_sec": 0.7, "dt_jac_sec": 0.7},
|
|
253
|
+
{"coef": COEF, "dt_func_sec": 0.2, "dt_jac_sec": 0.2},
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
# # Made to fail on check
|
|
257
|
+
# OPTS = [{"coef": COEF,
|
|
258
|
+
# "dt_func_sec": 2.0,
|
|
259
|
+
# "dt_jac_sec": 1.5
|
|
260
|
+
# },
|
|
261
|
+
# {"coef": COEF,
|
|
262
|
+
# "x_sol": 0.9,
|
|
263
|
+
# "dt_func_sec": 1.0,
|
|
264
|
+
# "dt_jac_sec": 1.0
|
|
265
|
+
# },
|
|
266
|
+
# {"coef": COEF,
|
|
267
|
+
# "x_sol": 0.7,
|
|
268
|
+
# "dt_func_sec": 1.5,
|
|
269
|
+
# "dt_jac_sec": 0.7
|
|
270
|
+
# },
|
|
271
|
+
# {"coef": COEF,
|
|
272
|
+
# "dt_func_sec": 0.2,
|
|
273
|
+
# "dt_jac_sec": 0.2
|
|
274
|
+
# }]
|
|
275
|
+
ros_builder = MFRosenCaseGenerator(FIDS, dimensions=DIMS, options=OPTS)
|
|
276
|
+
|
|
277
|
+
for disc in ros_builder._disciplines:
|
|
278
|
+
dt = -time()
|
|
279
|
+
out = disc.execute()
|
|
280
|
+
dt += time()
|
|
281
|
+
|
|
282
|
+
dt = -time()
|
|
283
|
+
out_lin = disc.linearize()
|
|
284
|
+
dt += time()
|