Source code for finat.mixed

import numpy

import gem

from finat.finiteelementbase import FiniteElementBase
from finat.enriched import EnrichedElement


[docs]def MixedElement(elements): """Constructor function for FEniCS-style mixed elements. Implements mixed element using :py:class:`EnrichedElement` and value shape transformations with :py:class:`MixedSubElement`. """ sizes = [numpy.prod(element.value_shape, dtype=int) for element in elements] offsets = [int(offset) for offset in numpy.cumsum([0] + sizes)] total_size = offsets.pop() return EnrichedElement([MixedSubElement(element, total_size, offset) for offset, element in zip(offsets, elements)])
[docs]class MixedSubElement(FiniteElementBase): """Element wrapper that flattens value shape and places the flattened vector in a longer vector of zeros.""" def __init__(self, element, size, offset): assert 0 <= offset <= size assert offset + numpy.prod(element.value_shape, dtype=int) <= size super(MixedSubElement, self).__init__() self.element = element self.size = size self.offset = offset @property def cell(self): return self.element.cell @property def complex(self): return self.element.complex @property def degree(self): return self.element.degree @property def formdegree(self): return self.element.formdegree
[docs] def entity_dofs(self): return self.element.entity_dofs()
[docs] def entity_closure_dofs(self): return self.element.entity_closure_dofs()
[docs] def entity_support_dofs(self): return self.element.entity_support_dofs()
[docs] def space_dimension(self): return self.element.space_dimension()
@property def index_shape(self): return self.element.index_shape @property def value_shape(self): return (self.size,) def _transform(self, v): u = [gem.Zero()] * self.size for j, zeta in enumerate(numpy.ndindex(self.element.value_shape)): u[self.offset + j] = gem.Indexed(v, zeta) return u def _transform_evaluation(self, core_eval): beta = self.get_indices() zeta = self.get_value_indices() def promote(table): v = gem.partial_indexed(table, beta) u = gem.ListTensor(self._transform(v)) return gem.ComponentTensor(gem.Indexed(u, zeta), beta + zeta) return {alpha: promote(table) for alpha, table in core_eval.items()}
[docs] def basis_evaluation(self, order, ps, entity=None, coordinate_mapping=None): core_eval = self.element.basis_evaluation(order, ps, entity, coordinate_mapping=coordinate_mapping) return self._transform_evaluation(core_eval)
[docs] def point_evaluation(self, order, refcoords, entity=None): core_eval = self.element.point_evaluation(order, refcoords, entity) return self._transform_evaluation(core_eval)
@property def mapping(self): return self.element.mapping