diff --git a/FIAT/bubble.py b/FIAT/bubble.py index 991328b6a..2c94e5363 100644 --- a/FIAT/bubble.py +++ b/FIAT/bubble.py @@ -73,9 +73,9 @@ def num_sub_elements(self): def space_dimension(self): return self.fsdim - def tabulate(self, order, points): + def tabulate(self, order, points, entity=None): return dict((k, v[self.first_node_index:, :]) - for k, v in self._element.tabulate(order, points).items()) + for k, v in self._element.tabulate(order, points, entity).items()) def value_shape(self): return self._element.value_shape() diff --git a/FIAT/discontinuous.py b/FIAT/discontinuous.py index 00bf9e961..11eaa93be 100644 --- a/FIAT/discontinuous.py +++ b/FIAT/discontinuous.py @@ -76,10 +76,10 @@ def space_dimension(self): "Return the dimension of the finite element space." return self._element.space_dimension() - def tabulate(self, order, points): + def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of basis functions at given points.""" - return self._element.tabulate(order, points) + return self._element.tabulate(order, points, entity) def value_shape(self): "Return the value shape of the finite element functions." diff --git a/FIAT/enriched.py b/FIAT/enriched.py index 4da453a19..4e59d5b82 100644 --- a/FIAT/enriched.py +++ b/FIAT/enriched.py @@ -1,5 +1,6 @@ # Copyright (C) 2008 Robert C. Kirby (Texas Tech University) # Copyright (C) 2013 Andrew T. T. McRae +# Modified by Thomas H. Gibson, 2016 # # This file is part of FIAT. # @@ -99,7 +100,7 @@ def space_dimension(self): # number of dofs just adds return self.A.space_dimension() + self.B.space_dimension() - def tabulate(self, order, points): + def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of basis functions at given points.""" @@ -109,8 +110,8 @@ def tabulate(self, order, points): Asd = self.A.space_dimension() Bsd = self.B.space_dimension() - Atab = self.A.tabulate(order, points) - Btab = self.B.tabulate(order, points) + Atab = self.A.tabulate(order, points, entity) + Btab = self.B.tabulate(order, points, entity) npoints = len(points) vs = self.A.value_shape() rank = len(vs) # scalar: 0, vector: 1 diff --git a/FIAT/finite_element.py b/FIAT/finite_element.py index 38f6f9aa7..bd164ff33 100644 --- a/FIAT/finite_element.py +++ b/FIAT/finite_element.py @@ -17,6 +17,7 @@ # along with FIAT. If not, see . # # Modified by David A. Ham (david.ham@imperial.ac.uk), 2014 +# Modified by Thomas H. Gibson (t.gibson15@imperial.ac.uk), 2016 from __future__ import absolute_import, print_function, division @@ -138,10 +139,23 @@ def space_dimension(self): "Return the dimension of the finite element space." return self.poly_set.get_num_members() - def tabulate(self, order, points): + def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of - basis functions at given points.""" - return self.poly_set.tabulate(points, order) + basis functions at given points. + + :arg order: The maximum order of derivative. + :arg points: An iterable of points. + :arg entity: Optional (dimension, entity number) pair + indicating which topological entity of the + reference element to tabulate on. If ``None``, + default cell-wise tabulation is performed. + """ + if entity is None: + entity = (self.ref_el.get_spatial_dimension(), 0) + + entity_dim, entity_id = entity + transform = self.ref_el.get_entity_transform(entity_dim, entity_id) + return self.poly_set.tabulate(list(map(transform, points)), order) def value_shape(self): "Return the value shape of the finite element functions." diff --git a/FIAT/hdivcurl.py b/FIAT/hdivcurl.py index c8568912c..49f6823a5 100644 --- a/FIAT/hdivcurl.py +++ b/FIAT/hdivcurl.py @@ -53,12 +53,12 @@ def value_shape(self): # redefine tabulate newelement.old_tabulate = newelement.tabulate - def tabulate(self, order, points): + def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of basis functions at given points.""" # don't duplicate what the old function does fine... - old_result = self.old_tabulate(order, points) + old_result = self.old_tabulate(order, points, entity) new_result = {} sd = self.get_reference_element().get_spatial_dimension() for alpha in old_result.keys(): @@ -175,12 +175,12 @@ def value_shape(self): # redefine tabulate newelement.old_tabulate = newelement.tabulate - def tabulate(self, order, points): + def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of basis functions at given points.""" # don't duplicate what the old function does fine... - old_result = self.old_tabulate(order, points) + old_result = self.old_tabulate(order, points, entity) new_result = {} sd = self.get_reference_element().get_spatial_dimension() for alpha in old_result.keys(): diff --git a/FIAT/restricted.py b/FIAT/restricted.py index 6f01c300d..45f21552d 100644 --- a/FIAT/restricted.py +++ b/FIAT/restricted.py @@ -85,8 +85,8 @@ def mapping(self): mappings = self._element.mapping() return [mappings[i] for i in self._indices] - def tabulate(self, order, points): - result = self._element.tabulate(order, points) + def tabulate(self, order, points, entity=None): + result = self._element.tabulate(order, points, entity) extracted = {} for (dtuple, values) in sorted_by_key(result): extracted[dtuple] = numpy.array([values[i] for i in self._indices]) diff --git a/FIAT/tensor_product.py b/FIAT/tensor_product.py index fac3414b7..9de798478 100644 --- a/FIAT/tensor_product.py +++ b/FIAT/tensor_product.py @@ -1,5 +1,6 @@ # Copyright (C) 2008 Robert C. Kirby (Texas Tech University) # Copyright (C) 2013 Andrew T. T. McRae +# Modified by Thomas H. Gibson, 2016 # # This file is part of FIAT. # @@ -240,16 +241,34 @@ def space_dimension(self): # number of dofs just multiplies return self.A.space_dimension() * self.B.space_dimension() - def tabulate(self, order, points): + def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of basis functions at given points.""" - - Asdim = self.A.get_reference_element().get_spatial_dimension() - Bsdim = self.B.get_reference_element().get_spatial_dimension() - pointsA = [point[0:Asdim] for point in points] - pointsB = [point[Asdim:Asdim + Bsdim] for point in points] - Atab = self.A.tabulate(order, pointsA) - Btab = self.B.tabulate(order, pointsB) + if entity is None: + entity = (self.ref_el.get_dimension(), 0) + entity_dim, entity_id = entity + + shape = tuple(len(c.get_topology()[d]) + for c, d in zip(self.ref_el.cells, entity_dim)) + idA, idB = numpy.unravel_index(entity_id, shape) + + # Factor the entity argument to get entities of the component elements + entityA_dim, entityB_dim = entity_dim + entityA = (entityA_dim, idA) + entityB = (entityB_dim, idB) + + pointsAdim, pointsBdim = [c.get_spatial_dimension() + for c in self.ref_el.construct_subelement(entity_dim).cells] + pointsA = [point[:pointsAdim] for point in points] + pointsB = [point[pointsAdim:pointsAdim + pointsBdim] for point in points] + + Asdim = self.A.ref_el.get_spatial_dimension() + Bsdim = self.B.ref_el.get_spatial_dimension() + # Note that for entities other than cells, the following + # tabulations are already appropriately zero-padded so no + # additional zero padding is required. + Atab = self.A.tabulate(order, pointsA, entityA) + Btab = self.B.tabulate(order, pointsB, entityB) npoints = len(points) # allow 2 scalar-valued FE spaces, or 1 scalar-valued,