Skip to content

Commit e13e6ec

Browse files
authored
Clean up WuXuH3NCSpace (#228)
* cleanup WuXuH3NCSpace
1 parent 69d8e4f commit e13e6ec

1 file changed

Lines changed: 27 additions & 47 deletions

File tree

FIAT/wuxu.py

Lines changed: 27 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -28,84 +28,64 @@
2828
polydim = expansions.polynomial_dimension
2929

3030

31-
def WuXuRobustH3NCSpace(ref_el):
32-
"""Constructs a basis for the the Wu Xu H^3 nonconforming space
33-
P^{(3,2)}(T) = P_3(T) + b_T P_1(T) + b_T^2 P_1(T),
31+
def WuXuH3NCSpace(ref_el, robust=False):
32+
"""Constructs a basis for the the Wu Xu H^3 nonconforming spaces
33+
34+
P^{(3,1)}(T) = P_3(T) + b_T P_1(T), if robust = False
35+
36+
P^{(3,2)}(T) = P_3(T) + b_T P_1(T) + b_T^2 P_1(T), if robust = True
37+
3438
where b_T is the standard cubic bubble."""
3539

3640
sd = ref_el.get_spatial_dimension()
3741
assert sd == 2
3842

39-
em_deg = 7
40-
4143
# Unfortunately, b_T^2 P_1 has degree 7 (cubic squared times a linear)
4244
# so we need a high embedded degree!
43-
p7 = polynomial_set.ONPolynomialSet(ref_el, 7)
45+
embedded_degree = 7 if robust else 4
46+
pk = polynomial_set.ONPolynomialSet(ref_el, embedded_degree)
4447

4548
dimp1 = polydim(ref_el, 1)
4649
dimp3 = polydim(ref_el, 3)
47-
dimp7 = polydim(ref_el, 7)
50+
dimpk = polydim(ref_el, embedded_degree)
4851

4952
# Here's the first bit we'll work with. It's already expressed in terms
50-
# of the ON basis for P7, so we're golden.
51-
p3fromp7 = p7.take(list(range(dimp3)))
53+
# of the ON basis for Pk, so we're golden.
54+
p3frompk = pk.take(list(range(dimp3)))
5255

5356
# Rather than creating the barycentric coordinates ourself, let's
5457
# reuse the existing bubble functionality
5558
bT = Bubble(ref_el, 3)
5659
p1 = Lagrange(ref_el, 1)
5760

58-
# next, we'll have to project b_T P1 and b_T^2 P1 onto P^7
59-
Q = create_quadrature(ref_el, 14)
61+
# next, we'll have to project b_T P1 and b_T^2 P1 onto Pk
62+
Q = create_quadrature(ref_el, 2*embedded_degree)
6063
Qpts = numpy.array(Q.get_points())
6164
Qwts = numpy.array(Q.get_weights())
6265

63-
zero_index = tuple([0 for i in range(sd)])
64-
6566
# it's just one bubble function: let's get a 1d array!
66-
bT_at_qpts = bT.tabulate(0, Qpts)[zero_index][0, :]
67-
p1_at_qpts = p1.tabulate(0, Qpts)[zero_index]
67+
bT_at_qpts = bT.tabulate(0, Qpts)[(0,)*sd][0, :]
68+
p1_at_qpts = p1.tabulate(0, Qpts)[(0,)*sd]
6869

69-
# Note: difference in signature because bT, p1 are FE and p7 is a
70+
# Note: difference in signature because bT, p1 are FE and pk is a
7071
# polynomial set
71-
p7_at_qpts = p7.tabulate(Qpts)[zero_index]
72+
pk_at_qpts = pk.tabulate(Qpts)[(0,)*sd]
7273

73-
bubble_coeffs = numpy.zeros((6, dimp7), "d")
74+
bubble_coeffs = numpy.zeros((6, dimpk), "d")
7475

7576
# first three: bT P1, last three will be bT^2 P1
7677
foo = bT_at_qpts * p1_at_qpts * Qwts
77-
bubble_coeffs[:dimp1, :] = numpy.dot(foo, p7_at_qpts.T)
78+
bubble_coeffs[:dimp1, :] = numpy.dot(foo, pk_at_qpts.T)
7879

79-
foo = bT_at_qpts * foo
80-
bubble_coeffs[dimp1:2*dimp1, :] = numpy.dot(foo, p7_at_qpts.T)
80+
if robust:
81+
foo = bT_at_qpts * foo
82+
bubble_coeffs[dimp1:2*dimp1, :] = numpy.dot(foo, pk_at_qpts.T)
8183

82-
bubbles = polynomial_set.PolynomialSet(ref_el, 3, em_deg,
83-
p7.get_expansion_set(),
84+
bubbles = polynomial_set.PolynomialSet(ref_el, 3, embedded_degree,
85+
pk.get_expansion_set(),
8486
bubble_coeffs)
8587

86-
return polynomial_set.polynomial_set_union_normalized(p3fromp7, bubbles)
87-
88-
89-
def WuXuH3NCSpace(ref_el):
90-
"""Constructs a basis for the the Wu Xu H^3 nonconforming space
91-
P(T) = P_3(T) + b_T P_1(T),
92-
where b_T is the standard cubic bubble."""
93-
94-
assert ref_el.get_spatial_dimension() == 2
95-
96-
em_deg = 4
97-
p4 = polynomial_set.ONPolynomialSet(ref_el, em_deg)
98-
99-
# Here's the first bit we'll work with. It's already expressed in terms
100-
# of the ON basis for P4, so we're golden.
101-
dimp3 = polydim(ref_el, 3)
102-
p3fromp4 = p4.take(list(range(dimp3)))
103-
104-
# Rather than creating the barycentric coordinates ourself, let's
105-
# reuse the existing bubble functionality
106-
bT = Bubble(ref_el, 4)
107-
108-
return polynomial_set.polynomial_set_union_normalized(p3fromp4, bT.get_nodal_basis())
88+
return polynomial_set.polynomial_set_union_normalized(p3frompk, bubbles)
10989

11090

11191
class WuXuRobustH3NCDualSet(dual_set.DualSet):
@@ -176,7 +156,7 @@ def __init__(self, ref_el, degree):
176156
class WuXuRobustH3NC(finite_element.CiarletElement):
177157
"""The Wu-Xu robust H3 nonconforming finite element"""
178158
def __init__(self, ref_el, degree=7):
179-
poly_set = WuXuRobustH3NCSpace(ref_el)
159+
poly_set = WuXuH3NCSpace(ref_el, robust=True)
180160
assert degree == poly_set.degree
181161
dual = WuXuRobustH3NCDualSet(ref_el, degree)
182162
super().__init__(poly_set, dual, degree)

0 commit comments

Comments
 (0)