def __init__(self, mesh, element, name=None, real_tensorproduct=False): super(FunctionSpace, self).__init__() if type(element) is ufl.MixedElement: raise ValueError("Can't create FunctionSpace for MixedElement") finat_element = create_element(element) if isinstance(finat_element, finat.TensorFiniteElement): # Retrieve scalar element finat_element = finat_element.base_element # Used for reconstruction of mixed/component spaces self.real_tensorproduct = real_tensorproduct sdata = get_shared_data(mesh, finat_element, real_tensorproduct=real_tensorproduct) # The function space shape is the number of dofs per node, # hence it is not always the value_shape. Vector and Tensor # element modifiers *must* live on the outside! if type(element) is ufl.TensorElement: # UFL enforces value_shape of the subelement to be empty # on a TensorElement. self.shape = element.value_shape() elif type(element) is ufl.VectorElement: # First dimension of the value_shape is the VectorElement # shape. self.shape = element.value_shape()[:1] else: self.shape = () self._ufl_function_space = ufl.FunctionSpace(mesh.ufl_mesh(), element) self._shared_data = sdata self._mesh = mesh self.rank = len(self.shape) r"""The rank of this :class:`FunctionSpace`. Spaces where the element is scalar-valued (or intrinsically vector-valued) have rank zero. Spaces built on :class:`~ufl.classes.VectorElement` or :class:`~ufl.classes.TensorElement` instances have rank equivalent to the number of components of their :meth:`~ufl.classes.FiniteElementBase.value_shape`.""" self.value_size = int(numpy.prod(self.shape, dtype=int)) r"""The total number of degrees of freedom at each function space node.""" self.name = name r"""The (optional) descriptive name for this space.""" self.node_set = sdata.node_set r"""A :class:`pyop2.Set` representing the function space nodes.""" self.dof_dset = op2.DataSet(self.node_set, self.shape or 1, name="%s_nodes_dset" % self.name) r"""A :class:`pyop2.DataSet` representing the function space degrees of freedom.""" self.comm = self.node_set.comm self.finat_element = finat_element self.extruded = sdata.extruded self.offset = sdata.offset self.cell_boundary_masks = sdata.cell_boundary_masks self.interior_facet_boundary_masks = sdata.interior_facet_boundary_masks
def __init__(self, mesh, element, name=None): super(FunctionSpace, self).__init__() if type(element) is ufl.MixedElement: raise ValueError("Can't create FunctionSpace for MixedElement") sdata = get_shared_data(mesh, element) # The function space shape is the number of dofs per node, # hence it is not always the value_shape. Vector and Tensor # element modifiers *must* live on the outside! if type(element) in {ufl.TensorElement, ufl.VectorElement}: # The number of "free" dofs is given by reference_value_shape, # not value_shape due to symmetry specifications rvs = element.reference_value_shape() # This requires that the sub element is not itself a # tensor element (which is checked by the top level # constructor of function spaces) sub = element.sub_elements()[0].value_shape() self.shape = rvs[:len(rvs) - len(sub)] else: self.shape = () self._ufl_function_space = ufl.FunctionSpace(mesh.ufl_mesh(), element) self._shared_data = sdata self._mesh = mesh self.rank = len(self.shape) r"""The rank of this :class:`FunctionSpace`. Spaces where the element is scalar-valued (or intrinsically vector-valued) have rank zero. Spaces built on :class:`~ufl.classes.VectorElement` or :class:`~ufl.classes.TensorElement` instances have rank equivalent to the number of components of their :meth:`~ufl.classes.FiniteElementBase.value_shape`.""" self.value_size = int(numpy.prod(self.shape, dtype=int)) r"""The total number of degrees of freedom at each function space node.""" self.name = name r"""The (optional) descriptive name for this space.""" self.node_set = sdata.node_set r"""A :class:`pyop2.Set` representing the function space nodes.""" self.dof_dset = op2.DataSet(self.node_set, self.shape or 1, name="%s_nodes_dset" % self.name) r"""A :class:`pyop2.DataSet` representing the function space degrees of freedom.""" self.comm = self.node_set.comm # Need to create finat element again as sdata does not # want to carry finat_element. self.finat_element = create_element(element) # Used for reconstruction of mixed/component spaces. # sdata carries real_tensorproduct. self.real_tensorproduct = sdata.real_tensorproduct self.extruded = sdata.extruded self.offset = sdata.offset self.cell_boundary_masks = sdata.cell_boundary_masks self.interior_facet_boundary_masks = sdata.interior_facet_boundary_masks
def __init__(self, mesh, element, name=None): super(FunctionSpace, self).__init__() if type(element) is ufl.MixedElement: raise ValueError("Can't create FunctionSpace for MixedElement") fiat_element = create_element(element, vector_is_mixed=False) sdata = get_shared_data(mesh, fiat_element) # The function space shape is the number of dofs per node, # hence it is not always the value_shape. Vector and Tensor # element modifiers *must* live on the outside! if type(element) is ufl.TensorElement: # UFL enforces value_shape of the subelement to be empty # on a TensorElement. self.shape = element.value_shape() elif type(element) is ufl.VectorElement: # First dimension of the value_shape is the VectorElement # shape. self.shape = element.value_shape()[:1] else: self.shape = () self._ufl_element = element self._shared_data = sdata self._mesh = mesh self.rank = len(self.shape) """The rank of this :class:`FunctionSpace`. Spaces where the element is scalar-valued (or intrinsically vector-valued) have rank zero. Spaces built on :class:`~ufl.classes.VectorElement` or :class:`~ufl.classes.TensorElement` instances have rank equivalent to the number of components of their :meth:`~ufl.classes.FiniteElementBase.value_shape`.""" self.dim = numpy.prod(self.shape, dtype=int) """The total number of degrees of freedom at each function space node.""" self.name = name """The (optional) descriptive name for this space.""" self.node_set = sdata.node_set """A :class:`pyop2.Set` representing the function space nodes.""" self.dof_dset = op2.DataSet(self.node_set, self.shape or 1, name="%s_nodes_dset" % self.name) """A :class:`pyop2.DataSet` representing the function space degrees of freedom.""" self.comm = self.node_set.comm self.fiat_element = fiat_element self.extruded = sdata.extruded self.offset = sdata.offset self.bt_masks = sdata.bt_masks