Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions docs/source/_rst/_code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ Equation Zoo
Acoustic Wave Equation <equation/zoo/acoustic_wave_equation.rst>
Advection Equation <equation/zoo/advection_equation.rst>
Allen-Cahn Equation <equation/zoo/allen_cahn_equation.rst>
Burgers' Equation <equation/zoo/burgers_equation.rst>
Diffusion-Reaction Equation <equation/zoo/diffusion_reaction_equation.rst>
Fixed Flux <equation/zoo/fixed_flux.rst>
Fixed Gradient <equation/zoo/fixed_gradient.rst>
Expand Down Expand Up @@ -252,14 +253,15 @@ Problem Zoo
.. toctree::
:titlesonly:

AcousticWaveProblem <problem/zoo/acoustic_wave_problem.rst>
AdvectionProblem <problem/zoo/advection_problem.rst>
AllenCahnProblem <problem/zoo/allen_cahn_problem.rst>
DiffusionReactionProblem <problem/zoo/diffusion_reaction_problem.rst>
HelmholtzProblem <problem/zoo/helmholtz_problem.rst>
InversePoisson2DSquareProblem <problem/zoo/inverse_poisson_problem.rst>
Poisson2DSquareProblem <problem/zoo/poisson_problem.rst>
SupervisedProblem <problem/zoo/supervised_problem.rst>
Acoustic Wave Problem <problem/zoo/acoustic_wave_problem.rst>
Advection Problem <problem/zoo/advection_problem.rst>
Allen-Cahn Problem <problem/zoo/allen_cahn_problem.rst>
Burgers' Problem <problem/zoo/burgers_problem.rst>
Diffusion-Reaction Problem <problem/zoo/diffusion_reaction_problem.rst>
Helmholtz Problem <problem/zoo/helmholtz_problem.rst>
Inverse Poisson 2D Square Problem <problem/zoo/inverse_poisson_problem.rst>
Poisson 2D Square Problem <problem/zoo/poisson_problem.rst>
Supervised Problem <problem/zoo/supervised_problem.rst>


Geometrical Domains
Expand Down
7 changes: 7 additions & 0 deletions docs/source/_rst/equation/zoo/burgers_equation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Burgers' Equation
====================
.. currentmodule:: pina.equation.zoo.burgers_equation

.. automodule:: pina._src.equation.zoo.burgers_equation
:members:
:show-inheritance:
9 changes: 9 additions & 0 deletions docs/source/_rst/problem/zoo/burgers_problem.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Burgers' Problem
=====================
.. currentmodule:: pina.problem.zoo.burgers_problem

.. automodule:: pina._src.problem.zoo.burgers_problem

.. autoclass:: pina._src.problem.zoo.burgers_problem.BurgersProblem
:members:
:show-inheritance:
84 changes: 84 additions & 0 deletions pina/_src/equation/zoo/burgers_equation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""Module for defining the Burgers equation."""

from pina._src.core.operator import laplacian, grad
from pina._src.core.utils import check_consistency
from pina._src.equation.equation import Equation
import torch


class BurgersEquation(Equation):
r"""
Implementation of the N-dimensional Burgers' equation, defined as follows:

.. math::

\frac{\partial u}{\partial t} + u \cdot \nabla u = \nu \Delta u

Here, :math:`\nu` is the viscosity coefficient.
"""

def __init__(self, nu):
"""
Initialization of the :class:`BurgersEquation` class.

:param nu: The viscosity coefficient.
:type nu: float | int
:raises ValueError: If ``nu`` is not a float or an int.
:raises ValueError: If ``nu`` is negative.
"""
# Check consistency
check_consistency(nu, (float, int))
if nu < 0:
raise ValueError(
"The viscosity ``nu`` must be a non-negative float or int."
)

# Store viscosity coefficient
self.nu = nu

def equation(input_, output_):
"""
Implementation of the Burgers' equation.

