Skip to content

Commit

Permalink
Add HCurlDiv space and covariant-contravariant Piola mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
pbrubeck committed Oct 28, 2024
1 parent 25f376a commit 64fc0c7
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 2 deletions.
5 changes: 4 additions & 1 deletion ufl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
-HCurl
-HEin
-HDivDiv
-HCurlDiv
* Pull backs::
Expand All @@ -84,6 +85,7 @@
-l2_piola
-double_contravariant_piola
-double_covariant_piola
-covariant_contravariant_piola
* Function spaces::
Expand Down Expand Up @@ -418,7 +420,7 @@
identity_pullback,
l2_piola,
)
from ufl.sobolevspace import H1, H2, L2, HCurl, HDiv, HDivDiv, HEin, HInf
from ufl.sobolevspace import H1, H2, L2, HCurl, HCurlDiv, HDiv, HDivDiv, HEin, HInf
from ufl.split_functions import split
from ufl.tensors import (
as_matrix,
Expand Down Expand Up @@ -448,6 +450,7 @@
"HInf",
"HEin",
"HDivDiv",
"HCurlDiv",
"identity_pullback",
"l2_piola",
"contravariant_piola",
Expand Down
46 changes: 46 additions & 0 deletions ufl/pullback.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,51 @@ def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
return (gdim, gdim)


class CovariantContravariantPiola(AbstractPullback):
"""The covariant contravariant Piola pull back."""

def __repr__(self) -> str:
"""Return a representation of the object."""
return "CovariantContravariantPiola()"

@property
def is_identity(self) -> bool:
"""Is this pull back the identity (or the identity applied to mutliple components)."""
return False

def apply(self, expr):
"""Apply the pull back.
Args:
expr: A function on a physical cell
Returns: The function pulled back to the reference cell
"""
from ufl.classes import Jacobian, JacobianDeterminant, JacobianInverse

domain = extract_unique_domain(expr)
J = Jacobian(domain)
detJ = JacobianDeterminant(J)
K = JacobianInverse(domain)
# Apply transform "row-wise" to TensorElement(PiolaMapped, ...)
*k, i, j, m, n = indices(len(expr.ufl_shape) + 2)
kmn = (*k, m, n)
return as_tensor((1.0 / detJ) * K[m, i] * expr[kmn] * J[j, n], (*k, i, j))

def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
"""Get the physical value shape when this pull back is applied to an element.
Args:
element: The element that the pull back is applied to
domain: The domain
Returns:
The value shape when the pull back is applied to the given element
"""
gdim = domain.geometric_dimension()
return (gdim, gdim)


class MixedPullback(AbstractPullback):
"""Pull back for a mixed element."""

Expand Down Expand Up @@ -589,6 +634,7 @@ def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
l2_piola = L2Piola()
double_covariant_piola = DoubleCovariantPiola()
double_contravariant_piola = DoubleContravariantPiola()
covariant_contravariant_piola = CovariantContravariantPiola()
physical_pullback = PhysicalPullback()
custom_pullback = CustomPullback()
undefined_pullback = UndefinedPullback()
4 changes: 3 additions & 1 deletion ufl/sobolevspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def __init__(self, name, parents=None):
"HCurl": 0,
"HEin": 0,
"HDivDiv": 0,
"HCurlDiv": 0,
"DirectionalH": 0,
}[self.name]

Expand Down Expand Up @@ -154,7 +155,7 @@ def __lt__(self, other):
return False
return any(self._orders[i] > other._orders[i] for i in self._spatial_indices)

if other in [HDiv, HCurl]:
if other in [HDiv, HCurl, HCurlDiv]:
return all(self._orders[i] >= 1 for i in self._spatial_indices)
elif other.name in ["HDivDiv", "HEin"]:
# Don't know how these spaces compare
Expand All @@ -175,3 +176,4 @@ def __str__(self):
HInf = SobolevSpace("HInf", [H2, H1, HDiv, HCurl, L2])
HEin = SobolevSpace("HEin", [L2])
HDivDiv = SobolevSpace("HDivDiv", [L2])
HCurlDiv = SobolevSpace("HCurlDiv", [L2])

0 comments on commit 64fc0c7

Please sign in to comment.