Source code for scimba_torch.physical_models.elliptic_pde.abstract_elliptic_pde
"""Abstract classes for elliptic PDEs."""
from abc import ABC, abstractmethod
from typing import Generator
import torch
from scimba_torch.approximation_space.abstract_space import AbstractApproxSpace
from scimba_torch.utils.scimba_tensors import LabelTensor, MultiLabelTensor
[docs]
class EllipticPDE(ABC):
"""Base class for representing elliptic Partial Differential Equations (PDEs).
Args:
space: Approximation space used for the PDE
linear: Indicates if the PDE is linear
**kwargs: Additional keyword arguments
"""
def __init__(self, space: AbstractApproxSpace, linear: bool = False, **kwargs):
super().__init__()
self.space = space
self.linear = linear
[docs]
def grad(
self,
w: torch.Tensor | MultiLabelTensor,
y: torch.Tensor | LabelTensor,
) -> torch.Tensor | Generator[torch.Tensor, None, None]:
"""Compute the gradient of the tensor `w` with respect to the tensor `y`.
Args:
w: Input tensor
y: Tensor with respect to which the gradient is computed
Returns:
Gradient tensor
"""
return self.space.grad(w, y)
[docs]
class StrongFormEllipticPDE(EllipticPDE):
"""Strong form of an elliptic PDE.
Args:
space: Approximation space used for the PDE
linear: Indicates if the PDE is linear
residual_size: Size of the residual, defaults to space.nb_unknowns
bc_residual_size: Size of the boundary condition residual, defaults to 0
**kwargs: Additional keyword arguments
"""
def __init__(
self,
space: AbstractApproxSpace,
linear: bool = False,
residual_size: int | None = None,
bc_residual_size: int = 0,
**kwargs,
):
super().__init__(space, linear, **kwargs)
if residual_size is None:
residual_size = space.nb_unknowns
self.residual_size = residual_size
self.bc_residual_size = bc_residual_size
[docs]
@abstractmethod
def rhs(self, w: MultiLabelTensor, x: LabelTensor, mu: LabelTensor) -> torch.Tensor:
"""Compute the right-hand side (RHS) of the PDE.
Args:
w: Solution tensor
x: Spatial coordinate tensor
mu: Parameter tensor
Returns:
The right-hand side of the PDE.
"""
[docs]
@abstractmethod
def operator(
self, w: MultiLabelTensor, x: LabelTensor, mu: LabelTensor
) -> torch.Tensor:
"""Apply the PDE operator.
Args:
w: Solution tensor
x: Spatial coordinate tensor
mu: Parameter tensor
Returns:
The result of the PDE operator.
"""
[docs]
@abstractmethod
def bc_rhs(
self, w: MultiLabelTensor, x: LabelTensor, n: LabelTensor, mu: LabelTensor
) -> torch.Tensor:
"""Compute the boundary condition RHS.
Args:
w: Solution tensor
x: Spatial coordinate tensor
n: Normal vector tensor
mu: Parameter tensor
Returns:
The boundary condition RHS.
"""
[docs]
@abstractmethod
def bc_operator(
self, w: MultiLabelTensor, x: LabelTensor, n: LabelTensor, mu: LabelTensor
) -> torch.Tensor:
"""Apply the boundary condition operator.
Args:
w: Solution tensor
x: Spatial coordinate tensor
n: Normal vector tensor
mu: Parameter tensor
Returns:
The result of the boundary condition operator.
"""
[docs]
class WeakFormEllipticPDE(EllipticPDE):
"""Weak form of an elliptic PDE.
Args:
space: Approximation space used for the PDE
residual_size: Size of the weak form, defaults to space.nb_unknowns
linear: Indicates if the PDE is linear
**kwargs: Additional keyword arguments
"""
def __init__(
self,
space: AbstractApproxSpace,
residual_size: int | None = None,
linear: bool = False,
**kwargs,
):
super().__init__(space, linear, **kwargs)
if residual_size is None:
residual_size = space.nb_unknowns
self.residual_size = residual_size
[docs]
@abstractmethod
def linearform(
self, w: MultiLabelTensor, v: LabelTensor, x: LabelTensor, mu: LabelTensor
) -> LabelTensor:
"""Compute the linear form of the weak formulation.
Args:
w: Solution tensor
v: Test function tensor
x: Spatial coordinate tensor
mu: Parameter tensor
Returns:
The linear form of the weak formulation.
"""
[docs]
@abstractmethod
def bilinearform(
self, w: MultiLabelTensor, v: LabelTensor, x: LabelTensor, mu: LabelTensor
) -> LabelTensor:
"""Compute the bilinear form of the weak formulation.
Args:
w: Solution tensor
v: Test function tensor
x: Spatial coordinate tensor
mu: Parameter tensor
Returns:
The bilinear form of the weak formulation.
"""
[docs]
@abstractmethod
def bc_linearform(
self,
w: MultiLabelTensor,
v: LabelTensor,
x: LabelTensor,
n: LabelTensor,
mu: LabelTensor,
) -> LabelTensor:
"""Compute the boundary condition linear form.
Args:
w: Solution tensor
v: Test function tensor
x: Spatial coordinate tensor
n: Normal vector tensor
mu: Parameter tensor
Returns:
The boundary condition linear form.
"""
[docs]
@abstractmethod
def bc_bilinearform(
self,
w: MultiLabelTensor,
v: LabelTensor,
x: LabelTensor,
n: LabelTensor,
mu: LabelTensor,
) -> LabelTensor:
"""Compute the boundary condition bilinear form.
Args:
w: Solution tensor
v: Test function tensor
x: Spatial coordinate tensor
n: Normal vector tensor
mu: Parameter tensor
Returns:
The boundary condition bilinear form.
"""
[docs]
class RitzFormEllipticPDE(EllipticPDE):
"""Ritz form of an elliptic PDE.
Args:
space: Approximation space used for the PDE
linear: Indicates if the PDE is linear
residual_size: Size of the weak form, defaults to space.nb_unknowns
bc_residual_size: Size of the boundary condition residual, defaults to 0
**kwargs: Additional keyword arguments
"""
def __init__(
self,
space: AbstractApproxSpace,
linear: bool = False,
residual_size: int | None = None,
bc_residual_size: int = 0,
**kwargs,
):
super().__init__(space, linear, **kwargs)
if residual_size is None:
residual_size = space.nb_unknowns
self.residual_size = residual_size
self.bc_residual_size = bc_residual_size
[docs]
@abstractmethod
def linearform(
self, w: MultiLabelTensor, x: LabelTensor, mu: LabelTensor
) -> torch.Tensor:
"""Compute the linear form of the Ritz formulation.
Args:
w: Solution tensor
x: Spatial coordinate tensor
mu: Parameter tensor
Returns:
The linear form of the Ritz formulation.
"""
[docs]
@abstractmethod
def quadraticform(
self, w: MultiLabelTensor, x: LabelTensor, mu: LabelTensor
) -> torch.Tensor:
"""Compute the bilinear form of the Ritz formulation.
Args:
w: Solution tensor
x: Spatial coordinate tensor
mu: Parameter tensor
Returns:
The bilinear form of the Ritz formulation.
"""
[docs]
@abstractmethod
def bc_rhs(
self, w: MultiLabelTensor, x: LabelTensor, n: LabelTensor, mu: LabelTensor
) -> torch.Tensor:
"""Compute the boundary condition RHS.
Args:
w: Solution tensor
x: Spatial coordinate tensor
n: Normal vector tensor
mu: Parameter tensor
Returns:
The boundary condition RHS.
"""
[docs]
@abstractmethod
def bc_operator(
self, w: MultiLabelTensor, x: LabelTensor, n: LabelTensor, mu: LabelTensor
) -> torch.Tensor:
"""Apply the boundary condition operator.
Args:
w: Solution tensor
x: Spatial coordinate tensor
n: Normal vector tensor
mu: Parameter tensor
Returns:
The result of the boundary condition operator.
"""