Source code for pina._src.problem.zoo.advection_problem
"""Formulation of the advection problem."""
import torch
from pina._src.problem.time_dependent_problem import TimeDependentProblem
from pina._src.domain.cartesian_domain import CartesianDomain
from pina._src.problem.spatial_problem import SpatialProblem
from pina._src.equation.zoo.advection_equation import AdvectionEquation
from pina._src.condition.condition import Condition
from pina._src.core.utils import check_consistency
from pina._src.equation.equation import Equation
def initial_condition(input_, output_):
"""
Implementation of the initial condition.
:param LabelTensor input_: Input data of the problem.
:param LabelTensor output_: Output data of the problem.
:return: The residual of the initial condition.
:rtype: LabelTensor
"""
return output_ - torch.sin(input_.extract("x"))
[docs]
class AdvectionProblem(SpatialProblem, TimeDependentProblem):
r"""
Implementation of the one-dimensional advection problem on the space-time
domain :math:`\Omega\times T = [0, 2\pi] \times [0, 1]`.
The problem is governed by the linear advection equation
.. math::
\frac{\partial u}{\partial t}
+
c \frac{\partial u}{\partial x}
=
0,
where :math:`u = u(x, t)` is the solution field and :math:`c` is the
advection velocity.
Periodic boundary conditions are imposed at the spatial boundaries:
.. math::
u(0, t) = u(2\pi, t), \qquad t \in [0, 1].
The initial condition is prescribed as
.. math::
u(x, 0) = \sin(x), \qquad x \in [0, 2\pi].
The analytical solution is given by
.. math::
u(x, t) = \sin(x - ct).
.. seealso::
**Original reference**: Wang, Sifan, et al. *An expert's guide to
training physics-informed neural networks*.
arXiv preprint arXiv:2308.08468 (2023).
DOI: `arXiv:2308.08468 <https://arxiv.org/abs/2308.08468>`_.
:Example:
>>> problem = AdvectionProblem()
"""
output_variables = ["u"]
spatial_domain = CartesianDomain({"x": [0, 2 * torch.pi]})
temporal_domain = CartesianDomain({"t": [0, 1]})
domains = {
"D": spatial_domain.update(temporal_domain),
"t0": spatial_domain.update(CartesianDomain({"t": 0})),
}
conditions = {
"t0": Condition(domain="t0", equation=Equation(initial_condition)),
}
def __init__(self, c=1.0):
"""
Initialization of the :class:`AdvectionProblem`.
:param c: The advection velocity parameter. Default is ``1.0``.
:type c: float | int
"""
super().__init__()
check_consistency(c, (float, int))
self.c = c
self.conditions["D"] = Condition(
domain="D", equation=AdvectionEquation(self.c)
)
[docs]
def solution(self, pts):
"""
Implementation of the analytical solution of the advection problem.
:param LabelTensor pts: Points where the solution is evaluated.
:return: The analytical solution of the advection problem.
:rtype: LabelTensor
"""
sol = torch.sin(pts.extract("x") - self.c * pts.extract("t"))
sol.labels = self.output_variables
return sol