Example #1
0
    def __init__(self, family, cell=None, degree=None, dim=None,
                 form_degree=None, quad_scheme=None):
        """
        Create vector element (repeated mixed element)

        *Arguments*
            family (string)
               The finite element family (or an existing FiniteElement)
            cell
               The geometric cell, ignored if family is a FiniteElement
            degree (int)
               The polynomial degree, ignored if family is a FiniteElement
            dim (int)
               The value dimension of the element (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form), ignored if family is a FiniteElement
            quad_scheme
               The quadrature scheme (optional), ignored if family is a FiniteElement
        """

        if isinstance(family, FiniteElementBase):
            sub_element = family
            cell = sub_element.cell()
        else:
            if cell is not None:
                cell = as_cell(cell)
            # Create sub element
            sub_element = FiniteElement(family, cell, degree,
                                        form_degree=form_degree,
                                        quad_scheme=quad_scheme)

        # Set default size if not specified
        if dim is None:
            if cell is None:
                error("Cannot infer vector dimension without a cell.")
            dim = cell.geometric_dimension()

        # Create list of sub elements for mixed element constructor
        sub_elements = [sub_element]*dim

        # Compute value shapes
        value_shape = (dim,) + sub_element.value_shape()
        reference_value_shape = (dim,) + sub_element.reference_value_shape()

        # Initialize element data
        MixedElement.__init__(self, sub_elements, value_shape=value_shape,
                              reference_value_shape=reference_value_shape)
        # FIXME: Storing this here is strange, isn't that handled by
        # subclass?
        self._family = sub_element.family()
        self._degree = sub_element.degree()
        self._sub_element = sub_element

        # Cache repr string
        self._repr = "VectorElement(%s, dim=%d)" % (
            repr(sub_element), len(self._sub_elements))
Example #2
0
    def __init__(self, family, cell=None, degree=None, dim=None,
                 form_degree=None, quad_scheme=None):
        """
        Create vector element (repeated mixed element)

        *Arguments*
            family (string)
               The finite element family (or an existing FiniteElement)
            cell
               The geometric cell, ignored if family is a FiniteElement
            degree (int)
               The polynomial degree, ignored if family is a FiniteElement
            dim (int)
               The value dimension of the element (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form), ignored if family is a FiniteElement
            quad_scheme
               The quadrature scheme (optional), ignored if family is a FiniteElement
        """

        if isinstance(family, FiniteElementBase):
            sub_element = family
            cell = sub_element.cell()
        else:
            if cell is not None:
                cell = as_cell(cell)
            # Create sub element
            sub_element = FiniteElement(family, cell, degree,
                                        form_degree=form_degree,
                                        quad_scheme=quad_scheme)

        # Set default size if not specified
        if dim is None:
            if cell is None:
                error("Cannot infer vector dimension without a cell.")
            dim = cell.geometric_dimension()

        # Create list of sub elements for mixed element constructor
        sub_elements = [sub_element] * dim

        # Compute value shapes
        value_shape = (dim,) + sub_element.value_shape()
        reference_value_shape = (dim,) + sub_element.reference_value_shape()

        # Initialize element data
        MixedElement.__init__(self, sub_elements, value_shape=value_shape,
                              reference_value_shape=reference_value_shape)
        # FIXME: Storing this here is strange, isn't that handled by
        # subclass?
        self._family = sub_element.family()
        self._degree = sub_element.degree()
        self._sub_element = sub_element

        # Cache repr string
        self._repr = "VectorElement(%s, dim=%d)" % (
            repr(sub_element), len(self._sub_elements))
