Skip to content

Commit e859a19

Browse files
authored
Correct BDFM on simplices (#278)
* fix bdfm on triangles * fix BDFM on tets * cache * correct
1 parent 9d053d6 commit e859a19

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

symfem/elements/bdfm.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Brezzi-Douglas-Fortin-Marini elements.
22
33
This element's definition appears in https://doi.org/10.1051/m2an/1987210405811
4-
(Brezzi, Douglas, Fortin, Marini, 1987)
4+
(Brezzi, Douglas, Fortin, Marini, 1987) and
5+
https://doi.org/10.1007/978-1-4612-3172-1 (Brezzi, Fortin, 1991)
56
"""
67

78
import typing
@@ -14,7 +15,8 @@
1415
from symfem.references import NonDefaultReferenceError, Reference
1516
from symfem.symbols import x
1617
from symfem.elements.dpc import DPC, VectorDPC
17-
from symfem.elements.lagrange import Lagrange, VectorLagrange
18+
from symfem.elements.lagrange import Lagrange
19+
from symfem.elements.nedelec import NedelecFirstKind
1820

1921
__all__ = ["bdfm_polyset", "BDFM"]
2022

@@ -38,9 +40,12 @@ def bdfm_polyset(reference: Reference, order: int) -> typing.List[FunctionInput]
3840
pset.append((x[0] ** i * x[1] ** j, 0))
3941
pset.append((0, x[1] ** i * x[0] ** j))
4042
elif reference.name == "triangle":
41-
for i in range(order):
42-
p = x[0] ** i * x[1] ** (order - 1 - i)
43-
pset.append((x[0] * p, x[1] * p))
43+
for i in range(order - 1):
44+
p = x[0] ** i * x[1] ** (order - 2 - i)
45+
pset.append((x[0] * (x[0] + x[1]) * p, 0))
46+
pset.append((0, x[1] * (x[0] + x[1]) * p))
47+
p = x[0] ** (order - 1)
48+
pset.append((x[0] * p, x[1] * p))
4449
elif reference.name == "hexahedron":
4550
for i in range(1, order + 1):
4651
for j in range(order + 1 - i):
@@ -49,10 +54,19 @@ def bdfm_polyset(reference: Reference, order: int) -> typing.List[FunctionInput]
4954
pset.append((0, x[1] ** i * x[0] ** j * x[2] ** k, 0))
5055
pset.append((0, 0, x[2] ** i * x[0] ** j * x[1] ** k))
5156
elif reference.name == "tetrahedron":
57+
for i in range(order - 1):
58+
for j in range(order - i - 1):
59+
p = x[0] ** i * x[1] ** j * x[2] ** (order - 2 - i - j)
60+
pset.append((x[0] * (x[0] + x[1] + x[2]) * p, 0, 0))
61+
pset.append((0, x[1] * (x[0] + x[1] + x[2]) * p, 0))
62+
pset.append((0, 0, x[2] * (x[0] + x[1] + x[2]) * p))
5263
for i in range(order):
53-
for j in range(order - i):
54-
p = x[0] ** i * x[1] ** j * x[2] ** (order - 1 - i - j)
55-
pset.append((x[0] * p, x[1] * p, x[2] * p))
64+
p = x[0] ** i * x[1] ** (order - 1 - i)
65+
pset.append((x[0] * p, x[1] * p, x[2] * p))
66+
for i in range(1, order):
67+
p = x[0] ** i * x[1] ** (order - 1 - i)
68+
pset.append((p * (x[0] + x[1]), 0, x[1] * p))
69+
5670
return pset
5771

5872

@@ -77,7 +91,7 @@ def __init__(self, reference: Reference, order: int, variant: str = "equispaced"
7791
dofs = make_integral_moment_dofs(
7892
reference,
7993
facets=(NormalIntegralMoment, Lagrange, order - 1, {"variant": variant}),
80-
cells=(IntegralMoment, VectorLagrange, order - 2, {"variant": variant}),
94+
cells=(IntegralMoment, NedelecFirstKind, order - 1, {"variant": variant}),
8195
)
8296
else:
8397
dofs = make_integral_moment_dofs(
@@ -121,4 +135,4 @@ def polynomial_superdegree(self) -> typing.Optional[int]:
121135
min_order = 1
122136
continuity = "H(div)"
123137
value_type = "vector"
124-
last_updated = "2023.06"
138+
last_updated = "2024.10"

test/test_polynomials.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def test_MTW_space(reference):
4848
)
4949
p_edge = p.subs(x, [i + t[0] * j for i, j in zip(sub_ref.origin, sub_ref.axes[0])])
5050
poly = p_edge.dot(sub_ref.normal()).as_sympy().expand().simplify()
51-
assert poly.is_real or sympy.Poly(poly).degree() <= 1
51+
assert poly.is_real or sympy.Poly(poly, x).degree() <= 1
5252

5353

5454
@pytest.mark.parametrize("reference", ["triangle", "quadrilateral", "tetrahedron", "hexahedron"])
@@ -73,7 +73,7 @@ def test_BDFM_space(reference, order):
7373
],
7474
)
7575
poly = p_edge.dot(sub_ref.normal()).as_sympy().expand().simplify()
76-
assert poly.is_real or sympy.Poly(poly).degree() <= order - 1
76+
assert poly.is_real or sympy.Poly(poly, x).degree() <= order - 1
7777

7878

7979
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)