1
1
import pytest
2
2
import numpy
3
3
4
- from FIAT import Argyris
4
+ from FIAT import Argyris , HsiehCloughTocher
5
5
from FIAT .jacobi import eval_jacobi_batch , eval_jacobi_deriv_batch
6
6
from FIAT .quadrature import FacetQuadratureRule
7
7
from FIAT .quadrature_schemes import create_quadrature
@@ -13,60 +13,78 @@ def cell():
13
13
return ufc_simplex (2 )
14
14
15
15
16
- @ pytest . mark . parametrize ( "degree" , range ( 6 , 10 ))
17
- def test_argyris_basis_functions ( cell , degree ):
18
- fe = Argyris ( cell , degree )
16
+ def directional_derivative ( direction , tab ):
17
+ return sum ( direction [ alpha . index ( 1 )] * tab [ alpha ]
18
+ for alpha in tab if sum ( alpha ) == 1 )
19
19
20
+
21
+ def inner (u , v , wts ):
22
+ return numpy .dot (numpy .multiply (u , wts ), v .T )
23
+
24
+
25
+ @pytest .mark .parametrize ("family, degree" , [
26
+ * ((Argyris , k ) for k in range (6 , 10 )),
27
+ * ((HsiehCloughTocher , k ) for k in range (4 , 8 ))])
28
+ def test_argyris_basis_functions (cell , family , degree ):
29
+ fe = family (cell , degree )
30
+
31
+ ref_el = fe .get_reference_element ()
32
+ sd = ref_el .get_spatial_dimension ()
33
+ top = ref_el .get_topology ()
20
34
entity_ids = fe .entity_dofs ()
21
- sd = cell .get_spatial_dimension ()
22
- top = cell .get_topology ()
35
+
36
+ degree = fe .degree ()
37
+ lowest_p = 5 if isinstance (fe , Argyris ) else 3
38
+ a = (lowest_p - 1 ) // 2
39
+ q = degree - lowest_p
40
+
23
41
rline = ufc_simplex (1 )
24
42
Qref = create_quadrature (rline , 2 * degree )
43
+ xref = 2.0 * Qref .get_points () - 1
25
44
26
- q = degree - 5
27
- xref = 2.0 * Qref .get_points ()- 1
28
45
ell_at_qpts = eval_jacobi_batch (0 , 0 , degree , xref )
29
- P_at_qpts = eval_jacobi_batch (2 , 2 , degree , xref )
30
- DP_at_qpts = eval_jacobi_deriv_batch (2 , 2 , degree , xref )
46
+ P_at_qpts = eval_jacobi_batch (a , a , degree , xref )
47
+ DP_at_qpts = eval_jacobi_deriv_batch (a , a , degree , xref )
31
48
32
49
for e in top [1 ]:
33
- n = cell .compute_normal (e )
34
- t = cell .compute_edge_tangent (e )
35
- Q = FacetQuadratureRule (cell , 1 , e , Qref )
50
+ n = ref_el .compute_normal (e )
51
+ t = ref_el .compute_edge_tangent (e )
52
+ Q = FacetQuadratureRule (ref_el , 1 , e , Qref )
36
53
qpts , qwts = Q .get_points (), Q .get_weights ()
37
54
38
55
ids = entity_ids [1 ][e ]
39
56
ids1 = ids [1 :- q ]
40
57
ids0 = ids [- q :]
41
58
42
59
tab = fe .tabulate (1 , qpts )
43
- # Test that normal derivative moment bfs have vanishing trace
44
- assert numpy .allclose (tab [(0 ,) * sd ][ids [:- q ]], 0 )
60
+ phi = tab [(0 ,) * sd ]
61
+ phi_n = directional_derivative (n , tab )
62
+ phi_t = directional_derivative (t , tab )
45
63
46
- phi = tab [(0 ,) * sd ][ids0 ]
47
-
48
- phi_n = sum (n [alpha .index (1 )] * tab [alpha ][ids1 ]
49
- for alpha in tab if sum (alpha ) == 1 )
64
+ # Test that normal derivative moment bfs have vanishing trace
65
+ assert numpy .allclose (phi [ids [:- q ]], 0 )
50
66
51
- phi_t = sum ( t [ alpha . index ( 1 )] * tab [ alpha ][ ids0 ]
52
- for alpha in tab if sum ( alpha ) == 1 )
67
+ # Test that trace moment bfs have vanishing normal derivative
68
+ assert numpy . allclose ( phi_n [ ids0 ], 0 )
53
69
54
70
# Test that facet bfs are hierarchical
55
- coeffs = numpy .dot (numpy .multiply (phi , qwts ), ell_at_qpts [6 :].T )
56
- assert numpy .allclose (numpy .triu (coeffs , k = 1 ), 0 )
71
+ coeffs = inner (ell_at_qpts [1 + lowest_p :], phi [ids0 ], qwts )
72
+ assert numpy .allclose (coeffs , numpy .triu (coeffs ))
73
+ coeffs = inner (ell_at_qpts [1 + lowest_p :], phi_n [ids1 ], qwts )
74
+ assert numpy .allclose (coeffs , numpy .triu (coeffs ))
57
75
58
- # Test duality of normal derivarive moments
59
- coeffs = numpy . dot ( numpy . multiply ( phi_n , qwts ), P_at_qpts [1 :]. T )
60
- assert numpy .allclose (coeffs [:, q :], 0 )
61
- assert numpy .allclose (coeffs [:, : q ], numpy .diag (numpy .diag (coeffs [:, :q ])))
76
+ # Test duality of normal derivative moments
77
+ coeffs = inner ( P_at_qpts [1 :], phi_n [ ids1 ], qwts )
78
+ assert numpy .allclose (coeffs [q :], 0 )
79
+ assert numpy .allclose (coeffs [:q ], numpy .diag (numpy .diag (coeffs [:q ])))
62
80
63
81
# Test duality of trace moments
64
- coeffs = numpy . dot ( numpy . multiply ( phi , qwts ), DP_at_qpts [1 :]. T )
65
- assert numpy .allclose (coeffs [:, q :], 0 )
66
- assert numpy .allclose (coeffs [:, : q ], numpy .diag (numpy .diag (coeffs [:, :q ])))
82
+ coeffs = inner ( DP_at_qpts [1 :], phi [ ids0 ], qwts )
83
+ assert numpy .allclose (coeffs [q :], 0 )
84
+ assert numpy .allclose (coeffs [:q ], numpy .diag (numpy .diag (coeffs [:q ])))
67
85
68
86
# Test the integration by parts property arising from the choice
69
87
# of normal derivative and trace moments DOFs.
70
88
# The normal derivative of the normal derviative bfs must be equal
71
89
# to minus the tangential derivative of the trace moment bfs
72
- assert numpy .allclose (numpy .dot ((phi_n + phi_t )** 2 , qwts ), 0 )
90
+ assert numpy .allclose (numpy .dot ((phi_n [ ids1 ] + phi_t [ ids0 ] )** 2 , qwts ), 0 )
0 commit comments