Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 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 @@ -255,6 +256,7 @@ Problem Zoo
AcousticWaveProblem <problem/zoo/acoustic_wave_problem.rst>
AdvectionProblem <problem/zoo/advection_problem.rst>
AllenCahnProblem <problem/zoo/allen_cahn_problem.rst>
BurgersProblem <problem/zoo/burgers_problem.rst>
DiffusionReactionProblem <problem/zoo/diffusion_reaction_problem.rst>
HelmholtzProblem <problem/zoo/helmholtz_problem.rst>
InversePoisson2DSquareProblem <problem/zoo/inverse_poisson_problem.rst>
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)
79 changes: 79 additions & 0 deletions pina/_src/problem/zoo/burgers_problem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""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 burgers problem in the spatial interval
:math:`[-1, 1]` and temporal interval :math:`[0, 1]`.
Comment thread
GiovanniCanali marked this conversation as resolved.
Outdated

.. 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