Beispiel #1
0
    def __init__(self, element):
        self._element = element
        self._repr = as_native_str("BrokenElement(%s)" % repr(element))

        family = "BrokenElement"
        cell = element.cell()
        degree = element.degree()
        quad_scheme = element.quadrature_scheme()
        value_shape = element.value_shape()
        reference_value_shape = element.reference_value_shape()
        FiniteElementBase.__init__(self, family, cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)
Beispiel #2
0
    def __init__(self, element):
        self._element = element
        self._repr = as_native_str("BrokenElement(%s)" % repr(element))

        family = "BrokenElement"
        cell = element.cell()
        degree = element.degree()
        quad_scheme = element.quadrature_scheme()
        value_shape = element.value_shape()
        reference_value_shape = element.reference_value_shape()
        FiniteElementBase.__init__(self, family, cell, degree,
                                   quad_scheme, value_shape, reference_value_shape)
Beispiel #3
0
    def __init__(self, element):
        self._element = element
        self._repr = as_native_str("HDivElement(%s)" % repr(element))

        family = "TensorProductElement"
        cell = element.cell()
        degree = element.degree()
        quad_scheme = element.quadrature_scheme()
        value_shape = (element.cell().geometric_dimension(), )
        reference_value_shape = (element.cell().topological_dimension(), )

        # Skipping TensorProductElement constructor! Bad code smell, refactor to avoid this non-inheritance somehow.
        FiniteElementBase.__init__(self, family, cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)
Beispiel #4
0
    def __init__(self, element):
        self._element = element
        self._repr = as_native_str("HDivElement(%s)" % repr(element))

        family = "TensorProductElement"
        cell = element.cell()
        degree = element.degree()
        quad_scheme = element.quadrature_scheme()
        value_shape = (element.cell().geometric_dimension(),)
        reference_value_shape = (element.cell().topological_dimension(),)

        # Skipping TensorProductElement constructor! Bad code smell, refactor to avoid this non-inheritance somehow.
        FiniteElementBase.__init__(self, family, cell, degree,
                                   quad_scheme, value_shape, reference_value_shape)
Beispiel #5
0
    def __init__(self, *elements):
        self._elements = elements

        cell = elements[0].cell()
        if not all(e.cell() == cell for e in elements[1:]):
            error("Cell mismatch for sub elements of enriched element.")

        if isinstance(elements[0].degree(), int):
            degrees = {e.degree() for e in elements} - {None}
            degree = max(degrees) if degrees else None
        else:
            degree = tuple(map(max, zip(*[e.degree() for e in elements])))

        # We can allow the scheme not to be defined, but all defined
        # should be equal
        quad_schemes = [e.quadrature_scheme() for e in elements]
        quad_schemes = [qs for qs in quad_schemes if qs is not None]
        quad_scheme = quad_schemes[0] if quad_schemes else None
        if not all(qs == quad_scheme for qs in quad_schemes):
            error("Quadrature scheme mismatch.")

        value_shape = elements[0].value_shape()
        if not all(e.value_shape() == value_shape for e in elements[1:]):
            error("Element value shape mismatch.")

        reference_value_shape = elements[0].reference_value_shape()
        if not all(e.reference_value_shape() == reference_value_shape
                   for e in elements[1:]):
            error("Element reference value shape mismatch.")

        # mapping = elements[0].mapping() # FIXME: This fails for a mixed subelement here.
        # if not all(e.mapping() == mapping for e in elements[1:]):
        #    error("Element mapping mismatch.")

        # Get name of subclass: EnrichedElement or NodalEnrichedElement
        class_name = as_native_str(self.__class__.__name__)

        # Initialize element data
        FiniteElementBase.__init__(self, class_name, cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)

        # Cache repr string
        self._repr = as_native_str(
            "%s(%s)" % (class_name, ", ".join(repr(e)
                                              for e in self._elements)))