:param LabelTensor input_: The input data of the problem.
:param LabelTensor output_: The output data of the problem.
:raises ValueError: If the number of output components does not
match the number of spatial dimensions.
:raises ValueError: If the ``input_`` labels do not contain the time
variable 't'.
:return: The residual of the Burgers' equation.
:rtype: LabelTensor
"""
# Store labels
spatial_d = [di for di in input_.labels if di != "t"]

# Ensure consistency between output and spatial dimensions
if len(output_.labels) != len(spatial_d):
raise ValueError(
f"The number of output components must match the number of "
f"spatial dimensions. Got {len(output_.labels)} and "
f"{len(spatial_d)}."
)

# Ensure time is passed as input
Comment thread
GiovanniCanali marked this conversation as resolved.
if "t" not in input_.labels:
raise ValueError(
"The ``input_`` labels must contain the time 't' variable."
)

# Compute the differential terms
u_t = grad(output_, input_, d=["t"])
u_x = grad(output_, input_, d=spatial_d)
u_xx = laplacian(output_, input_, d=spatial_d)

# Compute the convective term componentwise
convection = torch.zeros_like(output_)
for i, c in enumerate(output_.labels):
convection[:, i] = sum(
output_[output_.labels[j]] * u_x[f"d{c}d{spatial_d[j]}"]
for j in range(len(spatial_d))
).reshape(-1)

return u_t + convection - self.nu * u_xx

super().__init__(equation)
102 changes: 102 additions & 0 deletions pina/_src/problem/zoo/burgers_problem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Formulation of the Burgers' 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.condition.condition import Condition
from pina._src.core.utils import check_consistency
from pina._src.equation.equation import Equation
from pina._src.equation.zoo.fixed_value import FixedValue
from pina._src.equation.zoo.burgers_equation import BurgersEquation


def initial_condition(input_, output_):
"""
Definition of the initial condition of the Burgers' problem.

:param LabelTensor input_: The input data of the problem.
:param LabelTensor output_: The output data of the problem.
:return: The residual of the initial condition.
:rtype: LabelTensor
"""
return output_ + torch.sin(torch.pi * input_["x"])


class BurgersProblem(TimeDependentProblem, SpatialProblem):
r"""
Implementation of the one-dimensional Burgers' problem on the space-time
domain :math:`\Omega\times T = [-1, 1] \times [0, 1]`.

The problem is governed by the Burgers' equation

.. math::

\frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} =
\nu \frac{\partial^2 u}{\partial x^2},

where :math:`u = u(x, t)` is the solution field and :math:`\nu \geq 0`
is the viscosity coefficient. For :math:`\nu = 0`, the equation reduces
to the inviscid Burgers' equation.

Homogeneous Dirichlet boundary conditions are imposed at the spatial
boundaries:

.. math::
u(-1, t) = u(1, t) = 0, \qquad t \in [0, 1].

The initial condition is prescribed as

.. math::
u(x, 0) = -\sin(\pi x), \qquad x \in [-1, 1].


.. seealso::

**Original reference**: Raissi M., Perdikaris P., Karniadakis G. E.
(2017).
*Physics Informed Deep Learning (Part I): Data-driven Solutions of
Nonlinear Partial Differential Equations*.
DOI: `10.48550 <https://doi.org/10.48550/arXiv.1711.10561>`_.

:Example:

>>> problem = BurgersProblem()
"""

output_variables = ["u"]
spatial_domain = CartesianDomain({"x": [-1, 1]})
temporal_domain = CartesianDomain({"t": [0, 1]})

domains = {
"D": spatial_domain.update(temporal_domain),
"t0": spatial_domain.update(CartesianDomain({"t": 0})),
"boundary": spatial_domain.partial().update(temporal_domain),
}

conditions = {
"boundary": Condition(domain="boundary", equation=FixedValue(0.0)),
"t0": Condition(domain="t0", equation=Equation(initial_condition)),
}

def __init__(self, nu=0):
"""
Initialization of the :class:`BurgersProblem` class.

