Source code for gemseo.problems.mdo.scalable.parametric.disciplines.scalable_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 scalable discipline."""

from __future__ import annotations

from typing import TYPE_CHECKING

from gemseo.problems.mdo.scalable.parametric.core.disciplines.scalable_discipline import (  # noqa: E501
    ScalableDiscipline as _ScalableDiscipline,
)
from gemseo.problems.mdo.scalable.parametric.core.variable_names import (
    SHARED_DESIGN_VARIABLE_NAME,
)
from gemseo.problems.mdo.scalable.parametric.core.variable_names import get_u_local_name
from gemseo.problems.mdo.scalable.parametric.core.variable_names import get_x_local_name
from gemseo.problems.mdo.scalable.parametric.disciplines.base_discipline import (
    BaseDiscipline,
)

if TYPE_CHECKING:
    from collections.abc import Iterable
    from collections.abc import Mapping

    from numpy.typing import NDArray


[docs] class ScalableDiscipline(BaseDiscipline): r"""A scalable discipline. It computes the output :math:`y_i=a_i-D_{i,0}x_0-D_{i,i}x_i+\sum_{j=1\atop j\neq i}^N C_{i,j}y_j`. """ _CORE_DISCIPLINE_CLASS = _ScalableDiscipline __x_i_name: str r"""The name of the local design variable :math:`x_i`.""" __u_i_name: str r"""The name of the local uncertain variable :math:`u_i`.""" def __init__( self, index: int, a_i: NDArray, D_i0: NDArray, # noqa: N803 D_ii: NDArray, # noqa: N803 C_ij: Mapping[str, NDArray[float]], # noqa: N803 **default_input_values: NDArray[float], ) -> None: r""" Args: index: The index :math:`i` of the scalable discipline. a_i: The offset vector :math:`a_i`. D_i0: The coefficient matrix :math:`D_{i,0}` to multiply the shared design variable :math:`x_0`. D_ii: The coefficient matrix :math:`D_{i,i}` to multiply the local design variable :math:`x_i`. C_ij: The coefficient matrices :math:`\left(C_{i,j}\right)_{j=1\atop j\neq i}^N` where :math:`C_{i,j}` is used to multiply the coupling variable :math:`y_j`. **default_input_values: The default values of the input variables. """ # noqa: D205 D212 super().__init__(index, a_i, D_i0, D_ii, C_ij, **default_input_values) self.__u_i_name = get_u_local_name(self._discipline.index) self.__x_i_name = get_x_local_name(self._discipline.index) def _run(self) -> None: if self.__u_i_name in self.input_grammar: u_i = self.get_inputs_by_name(self.__u_i_name) else: u_i = 0 self.store_local_data( **self._discipline( self._local_data[SHARED_DESIGN_VARIABLE_NAME], self._local_data[self.__x_i_name], u_i, **{ y_j_name: self._local_data[y_j_name] for y_j_name in self._discipline.coefficients.C_ij }, ) ) 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], self._local_data[self.__x_i_name], { y_j_name: self._local_data[y_j_name] for y_j_name in self._discipline.coefficients.C_ij }, compute_jacobian=True, ) for output_name in jac: sub_jac = jac[output_name] self_sub_jac = self.jac[output_name] for input_name in jac[output_name]: self_sub_jac[input_name] = sub_jac[input_name]