Source code for pina.equation.system_equation

"""Module for the System of Equation."""

import torch
from .equation_interface import EquationInterface
from .equation import Equation
from ..utils import check_consistency


[docs] class SystemEquation(EquationInterface): """ Implementation of the System of Equations, to be passed to a :class:`~pina.condition.condition.Condition` object. Unlike the :class:`~pina.equation.equation.Equation` class, which represents a single equation, the :class:`SystemEquation` class allows multiple equations to be grouped together into a system. This is particularly useful when dealing with multi-component outputs or coupled physical models, where the residual must be computed collectively across several constraints. Each equation in the system must be either: - An instance of :class:`~pina.equation.equation.Equation`; - A callable function. The residuals from each equation are computed independently and then aggregated using an optional reduction strategy (e.g., ``mean``, ``sum``). The resulting residual is returned as a single :class:`~pina.LabelTensor`. :Example: >>> from pina.equation import SystemEquation, FixedValue, FixedGradient >>> from pina import LabelTensor >>> import torch >>> pts = LabelTensor(torch.rand(10, 2), labels=["x", "y"]) >>> pts.requires_grad = True >>> output_ = torch.pow(pts, 2) >>> output_.labels = ["u", "v"] >>> system_equation = SystemEquation( ... [ ... FixedValue(value=1.0, components=["u"]), ... FixedGradient(value=0.0, components=["v"],d=["y"]), ... ], ... reduction="mean", ... ) >>> residual = system_equation.residual(pts, output_) """ def __init__(self, list_equation, reduction=None): """ Initialization of the :class:`SystemEquation` class. :param list_equation: A list containing either callable functions or instances of :class:`~pina.equation.equation.Equation`, used to compute the residuals of mathematical equations. :type list_equation: list[Callable] | list[Equation] :param str reduction: The reduction method to aggregate the residuals of each equation. Available options are: ``None``, ``mean``, ``sum``, ``callable``. If ``None``, no reduction is applied. If ``mean``, the output sum is divided by the number of elements in the output. If ``sum``, the output is summed. ``callable`` is a user-defined callable function to perform reduction, no checks guaranteed. Default is ``None``. :raises NotImplementedError: If the reduction is not implemented. """ check_consistency([list_equation], list) # equations definition self.equations = [ equation if isinstance(equation, Equation) else Equation(equation) for equation in list_equation ] # possible reduction if reduction == "mean": self.reduction = torch.mean elif reduction == "sum": self.reduction = torch.sum elif (reduction is None) or callable(reduction): self.reduction = reduction else: raise NotImplementedError( "Only mean and sum reductions are currenly supported." )
[docs] def residual(self, input_, output_, params_=None): """ Compute the residual for each equation in the system of equations and aggregate it according to the ``reduction`` specified in the ``__init__`` method. :param LabelTensor input_: Input points where each equation of the system is evaluated. :param LabelTensor output_: Output tensor, eventually produced by a :class:`torch.nn.Module` instance. :param dict params_: Dictionary of unknown parameters, associated with a :class:`~pina.problem.inverse_problem.InverseProblem` instance. If the equation is not related to a :class:`~pina.problem.inverse_problem.InverseProblem` instance, the parameters must be initialized to ``None``. Default is ``None``. :return: The aggregated residuals of the system of equations. :rtype: LabelTensor """ residual = torch.hstack( [ equation.residual(input_, output_, params_) for equation in self.equations ] ) if self.reduction is None: return residual return self.reduction(residual, dim=-1)