Beispiel #6
0
    def __init__(self, element, restriction_domain):
        if not isinstance(element, FiniteElementBase):
            error("Expecting a finite element instance.")
        if restriction_domain not in valid_restriction_domains:
            error("Expecting one of the strings %s." % (valid_restriction_domains,))

        FiniteElementBase.__init__(self, "RestrictedElement", element.cell(),
                                   element.degree(),
                                   element.quadrature_scheme(),
                                   element.value_shape(),
                                   element.reference_value_shape())

        self._element = element

        self._restriction_domain = restriction_domain

        self._repr = as_native_str("RestrictedElement(%s, %s)" % (
            repr(self._element), repr(self._restriction_domain)))
Beispiel #7
0
    def __init__(self, *elements):
        self._elements = elements

        cell = elements[0].cell()
        if not all(e.cell() == cell for e in elements[1:]):
            error("Cell mismatch for sub elements of enriched element.")

        if isinstance(elements[0].degree(), int):
            degrees = {e.degree() for e in elements} - {None}
            degree = max(degrees) if degrees else None
        else:
            degree = tuple(map(max, zip(*[e.degree() for e in elements])))

        # We can allow the scheme not to be defined, but all defined
        # should be equal
        quad_schemes = [e.quadrature_scheme() for e in elements]
        quad_schemes = [qs for qs in quad_schemes if qs is not None]
        quad_scheme = quad_schemes[0] if quad_schemes else None
        if not all(qs == quad_scheme for qs in quad_schemes):
            error("Quadrature scheme mismatch.")

        value_shape = elements[0].value_shape()
        if not all(e.value_shape() == value_shape for e in elements[1:]):
            error("Element value shape mismatch.")

        reference_value_shape = elements[0].reference_value_shape()
        if not all(e.reference_value_shape() == reference_value_shape for e in elements[1:]):
            error("Element reference value shape mismatch.")

        # mapping = elements[0].mapping() # FIXME: This fails for a mixed subelement here.
        # if not all(e.mapping() == mapping for e in elements[1:]):
        #    error("Element mapping mismatch.")

        # Get name of subclass: EnrichedElement or NodalEnrichedElement
        class_name = as_native_str(self.__class__.__name__)

        # Initialize element data
        FiniteElementBase.__init__(self, class_name, cell, degree,
                                   quad_scheme, value_shape,
                                   reference_value_shape)

        # Cache repr string
        self._repr = as_native_str("%s(%s)" %
                                   (class_name, ", ".join(repr(e) for e in self._elements)))
Beispiel #8
0
    def __init__(self, element, restriction_domain):
        if not isinstance(element, FiniteElementBase):
            error("Expecting a finite element instance.")
        if restriction_domain not in valid_restriction_domains:
            error("Expecting one of the strings %s." %
                  (valid_restriction_domains, ))

        FiniteElementBase.__init__(self, "RestrictedElement", element.cell(),
                                   element.degree(),
                                   element.quadrature_scheme(),
                                   element.value_shape(),
                                   element.reference_value_shape())

        self._element = element

        self._restriction_domain = restriction_domain

        self._repr = "RestrictedElement(%s, %s)" % (repr(
            self._element), repr(self._restriction_domain))
Beispiel #9
0
    def __init__(self, *elements, **kwargs):
        "Create TensorProductElement from a given list of elements."
        if not elements:
            error("Cannot create TensorProductElement from empty list.")

        keywords = list(kwargs.keys())
        if keywords and keywords != ["cell"]:
            raise ValueError(
                "TensorProductElement got an unexpected keyword argument '%s'"
                % keywords[0])
        cell = kwargs.get("cell")

        family = "TensorProductElement"

        if cell is None:
            # Define cell as the product of each elements cell
            cell = TensorProductCell(*[e.cell() for e in elements])
        else:
            cell = as_cell(cell)

        # Define polynomial degree as a tuple of sub-degrees
        degree = tuple(e.degree() for e in elements)

        # No quadrature scheme defined
        quad_scheme = None

        # match FIAT implementation
        value_shape = tuple(chain(*[e.value_shape() for e in elements]))
        reference_value_shape = tuple(
            chain(*[e.reference_value_shape() for e in elements]))
        if len(value_shape) > 1:
            error("Product of vector-valued elements not supported")
        if len(reference_value_shape) > 1:
            error("Product of vector-valued elements not supported")

        FiniteElementBase.__init__(self, family, cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)
        self._sub_elements = elements
        self._cell = cell
        self._repr = "TensorProductElement(%s, cell=%s)" % (", ".join(
            repr(e) for e in elements), repr(cell))