Example #3
0
    def __init__(self, family, cell=None, degree=None, shape=None,
                 symmetry=None, quad_scheme=None):
        """Create tensor element (repeated mixed element with optional symmetries).

        :arg family: The family string, or an existing FiniteElement.
        :arg cell: The geometric cell (ignored if family is a FiniteElement).
        :arg degree: The polynomial degree (ignored if family is a FiniteElement).
        :arg shape: The shape of the element (defaults to a square
             tensor given by the geometric dimension of the cell).
        :arg symmetry: Optional symmetries.
        :arg quad_scheme: Optional quadrature scheme (ignored if
             family is a FiniteElement)."""

        if isinstance(family, FiniteElementBase):
            sub_element = family
            cell = sub_element.cell()
        else:
            if cell is not None:
                cell = as_cell(cell)
            # Create scalar sub element
            sub_element = FiniteElement(family, cell, degree, quad_scheme=quad_scheme)

        if sub_element.value_shape() != ():
            error("Expecting only scalar valued subelement for TensorElement.")

        # Set default shape if not specified
        if shape is None:
            if cell is None:
                error("Cannot infer tensor shape without a cell.")
            dim = cell.geometric_dimension()
            shape = (dim, dim)

        if symmetry is None:
            symmetry = EmptyDict
        elif symmetry is True:
            # Construct default symmetry dict for matrix elements
            if not (len(shape) == 2 and shape[0] == shape[1]):
                error("Cannot set automatic symmetry for non-square tensor.")
            symmetry = dict(((i, j), (j, i)) for i in range(shape[0])
                            for j in range(shape[1]) if i > j)
        else:
            if not isinstance(symmetry, dict):
                error("Expecting symmetry to be None (unset), True, or dict.")

        # Validate indices in symmetry dict
        for i, j in symmetry.items():
            if len(i) != len(j):
                error("Non-matching length of symmetry index tuples.")
            for k in range(len(i)):
                if not (i[k] >= 0 and j[k] >= 0 and i[k] < shape[k] and j[k] < shape[k]):
                    error("Symmetry dimensions out of bounds.")

        # Compute all index combinations for given shape
        indices = compute_indices(shape)

        # Compute mapping from indices to sub element number,
        # accounting for symmetry
        sub_elements = []
        sub_element_mapping = {}
        for index in indices:
            if index in symmetry:
                continue
            sub_element_mapping[index] = len(sub_elements)
            sub_elements += [sub_element]

        # Update mapping for symmetry
        for index in indices:
            if index in symmetry:
                sub_element_mapping[index] = sub_element_mapping[symmetry[index]]
        flattened_sub_element_mapping = [sub_element_mapping[index] for i,
                                         index in enumerate(indices)]

        # Compute value shape
        value_shape = shape

        # Compute reference value shape based on symmetries
        if symmetry:
            # Flatten and subtract symmetries
            reference_value_shape = (product(shape)-len(symmetry),)
            self._mapping = "symmetries"
        else:
            # Do not flatten if there are no symmetries
            reference_value_shape = shape
            self._mapping = "identity"

        # Initialize element data
        MixedElement.__init__(self, sub_elements, value_shape=value_shape,
                              reference_value_shape=reference_value_shape)
        self._family = sub_element.family()
        self._degree = sub_element.degree()
        self._sub_element = sub_element
        self._shape = shape
        self._symmetry = symmetry
        self._sub_element_mapping = sub_element_mapping
        self._flattened_sub_element_mapping = flattened_sub_element_mapping

        # Cache repr string
        self._repr = "TensorElement(%s, shape=%s, symmetry=%s)" % (
            repr(sub_element), repr(self._shape), repr(self._symmetry))
