Skip to content

Commit 0b60daa

Browse files
authored
HCT: basis transformation for hierarchical edge functions (#131)
1 parent 2c7aa93 commit 0b60daa

File tree

3 files changed

+30
-42
lines changed

3 files changed

+30
-42
lines changed

finat/argyris.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,28 @@
99
from finat.physically_mapped import PhysicallyMappedElement, Citations
1010

1111

12-
def _edge_transform(V, voffset, fiat_cell, moment_deg, coordinate_mapping, avg=False):
13-
"""Basis transformation for integral edge moments."""
14-
15-
J = coordinate_mapping.jacobian_at([1/3, 1/3])
12+
def _edge_transform(V, vorder, eorder, fiat_cell, coordinate_mapping, avg=False):
13+
"""Basis transformation for integral edge moments.
14+
15+
:arg V: the transpose of the basis transformation.
16+
:arg vorder: the jet order at vertices, matching the Jacobi weights in the
17+
normal derivative moments on edges.
18+
:arg eorder: the order of the normal derivative moments.
19+
:arg fiat_cell: the reference triangle.
20+
:arg coordinate_mapping: the coordinate mapping.
21+
:kwarg avg: are we scaling integrals by dividing by the edge length?
22+
"""
23+
sd = fiat_cell.get_spatial_dimension()
24+
J = coordinate_mapping.jacobian_at(fiat_cell.make_points(sd, 0, sd+1)[0])
1625
rns = coordinate_mapping.reference_normals()
1726
pts = coordinate_mapping.physical_tangents()
1827
pns = coordinate_mapping.physical_normals()
1928
pel = coordinate_mapping.physical_edge_lengths()
2029

30+
# number of DOFs per vertex/edge
31+
voffset = comb(sd + vorder, vorder)
32+
eoffset = 2 * eorder + 1
2133
top = fiat_cell.get_topology()
22-
eoffset = 2 * moment_deg - 1
23-
toffset = moment_deg - 1
2434
for e in sorted(top[1]):
2535
nhat = partial_indexed(rns, (e, ))
2636
n = partial_indexed(pns, (e, ))
@@ -33,15 +43,16 @@ def _edge_transform(V, voffset, fiat_cell, moment_deg, coordinate_mapping, avg=F
3343

3444
v0id, v1id = (v * voffset for v in top[1][e])
3545
s0 = len(top[0]) * voffset + e * eoffset
36-
for k in range(moment_deg):
46+
for k in range(eorder+1):
3747
s = s0 + k
38-
P1 = Literal(comb(k + 2, k))
48+
# Jacobi polynomial at the endpoints
49+
P1 = comb(k + vorder, k)
3950
P0 = -(-1)**k * P1
4051
V[s, s] = Bnn
4152
V[s, v1id] = P1 * Bnt
4253
V[s, v0id] = P0 * Bnt
4354
if k > 0:
44-
V[s, s + toffset] = -1 * Bnt
55+
V[s, s + eorder] = -1 * Bnt
4556

4657

4758
class Argyris(PhysicallyMappedElement, ScalarFiatElement):
@@ -68,7 +79,8 @@ def basis_transformation(self, coordinate_mapping):
6879

6980
sd = self.cell.get_spatial_dimension()
7081
top = self.cell.get_topology()
71-
voffset = (sd+1)*sd//2 + sd + 1
82+
vorder = 2
83+
voffset = comb(sd + vorder, vorder)
7284
for v in sorted(top[0]):
7385
s = voffset * v
7486
for i in range(sd):
@@ -84,9 +96,9 @@ def basis_transformation(self, coordinate_mapping):
8496
V[s+5, s+4] = 2*J[0, 1]*J[1, 1]
8597
V[s+5, s+5] = J[1, 1]*J[1, 1]
8698

87-
q = self.degree - 4
99+
eorder = self.degree - 5
88100
if self.variant == "integral":
89-
_edge_transform(V, voffset, self.cell, q, coordinate_mapping, avg=self.avg)
101+
_edge_transform(V, vorder, eorder, self.cell, coordinate_mapping, avg=self.avg)
90102
else:
91103
rns = coordinate_mapping.reference_normals()
92104
pns = coordinate_mapping.physical_normals()
@@ -128,10 +140,10 @@ def basis_transformation(self, coordinate_mapping):
128140
V[:, voffset*v+3+k] *= 1 / (h[v]*h[v])
129141

130142
if self.variant == "point":
131-
eoffset = 2 * q - 1
143+
eoffset = 2 * eorder + 1
132144
for e in sorted(top[1]):
133145
v0, v1 = top[1][e]
134146
s = len(top[0]) * voffset + e * eoffset
135-
V[:, s:s+q] *= 2 / (h[v0] + h[v1])
147+
V[:, s:s+eorder+1] *= 2 / (h[v0] + h[v1])
136148

137149
return ListTensor(V.T)

finat/hct.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@ def basis_transformation(self, coordinate_mapping):
3030

3131
sd = self.cell.get_dimension()
3232
top = self.cell.get_topology()
33-
voffset = sd + 1
33+
voffset = 1 + sd
3434
for v in sorted(top[0]):
3535
s = voffset * v
3636
for i in range(sd):
3737
for j in range(sd):
3838
V[s+1+i, s+1+j] = J[j, i]
3939

40-
q = self.degree - 2
41-
_edge_transform(V, voffset, self.cell, q, coordinate_mapping, avg=self.avg)
40+
vorder = 1
41+
eorder = self.degree - 3
42+
_edge_transform(V, vorder, eorder, self.cell, coordinate_mapping, avg=self.avg)
4243

4344
# Patch up conditioning
4445
h = coordinate_mapping.cell_size()

test/test_morley.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)