@@ -345,6 +345,8 @@ def distance(alpha, beta):
345345
346346 def _tabulate (self , n , pts , order = 0 ):
347347 """A version of tabulate() that also works for a single point."""
348+ from FIAT .hdiv_trace import TraceError
349+ from FIAT .polynomial_set import mis
348350 pts = numpy .asarray (pts )
349351 unique = self .continuity is not None and order == 0
350352 cell_point_map = compute_cell_point_map (self .ref_el , pts , unique = unique )
@@ -354,6 +356,28 @@ def _tabulate(self, n, pts, order=0):
354356 if not self .ref_el .is_macrocell ():
355357 return phis [0 ]
356358
359+ if self .ref_el .is_trace ():
360+ parent = self .ref_el .get_parent ()
361+ tdim = self .ref_el .get_spatial_dimension ()
362+ gdim = parent .get_spatial_dimension ()
363+ for cell in phis :
364+ # Promote facet keys to cell keys
365+ phi = phis [cell ][(0 ,) * tdim ]
366+ # Raise TraceError on gradient tabulations
367+ msg = "Gradients on trace elements are not well-defined."
368+ phis [cell ] = {alpha : phi if sum (alpha ) == 0 else TraceError (msg )
369+ for i in range (order + 1 )
370+ for alpha in mis (gdim , i )}
371+ if tdim == 0 and len (phis ) == 0 :
372+ # Hack for TensorProduct HDivTrace: do not raise TraceError on the interval
373+ for cell in parent .topology [gdim ]:
374+ phis [cell ] = {(0 ,)* gdim : numpy .zeros ((1 , 1 ))}
375+ elif sum (len (cell_point_map [cell ]) for cell in cell_point_map ) < len (pts ):
376+ # Raise TraceError when interior points fail to be binned on facets
377+ for cell in parent .topology [gdim ]:
378+ msg = "The HDivTrace element can only be tabulated on facets."
379+ phis [cell ] = {(0 ,)* gdim : TraceError (msg )}
380+
357381 if pts .dtype == object :
358382 # If binning is undefined, scale by the characteristic function of each subcell
359383 Xi = compute_partition_of_unity (self .ref_el , pts , unique = unique )
@@ -362,13 +386,14 @@ def _tabulate(self, n, pts, order=0):
362386 phi [alpha ] *= Xi [cell ]
363387 elif not unique :
364388 # If binning is not unique, divide by the multiplicity of each point
365- mult = numpy .zeros (pts .shape [:- 1 ])
389+ mult = numpy .zeros (pts .shape [:- 1 ], dtype = int )
366390 for cell , ipts in cell_point_map .items ():
367391 mult [ipts ] += 1
368- for cell , ipts in cell_point_map .items ():
369- phi = phis [cell ]
370- for alpha in phi :
371- phi [alpha ] /= mult [None , ipts ]
392+ if (mult != 1 ).any ():
393+ for cell , ipts in cell_point_map .items ():
394+ phi = phis [cell ]
395+ for alpha in phi :
396+ phi [alpha ] /= mult [None , ipts ]
372397
373398 # Insert subcell tabulations into the corresponding submatrices
374399 idx = lambda * args : args if args [1 ] is Ellipsis else numpy .ix_ (* args )
@@ -377,6 +402,9 @@ def _tabulate(self, n, pts, order=0):
377402 result = {}
378403 base_phi = tuple (phis .values ())[0 ]
379404 for alpha in base_phi :
405+ if isinstance (base_phi [alpha ], TraceError ):
406+ result [alpha ] = base_phi [alpha ]
407+ continue
380408 dtype = base_phi [alpha ].dtype
381409 result [alpha ] = numpy .zeros ((num_phis , * pts .shape [:- 1 ]), dtype = dtype )
382410 for cell in cell_point_map :
@@ -497,8 +525,7 @@ def get_dmats(self, degree, cell=0):
497525 def tabulate (self , n , pts ):
498526 if len (pts ) == 0 :
499527 return numpy .array ([])
500- sd = self .ref_el .get_spatial_dimension ()
501- return self ._tabulate (n , pts )[(0 ,) * sd ]
528+ return tuple (self ._tabulate (n , pts ).values ())[0 ]
502529
503530 def tabulate_derivatives (self , n , pts ):
504531 from FIAT .polynomial_set import mis
@@ -597,7 +624,6 @@ def polynomial_dimension(ref_el, n, continuity=None):
597624 if ref_el .get_shape () == reference_element .POINT :
598625 if n > 0 :
599626 raise ValueError ("Only degree zero polynomials supported on point elements." )
600- return 1
601627 top = ref_el .get_topology ()
602628 if continuity == "C0" :
603629 space_dimension = sum (math .comb (n - 1 , dim ) * len (top [dim ]) for dim in top )
0 commit comments