Beispiel #10
0
    def __init__(self, *elements, **kwargs):
        "Create TensorProductElement from a given list of elements."
        if not elements:
            error("Cannot create TensorProductElement from empty list.")

        keywords = list(kwargs.keys())
        if keywords and keywords != ["cell"]:
            raise ValueError("TensorProductElement got an unexpected keyword argument '%s'" % keywords[0])
        cell = kwargs.get("cell")

        family = "TensorProductElement"

        if cell is None:
            # Define cell as the product of each elements cell
            cell = TensorProductCell(*[e.cell() for e in elements])
        else:
            cell = as_cell(cell)

        # Define polynomial degree as a tuple of sub-degrees
        degree = tuple(e.degree() for e in elements)

        # No quadrature scheme defined
        quad_scheme = None

        # match FIAT implementation
        value_shape = tuple(chain(*[e.value_shape() for e in elements]))
        reference_value_shape = tuple(chain(*[e.reference_value_shape() for e in elements]))
        if len(value_shape) > 1:
            error("Product of vector-valued elements not supported")
        if len(reference_value_shape) > 1:
            error("Product of vector-valued elements not supported")

        FiniteElementBase.__init__(self, family, cell, degree,
                                   quad_scheme, value_shape,
                                   reference_value_shape)
        self._sub_elements = elements
        self._cell = cell
        self._repr = "TensorProductElement(%s, cell=%s)" % (
            ", ".join(repr(e) for e in elements), repr(cell))
Beispiel #11
0
    def __init__(self, *elements, **kwargs):
        "Create mixed finite element from given list of elements"

        if type(self) is MixedElement:
            if kwargs:
                error("Not expecting keyword arguments to MixedElement constructor.")

        # Un-nest arguments if we get a single argument with a list of elements
        if len(elements) == 1 and isinstance(elements[0], (tuple, list)):
            elements = elements[0]
        # Interpret nested tuples as sub-mixedelements recursively
        elements = [MixedElement(e) if isinstance(e, (tuple, list)) else e
                    for e in elements]
        self._sub_elements = elements

        # Pick the first cell, for now all should be equal
        cells = tuple(sorted(set(element.cell() for element in elements) - set([None])))
        self._cells = cells
        if cells:
            cell = cells[0]
            # Require that all elements are defined on the same cell
            if not all(c == cell for c in cells[1:]):
                error("Sub elements must live on the same cell.")
        else:
            cell = None

        # Check that all elements use the same quadrature scheme TODO:
        # We can allow the scheme not to be defined.
        quad_scheme = elements[0].quadrature_scheme()
        if not all(e.quadrature_scheme() == quad_scheme for e in elements):
            error("Quadrature scheme mismatch for sub elements of mixed element.")

        # Compute value sizes in global and reference configurations
        value_size_sum = sum(product(s.value_shape()) for s in self._sub_elements)
        reference_value_size_sum = sum(product(s.reference_value_shape()) for s in self._sub_elements)

        # Default value shape: Treated simply as all subelement values
        # unpacked in a vector.
        value_shape = kwargs.get('value_shape', (value_size_sum,))

        # Default reference value shape: Treated simply as all
        # subelement reference values unpacked in a vector.
        reference_value_shape = kwargs.get('reference_value_shape', (reference_value_size_sum,))

        # Validate value_shape (deliberately not for subclasses
        # VectorElement and TensorElement)
        if type(self) is MixedElement:
            # This is not valid for tensor elements with symmetries,
            # assume subclasses deal with their own validation
            if product(value_shape) != value_size_sum:
                error("Provided value_shape doesn't match the "
                      "total value size of all subelements.")

        # Initialize element data
        degrees = {e.degree() for e in self._sub_elements} - {None}
        degree = max_degree(degrees) if degrees else None
        FiniteElementBase.__init__(self, "Mixed", cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)

        # Cache repr string
        if type(self) is MixedElement:
            self._repr = "MixedElement(%s)" % (
                ", ".join(repr(e) for e in self._sub_elements),)