:param nu: The viscosity coefficient.
:type nu: float | int
:raises ValueError: If ``nu`` is not a float or an int.
:raises ValueError: If ``nu`` is negative.
"""
super().__init__()

# Check consistency
check_consistency(nu, (float, int))
if nu < 0:
raise ValueError(
"The viscosity ``nu`` must be a non-negative float or int."
)

self.conditions["D"] = Condition(
domain="D", equation=BurgersEquation(nu)
)
1 change: 1 addition & 0 deletions pina/equation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"AdvectionEquation": ".zoo",
"AllenCahnEquation": ".zoo",
"DiffusionReactionEquation": ".zoo",
"BurgersEquation": ".zoo",
}


Expand Down
2 changes: 2 additions & 0 deletions pina/equation/zoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"Laplace",
"PoissonEquation",
"AcousticWaveEquation",
"BurgersEquation",
]

from pina._src.equation.zoo.acoustic_wave_equation import AcousticWaveEquation
Expand All @@ -22,6 +23,7 @@
)
from pina._src.equation.zoo.helmholtz_equation import HelmholtzEquation
from pina._src.equation.zoo.poisson_equation import PoissonEquation
from pina._src.equation.zoo.burgers_equation import BurgersEquation
from pina._src.equation.zoo.fixed_value import FixedValue
from pina._src.equation.zoo.fixed_gradient import FixedGradient
from pina._src.equation.zoo.fixed_flux import FixedFlux
Expand Down
2 changes: 2 additions & 0 deletions pina/problem/zoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"DiffusionReactionProblem",
"InversePoisson2DSquareProblem",
"AcousticWaveProblem",
"BurgersProblem",
]

from pina._src.problem.zoo.acoustic_wave_problem import AcousticWaveProblem
Expand All @@ -17,6 +18,7 @@
from pina._src.problem.zoo.advection_problem import AdvectionProblem
from pina._src.problem.zoo.helmholtz_problem import HelmholtzProblem
from pina._src.problem.zoo.poisson_problem import Poisson2DSquareProblem
from pina._src.problem.zoo.burgers_problem import BurgersProblem
from pina._src.problem.zoo.diffusion_reaction_problem import (
DiffusionReactionProblem,
)
Expand Down
37 changes: 37 additions & 0 deletions tests/test_equation_zoo/test_burgers_equation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pytest
import torch
from pina import LabelTensor
from pina.equation.zoo import BurgersEquation


# Define input and output values
pts = LabelTensor(torch.rand(10, 3, requires_grad=True), labels=["x", "y", "t"])
u = torch.sin(pts["x", "y"]) * torch.cos(pts["y", "t"])
u.labels = ["u", "v"]


@pytest.mark.parametrize("nu", [0, 1, 2.5])
def test_burgers_equation(nu):

# Constructor
equation = BurgersEquation(nu=nu)

# Should fail if nu is not a float or int
with pytest.raises(ValueError):
BurgersEquation(nu="invalid")

# Should fail if nu is negative
with pytest.raises(ValueError):
BurgersEquation(nu=-1)

# Residual
residual = equation.residual(pts, u)
assert residual.shape == u.shape

# Should fail if the input has no 't' label
with pytest.raises(ValueError):
residual = equation.residual(pts["x", "y"], u)

# Should fail if output and spatial dimensions do not match
with pytest.raises(ValueError):
residual = equation.residual(pts, u["u"])
23 changes: 23 additions & 0 deletions tests/test_problem_zoo/test_burgers_problem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import pytest
from pina.problem.zoo import BurgersProblem
from pina.problem import SpatialProblem, TimeDependentProblem


@pytest.mark.parametrize("nu", [0.1, 1])
def test_constructor(nu):

problem = BurgersProblem(nu=nu)
problem.discretise_domain(n=10, mode="random", domains=None)
assert problem.are_all_domains_discretised
assert isinstance(problem, SpatialProblem)
assert isinstance(problem, TimeDependentProblem)
assert hasattr(problem, "conditions")
assert isinstance(problem.conditions, dict)

# Should fail if nu is not a float or int
with pytest.raises(ValueError):
BurgersProblem(nu="invalid")

# Should fail if nu is negative
with pytest.raises(ValueError):
BurgersProblem(nu=-0.1)
Loading