예제 #1
0
    def basis_evaluation(self, order, ps, entity=None):
        '''Return code for evaluating the element at known points on the
        reference element.

        :param order: return derivatives up to this order.
        :param ps: the point set.
        :param entity: the cell entity on which to tabulate.
        '''
        space_dimension = self._element.space_dimension()
        value_size = np.prod(self._element.value_shape(), dtype=int)
        fiat_result = self._element.tabulate(order, ps.points, entity)
        result = {}
        for alpha, fiat_table in iteritems(fiat_result):
            if isinstance(fiat_table, Exception):
                result[alpha] = gem.Failure(
                    self.index_shape + self.value_shape, fiat_table)
                continue

            derivative = sum(alpha)
            table_roll = fiat_table.reshape(space_dimension, value_size,
                                            len(ps.points)).transpose(1, 2, 0)

            exprs = []
            for table in table_roll:
                if derivative < self.degree:
                    point_indices = ps.indices
                    point_shape = tuple(index.extent
                                        for index in point_indices)
                    exprs.append(
                        gem.partial_indexed(
                            gem.Literal(
                                table.reshape(point_shape + self.index_shape)),
                            point_indices))
                elif derivative == self.degree:
                    # Make sure numerics satisfies theory
                    assert np.allclose(table, table.mean(axis=0,
                                                         keepdims=True))
                    exprs.append(gem.Literal(table[0]))
                else:
                    # Make sure numerics satisfies theory
                    assert np.allclose(table, 0.0)
                    exprs.append(gem.Zero(self.index_shape))
            if self.value_shape:
                beta = self.get_indices()
                zeta = self.get_value_indices()
                result[alpha] = gem.ComponentTensor(
                    gem.Indexed(
                        gem.ListTensor(
                            np.array([
                                gem.Indexed(expr, beta) for expr in exprs
                            ]).reshape(self.value_shape)), zeta), beta + zeta)
            else:
                expr, = exprs
                result[alpha] = expr
        return result
예제 #2
0
def point_evaluation_generic(fiat_element, order, refcoords, entity):
    # Coordinates on the reference entity (SymPy)
    esd, = refcoords.shape
    Xi = sp.symbols('X Y Z')[:esd]

    space_dimension = fiat_element.space_dimension()
    value_size = np.prod(fiat_element.value_shape(), dtype=int)
    fiat_result = fiat_element.tabulate(order, [Xi], entity)
    result = {}
    for alpha, fiat_table in fiat_result.items():
        if isinstance(fiat_table, Exception):
            result[alpha] = gem.Failure(
                (space_dimension, ) + fiat_element.value_shape(), fiat_table)
            continue

        # Convert SymPy expression to GEM
        mapper = gem.node.Memoizer(sympy2gem)
        mapper.bindings = {
            s: gem.Indexed(refcoords, (i, ))
            for i, s in enumerate(Xi)
        }
        gem_table = np.vectorize(mapper)(fiat_table)

        table_roll = gem_table.reshape(space_dimension, value_size).transpose()

        exprs = []
        for table in table_roll:
            exprs.append(gem.ListTensor(table.reshape(space_dimension)))
        if fiat_element.value_shape():
            beta = (gem.Index(extent=space_dimension), )
            zeta = tuple(
                gem.Index(extent=d) for d in fiat_element.value_shape())
            result[alpha] = gem.ComponentTensor(
                gem.Indexed(
                    gem.ListTensor(
                        np.array([gem.Indexed(expr, beta) for expr in exprs
                                  ]).reshape(fiat_element.value_shape())),
                    zeta), beta + zeta)
        else:
            expr, = exprs
            result[alpha] = expr
    return result
예제 #3
0
    def basis_evaluation(self,
                         order,
                         ps,
                         entity=None,
                         coordinate_mapping=None):
        '''Return code for evaluating the element at known points on the
        reference element.

        :param order: return derivatives up to this order.
        :param ps: the point set.
        :param entity: the cell entity on which to tabulate.
        '''
        space_dimension = self._element.space_dimension()
        value_size = np.prod(self._element.value_shape(), dtype=int)
        fiat_result = self._element.tabulate(order, ps.points, entity)
        result = {}
        # In almost all cases, we have
        # self.space_dimension() == self._element.space_dimension()
        # But for Bell, FIAT reports 21 basis functions,
        # but FInAT only 18 (because there are actually 18
        # basis functions, and the additional 3 are for
        # dealing with transformations between physical
        # and reference space).
        index_shape = (self._element.space_dimension(), )
        for alpha, fiat_table in fiat_result.items():
            if isinstance(fiat_table, Exception):
                result[alpha] = gem.Failure(
                    self.index_shape + self.value_shape, fiat_table)
                continue

            derivative = sum(alpha)
            table_roll = fiat_table.reshape(space_dimension, value_size,
                                            len(ps.points)).transpose(1, 2, 0)

            exprs = []
            for table in table_roll:
                if derivative < self.degree:
                    point_indices = ps.indices
                    point_shape = tuple(index.extent
                                        for index in point_indices)

                    exprs.append(
                        gem.partial_indexed(
                            gem.Literal(
                                table.reshape(point_shape + index_shape)),
                            point_indices))
                elif derivative == self.degree:
                    # Make sure numerics satisfies theory
                    exprs.append(gem.Literal(table[0]))
                else:
                    # Make sure numerics satisfies theory
                    assert np.allclose(table, 0.0)
                    exprs.append(gem.Zero(self.index_shape))
            if self.value_shape:
                # As above, this extent may be different from that
                # advertised by the finat element.
                beta = tuple(gem.Index(extent=i) for i in index_shape)
                assert len(beta) == len(self.get_indices())

                zeta = self.get_value_indices()
                result[alpha] = gem.ComponentTensor(
                    gem.Indexed(
                        gem.ListTensor(
                            np.array([
                                gem.Indexed(expr, beta) for expr in exprs
                            ]).reshape(self.value_shape)), zeta), beta + zeta)
            else:
                expr, = exprs
                result[alpha] = expr
        return result