Beispiel #12
0
    def __init__(self, *elements, **kwargs):
        "Create mixed finite element from given list of elements"

        if type(self) is MixedElement:
            if kwargs:
                error(
                    "Not expecting keyword arguments to MixedElement constructor."
                )

        # Un-nest arguments if we get a single argument with a list of elements
        if len(elements) == 1 and isinstance(elements[0], (tuple, list)):
            elements = elements[0]
        # Interpret nested tuples as sub-mixedelements recursively
        elements = [
            MixedElement(e) if isinstance(e, (tuple, list)) else e
            for e in elements
        ]
        self._sub_elements = elements

        # Pick the first cell, for now all should be equal
        cells = tuple(
            sorted(set(element.cell() for element in elements) - set([None])))
        self._cells = cells
        if cells:
            cell = cells[0]
            # Require that all elements are defined on the same cell
            if not all(c == cell for c in cells[1:]):
                error("Sub elements must live on the same cell.")
        else:
            cell = None

        # Check that all elements use the same quadrature scheme TODO:
        # We can allow the scheme not to be defined.
        if len(elements) == 0:
            quad_scheme = None
        else:
            quad_scheme = elements[0].quadrature_scheme()
            if not all(e.quadrature_scheme() == quad_scheme for e in elements):
                error(
                    "Quadrature scheme mismatch for sub elements of mixed element."
                )

        # Compute value sizes in global and reference configurations
        value_size_sum = sum(
            product(s.value_shape()) for s in self._sub_elements)
        reference_value_size_sum = sum(
            product(s.reference_value_shape()) for s in self._sub_elements)

        # Default value shape: Treated simply as all subelement values
        # unpacked in a vector.
        value_shape = kwargs.get('value_shape', (value_size_sum, ))

        # Default reference value shape: Treated simply as all
        # subelement reference values unpacked in a vector.
        reference_value_shape = kwargs.get('reference_value_shape',
                                           (reference_value_size_sum, ))

        # Validate value_shape (deliberately not for subclasses
        # VectorElement and TensorElement)
        if type(self) is MixedElement:
            # This is not valid for tensor elements with symmetries,
            # assume subclasses deal with their own validation
            if product(value_shape) != value_size_sum:
                error("Provided value_shape doesn't match the "
                      "total value size of all subelements.")

        # Initialize element data
        degrees = {e.degree() for e in self._sub_elements} - {None}
        degree = max_degree(degrees) if degrees else None
        FiniteElementBase.__init__(self, "Mixed", cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)

        # Cache repr string
        if type(self) is MixedElement:
            self._repr = "MixedElement(%s)" % (", ".join(
                repr(e) for e in self._sub_elements), )
Beispiel #13
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)
        FiniteElementBase.__init__(self, sub_element.family(), cell,
                                   sub_element.degree(), quad_scheme,
                                   value_shape, reference_value_shape)
        self._sub_element = sub_element

        # Cache repr string
        self._repr = "VectorElement(%s, dim=%d)" % (repr(sub_element),
                                                    len(self._sub_elements))
