Update Laplace class and add unit tests (#645)
This commit is contained in:
197
tests/test_equation/test_equation_factory.py
Normal file
197
tests/test_equation/test_equation_factory.py
Normal file
@@ -0,0 +1,197 @@
|
||||
from pina.equation import (
|
||||
FixedValue,
|
||||
FixedGradient,
|
||||
FixedFlux,
|
||||
FixedLaplacian,
|
||||
Advection,
|
||||
AllenCahn,
|
||||
DiffusionReaction,
|
||||
Helmholtz,
|
||||
Poisson,
|
||||
)
|
||||
from pina import LabelTensor
|
||||
import torch
|
||||
import pytest
|
||||
|
||||
# Define input and output values
|
||||
pts = LabelTensor(torch.rand(10, 3, requires_grad=True), labels=["x", "y", "t"])
|
||||
u = torch.pow(pts, 2)
|
||||
u.labels = ["u", "v", "w"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", [0, 10, -7.5])
|
||||
@pytest.mark.parametrize("components", [None, "u", ["u", "w"]])
|
||||
def test_fixed_value(value, components):
|
||||
|
||||
# Constructor
|
||||
equation = FixedValue(value=value, components=components)
|
||||
|
||||
# Residual
|
||||
residual = equation.residual(pts, u)
|
||||
len_c = len(components) if components is not None else u.shape[1]
|
||||
assert residual.shape == (pts.shape[0], len_c)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", [0, 10, -7.5])
|
||||
@pytest.mark.parametrize("components", [None, "u", ["u", "w"]])
|
||||
@pytest.mark.parametrize("d", [None, "x", ["x", "y"]])
|
||||
def test_fixed_gradient(value, components, d):
|
||||
|
||||
# Constructor
|
||||
equation = FixedGradient(value=value, components=components, d=d)
|
||||
|
||||
# Residual
|
||||
residual = equation.residual(pts, u)
|
||||
len_c = len(components) if components is not None else u.shape[1]
|
||||
len_d = len(d) if d is not None else pts.shape[1]
|
||||
assert residual.shape == (pts.shape[0], len_c * len_d)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", [0, 10, -7.5])
|
||||
@pytest.mark.parametrize("components", [None, "u", ["u", "w"]])
|
||||
@pytest.mark.parametrize("d", [None, "x", ["x", "y"]])
|
||||
def test_fixed_flux(value, components, d):
|
||||
|
||||
# Divergence requires components and d to be of the same length
|
||||
len_c = len(components) if components is not None else u.shape[1]
|
||||
len_d = len(d) if d is not None else pts.shape[1]
|
||||
if len_c != len_d:
|
||||
return
|
||||
|
||||
# Constructor
|
||||
equation = FixedFlux(value=value, components=components, d=d)
|
||||
|
||||
# Residual
|
||||
residual = equation.residual(pts, u)
|
||||
assert residual.shape == (pts.shape[0], 1)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", [0, 10, -7.5])
|
||||
@pytest.mark.parametrize("components", [None, "u", ["u", "w"]])
|
||||
@pytest.mark.parametrize("d", [None, "x", ["x", "y"]])
|
||||
def test_fixed_laplacian(value, components, d):
|
||||
|
||||
# Constructor
|
||||
equation = FixedLaplacian(value=value, components=components, d=d)
|
||||
|
||||
# Residual
|
||||
residual = equation.residual(pts, u)
|
||||
len_c = len(components) if components is not None else u.shape[1]
|
||||
assert residual.shape == (pts.shape[0], len_c)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("c", [1.0, 10, [1, 2.5]])
|
||||
def test_advection_equation(c):
|
||||
|
||||
# Constructor
|
||||
equation = Advection(c)
|
||||
|
||||
# Should fail if c is an empty list
|
||||
with pytest.raises(ValueError):
|
||||
Advection([])
|
||||
|
||||
# Should fail if c is not a float, int, or list
|
||||
with pytest.raises(ValueError):
|
||||
Advection("invalid")
|
||||
|
||||
# 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 c is a list and its length != spatial dimension
|
||||
with pytest.raises(ValueError):
|
||||
Advection([1, 2, 3])
|
||||
residual = equation.residual(pts, u)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("alpha", [1.0, 10, -7.5])
|
||||
@pytest.mark.parametrize("beta", [1.0, 10, -7.5])
|
||||
def test_allen_cahn_equation(alpha, beta):
|
||||
|
||||
# Constructor
|
||||
equation = AllenCahn(alpha=alpha, beta=beta)
|
||||
|
||||
# Should fail if alpha is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
AllenCahn(alpha="invalid", beta=beta)
|
||||
|
||||
# Should fail if beta is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
AllenCahn(alpha=alpha, beta="invalid")
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("alpha", [1.0, 10, -7.5])
|
||||
@pytest.mark.parametrize(
|
||||
"forcing_term", [lambda x: torch.sin(x), lambda x: torch.exp(x)]
|
||||
)
|
||||
def test_diffusion_reaction_equation(alpha, forcing_term):
|
||||
|
||||
# Constructor
|
||||
equation = DiffusionReaction(alpha=alpha, forcing_term=forcing_term)
|
||||
|
||||
# Should fail if alpha is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
DiffusionReaction(alpha="invalid", forcing_term=forcing_term)
|
||||
|
||||
# Should fail if forcing_term is not a callable
|
||||
with pytest.raises(ValueError):
|
||||
DiffusionReaction(alpha=alpha, forcing_term="invalid")
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("k", [1.0, 10, -7.5])
|
||||
@pytest.mark.parametrize(
|
||||
"forcing_term", [lambda x: torch.sin(x), lambda x: torch.exp(x)]
|
||||
)
|
||||
def test_helmholtz_equation(k, forcing_term):
|
||||
|
||||
# Constructor
|
||||
equation = Helmholtz(k=k, forcing_term=forcing_term)
|
||||
|
||||
# Should fail if k is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
Helmholtz(k="invalid", forcing_term=forcing_term)
|
||||
|
||||
# Should fail if forcing_term is not a callable
|
||||
with pytest.raises(ValueError):
|
||||
Helmholtz(k=k, forcing_term="invalid")
|
||||
|
||||
# Residual
|
||||
residual = equation.residual(pts, u)
|
||||
assert residual.shape == u.shape
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"forcing_term", [lambda x: torch.sin(x), lambda x: torch.exp(x)]
|
||||
)
|
||||
def test_poisson_equation(forcing_term):
|
||||
|
||||
# Constructor
|
||||
equation = Poisson(forcing_term=forcing_term)
|
||||
|
||||
# Should fail if forcing_term is not a callable
|
||||
with pytest.raises(ValueError):
|
||||
Poisson(forcing_term="invalid")
|
||||
|
||||
# Residual
|
||||
residual = equation.residual(pts, u)
|
||||
assert residual.shape == u.shape
|
||||
@@ -5,7 +5,7 @@ from pina.problem import SpatialProblem, TimeDependentProblem
|
||||
|
||||
@pytest.mark.parametrize("c", [1.5, 3])
|
||||
def test_constructor(c):
|
||||
print(f"Testing with c = {c} (type: {type(c)})")
|
||||
|
||||
problem = AdvectionProblem(c=c)
|
||||
problem.discretise_domain(n=10, mode="random", domains="all")
|
||||
assert problem.are_all_domains_discretised
|
||||
@@ -14,5 +14,6 @@ def test_constructor(c):
|
||||
assert hasattr(problem, "conditions")
|
||||
assert isinstance(problem.conditions, dict)
|
||||
|
||||
# Should fail if c is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
AdvectionProblem(c="a")
|
||||
AdvectionProblem(c="invalid")
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import pytest
|
||||
from pina.problem.zoo import AllenCahnProblem
|
||||
from pina.problem import SpatialProblem, TimeDependentProblem
|
||||
|
||||
|
||||
def test_constructor():
|
||||
problem = AllenCahnProblem()
|
||||
@pytest.mark.parametrize("alpha", [0.1, 1])
|
||||
@pytest.mark.parametrize("beta", [0.1, 1])
|
||||
def test_constructor(alpha, beta):
|
||||
|
||||
problem = AllenCahnProblem(alpha=alpha, beta=beta)
|
||||
problem.discretise_domain(n=10, mode="random", domains="all")
|
||||
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 alpha is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
AllenCahnProblem(alpha="invalid", beta=beta)
|
||||
|
||||
# Should fail if beta is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
AllenCahnProblem(alpha=alpha, beta="invalid")
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import pytest
|
||||
from pina.problem.zoo import DiffusionReactionProblem
|
||||
from pina.problem import TimeDependentProblem, SpatialProblem
|
||||
|
||||
|
||||
def test_constructor():
|
||||
problem = DiffusionReactionProblem()
|
||||
@pytest.mark.parametrize("alpha", [0.1, 1])
|
||||
def test_constructor(alpha):
|
||||
|
||||
problem = DiffusionReactionProblem(alpha=alpha)
|
||||
problem.discretise_domain(n=10, mode="random", domains="all")
|
||||
assert problem.are_all_domains_discretised
|
||||
assert isinstance(problem, TimeDependentProblem)
|
||||
assert isinstance(problem, SpatialProblem)
|
||||
assert hasattr(problem, "conditions")
|
||||
assert isinstance(problem.conditions, dict)
|
||||
|
||||
# Should fail if alpha is not a float or int
|
||||
with pytest.raises(ValueError):
|
||||
problem = DiffusionReactionProblem(alpha="invalid")
|
||||
|
||||
@@ -5,6 +5,7 @@ from pina.problem import SpatialProblem
|
||||
|
||||
@pytest.mark.parametrize("alpha", [1.5, 3])
|
||||
def test_constructor(alpha):
|
||||
|
||||
problem = HelmholtzProblem(alpha=alpha)
|
||||
problem.discretise_domain(n=10, mode="random", domains="all")
|
||||
assert problem.are_all_domains_discretised
|
||||
@@ -13,4 +14,4 @@ def test_constructor(alpha):
|
||||
assert isinstance(problem.conditions, dict)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
HelmholtzProblem(alpha="a")
|
||||
HelmholtzProblem(alpha="invalid")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
from pina.problem.zoo import InversePoisson2DSquareProblem
|
||||
from pina.problem import InverseProblem, SpatialProblem
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize("load", [True, False])
|
||||
|
||||
@@ -3,6 +3,7 @@ from pina.problem import SpatialProblem
|
||||
|
||||
|
||||
def test_constructor():
|
||||
|
||||
problem = Poisson2DSquareProblem()
|
||||
problem.discretise_domain(n=10, mode="random", domains="all")
|
||||
assert problem.are_all_domains_discretised
|
||||
|
||||
Reference in New Issue
Block a user