diff --git a/CHANGELOG_SINCE_LAST_VERSION.md b/CHANGELOG_SINCE_LAST_VERSION.md index 9503d837..b1fde980 100644 --- a/CHANGELOG_SINCE_LAST_VERSION.md +++ b/CHANGELOG_SINCE_LAST_VERSION.md @@ -1 +1,2 @@ - Corrected polyset for Arnold-Winther element +- Added sub- and superdegree functions diff --git a/demo/custom_element.py b/demo/custom_element.py index 7679df81..0ca7f4b9 100644 --- a/demo/custom_element.py +++ b/demo/custom_element.py @@ -40,6 +40,7 @@ def __init__(self, reference, order): min_order = 1 max_order = 1 continuity = "L2" + value_type = "scalar" mapping = "identity" diff --git a/symfem/elements/abf.py b/symfem/elements/abf.py index c41fe459..864e7a4d 100644 --- a/symfem/elements/abf.py +++ b/symfem/elements/abf.py @@ -77,8 +77,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 2 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * 2 + 2 + names = ["Arnold-Boffi-Falk", "ABF"] references = ["quadrilateral"] min_order = 0 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/ac.py b/symfem/elements/ac.py index a2dffb8a..d34c6d18 100644 --- a/symfem/elements/ac.py +++ b/symfem/elements/ac.py @@ -75,8 +75,28 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + if self.order < 2: + return self.order + else: + return self.order // 2 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + names = ["Arbogast-Correa", "AC", "AC full", "Arbogast-Correa full"] references = ["quadrilateral"] min_order = 0 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/alfeld_sorokina.py b/symfem/elements/alfeld_sorokina.py index c0c41f27..2c19329b 100644 --- a/symfem/elements/alfeld_sorokina.py +++ b/symfem/elements/alfeld_sorokina.py @@ -125,9 +125,26 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["Alfeld-Sorokina", "AS"] references = ["triangle"] min_order = 2 max_order = 2 continuity = "C0" + value_type = "scalar macro" last_updated = "2023.05" diff --git a/symfem/elements/argyris.py b/symfem/elements/argyris.py index 11c85cc5..b4f53e02 100644 --- a/symfem/elements/argyris.py +++ b/symfem/elements/argyris.py @@ -64,9 +64,26 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Argyris"] references = ["triangle"] min_order = 5 max_order = 5 continuity = "L2" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/aw.py b/symfem/elements/aw.py index 516210c9..1ccdf521 100644 --- a/symfem/elements/aw.py +++ b/symfem/elements/aw.py @@ -132,10 +132,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Arnold-Winther", "AW", "conforming Arnold-Winther"] references = ["triangle"] min_order = 3 continuity = "integral inner H(div)" + value_type = "symmetric matrix" last_updated = "2024.09" @@ -216,9 +233,26 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["nonconforming Arnold-Winther", "nonconforming AW"] references = ["triangle"] min_order = 2 max_order = 2 continuity = "integral inner H(div)" + value_type = "symmetric matrix" last_updated = "2023.06" diff --git a/symfem/elements/bddm.py b/symfem/elements/bddf.py similarity index 87% rename from symfem/elements/bddm.py rename to symfem/elements/bddf.py index 442f0ca9..7d0cdd57 100644 --- a/symfem/elements/bddm.py +++ b/symfem/elements/bddf.py @@ -78,8 +78,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order // 3 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + names = ["Brezzi-Douglas-Duran-Fortin", "BDDF"] references = ["hexahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/bdfm.py b/symfem/elements/bdfm.py index 80948319..29ca1a31 100644 --- a/symfem/elements/bdfm.py +++ b/symfem/elements/bdfm.py @@ -97,8 +97,28 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + if self.reference.name in ["triangle", "tetrahedron"]: + return self.order - 1 + else: + return self.order // self.reference.tdim + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Brezzi-Douglas-Fortin-Marini", "BDFM"] references = ["triangle", "quadrilateral", "hexahedron", "tetrahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/bdm.py b/symfem/elements/bdm.py index 9ff73d66..05d0f0e1 100644 --- a/symfem/elements/bdm.py +++ b/symfem/elements/bdm.py @@ -52,8 +52,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Brezzi-Douglas-Marini", "BDM", "N2div"] references = ["triangle", "tetrahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/bell.py b/symfem/elements/bell.py index 3cf7a3ac..c141f1fb 100644 --- a/symfem/elements/bell.py +++ b/symfem/elements/bell.py @@ -54,9 +54,26 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return 4 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return 5 + + @property + def polynomial_subdegree(self) -> int: + return 4 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return 5 + names = ["Bell"] references = ["triangle"] min_order = 5 max_order = 5 continuity = "C1" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/bernardi_raugel.py b/symfem/elements/bernardi_raugel.py index 54d9c2f8..8e75d484 100644 --- a/symfem/elements/bernardi_raugel.py +++ b/symfem/elements/bernardi_raugel.py @@ -115,12 +115,28 @@ def __init__(self, reference: Reference, order: int): reference, x[i], p.dofs[0], entity=(3, 0), mapping="contravariant" ) ) - super().__init__(reference, order, poly, dofs, reference.tdim, reference.tdim) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + self.reference.tdim - 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + self.reference.tdim - 1 + names = ["Bernardi-Raugel"] references = ["triangle", "tetrahedron"] min_order = 1 max_order = {"triangle": 1, "tetrahedron": 2} continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/bernstein.py b/symfem/elements/bernstein.py index adf25d1b..fbe9d576 100644 --- a/symfem/elements/bernstein.py +++ b/symfem/elements/bernstein.py @@ -234,8 +234,25 @@ def index(x: int, y: int = 0, z: int = 0) -> int: super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Bernstein", "Bernstein-Bezier"] references = ["interval", "triangle", "tetrahedron"] min_order = 0 continuity = "C0" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/bfs.py b/symfem/elements/bfs.py index 43634c78..d249d71f 100644 --- a/symfem/elements/bfs.py +++ b/symfem/elements/bfs.py @@ -50,10 +50,27 @@ def __init__(self, reference: Reference, order: int): poly += quolynomial_set_1d(reference.tdim, order) super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * 2 + names = ["Bogner-Fox-Schmit", "BFS"] references = ["quadrilateral"] min_order = 3 max_order = 3 continuity = "C0" # continuity = "C1" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/bubble.py b/symfem/elements/bubble.py index 4fb88955..28cf61c2 100644 --- a/symfem/elements/bubble.py +++ b/symfem/elements/bubble.py @@ -32,9 +32,17 @@ def __init__(self, reference: Reference, order: int, variant: str = "equispaced" from symfem import create_element p1 = create_element(reference.name, "Lagrange", 1, vertices=reference.vertices) + basis = p1.get_basis_functions() bubble = 1 - for f in p1.get_basis_functions(): - bubble *= f + if reference.name in "quadrilateral": + bubble *= basis[0] + bubble *= basis[3] + elif reference.name in "hexahedron": + bubble *= basis[0] + bubble *= basis[7] + else: + for f in basis: + bubble *= f if reference.name in ["interval", "quadrilateral", "hexahedron"]: o = order - 2 @@ -78,6 +86,24 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return -1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return -1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + if self.reference.name in ["quadrilateral", "hexahedron"]: + return self.order * self.reference.tdim + return self.order + names = ["bubble"] references = ["interval", "triangle", "tetrahedron", "quadrilateral", "hexahedron"] min_order = { @@ -88,7 +114,8 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: "hexahedron": 2, } continuity = "C0" - last_updated = "2023.09" + value_type = "scalar" + last_updated = "2024.09" class BubbleEnrichedLagrange(CiarletElement): @@ -122,11 +149,28 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 2 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + 2 + names = ["bubble enriched Lagrange"] references = ["triangle"] min_order = 1 continuity = "C0" - last_updated = "2023.09" + value_type = "scalar" + last_updated = "2024.09" class BubbleEnrichedVectorLagrange(CiarletElement): @@ -167,8 +211,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 2 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + 2 + names = ["bubble enriched vector Lagrange"] references = ["triangle"] min_order = 1 continuity = "C0" - last_updated = "2023.09" + value_type = "vector" + last_updated = "2024.09" diff --git a/symfem/elements/conforming_crouzeix_raviart.py b/symfem/elements/conforming_crouzeix_raviart.py index d8940bd4..4fa22aa4 100644 --- a/symfem/elements/conforming_crouzeix_raviart.py +++ b/symfem/elements/conforming_crouzeix_raviart.py @@ -58,8 +58,29 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + if self.order == 1: + return 1 + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + if self.order == 1: + return 1 + return self.order + 1 + names = ["conforming Crouzeix-Raviart", "conforming CR"] references = ["triangle"] min_order = 1 continuity = "L2" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/crouzeix_raviart.py b/symfem/elements/crouzeix_raviart.py index 3bd55dce..1bc2a00e 100644 --- a/symfem/elements/crouzeix_raviart.py +++ b/symfem/elements/crouzeix_raviart.py @@ -80,9 +80,26 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Crouzeix-Raviart", "CR", "Crouzeix-Falk", "CF"] references = ["triangle", "tetrahedron"] min_order = 1 max_order = {"tetrahedron": 1} continuity = "L2" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/direct_serendipity.py b/symfem/elements/direct_serendipity.py index 8f08fad4..96945514 100644 --- a/symfem/elements/direct_serendipity.py +++ b/symfem/elements/direct_serendipity.py @@ -4,6 +4,8 @@ (Arbogast, Tao, 2018) """ +import typing + from symfem.finite_element import DirectElement from symfem.references import Reference from symfem.symbols import x @@ -77,8 +79,25 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, basis_functions, basis_entities, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["direct serendipity"] references = ["quadrilateral"] min_order = 1 continuity = "C0" + value_type = "scalar non-polynomial" last_updated = "2023.05" diff --git a/symfem/elements/dpc.py b/symfem/elements/dpc.py index c895a7c0..4c704c92 100644 --- a/symfem/elements/dpc.py +++ b/symfem/elements/dpc.py @@ -71,10 +71,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order // self.reference.tdim + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["dPc"] references = ["interval", "quadrilateral", "hexahedron"] min_order = 0 continuity = "L2" + value_type = "scalar" last_updated = "2023.07.1" @@ -119,8 +136,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order // self.reference.tdim + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["vector dPc"] references = ["quadrilateral", "hexahedron"] min_order = 0 continuity = "L2" + value_type = "vector" last_updated = "2023.07" diff --git a/symfem/elements/dual.py b/symfem/elements/dual.py index 1fb19a9a..ecb5be93 100644 --- a/symfem/elements/dual.py +++ b/symfem/elements/dual.py @@ -254,11 +254,28 @@ def __init__(self, reference: DualPolygon, order: int): dual_coefficients, fine_space, reference, order, dof_entities, reference.tdim, 1 ) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["dual polynomial", "dual P", "dual"] references = ["dual polygon"] min_order = 0 max_order = 1 continuity = "C0" + value_type = "scalar dual" last_updated = "2023.05" @@ -306,11 +323,28 @@ def __init__(self, reference: DualPolygon, order: int): dof_directions=tuple(dof_directions), ) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["Buffa-Christiansen", "BC"] references = ["dual polygon"] min_order = 1 max_order = 1 continuity = "H(div)" + value_type = "vector dual" last_updated = "2023.05" @@ -358,9 +392,26 @@ def __init__(self, reference: DualPolygon, order: int): dof_directions=tuple(dof_directions), ) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["rotated Buffa-Christiansen", "RBC"] references = ["dual polygon"] min_order = 1 max_order = 1 continuity = "H(div)" + value_type = "vector dual" last_updated = "2023.05" diff --git a/symfem/elements/enriched_galerkin.py b/symfem/elements/enriched_galerkin.py index a56043cc..51b30fa4 100644 --- a/symfem/elements/enriched_galerkin.py +++ b/symfem/elements/enriched_galerkin.py @@ -4,6 +4,8 @@ (Sun, Liu, 2009). """ +import typing + from symfem.finite_element import EnrichedElement from symfem.references import Reference from symfem.elements.lagrange import Lagrange @@ -27,8 +29,27 @@ def __init__(self, reference: Reference, order: int): else: super().__init__([Lagrange(reference, order), Lagrange(reference, 0)]) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + if self.reference.name in ["quadrilateral", "hexahedron"]: + return self.order * self.reference.tdim + return self.order + names = ["enriched Galerkin", "EG"] references = ["interval", "triangle", "quadrilateral", "tetrahedron", "hexahedron"] min_order = 1 continuity = "C0" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/fortin_soulie.py b/symfem/elements/fortin_soulie.py index cafd6b78..99fc7f29 100644 --- a/symfem/elements/fortin_soulie.py +++ b/symfem/elements/fortin_soulie.py @@ -47,9 +47,26 @@ def __init__(self, reference: Reference, order: int): poly += polynomial_set_1d(reference.tdim, order) super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Fortin-Soulie", "FS"] references = ["triangle"] min_order = 2 max_order = 2 continuity = "L2" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/guzman_neilan.py b/symfem/elements/guzman_neilan.py index 18ed8218..76a545db 100644 --- a/symfem/elements/guzman_neilan.py +++ b/symfem/elements/guzman_neilan.py @@ -199,11 +199,28 @@ def _make_polyset_tetrahedron( basis.append(PiecewiseFunction(pieces, 3)) return basis + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["Guzman-Neilan"] references = ["triangle", "tetrahedron"] min_order = 1 max_order = {"triangle": 1, "tetrahedron": 2} continuity = "H(div)" + value_type = "vector macro" last_updated = "2023.06" diff --git a/symfem/elements/hct.py b/symfem/elements/hct.py index 46ad5f7e..a6e6fdf3 100644 --- a/symfem/elements/hct.py +++ b/symfem/elements/hct.py @@ -127,10 +127,27 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["Hsieh-Clough-Tocher", "Clough-Tocher", "HCT", "CT"] references = ["triangle"] min_order = 3 max_order = 3 # continuity = "C1" continuity = "C0" + value_type = "scalar macro" last_updated = "2023.06" diff --git a/symfem/elements/hermite.py b/symfem/elements/hermite.py index 9499566a..7d9748a7 100644 --- a/symfem/elements/hermite.py +++ b/symfem/elements/hermite.py @@ -47,9 +47,26 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Hermite"] references = ["interval", "triangle", "tetrahedron"] min_order = 3 max_order = 3 continuity = "C0" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/hhj.py b/symfem/elements/hhj.py index 2d41e5d9..c97dfb46 100644 --- a/symfem/elements/hhj.py +++ b/symfem/elements/hhj.py @@ -122,8 +122,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Hellan-Herrmann-Johnson", "HHJ"] references = ["triangle", "tetrahedron"] min_order = 0 continuity = "inner H(div)" + value_type = "symmetric matrix" last_updated = "2024.02" diff --git a/symfem/elements/huang_zhang.py b/symfem/elements/huang_zhang.py index ac89306a..41fdeded 100644 --- a/symfem/elements/huang_zhang.py +++ b/symfem/elements/huang_zhang.py @@ -76,8 +76,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * 2 - 1 + names = ["Huang-Zhang", "HZ"] references = ["quadrilateral"] min_order = 2 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/kmv.py b/symfem/elements/kmv.py index 43a375f6..94404218 100644 --- a/symfem/elements/kmv.py +++ b/symfem/elements/kmv.py @@ -87,7 +87,7 @@ def __init__(self, reference: Reference, order: int): WeightedPointEvaluation(reference, v, sympy.Rational(1, 6), entity=(0, v_n)) ) poly = kmv_tri_polyset(1, 1) - + self._superdegree = 1 elif order == 2: for v_n, v in enumerate(reference.vertices): dofs.append( @@ -114,6 +114,7 @@ def __init__(self, reference: Reference, order: int): ) ) poly = kmv_tri_polyset(2, 3) + self._superdegree = 3 elif order == 3: for v_n, v in enumerate(reference.vertices): @@ -163,7 +164,7 @@ def __init__(self, reference: Reference, order: int): ) ) poly = kmv_tri_polyset(3, 4) - + self._superdegree = 4 else: raise NotImplementedError @@ -176,6 +177,7 @@ def __init__(self, reference: Reference, order: int): ) ) poly = kmv_tet_polyset(1, 1, 1) + self._superdegree = 1 elif order == 2: for v_n, v in enumerate(reference.vertices): @@ -218,6 +220,7 @@ def __init__(self, reference: Reference, order: int): ) ) poly = kmv_tet_polyset(2, 4, 4) + self._superdegree = 4 else: raise NotImplementedError @@ -226,8 +229,25 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self._superdegree + + @property + def polynomial_subdegree(self) -> int: + return self.lagrange_subdegree + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.lagrange_superdegree + names = ["Kong-Mulder-Veldhuizen", "KMV"] references = ["triangle", "tetrahedron"] min_order = 1 continuity = "C0" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/lagrange.py b/symfem/elements/lagrange.py index 2380b420..a0797b10 100644 --- a/symfem/elements/lagrange.py +++ b/symfem/elements/lagrange.py @@ -88,10 +88,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Lagrange", "P"] references = ["interval", "triangle", "tetrahedron"] min_order = 0 continuity = "C0" + value_type = "scalar" last_updated = "2023.09" @@ -148,10 +165,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["vector Lagrange", "vP"] references = ["interval", "triangle", "tetrahedron"] min_order = 0 continuity = "C0" + value_type = "vector" last_updated = "2023.09" @@ -201,10 +235,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["matrix Lagrange"] references = ["triangle", "tetrahedron"] min_order = 0 continuity = "L2" + value_type = "matrix" last_updated = "2023.09" @@ -277,8 +328,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["symmetric matrix Lagrange"] references = ["triangle", "tetrahedron"] min_order = 0 continuity = "L2" + value_type = "symmetric matrix" last_updated = "2023.09" diff --git a/symfem/elements/lagrange_prism.py b/symfem/elements/lagrange_prism.py index 613fabeb..e0c11d53 100644 --- a/symfem/elements/lagrange_prism.py +++ b/symfem/elements/lagrange_prism.py @@ -117,10 +117,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * 2 + names = ["Lagrange", "P"] references = ["prism"] min_order = 0 continuity = "C0" + value_type = "scalar" last_updated = "2023.07" @@ -165,8 +182,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * 2 + names: typing.List[str] = [] references = ["prism"] min_order = 0 continuity = "C0" + value_type = "vector" last_updated = "2023.05" diff --git a/symfem/elements/lagrange_pyramid.py b/symfem/elements/lagrange_pyramid.py index 261cea6d..19db1a33 100644 --- a/symfem/elements/lagrange_pyramid.py +++ b/symfem/elements/lagrange_pyramid.py @@ -112,8 +112,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return None + names = ["Lagrange", "P"] references = ["pyramid"] min_order = 0 continuity = "C0" - last_updated = "2023.07" + value_type = "scalar" + last_updated = "2024.09" diff --git a/symfem/elements/morley.py b/symfem/elements/morley.py index 638022d1..6233aba2 100644 --- a/symfem/elements/morley.py +++ b/symfem/elements/morley.py @@ -44,9 +44,26 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Morley"] references = ["triangle"] min_order = 2 max_order = 2 continuity = "L2" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/morley_wang_xu.py b/symfem/elements/morley_wang_xu.py index 816bab63..340a2b59 100644 --- a/symfem/elements/morley_wang_xu.py +++ b/symfem/elements/morley_wang_xu.py @@ -102,10 +102,27 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Morley-Wang-Xu", "MWX"] references = ["interval", "triangle", "tetrahedron"] min_order = 1 max_order = {"interval": 1, "triangle": 2, "tetrahedron": 3} # continuity = "C{order}" continuity = "C0" + value_type = "scalar" last_updated = "2023.06" diff --git a/symfem/elements/mtw.py b/symfem/elements/mtw.py index 7619ace3..147d1498 100644 --- a/symfem/elements/mtw.py +++ b/symfem/elements/mtw.py @@ -98,9 +98,26 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + self.reference.tdim - 2 + + @property + def polynomial_subdegree(self) -> int: + return self.lagrange_subdegree + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.lagrange_superdegree + names = ["Mardal-Tai-Winther", "MTW"] references = ["triangle", "tetrahedron"] min_order = 3 max_order = 3 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/nedelec.py b/symfem/elements/nedelec.py index 306ab378..29502cf0 100644 --- a/symfem/elements/nedelec.py +++ b/symfem/elements/nedelec.py @@ -50,10 +50,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Nedelec", "Nedelec1", "N1curl"] references = ["triangle", "tetrahedron"] min_order = 1 continuity = "H(curl)" + value_type = "vector" last_updated = "2023.06" @@ -89,8 +106,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Nedelec2", "N2curl"] references = ["triangle", "tetrahedron"] min_order = 1 continuity = "H(curl)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/nedelec_prism.py b/symfem/elements/nedelec_prism.py index 3eead6fa..64f66c8e 100644 --- a/symfem/elements/nedelec_prism.py +++ b/symfem/elements/nedelec_prism.py @@ -99,9 +99,26 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * 2 + names = ["Nedelec", "Ncurl"] references = ["prism"] min_order = 1 max_order = 2 continuity = "H(curl)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/p1_iso_p2.py b/symfem/elements/p1_iso_p2.py index e81d432a..fd14e2de 100644 --- a/symfem/elements/p1_iso_p2.py +++ b/symfem/elements/p1_iso_p2.py @@ -47,11 +47,28 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["P1-iso-P2", "P2-iso-P1", "iso-P2 P1"] references = ["interval"] min_order = 1 max_order = 1 continuity = "C0" + value_type = "scalar macro" last_updated = "2023.08" @@ -106,11 +123,28 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["P1-iso-P2", "P2-iso-P1", "iso-P2 P1"] references = ["triangle"] min_order = 1 max_order = 1 continuity = "C0" + value_type = "scalar macro" last_updated = "2023.06" @@ -168,9 +202,26 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["P1-iso-P2", "P2-iso-P1", "iso-P2 P1"] references = ["quadrilateral"] min_order = 1 max_order = 1 continuity = "C0" + value_type = "scalar macro" last_updated = "2023.06" diff --git a/symfem/elements/p1_macro.py b/symfem/elements/p1_macro.py index 8bef9b0b..6c5d0d34 100644 --- a/symfem/elements/p1_macro.py +++ b/symfem/elements/p1_macro.py @@ -60,9 +60,26 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["P1 macro"] references = ["triangle"] min_order = 1 max_order = 1 continuity = "C0" + value_type = "scalar macro" last_updated = "2023.06" diff --git a/symfem/elements/q.py b/symfem/elements/q.py index b3d09235..69157bb5 100644 --- a/symfem/elements/q.py +++ b/symfem/elements/q.py @@ -146,10 +146,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * self.reference.tdim + names = ["Q", "Lagrange", "P"] references = ["quadrilateral", "hexahedron"] min_order = 0 continuity = "C0" + value_type = "scalar" last_updated = "2023.07.1" @@ -197,10 +214,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * self.reference.tdim + names = ["vector Q", "vQ"] references = ["quadrilateral", "hexahedron"] min_order = 0 continuity = "C0" + value_type = "vector" last_updated = "2023.06" @@ -240,10 +274,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * self.reference.tdim - 1 + names = ["NCE", "RTCE", "Qcurl", "Nedelec", "Ncurl"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(curl)" + value_type = "vector" last_updated = "2023.06" @@ -282,8 +333,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return (self.order - 1) * self.reference.tdim + 1 + names = ["NCF", "RTCF", "Qdiv"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/rannacher_turek.py b/symfem/elements/rannacher_turek.py index a25f5dfc..55315dd4 100644 --- a/symfem/elements/rannacher_turek.py +++ b/symfem/elements/rannacher_turek.py @@ -50,9 +50,26 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {} + @property + def lagrange_subdegree(self) -> int: + return 0 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return 2 + + @property + def polynomial_subdegree(self) -> int: + return 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return 2 + names = ["Rannacher-Turek"] references = ["quadrilateral", "hexahedron"] min_order = 1 max_order = 1 continuity = "L2" + value_type = "scalar" last_updated = "2023.05" diff --git a/symfem/elements/regge.py b/symfem/elements/regge.py index 12ea4629..47f04b8d 100644 --- a/symfem/elements/regge.py +++ b/symfem/elements/regge.py @@ -175,10 +175,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Regge"] references = ["triangle", "tetrahedron"] min_order = 0 continuity = "inner H(curl)" + value_type = "symmetric matrix" last_updated = "2023.06" @@ -386,8 +403,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return (self.order + 1) * self.reference.tdim - 1 + names = ["Regge"] references = ["quadrilateral", "hexahedron"] min_order = 0 continuity = "inner H(curl)" + value_type = "symmetric matrix" last_updated = "2023.06" diff --git a/symfem/elements/rhct.py b/symfem/elements/rhct.py index df2fa646..a4f2a4e2 100644 --- a/symfem/elements/rhct.py +++ b/symfem/elements/rhct.py @@ -100,10 +100,27 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + raise NotImplementedError() + names = ["reduced Hsieh-Clough-Tocher", "rHCT"] references = ["triangle"] min_order = 3 max_order = 3 # continuity = "C1" continuity = "C0" + value_type = "scalar macro" last_updated = "2023.06" diff --git a/symfem/elements/rt.py b/symfem/elements/rt.py index 369075bc..a924b463 100644 --- a/symfem/elements/rt.py +++ b/symfem/elements/rt.py @@ -55,8 +55,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order - 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Raviart-Thomas", "RT", "N1div"] references = ["triangle", "tetrahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/serendipity.py b/symfem/elements/serendipity.py index 94718ec2..453de53a 100644 --- a/symfem/elements/serendipity.py +++ b/symfem/elements/serendipity.py @@ -66,11 +66,30 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + if self.order < self.reference.tdim: + return 1 + return self.order // self.reference.tdim + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + self.reference.tdim - 1 + names = ["serendipity", "S"] references = ["interval", "quadrilateral", "hexahedron"] min_order = 1 continuity = "C0" - last_updated = "2023.06" + value_type = "scalar" + last_updated = "2024.09" class SerendipityCurl(CiarletElement): @@ -109,10 +128,29 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + if self.order == 2 and self.reference.tdim == 3: + return 1 + return self.order // self.reference.tdim + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + self.reference.tdim - 1 + names = ["serendipity Hcurl", "Scurl", "BDMCE", "AAE"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(curl)" + value_type = "vector" last_updated = "2023.07" @@ -151,8 +189,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order // self.reference.tdim + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + names = ["serendipity Hdiv", "Sdiv", "BDMCF", "AAF"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.07" diff --git a/symfem/elements/taylor.py b/symfem/elements/taylor.py index f23402c9..4e67c4af 100644 --- a/symfem/elements/taylor.py +++ b/symfem/elements/taylor.py @@ -41,8 +41,25 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["Taylor", "discontinuous Taylor"] references = ["interval", "triangle", "tetrahedron"] min_order = 0 continuity = "L2" + value_type = "scalar" last_updated = "2023.06" diff --git a/symfem/elements/tnt.py b/symfem/elements/tnt.py index 6438d81a..5fb4da20 100644 --- a/symfem/elements/tnt.py +++ b/symfem/elements/tnt.py @@ -130,10 +130,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return max(self.order * self.reference.tdim, self.order + self.reference.tdim) + names = ["tiniest tensor", "TNT"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "C0" + value_type = "scalar" last_updated = "2023.06" @@ -291,10 +308,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * self.reference.tdim + 1 + names = ["tiniest tensor Hcurl", "TNTcurl"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(curl)" + value_type = "vector" last_updated = "2023.06" @@ -445,8 +479,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order * self.reference.tdim + 1 + names = ["tiniest tensor Hdiv", "TNTdiv"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/transition.py b/symfem/elements/transition.py index b216c8ab..39a3abd0 100644 --- a/symfem/elements/transition.py +++ b/symfem/elements/transition.py @@ -129,8 +129,42 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: "edge_orders": self.edge_orders, } + @property + def lagrange_subdegree(self) -> int: + poly_coeff = [p.as_sympy().expand().as_poly(*x).as_dict() for p in self._basis] # type: ignore + degree = 0 + while True: + basis_coeff = [ + p.as_sympy().expand().as_poly(*x).as_dict() # type: ignore + for p in polynomial_set_1d(self.reference.tdim, degree) + ] + monomials = list(set([m for p in poly_coeff + basis_coeff for m in p])) + mat = sympy.Matrix([[p[m] if m in p else 0 for m in monomials] for p in poly_coeff]) + mat2 = sympy.Matrix( + [[p[m] if m in p else 0 for m in monomials] for p in poly_coeff + basis_coeff] + ) + if mat.rank() < mat2.rank(): + return degree - 1 + degree += 1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return max( + p.subs(x[2], x[0]).subs(x[1], x[0]).as_sympy().as_poly(x[0]).degree() + for p in self._basis + ) + + @property + def polynomial_subdegree(self) -> int: + return self.lagrange_subdegree + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.lagrange_superdegree + names = ["transition"] references = ["triangle", "tetrahedron"] min_order = 1 continuity = "C0" + value_type = "scalar" last_updated = "2023.06" diff --git a/symfem/elements/trimmed_serendipity.py b/symfem/elements/trimmed_serendipity.py index 2fa90ff5..5e050d07 100644 --- a/symfem/elements/trimmed_serendipity.py +++ b/symfem/elements/trimmed_serendipity.py @@ -120,10 +120,27 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return (self.order + self.reference.tdim - 1) // (self.reference.tdim + 1) + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + self.reference.tdim - 2 + names = ["trimmed serendipity Hcurl", "TScurl"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(curl)" + value_type = "vector" last_updated = "2023.06" @@ -204,8 +221,25 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]: """ return {"variant": self.variant} + @property + def lagrange_subdegree(self) -> int: + return (self.order + 1) // (self.reference.tdim + 1) + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order - 1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + names = ["trimmed serendipity Hdiv", "TSdiv"] references = ["quadrilateral", "hexahedron"] min_order = 1 continuity = "H(div)" + value_type = "vector" last_updated = "2023.06" diff --git a/symfem/elements/vector_enriched_galerkin.py b/symfem/elements/vector_enriched_galerkin.py index 1272fed0..bdc65384 100644 --- a/symfem/elements/vector_enriched_galerkin.py +++ b/symfem/elements/vector_enriched_galerkin.py @@ -39,11 +39,28 @@ def __init__(self, reference: Reference): super().__init__(reference, 1, poly, dofs, reference.tdim, reference.tdim) + @property + def lagrange_subdegree(self) -> int: + return -1 + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return 1 + + @property + def polynomial_subdegree(self) -> int: + return -1 + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return 1 + names: typing.List[str] = [] references = ["triangle", "quadrilateral", "tetrahedron", "hexahedron"] min_order = 1 max_order = 1 continuity = "C0" + value_type = "vector" last_updated = "2023.05" @@ -62,8 +79,27 @@ def __init__(self, reference: Reference, order: int): else: super().__init__([VectorLagrange(reference, order), Enrichment(reference)]) + @property + def lagrange_subdegree(self) -> int: + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + + @property + def polynomial_subdegree(self) -> int: + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + if self.reference.name in ["quadrilateral", "hexahedron"]: + return self.order * self.reference.tdim + return self.order + names = ["enriched vector Galerkin", "locking-free enriched Galerkin", "LFEG"] references = ["triangle", "quadrilateral", "tetrahedron", "hexahedron"] min_order = 1 continuity = "C0" + value_type = "vector" last_updated = "2023.05" diff --git a/symfem/elements/wu_xu.py b/symfem/elements/wu_xu.py index f9d3e0e8..af976671 100644 --- a/symfem/elements/wu_xu.py +++ b/symfem/elements/wu_xu.py @@ -102,10 +102,31 @@ def __init__(self, reference: Reference, order: int): super().__init__(reference, order, poly, dofs, reference.tdim, 1) + @property + def lagrange_subdegree(self) -> int: + if self.reference.name == "interval": + return 3 + return self.order + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + + @property + def polynomial_subdegree(self) -> int: + if self.reference.name == "interval": + return 3 + return self.order + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + return self.order + 1 + names = ["Wu-Xu"] references = ["interval", "triangle", "tetrahedron"] min_order = {"interval": 2, "triangle": 3, "tetrahedron": 4} max_order = {"interval": 2, "triangle": 3, "tetrahedron": 4} continuity = "C0" # continuity = "C{order}" + value_type = "scalar" last_updated = "2023.06.1" diff --git a/symfem/finite_element.py b/symfem/finite_element.py index 68d38212..674fc9e9 100644 --- a/symfem/finite_element.py +++ b/symfem/finite_element.py @@ -88,6 +88,42 @@ def __init__( self._float_basis_functions = None self._value_scale = None + @property + def lagrange_subdegree(self) -> int: + """Get the Lagrange subdegree of the element. + + This is the degree of the highest degree Lagrange space whose polynomial space is a + subspace of this element's polynomial space. + """ + raise NotImplementedError() + + @property + def lagrange_superdegree(self) -> typing.Optional[int]: + """Get the Lagrange superdegree of the element. + + This is the degree of the highest degree Lagrange space whose polynomial space is a + superspace of this element's polynomial space. + """ + raise NotImplementedError() + + @property + def polynomial_subdegree(self) -> int: + """Get the polynomial subdegree of the element. + + This is the degree of the highest degree complete polynomial space that is a + subspace of this element's polynomial space. + """ + raise NotImplementedError() + + @property + def polynomial_superdegree(self) -> typing.Optional[int]: + """Get the polynomial superdegree of the element. + + This is the degree of the highest degree complete polynomial space that is a + superspace of this element's polynomial space. + """ + raise NotImplementedError() + @abstractmethod def dof_plot_positions(self) -> typing.List[PointType]: """Get the points to plot each DOF at on a DOF diagram. @@ -547,6 +583,7 @@ def name(self) -> str: references: typing.List[str] = [] last_updated = version cache = True + value_type = "unknown" _max_continuity_test_order = 4 diff --git a/symfem/polynomials/__init__.py b/symfem/polynomials/__init__.py index 6189d686..f2092195 100644 --- a/symfem/polynomials/__init__.py +++ b/symfem/polynomials/__init__.py @@ -10,6 +10,7 @@ Hdiv_polynomials, Hdiv_quolynomials, Hdiv_serendipity, + polynomial_set, polynomial_set_1d, polynomial_set_vector, prism_polynomial_set_1d, diff --git a/symfem/polynomials/polysets.py b/symfem/polynomials/polysets.py index c4133a4e..decc39c6 100644 --- a/symfem/polynomials/polysets.py +++ b/symfem/polynomials/polysets.py @@ -511,18 +511,12 @@ def pyramid_polynomial_set_1d( A set of polynomials """ assert dim == 3 - if order == 0: - return [ScalarFunction(1)] - - poly = polynomial_set_1d(3, order) - for d in range(order): - for i in range(d + 1): - for j in range(d + 1 - i): - p = variables[0] ** i * variables[1] ** j * variables[2] ** (d - i - j) - p *= (variables[0] * variables[1] / (1 - variables[2])) ** (order - d) - poly.append(ScalarFunction(p)) - - return poly + return [ + variables[0] ** i * variables[1] ** j * variables[2] ** k / (1 - variables[2]) ** min(i, j) + for k in range(order + 1) + for i in range(order + 1 - k) + for j in range(order + 1 - k) + ] def pyramid_polynomial_set_vector( @@ -545,3 +539,34 @@ def pyramid_polynomial_set_vector( for p in set1d for i in range(range_dim) ] + + +def polynomial_set( + cell: str, order: int, variables: AxisVariablesNotSingle = x +) -> typing.List[ScalarFunction]: + """One dimensional polynomial set for a cell. + + Args: + cell: Cell name + order: The maximum degree + variabtles: The variables to use + + Returns: + A set of polynomials + """ + if cell == "interval": + return polynomial_set_1d(1, order, variables) + if cell == "triangle": + return polynomial_set_1d(2, order, variables) + if cell == "tetrahedron": + return polynomial_set_1d(3, order, variables) + if cell == "quadrilateral": + return quolynomial_set_1d(2, order, variables) + if cell == "hexahedron": + return quolynomial_set_1d(3, order, variables) + if cell == "pyramid": + return pyramid_polynomial_set_1d(3, order, variables) + if cell == "prism": + return prism_polynomial_set_1d(3, order, variables) + + raise ValueError(f"Unsupported cell: {cell}") diff --git a/test/test_degrees.py b/test/test_degrees.py new file mode 100644 index 00000000..f93e075a --- /dev/null +++ b/test/test_degrees.py @@ -0,0 +1,220 @@ +"""Test every element.""" + +import pytest + +import sympy +from symfem import create_element +from symfem.functions import VectorFunction, MatrixFunction +from symfem.symbols import x +from symfem.polynomials import polynomial_set, polynomial_set_1d + +from .utils import test_elements + + +def make_into_value_type(poly, element): + if element.value_type == "scalar" or element.reference.gdim == 1: + return poly + if element.value_type == "vector": + return [ + VectorFunction([p if i == j else 0 for j in range(element.range_dim)]) + for i in range(element.range_dim) + for p in poly + ] + if element.value_type == "matrix": + return [ + MatrixFunction( + [ + [p if i0 == j0 and i1 == j1 else 0 for j1 in range(element.range_shape[1])] + for j0 in range(element.range_shape[0]) + ] + ) + for i0 in range(element.range_shape[0]) + for i1 in range(element.range_shape[1]) + for p in poly + ] + if element.value_type == "symmetric matrix": + assert element.range_shape[0] == element.range_shape[1] + return [ + MatrixFunction( + [ + [ + p if (i0 == j0 and i1 == j1) or (i1 == j0 and i0 == j1) else 0 + for j1 in range(element.range_shape[1]) + ] + for j0 in range(element.range_shape[0]) + ] + ) + for i0 in range(element.range_shape[0]) + for i1 in range(i0, element.range_shape[1]) + for p in poly + ] + + +def polydict(f, element, pyramid_mult=None): + if element.reference.name == "pyramid" and pyramid_mult is None: + pyramid_mult = element.lagrange_superdegree + 1 + if hasattr(f, "as_sympy"): + f = f.as_sympy() + + if element.value_type == "scalar" or element.reference.gdim == 1: + if element.reference.name == "pyramid": + f *= (1 - x[2]) ** pyramid_mult + return f.expand().as_poly(*x).as_dict() + if element.value_type == "vector": + if element.reference.name == "pyramid": + f = [i * (1 - x[2]) ** pyramid_mult for i in f] + out = {} + for i, f_i in enumerate(f): + for term, coeff in f_i.expand().as_poly(*x).as_dict().items(): + t = tuple(term if i == j else 0 for j, _ in enumerate(f)) + assert t not in out + out[t] = coeff + return out + if element.value_type in ["matrix", "symmetric matrix"]: + if element.reference.name == "pyramid": + f = [i * (1 - x[2]) ** pyramid_mult for i in f] + out = {} + for i, f_i in enumerate(f): + for term, coeff in f_i.expand().as_poly(*x).as_dict().items(): + t = tuple(term if i == j else 0 for j, _ in enumerate(f)) + assert t not in out + assert len(t) == element.range_dim + out[t] = coeff + return out + raise ValueError(f"Unsupported function type: {element.value_type}") + + +def run_subdegree_test(element, subdegree, pfunc, pargs): + if "non-polynomial" in element.value_type: + pytest.xfail("Cannot test non-polynomial elements yet") + if "dual" in element.value_type: + pytest.xfail("Cannot test dual elements yet") + if "macro" in element.value_type: + pytest.xfail("Cannot test macro elements yet") + + try: + basis_coeff = [polydict(p, element) for p in element.get_polynomial_basis()] + except NotImplementedError: + basis_coeff = [polydict(p, element) for p in element.get_basis_functions()] + + if subdegree > -1: + poly = pfunc(*[subdegree if p == "SUBDEGREE" else p for p in pargs]) + poly_coeff = [polydict(p, element) for p in make_into_value_type(poly, element)] + + monomials = list(set([m for p in poly_coeff + basis_coeff for m in p])) + + mat = sympy.Matrix([[p[m] if m in p else 0 for m in monomials] for p in basis_coeff]) + mat2 = sympy.Matrix( + [[p[m] if m in p else 0 for m in monomials] for p in poly_coeff + basis_coeff] + ) + + assert mat.rank() == mat2.rank() + + poly = pfunc(*[subdegree + 1 if p == "SUBDEGREE" else p for p in pargs]) + poly_coeff = [polydict(p, element) for p in make_into_value_type(poly, element)] + + monomials = list(set([m for p in poly_coeff + basis_coeff for m in p])) + + mat = sympy.Matrix([[p[m] if m in p else 0 for m in monomials] for p in basis_coeff]) + mat2 = sympy.Matrix( + [[p[m] if m in p else 0 for m in monomials] for p in poly_coeff + basis_coeff] + ) + + assert mat.rank() != mat2.rank() + + +def run_superdegree_test(element, superdegree, pfunc, pargs): + if "non-polynomial" in element.value_type: + pytest.xfail("Cannot test non-polynomial elements yet") + if "dual" in element.value_type: + pytest.xfail("Cannot test dual elements yet") + if "macro" in element.value_type: + pytest.xfail("Cannot test macro elements yet") + + try: + basis_coeff = [polydict(p, element) for p in element.get_polynomial_basis()] + except NotImplementedError: + basis_coeff = [polydict(p, element) for p in element.get_basis_functions()] + + if superdegree is not None: + poly = pfunc(*[superdegree if p == "SUPERDEGREE" else p for p in pargs]) + poly_coeff = [polydict(p, element) for p in make_into_value_type(poly, element)] + + monomials = list(set([m for p in poly_coeff + basis_coeff for m in p])) + + mat = sympy.Matrix([[p[m] if m in p else 0 for m in monomials] for p in poly_coeff]) + mat2 = sympy.Matrix( + [[p[m] if m in p else 0 for m in monomials] for p in poly_coeff + basis_coeff] + ) + + assert mat.rank() == mat2.rank() + + poly = pfunc( + *[ + (10 if superdegree is None else superdegree - 1) if p == "SUPERDEGREE" else p + for p in pargs + ] + ) + poly_coeff = [ + polydict(p, element, 10 if superdegree is None else None) + for p in make_into_value_type(poly, element) + ] + + monomials = list(set([m for p in poly_coeff + basis_coeff for m in p])) + + mat = sympy.Matrix([[p[m] if m in p else 0 for m in monomials] for p in poly_coeff]) + mat2 = sympy.Matrix( + [[p[m] if m in p else 0 for m in monomials] for p in poly_coeff + basis_coeff] + ) + + assert mat.rank() != mat2.rank() + + +@pytest.mark.parametrize( + ("cell_type", "element_type", "order", "kwargs"), + [ + [reference, element, order, kwargs] + for reference, i in test_elements.items() + for element, j in i.items() + for kwargs, k in j + for order in k + ], +) +def test_degrees(elements_to_test, cells_to_test, cell_type, element_type, order, kwargs, speed): + """Check Lagrange subdegrees of each element.""" + if elements_to_test != "ALL" and element_type not in elements_to_test: + pytest.skip() + if cells_to_test != "ALL" and cell_type not in cells_to_test: + pytest.skip() + if speed == "fast": + if order > 2: + pytest.skip() + if order == 2 and cell_type in ["tetrahedron", "hexahedron", "prism", "pyramid"]: + pytest.skip() + + element = create_element(cell_type, element_type, order, **kwargs) + if "non-polynomial" in element.value_type: + pytest.xfail("Cannot test non-polynomial elements yet") + if "dual" in element.value_type: + pytest.xfail("Cannot test dual elements yet") + if "macro" in element.value_type: + pytest.xfail("Cannot test macro elements yet") + + run_subdegree_test( + element, element.lagrange_subdegree, polynomial_set, (cell_type, "SUBDEGREE") + ) + run_subdegree_test( + element, + element.polynomial_subdegree, + polynomial_set_1d, + (element.reference.tdim, "SUBDEGREE"), + ) + run_superdegree_test( + element, element.lagrange_superdegree, polynomial_set, (cell_type, "SUPERDEGREE") + ) + run_superdegree_test( + element, + element.polynomial_superdegree, + polynomial_set_1d, + (element.reference.tdim, "SUPERDEGREE"), + )