9
9
from finat .physically_mapped import PhysicallyMappedElement , Citations
10
10
11
11
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 ])
16
25
rns = coordinate_mapping .reference_normals ()
17
26
pts = coordinate_mapping .physical_tangents ()
18
27
pns = coordinate_mapping .physical_normals ()
19
28
pel = coordinate_mapping .physical_edge_lengths ()
20
29
30
+ # number of DOFs per vertex/edge
31
+ voffset = comb (sd + vorder , vorder )
32
+ eoffset = 2 * eorder + 1
21
33
top = fiat_cell .get_topology ()
22
- eoffset = 2 * moment_deg - 1
23
- toffset = moment_deg - 1
24
34
for e in sorted (top [1 ]):
25
35
nhat = partial_indexed (rns , (e , ))
26
36
n = partial_indexed (pns , (e , ))
@@ -33,15 +43,16 @@ def _edge_transform(V, voffset, fiat_cell, moment_deg, coordinate_mapping, avg=F
33
43
34
44
v0id , v1id = (v * voffset for v in top [1 ][e ])
35
45
s0 = len (top [0 ]) * voffset + e * eoffset
36
- for k in range (moment_deg ):
46
+ for k in range (eorder + 1 ):
37
47
s = s0 + k
38
- P1 = Literal (comb (k + 2 , k ))
48
+ # Jacobi polynomial at the endpoints
49
+ P1 = comb (k + vorder , k )
39
50
P0 = - (- 1 )** k * P1
40
51
V [s , s ] = Bnn
41
52
V [s , v1id ] = P1 * Bnt
42
53
V [s , v0id ] = P0 * Bnt
43
54
if k > 0 :
44
- V [s , s + toffset ] = - 1 * Bnt
55
+ V [s , s + eorder ] = - 1 * Bnt
45
56
46
57
47
58
class Argyris (PhysicallyMappedElement , ScalarFiatElement ):
@@ -68,7 +79,8 @@ def basis_transformation(self, coordinate_mapping):
68
79
69
80
sd = self .cell .get_spatial_dimension ()
70
81
top = self .cell .get_topology ()
71
- voffset = (sd + 1 )* sd // 2 + sd + 1
82
+ vorder = 2
83
+ voffset = comb (sd + vorder , vorder )
72
84
for v in sorted (top [0 ]):
73
85
s = voffset * v
74
86
for i in range (sd ):
@@ -84,9 +96,9 @@ def basis_transformation(self, coordinate_mapping):
84
96
V [s + 5 , s + 4 ] = 2 * J [0 , 1 ]* J [1 , 1 ]
85
97
V [s + 5 , s + 5 ] = J [1 , 1 ]* J [1 , 1 ]
86
98
87
- q = self .degree - 4
99
+ eorder = self .degree - 5
88
100
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 )
90
102
else :
91
103
rns = coordinate_mapping .reference_normals ()
92
104
pns = coordinate_mapping .physical_normals ()
@@ -128,10 +140,10 @@ def basis_transformation(self, coordinate_mapping):
128
140
V [:, voffset * v + 3 + k ] *= 1 / (h [v ]* h [v ])
129
141
130
142
if self .variant == "point" :
131
- eoffset = 2 * q - 1
143
+ eoffset = 2 * eorder + 1
132
144
for e in sorted (top [1 ]):
133
145
v0 , v1 = top [1 ][e ]
134
146
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 ])
136
148
137
149
return ListTensor (V .T )
0 commit comments