Skip to content

Commit

Permalink
Merge branch 'perp_operator' into perp_operator_rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
tommbendall committed Jul 25, 2023
2 parents 4e32e86 + 5b7a3a9 commit d9d7ff3
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 17 deletions.
7 changes: 7 additions & 0 deletions test/test_tensoralgebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ def test_cross(self):
self.assertEqualValues(C, D)


def test_perp(self):
u = as_vector([3, 1])
v = perp(u)
w = as_vector([-1, 3])
self.assertEqualValues(v, w)


def xtest_dev(self, A):
C = dev(A)
D = 0*C # FIXME: Add expected value here
Expand Down
3 changes: 3 additions & 0 deletions ufl/algorithms/apply_algebra_lowering.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def c(i, j):
return Product(a[i], b[j]) - Product(a[j], b[i])
return as_vector((c(1, 2), c(2, 0), c(0, 1)))

def perp(self, o, a):
return as_vector([-a[1], a[0]])

def dot(self, o, a, b):
ai = indices(len(a.ufl_shape) - 1)
bi = indices(len(b.ufl_shape) - 1)
Expand Down
34 changes: 19 additions & 15 deletions ufl/finiteelement/elementlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def show_elements():
register_alias("Lob",
lambda family, dim, order, degree: ("Gauss-Lobatto-Legendre", order))

register_element("Bernstein", None, 0, H1, "identity", (1, None), simplices)
register_element("Bernstein", "Bernstein", 0, H1, "identity", (1, None), simplices)


# Let Nedelec H(div) elements be aliases to BDMs/RTs
Expand All @@ -175,26 +175,30 @@ def show_elements():
lambda family, dim, order, degree: ("HDiv Trace", order))

# New elements introduced for the periodic table 2014
register_element("Q", None, 0, H1, "identity", (1, None), cubes)
register_element("DQ", None, 0, L2, "identity", (0, None), cubes)
register_element("RTCE", None, 1, HCurl, "covariant Piola", (1, None),
register_element("Q", "Q", 0, H1, "identity", (1, None), cubes)
register_element("DQ", "DQ", 0, L2, "identity", (0, None), cubes)
register_element("RTCE", "RTCE", 1, HCurl, "covariant Piola", (1, None),
("quadrilateral",))
register_element("RTCF", None, 1, HDiv, "contravariant Piola", (1, None),
register_element("RTCF", "RTCF", 1, HDiv, "contravariant Piola", (1, None),
("quadrilateral",))
register_element("NCE", None, 1, HCurl, "covariant Piola", (1, None),
register_element("NCE", "NCE", 1, HCurl, "covariant Piola", (1, None),
("hexahedron",))
register_element("NCF", None, 1, HDiv, "contravariant Piola", (1, None),
register_element("NCF", "NCF", 1, HDiv, "contravariant Piola", (1, None),
("hexahedron",))

register_element("S", None, 0, H1, "identity", (1, None), cubes)
register_element("DPC", None, 0, L2, "identity", (0, None), cubes)
register_element("BDMCE", None, 1, HCurl, "covariant Piola", (1, None),
register_element("S", "S", 0, H1, "identity", (1, None), cubes)
register_element("DPC", "DPC", 0, L2, "identity", (0, None), cubes)
register_element("BDMCE", "BDMCE", 1, HCurl, "covariant Piola", (1, None),
("quadrilateral",))
register_element("BDMCF", None, 1, HDiv, "contravariant Piola", (1, None),
register_element("BDMCF", "BDMCF", 1, HDiv, "contravariant Piola", (1, None),
("quadrilateral",))
register_element("AAE", None, 1, HCurl, "covariant Piola", (1, None),
register_element("SminusE", "SminusE", 1, HCurl, "covariant Piola", (1, None), cubes[1:3])
register_element("SminusF", "SminusF", 1, HDiv, "contravariant Piola", (1, None), cubes[1:2])
register_element("SminusDiv", "SminusDiv", 1, HDiv, "contravariant Piola", (1, None), cubes[1:3])
register_element("SminusCurl", "SminusCurl", 1, HCurl, "covariant Piola", (1, None), cubes[1:3])
register_element("AAE", "AAE", 1, HCurl, "covariant Piola", (1, None),
("hexahedron",))
register_element("AAF", None, 1, HDiv, "contravariant Piola", (1, None),
register_element("AAF", "AAF", 1, HDiv, "contravariant Piola", (1, None),
("hexahedron",))

# New aliases introduced for the periodic table 2014
Expand All @@ -220,8 +224,8 @@ def show_elements():
degree: ("Brezzi-Douglas-Marini", order))

# discontinuous elements using l2 pullbacks
register_element("DPC L2", None, 0, L2, "L2 Piola", (1, None), cubes)
register_element("DQ L2", None, 0, L2, "L2 Piola", (0, None), cubes)
register_element("DPC L2", "DPC L2", 0, L2, "L2 Piola", (1, None), cubes)
register_element("DQ L2", "DQ L2", 0, L2, "L2 Piola", (0, None), cubes)
register_element("Gauss-Legendre L2", "GL L2", 0, L2, "L2 Piola", (0, None),
("interval",))
register_element("Discontinuous Lagrange L2", "DG L2", 0, L2, "L2 Piola", (0, None),
Expand Down
4 changes: 2 additions & 2 deletions ufl/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from ufl.form import Form
from ufl.constantvalue import Zero, RealValue, ComplexValue, as_ufl
from ufl.differentiation import VariableDerivative, Grad, Div, Curl, NablaGrad, NablaDiv
from ufl.tensoralgebra import Transposed, Inner, Outer, Dot, Cross, \
from ufl.tensoralgebra import Transposed, Inner, Outer, Dot, Cross, Perp, \
Determinant, Inverse, Cofactor, Trace, Deviatoric, Skew, Sym
from ufl.coefficient import Coefficient
from ufl.variable import Variable
Expand Down Expand Up @@ -174,7 +174,7 @@ def perp(v):
v = as_ufl(v)
if v.ufl_shape != (2,):
raise ValueError("Expecting a 2D vector expression.")
return as_vector((-v[1], v[0]))
return Perp(v)


def cross(a, b):
Expand Down
28 changes: 28 additions & 0 deletions ufl/tensoralgebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,34 @@ def __str__(self):
parstr(self.ufl_operands[1], self))


@ufl_type(is_index_free=True, num_ops=1)
class Perp(CompoundTensorOperator):
__slots__ = ()

def __new__(cls, A):
sh = A.ufl_shape

# Checks
if not len(sh) == 1:
raise ValueError(f"Perp requires arguments of rank 1, got {ufl_err_str(A)}")
if not sh[0] == 2:
raise ValueError(f"Perp can only work on 2D vectors, got {ufl_err_str(A)}")

# Simplification
if isinstance(A, Zero):
return Zero((), A.ufl_free_indices, A.ufl_index_dimensions)

return CompoundTensorOperator.__new__(cls)

def __init__(self, A):
CompoundTensorOperator.__init__(self, (A,))

ufl_shape = (2,)

def __str__(self):
return "perp(%s)" % self.ufl_operands[0]


@ufl_type(num_ops=2)
class Cross(CompoundTensorOperator):
__slots__ = ("ufl_free_indices", "ufl_index_dimensions")
Expand Down

0 comments on commit d9d7ff3

Please sign in to comment.