Example #4
0
    def __init__(self,
                 family,
                 cell=None,
                 degree=None,
                 shape=None,
                 symmetry=None,
                 quad_scheme=None):
        """Create tensor element (repeated mixed element with optional symmetries).

        :arg family: The family string, or an existing FiniteElement.
        :arg cell: The geometric cell (ignored if family is a FiniteElement).
        :arg degree: The polynomial degree (ignored if family is a FiniteElement).
        :arg shape: The shape of the element (defaults to a square
             tensor given by the geometric dimension of the cell).
        :arg symmetry: Optional symmetries.
        :arg quad_scheme: Optional quadrature scheme (ignored if
             family is a FiniteElement)."""

        if isinstance(family, FiniteElementBase):
            sub_element = family
            cell = sub_element.cell()
        else:
            if cell is not None:
                cell = as_cell(cell)
            # Create scalar sub element
            sub_element = FiniteElement(family,
                                        cell,
                                        degree,
                                        quad_scheme=quad_scheme)

        # Set default shape if not specified
        if shape is None:
            if cell is None:
                error("Cannot infer tensor shape without a cell.")
            dim = cell.geometric_dimension()
            shape = (dim, dim)

        if symmetry is None:
            symmetry = EmptyDict
        elif symmetry is True:
            # Construct default symmetry dict for matrix elements
            if not (len(shape) == 2 and shape[0] == shape[1]):
                error("Cannot set automatic symmetry for non-square tensor.")
            symmetry = dict(((i, j), (j, i)) for i in range(shape[0])
                            for j in range(shape[1]) if i > j)
        else:
            if not isinstance(symmetry, dict):
                error("Expecting symmetry to be None (unset), True, or dict.")

        # Validate indices in symmetry dict
        for i, j in symmetry.items():
            if len(i) != len(j):
                error("Non-matching length of symmetry index tuples.")
            for k in range(len(i)):
                if not (i[k] >= 0 and j[k] >= 0 and i[k] < shape[k]
                        and j[k] < shape[k]):
                    error("Symmetry dimensions out of bounds.")

        # Compute all index combinations for given shape
        indices = compute_indices(shape)

        # Compute mapping from indices to sub element number,
        # accounting for symmetry
        sub_elements = []
        sub_element_mapping = {}
        for index in indices:
            if index in symmetry:
                continue
            sub_element_mapping[index] = len(sub_elements)
            sub_elements += [sub_element]

        # Update mapping for symmetry
        for index in indices:
            if index in symmetry:
                sub_element_mapping[index] = sub_element_mapping[
                    symmetry[index]]
        flattened_sub_element_mapping = [
            sub_element_mapping[index] for i, index in enumerate(indices)
        ]

        # Compute value shape
        value_shape = shape

        # Compute reference value shape based on symmetries
        if symmetry:
            # Flatten and subtract symmetries
            reference_value_shape = (product(shape) - len(symmetry), )
            self._mapping = "symmetries"
        else:
            # Do not flatten if there are no symmetries
            reference_value_shape = shape
            self._mapping = "identity"

        value_shape = value_shape + sub_element.value_shape()
        reference_value_shape = reference_value_shape + sub_element.reference_value_shape(
        )
        # Initialize element data
        MixedElement.__init__(self,
                              sub_elements,
                              value_shape=value_shape,
                              reference_value_shape=reference_value_shape)
        self._family = sub_element.family()
        self._degree = sub_element.degree()
        self._sub_element = sub_element
        self._shape = shape
        self._symmetry = symmetry
        self._sub_element_mapping = sub_element_mapping
        self._flattened_sub_element_mapping = flattened_sub_element_mapping

        # Cache repr string
        self._repr = "TensorElement(%s, shape=%s, symmetry=%s)" % (
            repr(sub_element), repr(self._shape), repr(self._symmetry))
Example #5
0
    def __init__(self, family, cell=None, degree=None, dim=None,
                 form_degree=None, quad_scheme=None, variant=None):
        """
        Create vector element (repeated mixed element)

        *Arguments*
            family (string)
               The finite element family (or an existing FiniteElement)
            cell
               The geometric cell, ignored if family is a FiniteElement
            degree (int)
               The polynomial degree, ignored if family is a FiniteElement
            dim (int)
               The value dimension of the element (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form), ignored if family is a FiniteElement
            quad_scheme
               The quadrature scheme (optional), ignored if family is a FiniteElement
            variant
               Hint for the local basis function variant (optional)
        """

        if isinstance(family, FiniteElementBase):
            sub_element = family
            cell = sub_element.cell()
            variant = sub_element.variant()
        else:
            if cell is not None:
                cell = as_cell(cell)
            # Create sub element
            sub_element = FiniteElement(family, cell, degree,
                                        form_degree=form_degree,
                                        quad_scheme=quad_scheme,
                                        variant=variant)

        # Set default size if not specified
        if dim is None:
            if cell is None:
                error("Cannot infer vector dimension without a cell.")
            dim = cell.geometric_dimension()

        self._mapping = sub_element.mapping()
        # Create list of sub elements for mixed element constructor
        sub_elements = [sub_element] * dim

        # Compute value shapes
        value_shape = (dim,) + sub_element.value_shape()
        reference_value_shape = (dim,) + sub_element.reference_value_shape()

        # Initialize element data
        MixedElement.__init__(self, sub_elements, value_shape=value_shape,
                              reference_value_shape=reference_value_shape)
        FiniteElementBase.__init__(self, sub_element.family(), cell, sub_element.degree(), quad_scheme,
                                   value_shape, reference_value_shape)
        self._sub_element = sub_element

        if variant is None:
            var_str = ""
        else:
            var_str = ", variant='" + variant + "'"

        # Cache repr string
        self._repr = "VectorElement(%s, dim=%d%s)" % (
            repr(sub_element), len(self._sub_elements), var_str)