22
33This element's definition appears in https://arxiv.org/abs/1909.09687
44(Arnold, Walker, 2020)
5+
6+ For an alternative construction see (Sinwel, 2009) and sections 4.4.2.2 and 4.4.3.2
7+ https://numa.jku.at/media/filer_public/b7/42/b74263c9-f723-4076-b1b2-c2726126bf32/phd-sinwel.pdf
58"""
69
710import typing
811
912from ..finite_element import CiarletElement
1013from ..functionals import IntegralMoment , ListOfFunctionals , NormalInnerProductIntegralMoment
11- from ..functions import FunctionInput
14+ from ..functions import FunctionInput , MatrixFunction
1215from ..moments import make_integral_moment_dofs
1316from ..polynomials import polynomial_set_vector
1417from ..references import NonDefaultReferenceError , Reference
15- from .lagrange import Lagrange , SymmetricMatrixLagrange
18+ from .lagrange import Lagrange
1619
1720
1821class HellanHerrmannJohnson (CiarletElement ):
@@ -28,20 +31,53 @@ def __init__(self, reference: Reference, order: int, variant: str = "equispaced"
2831 """
2932 if reference .vertices != reference .reference_vertices :
3033 raise NonDefaultReferenceError ()
31- assert reference .name == "triangle"
34+ assert reference .name == "triangle" or reference . name == "tetrahedron"
3235
3336 poly : typing .List [FunctionInput ] = []
34- poly += [((p [0 ], p [1 ]), (p [1 ], p [2 ]))
35- for p in polynomial_set_vector (reference .tdim , 3 , order )]
37+ directions : typing .List [typing .Tuple [typing .Tuple [int , ...], ...]] = []
38+ directions_extra : typing .List [typing .Tuple [typing .Tuple [int , ...], ...]] = []
39+
40+ if reference .tdim == 2 :
41+ poly = [((p [0 ], p [1 ]), (p [1 ], p [2 ]))
42+ for p in polynomial_set_vector (reference .tdim , 3 , order )]
43+ directions = [((0 , 1 ), (1 , 0 )),
44+ ((- 2 , 1 ), (1 , 0 )),
45+ ((0 , - 1 ), (- 1 , 2 ))]
46+ directions_extra = []
47+ if reference .tdim == 3 :
48+ poly = [((p [0 ], p [1 ], p [2 ]), (p [1 ], p [3 ], p [4 ]), (p [2 ], p [4 ], p [5 ]))
49+ for p in polynomial_set_vector (reference .tdim , 6 , order )]
50+ directions = [((- 2 , 1 , 0 ), (1 , 0 , 0 ), (0 , 0 , 0 )),
51+ ((0 , 1 , - 1 ), (1 , - 2 , 1 ), (- 1 , 1 , 0 )),
52+ ((0 , 0 , 0 ), (0 , 0 , - 1 ), (0 , - 1 , 2 )),
53+ ((0 , 0 , 1 ), (0 , 0 , 0 ), (1 , 0 , 0 ))]
54+ directions_extra = [((0 , 0 , - 1 ), (0 , 0 , 1 ), (- 1 , 1 , 0 )),
55+ ((0 , - 1 , 0 ), (- 1 , 0 , 1 ), (0 , 1 , 0 ))]
3656
3757 dofs : ListOfFunctionals = make_integral_moment_dofs (
3858 reference ,
3959 facets = (NormalInnerProductIntegralMoment , Lagrange , order ,
4060 {"variant" : variant }),
41- cells = (IntegralMoment , SymmetricMatrixLagrange , order - 1 ,
42- {"variant" : variant }),
4361 )
4462
63+ # cell functions
64+ if order > 0 :
65+ space = Lagrange (reference , order - 1 , variant )
66+ basis = space .get_basis_functions ()
67+ for p , dof in zip (basis , space .dofs ):
68+ for d in directions :
69+ dofs .append (IntegralMoment (
70+ reference , p * MatrixFunction (d ), dof , entity = (reference .tdim , 0 ),
71+ mapping = "double_covariant" ))
72+ # cell functions extra
73+ space_extra = Lagrange (reference , order , variant )
74+ basis_extra = space_extra .get_basis_functions ()
75+ for p , dof in zip (basis_extra , space_extra .dofs ):
76+ for d in directions_extra :
77+ dofs .append (IntegralMoment (
78+ reference , p * MatrixFunction (d ), dof , entity = (reference .tdim , 0 ),
79+ mapping = "double_covariant" ))
80+
4581 self .variant = variant
4682
4783 super ().__init__ (reference , order , poly , dofs , reference .tdim , reference .tdim ** 2 ,
@@ -56,7 +92,7 @@ def init_kwargs(self) -> typing.Dict[str, typing.Any]:
5692 return {"variant" : self .variant }
5793
5894 names = ["Hellan-Herrmann-Johnson" , "HHJ" ]
59- references = ["triangle" ]
95+ references = ["triangle" , "tetrahedron" ]
6096 min_order = 0
6197 continuity = "inner H(div)"
62- last_updated = "2023.06 "
98+ last_updated = "2023.08 "
0 commit comments