From 44d5ec52d293bc3a0e6988358c0641e6dcc6bc1e Mon Sep 17 00:00:00 2001 From: GiovanniCanali Date: Thu, 23 Apr 2026 17:27:13 +0200 Subject: [PATCH 1/3] add burgers equation --- docs/source/_rst/_code.rst | 1 + .../_rst/equation/zoo/burgers_equation.rst | 7 ++ pina/_src/equation/zoo/burgers_equation.py | 84 +++++++++++++++++++ pina/equation/__init__.py | 1 + pina/equation/zoo.py | 2 + .../test_burgers_equation.py | 37 ++++++++ 6 files changed, 132 insertions(+) create mode 100644 docs/source/_rst/equation/zoo/burgers_equation.rst create mode 100644 pina/_src/equation/zoo/burgers_equation.py create mode 100644 tests/test_equation_zoo/test_burgers_equation.py diff --git a/docs/source/_rst/_code.rst b/docs/source/_rst/_code.rst index 704298020..63bf33cc1 100644 --- a/docs/source/_rst/_code.rst +++ b/docs/source/_rst/_code.rst @@ -224,6 +224,7 @@ Equation Zoo Acoustic Wave Equation Advection Equation Allen-Cahn Equation + Burgers Equation Diffusion-Reaction Equation Fixed Flux Fixed Gradient diff --git a/docs/source/_rst/equation/zoo/burgers_equation.rst b/docs/source/_rst/equation/zoo/burgers_equation.rst new file mode 100644 index 000000000..376d281fb --- /dev/null +++ b/docs/source/_rst/equation/zoo/burgers_equation.rst @@ -0,0 +1,7 @@ +Burgers Equation +==================== +.. currentmodule:: pina.equation.zoo.burgers_equation + +.. automodule:: pina._src.equation.zoo.burgers_equation + :members: + :show-inheritance: diff --git a/pina/_src/equation/zoo/burgers_equation.py b/pina/_src/equation/zoo/burgers_equation.py new file mode 100644 index 000000000..133ffd323 --- /dev/null +++ b/pina/_src/equation/zoo/burgers_equation.py @@ -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 positive 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 + 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) diff --git a/pina/equation/__init__.py b/pina/equation/__init__.py index 5c2806f53..1a0ce8bb0 100644 --- a/pina/equation/__init__.py +++ b/pina/equation/__init__.py @@ -36,6 +36,7 @@ "AdvectionEquation": ".zoo", "AllenCahnEquation": ".zoo", "DiffusionReactionEquation": ".zoo", + "BurgersEquation": ".zoo", } diff --git a/pina/equation/zoo.py b/pina/equation/zoo.py index 140c836d7..4febb63e6 100644 --- a/pina/equation/zoo.py +++ b/pina/equation/zoo.py @@ -12,6 +12,7 @@ "Laplace", "PoissonEquation", "AcousticWaveEquation", + "BurgersEquation", ] from pina._src.equation.zoo.acoustic_wave_equation import AcousticWaveEquation @@ -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 diff --git a/tests/test_equation_zoo/test_burgers_equation.py b/tests/test_equation_zoo/test_burgers_equation.py new file mode 100644 index 000000000..89825aa9b --- /dev/null +++ b/tests/test_equation_zoo/test_burgers_equation.py @@ -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"]) From b41530d7f3d4f8d1ad24b70d8fd8fbaed2fb6e58 Mon Sep 17 00:00:00 2001 From: GiovanniCanali Date: Thu, 23 Apr 2026 17:44:24 +0200 Subject: [PATCH 2/3] add burgers problem --- docs/source/_rst/_code.rst | 1 + .../_rst/problem/zoo/burgers_problem.rst | 9 +++ pina/_src/equation/zoo/burgers_equation.py | 2 +- pina/_src/problem/zoo/burgers_problem.py | 79 +++++++++++++++++++ pina/problem/zoo.py | 2 + .../test_problem_zoo/test_burgers_problem.py | 23 ++++++ 6 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 docs/source/_rst/problem/zoo/burgers_problem.rst create mode 100644 pina/_src/problem/zoo/burgers_problem.py create mode 100644 tests/test_problem_zoo/test_burgers_problem.py diff --git a/docs/source/_rst/_code.rst b/docs/source/_rst/_code.rst index 63bf33cc1..36f11e6ee 100644 --- a/docs/source/_rst/_code.rst +++ b/docs/source/_rst/_code.rst @@ -256,6 +256,7 @@ Problem Zoo AcousticWaveProblem AdvectionProblem AllenCahnProblem + BurgersProblem DiffusionReactionProblem HelmholtzProblem InversePoisson2DSquareProblem diff --git a/docs/source/_rst/problem/zoo/burgers_problem.rst b/docs/source/_rst/problem/zoo/burgers_problem.rst new file mode 100644 index 000000000..ce00371b7 --- /dev/null +++ b/docs/source/_rst/problem/zoo/burgers_problem.rst @@ -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: diff --git a/pina/_src/equation/zoo/burgers_equation.py b/pina/_src/equation/zoo/burgers_equation.py index 133ffd323..44ef1081b 100644 --- a/pina/_src/equation/zoo/burgers_equation.py +++ b/pina/_src/equation/zoo/burgers_equation.py @@ -30,7 +30,7 @@ def __init__(self, nu): check_consistency(nu, (float, int)) if nu < 0: raise ValueError( - "The viscosity ``nu`` must be a positive float or int." + "The viscosity ``nu`` must be a non-negative float or int." ) # Store viscosity coefficient diff --git a/pina/_src/problem/zoo/burgers_problem.py b/pina/_src/problem/zoo/burgers_problem.py new file mode 100644 index 000000000..112bf7e54 --- /dev/null +++ b/pina/_src/problem/zoo/burgers_problem.py @@ -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]`. + + .. 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 `_. + + :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) + ) diff --git a/pina/problem/zoo.py b/pina/problem/zoo.py index 6c027ed54..47b204425 100644 --- a/pina/problem/zoo.py +++ b/pina/problem/zoo.py @@ -9,6 +9,7 @@ "DiffusionReactionProblem", "InversePoisson2DSquareProblem", "AcousticWaveProblem", + "BurgersProblem", ] from pina._src.problem.zoo.acoustic_wave_problem import AcousticWaveProblem @@ -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, ) diff --git a/tests/test_problem_zoo/test_burgers_problem.py b/tests/test_problem_zoo/test_burgers_problem.py new file mode 100644 index 000000000..d7f9d2128 --- /dev/null +++ b/tests/test_problem_zoo/test_burgers_problem.py @@ -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) From e990d70f7e86af9707db86b2972856a02b6cd780 Mon Sep 17 00:00:00 2001 From: GiovanniCanali Date: Tue, 28 Apr 2026 12:14:29 +0200 Subject: [PATCH 3/3] fix docstring in burgers' problem --- docs/source/_rst/_code.rst | 20 ++++++------ .../_rst/equation/zoo/burgers_equation.rst | 2 +- .../_rst/problem/zoo/burgers_problem.rst | 2 +- pina/_src/equation/zoo/burgers_equation.py | 6 ++-- pina/_src/problem/zoo/burgers_problem.py | 31 ++++++++++++++++--- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/docs/source/_rst/_code.rst b/docs/source/_rst/_code.rst index 36f11e6ee..60eb42408 100644 --- a/docs/source/_rst/_code.rst +++ b/docs/source/_rst/_code.rst @@ -224,7 +224,7 @@ Equation Zoo Acoustic Wave Equation Advection Equation Allen-Cahn Equation - Burgers Equation + Burgers' Equation Diffusion-Reaction Equation Fixed Flux Fixed Gradient @@ -253,15 +253,15 @@ Problem Zoo .. toctree:: :titlesonly: - AcousticWaveProblem - AdvectionProblem - AllenCahnProblem - BurgersProblem - DiffusionReactionProblem - HelmholtzProblem - InversePoisson2DSquareProblem - Poisson2DSquareProblem - SupervisedProblem + Acoustic Wave Problem + Advection Problem + Allen-Cahn Problem + Burgers' Problem + Diffusion-Reaction Problem + Helmholtz Problem + Inverse Poisson 2D Square Problem + Poisson 2D Square Problem + Supervised Problem Geometrical Domains diff --git a/docs/source/_rst/equation/zoo/burgers_equation.rst b/docs/source/_rst/equation/zoo/burgers_equation.rst index 376d281fb..8f478621f 100644 --- a/docs/source/_rst/equation/zoo/burgers_equation.rst +++ b/docs/source/_rst/equation/zoo/burgers_equation.rst @@ -1,4 +1,4 @@ -Burgers Equation +Burgers' Equation ==================== .. currentmodule:: pina.equation.zoo.burgers_equation diff --git a/docs/source/_rst/problem/zoo/burgers_problem.rst b/docs/source/_rst/problem/zoo/burgers_problem.rst index ce00371b7..75151d8d8 100644 --- a/docs/source/_rst/problem/zoo/burgers_problem.rst +++ b/docs/source/_rst/problem/zoo/burgers_problem.rst @@ -1,4 +1,4 @@ -Burgers Problem +Burgers' Problem ===================== .. currentmodule:: pina.problem.zoo.burgers_problem diff --git a/pina/_src/equation/zoo/burgers_equation.py b/pina/_src/equation/zoo/burgers_equation.py index 44ef1081b..07c8eed22 100644 --- a/pina/_src/equation/zoo/burgers_equation.py +++ b/pina/_src/equation/zoo/burgers_equation.py @@ -8,7 +8,7 @@ class BurgersEquation(Equation): r""" - Implementation of the N-dimensional Burgers equation, defined as follows: + Implementation of the N-dimensional Burgers' equation, defined as follows: .. math:: @@ -38,7 +38,7 @@ def __init__(self, nu): def equation(input_, output_): """ - Implementation of the Burgers equation. + Implementation of the Burgers' equation. :param LabelTensor input_: The input data of the problem. :param LabelTensor output_: The output data of the problem. @@ -46,7 +46,7 @@ def equation(input_, output_): 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. + :return: The residual of the Burgers' equation. :rtype: LabelTensor """ # Store labels diff --git a/pina/_src/problem/zoo/burgers_problem.py b/pina/_src/problem/zoo/burgers_problem.py index 112bf7e54..0ba779a22 100644 --- a/pina/_src/problem/zoo/burgers_problem.py +++ b/pina/_src/problem/zoo/burgers_problem.py @@ -1,4 +1,4 @@ -"""Formulation of the burgers problem.""" +"""Formulation of the Burgers' problem.""" import torch from pina._src.problem.time_dependent_problem import TimeDependentProblem @@ -13,7 +13,7 @@ def initial_condition(input_, output_): """ - Definition of the initial condition of the burgers problem. + 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. @@ -25,8 +25,31 @@ def initial_condition(input_, output_): class BurgersProblem(TimeDependentProblem, SpatialProblem): r""" - Implementation of the burgers problem in the spatial interval - :math:`[-1, 1]` and temporal interval :math:`[0, 1]`. + 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::