Beispiel #14
0
    def __init__(self,
                 family,
                 cell=None,
                 degree=None,
                 form_degree=None,
                 quad_scheme=None,
                 variant=None):
        """Create finite element.

        *Arguments*
            family (string)
               The finite element family
            cell
               The geometric cell
            degree (int)
               The polynomial degree (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form)
            quad_scheme
               The quadrature scheme (optional)
            variant
               Hint for the local basis function variant (optional)
        """
        # Note: Unfortunately, dolfin sometimes passes None for
        # cell. Until this is fixed, allow it:
        if cell is not None:
            cell = as_cell(cell)

        family, short_name, degree, value_shape, reference_value_shape, sobolev_space, mapping = canonical_element_description(
            family, cell, degree, form_degree)

        # TODO: Move these to base? Might be better to instead
        # simplify base though.
        self._sobolev_space = sobolev_space
        self._mapping = mapping
        self._short_name = short_name
        self._variant = variant

        # Finite elements on quadrilaterals have an IrreducibleInt as degree
        if cell is not None:
            if cell.cellname() == "quadrilateral":
                from ufl.algorithms.estimate_degrees import IrreducibleInt
                degree = IrreducibleInt(degree)

        # Type check variant
        if variant is not None and not isinstance(variant, str):
            raise ValueError("Illegal variant: must be string or None")

        # Initialize element data
        FiniteElementBase.__init__(self, family, cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)

        # Cache repr string
        qs = self.quadrature_scheme()
        if qs is None:
            quad_str = ""
        else:
            quad_str = ", quad_scheme=%s" % repr(qs)
        v = self.variant()
        if v is None:
            var_str = ""
        else:
            var_str = ", variant=%s" % repr(qs)
        self._repr = as_native_str("FiniteElement(%s, %s, %s%s%s)" %
                                   (repr(self.family()), repr(self.cell()),
                                    repr(self.degree()), quad_str, var_str))
        assert '"' not in self._repr
Beispiel #15
0
    def __init__(self,
                 family,
                 cell=None,
                 degree=None,
                 form_degree=None,
                 quad_scheme=None,
                 variant=None):
        """Create finite element.

        *Arguments*
            family (string)
               The finite element family
            cell
               The geometric cell
            degree (int)
               The polynomial degree (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form)
            quad_scheme
               The quadrature scheme (optional)
            variant
               Hint for the local basis function variant (optional)
        """
        # Note: Unfortunately, dolfin sometimes passes None for
        # cell. Until this is fixed, allow it:
        if cell is not None:
            cell = as_cell(cell)

        family, short_name, degree, value_shape, reference_value_shape, sobolev_space, mapping = canonical_element_description(family, cell, degree, form_degree)

        # TODO: Move these to base? Might be better to instead
        # simplify base though.
        self._sobolev_space = sobolev_space
        self._mapping = mapping
        self._short_name = short_name
        self._variant = variant

        # Finite elements on quadrilaterals and hexahedrons have an IrreducibleInt as degree
        if cell is not None:
            if cell.cellname() in ["quadrilateral", "hexahedron"]:
                from ufl.algorithms.estimate_degrees import IrreducibleInt
                degree = IrreducibleInt(degree)

        # Type check variant
        if variant is not None and not isinstance(variant, str):
            raise ValueError("Illegal variant: must be string or None")

        # Initialize element data
        FiniteElementBase.__init__(self, family, cell, degree, quad_scheme,
                                   value_shape, reference_value_shape)

        # Cache repr string
        qs = self.quadrature_scheme()
        if qs is None:
            quad_str = ""
        else:
            quad_str = ", quad_scheme=%s" % repr(qs)
        v = self.variant()
        if v is None:
            var_str = ""
        else:
            var_str = ", variant=%s" % repr(v)
        self._repr = as_native_str("FiniteElement(%s, %s, %s%s%s)" % (
            repr(self.family()), repr(self.cell()), repr(self.degree()), quad_str, var_str))
        assert '"' not in self._repr