Source code for gemseo.problems.scalable.parametric.disciplines.main_discipline
# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Contributors:
# INITIAL AUTHORS - initial API and implementation and/or initial
# documentation
# :author: Matthias De Lozzo
# OTHER AUTHORS - MACROSCOPIC CHANGES
"""The main discipline."""
from __future__ import annotations
from typing import TYPE_CHECKING
from gemseo.problems.scalable.parametric.core.disciplines.main_discipline import (
MainDiscipline as _MainDiscipline,
)
from gemseo.problems.scalable.parametric.core.variable_names import (
SHARED_DESIGN_VARIABLE_NAME,
)
from gemseo.problems.scalable.parametric.core.variable_names import get_coupling_name
from gemseo.problems.scalable.parametric.disciplines.base_discipline import (
BaseDiscipline,
)
if TYPE_CHECKING:
from collections.abc import Iterable
from numpy.typing import NDArray
[docs]
class MainDiscipline(BaseDiscipline):
r"""The main discipline of the scalable problem.
It computes the objective :math:`x_0^Tx_0 + \sum_{i=1}^N y_i^Ty_i`. and the left-
hand side of the constraints :math:`t_1-y_1\leq 0,\ldots,t_N-y_N\leq 0`.
"""
_CORE_DISCIPLINE_CLASS = _MainDiscipline
__n_scalable_disciplines: int
r"""The number of scalable disciplines :math:`N`."""
__y_i_names: list[str]
r"""The names of the coupling variables :math:`y_1,\ldots,y_N`."""
def __init__(
self,
*t_i: NDArray[float],
**default_input_values: NDArray[float],
) -> None:
r"""
Args:
*t_i: The threshold vectors :math:`t_1,\ldots,t_N`.
**default_input_values: The default values of the input variables.
""" # noqa: D205 D212
self.__n_scalable_disciplines = len(t_i)
self.__y_i_names = [
get_coupling_name(index) for index in range(1, len(t_i) + 1)
]
super().__init__(*t_i, **default_input_values)
def _run(self) -> None:
self.store_local_data(
**self._discipline(
self._local_data[SHARED_DESIGN_VARIABLE_NAME],
**{
y_i_name: self._local_data[y_i_name]
for y_i_name in self.__y_i_names
},
)
)
def _compute_jacobian(
self,
inputs: Iterable[str] | None = None,
outputs: Iterable[str] | None = None,
) -> None:
self._init_jacobian(inputs, outputs)
jac = self._discipline(
self.local_data[SHARED_DESIGN_VARIABLE_NAME],
compute_jacobian=True,
**{y_i_name: self.local_data[y_i_name] for y_i_name in self.__y_i_names},
)
for output_name in jac:
self_sub_jac = self.jac[output_name]
sub_jac = jac[output_name]
for input_name in jac[output_name]:
self_sub_jac[input_name] = sub_jac[input_name]