8
8
import scipy
9
9
10
10
from FIAT .dual_set import DualSet
11
+ from FIAT .restricted import RestrictedDualSet
11
12
from FIAT .functional import PointEvaluation , FrobeniusIntegralMoment
12
13
from FIAT .polynomial_set import make_bubbles , ONPolynomialSet , PolynomialSet
13
14
from FIAT .quadrature import FacetQuadratureRule
@@ -68,6 +69,7 @@ class DemkowiczDual(DualSet):
68
69
def __init__ (self , ref_el , degree , sobolev_space , kind = 2 ):
69
70
nodes = []
70
71
entity_ids = {}
72
+ reduced_dofs = {}
71
73
top = ref_el .get_topology ()
72
74
sd = ref_el .get_spatial_dimension ()
73
75
formdegree = {"H1" : 0 , "HCurl" : 1 , "HDiv" : sd - 1 , "L2" : sd }[sobolev_space ]
@@ -79,21 +81,25 @@ def __init__(self, ref_el, degree, sobolev_space, kind=2):
79
81
if dim < formdegree or degree <= dim - formdegree :
80
82
for entity in top [dim ]:
81
83
entity_ids [dim ][entity ] = []
84
+ reduced_dofs [dim ] = 0
82
85
elif dim == 0 and formdegree == 0 :
83
86
for entity in sorted (top [dim ]):
84
87
cur = len (nodes )
85
88
pts = ref_el .make_points (dim , entity , degree )
86
89
nodes .extend (PointEvaluation (ref_el , pt ) for pt in pts )
87
90
entity_ids [dim ][entity ] = list (range (cur , len (nodes )))
91
+ reduced_dofs [dim ] = len (nodes )
88
92
else :
89
- Q_ref , Phis = self ._reference_duals (dim , degree , formdegree , sobolev_space , kind )
93
+ Q_ref , Phis , rdofs = self ._reference_duals (dim , degree , formdegree , sobolev_space , kind )
94
+ reduced_dofs [dim ] = rdofs
90
95
mapping = dual_mapping if dim == sd else trace
91
96
for entity in sorted (top [dim ]):
92
97
cur = len (nodes )
93
98
Q , phis = map_duals (ref_el , dim , entity , mapping , Q_ref , Phis )
94
99
nodes .extend (FrobeniusIntegralMoment (ref_el , Q , phi ) for phi in phis )
95
100
entity_ids [dim ][entity ] = list (range (cur , len (nodes )))
96
101
102
+ self ._reduced_dofs = reduced_dofs
97
103
super (DemkowiczDual , self ).__init__ (nodes , ref_el , entity_ids )
98
104
99
105
def _reference_duals (self , dim , degree , formdegree , sobolev_space , kind ):
@@ -117,6 +123,7 @@ def _reference_duals(self, dim, degree, formdegree, sobolev_space, kind):
117
123
dtrial = dtrial [:, None , :]
118
124
K = self ._bubble_derivative_moments (facet , degree , formdegree , kind , Qpts , Qwts , dtrial )
119
125
126
+ reduced_dofs = K .shape [0 ]
120
127
if formdegree > 0 :
121
128
if dim == 2 and formdegree == 1 and sobolev_space == "HDiv" :
122
129
trial = perp (trial )
@@ -125,7 +132,7 @@ def _reference_duals(self, dim, degree, formdegree, sobolev_space, kind):
125
132
K = numpy .vstack ((K , M ))
126
133
127
134
duals = numpy .tensordot (K , P_at_qpts [(0 ,) * dim ], axes = (1 , 0 ))
128
- return Q , duals
135
+ return Q , duals , reduced_dofs
129
136
130
137
def _bubble_derivative_moments (self , facet , degree , formdegree , kind , Qpts , Qwts , trial ):
131
138
"""Integrate trial expressions against an orthonormal basis for
@@ -164,6 +171,26 @@ def _bubble_derivative_moments(self, facet, degree, formdegree, kind, Qpts, Qwts
164
171
dtest = numpy .tensordot (S .T , dtest , axes = (1 , 0 ))
165
172
return inner (dtest , trial , Qwts )
166
173
174
+ def get_indices (self , restriction_domain , take_closure = True ):
175
+ """Return the list of dofs with support on the given restriction domain.
176
+ Allows for reduced Demkowicz elements, excluding the exterior
177
+ derivative of the previous space in the de Rham complex.
178
+
179
+ :arg restriction_domain: can be 'reduced', 'interior', 'vertex',
180
+ 'edge', 'face' or 'facet'
181
+ :kwarg take_closure: Are we taking the closure of the restriction domain?
182
+ """
183
+ if restriction_domain == "reduced" :
184
+ indices = []
185
+ entity_ids = self .get_entity_ids ()
186
+ for dim in entity_ids :
187
+ reduced_dofs = self ._reduced_dofs [dim ]
188
+ for entity , ids in entity_ids [dim ].items ():
189
+ indices .extend (ids [:reduced_dofs ])
190
+ return indices
191
+ else :
192
+ return super (DemkowiczDual , self ).get_indices (restriction_domain , take_closure = take_closure )
193
+
167
194
168
195
class FDMDual (DualSet ):
169
196
0 commit comments