예제 #1
0
def affine_mesh(cell, ufl_id=None):
    "Create a Mesh over a given cell type with an affine geometric parameterization."
    from ufl.finiteelement import VectorElement
    cell = as_cell(cell)
    gdim = cell.geometric_dimension()
    degree = 1
    coordinate_element = VectorElement("Lagrange", cell, degree, dim=gdim)
    return Mesh(coordinate_element, ufl_id=ufl_id)
예제 #2
0
파일: domain.py 프로젝트: strekalloff/mpm
def affine_mesh(cell, ufl_id=None):
    "Create a Mesh over a given cell type with an affine geometric parameterization."
    from ufl.finiteelement import VectorElement
    cell = as_cell(cell)
    gdim = cell.geometric_dimension()
    degree = 1
    coordinate_element = VectorElement("Lagrange", cell, degree, dim=gdim)
    return Mesh(coordinate_element, ufl_id=ufl_id)
예제 #3
0
파일: mixedelement.py 프로젝트: FEniCS/ufl
    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))
예제 #4
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))
예제 #5
0
def as_domain(domain):
    """Convert any valid object to an AbstractDomain type."""
    if isinstance(domain, AbstractDomain):
        # Modern .ufl files and dolfin behaviour
        return domain
    elif hasattr(domain, "ufl_domain"):
        # If we get a dolfin.Mesh, it can provide us a corresponding
        # ufl.Mesh.  This would be unnecessary if dolfin.Mesh could
        # subclass ufl.Mesh.
        return domain.ufl_domain()
    else:
        # Legacy .ufl files
        # TODO: Make this conversion in the relevant constructors
        # closer to the user interface?
        # TODO: Make this configurable to be an error from the dolfin side?
        cell = as_cell(domain)
        return default_domain(cell)
예제 #6
0
파일: domain.py 프로젝트: strekalloff/mpm
def as_domain(domain):
    """Convert any valid object to an AbstractDomain type."""
    if isinstance(domain, AbstractDomain):
        # Modern .ufl files and dolfin behaviour
        return domain
    elif hasattr(domain, "ufl_domain"):
        # If we get a dolfin.Mesh, it can provide us a corresponding
        # ufl.Mesh.  This would be unnecessary if dolfin.Mesh could
        # subclass ufl.Mesh.
        return domain.ufl_domain()
    else:
        # Legacy .ufl files
        # TODO: Make this conversion in the relevant constructors
        # closer to the user interface?
        # TODO: Make this configurable to be an error from the dolfin side?
        cell = as_cell(domain)
        return default_domain(cell)
예제 #7
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))
예제 #8
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))
예제 #9
0
    def __init__(self, family, cell, degree, quad_scheme, value_shape,
                 reference_value_shape):
        "Initialize basic finite element data."
        if not isinstance(family, str):
            error("Invalid family type.")
        if not (degree is None or isinstance(degree, (int, tuple))):
            error("Invalid degree type.")
        if not isinstance(value_shape, tuple):
            error("Invalid value_shape type.")
        if not isinstance(reference_value_shape, tuple):
            error("Invalid reference_value_shape type.")

        if cell is not None:
            cell = as_cell(cell)
            if not isinstance(cell, AbstractCell):
                error("Invalid cell type.")

        self._family = family
        self._cell = cell
        self._degree = degree
        self._value_shape = value_shape
        self._reference_value_shape = reference_value_shape
        self._quad_scheme = quad_scheme
예제 #10
0
    def __init__(self, family, cell, degree, quad_scheme, value_shape,
                 reference_value_shape):
        "Initialize basic finite element data."
        if not isinstance(family, str):
            error("Invalid family type.")
        if not (degree is None or isinstance(degree, (int, tuple))):
            error("Invalid degree type.")
        if not isinstance(value_shape, tuple):
            error("Invalid value_shape type.")
        if not isinstance(reference_value_shape, tuple):
            error("Invalid reference_value_shape type.")

        if cell is not None:
            cell = as_cell(cell)
            if not isinstance(cell, AbstractCell):
                error("Invalid cell type.")

        self._family = family
        self._cell = cell
        self._degree = degree
        self._value_shape = value_shape
        self._reference_value_shape = reference_value_shape
        self._quad_scheme = quad_scheme
예제 #11
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))
예제 #12
0
파일: finiteelement.py 프로젝트: FEniCS/ufl
    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
예제 #13
0
    def __new__(cls,
                family,
                cell=None,
                degree=None,
                form_degree=None,
                quad_scheme=None,
                variant=None):
        """Intercepts construction to expand CG, DG, RTCE and RTCF
        spaces on TensorProductCells."""
        if cell is not None:
            cell = as_cell(cell)

        if isinstance(cell, TensorProductCell):
            # Delay import to avoid circular dependency at module load time
            from ufl.finiteelement.tensorproductelement import TensorProductElement
            from ufl.finiteelement.enrichedelement import EnrichedElement
            from ufl.finiteelement.hdivcurl import HDivElement as HDiv, HCurlElement as HCurl

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

            if family in ["RTCF", "RTCE"]:
                cell_h, cell_v = cell.sub_cells()
                if cell_h.cellname() != "interval":
                    error(
                        "%s is available on TensorProductCell(interval, interval) only."
                        % family)
                if cell_v.cellname() != "interval":
                    error(
                        "%s is available on TensorProductCell(interval, interval) only."
                        % family)

                C_elt = FiniteElement("CG",
                                      "interval",
                                      degree,
                                      variant=variant)
                D_elt = FiniteElement("DG",
                                      "interval",
                                      degree - 1,
                                      variant=variant)

                CxD_elt = TensorProductElement(C_elt, D_elt, cell=cell)
                DxC_elt = TensorProductElement(D_elt, C_elt, cell=cell)

                if family == "RTCF":
                    return EnrichedElement(HDiv(CxD_elt), HDiv(DxC_elt))
                if family == "RTCE":
                    return EnrichedElement(HCurl(CxD_elt), HCurl(DxC_elt))

            elif family == "NCF":
                cell_h, cell_v = cell.sub_cells()
                if cell_h.cellname() != "quadrilateral":
                    error(
                        "%s is available on TensorProductCell(quadrilateral, interval) only."
                        % family)
                if cell_v.cellname() != "interval":
                    error(
                        "%s is available on TensorProductCell(quadrilateral, interval) only."
                        % family)

                Qc_elt = FiniteElement("RTCF",
                                       "quadrilateral",
                                       degree,
                                       variant=variant)
                Qd_elt = FiniteElement("DQ",
                                       "quadrilateral",
                                       degree - 1,
                                       variant=variant)

                Id_elt = FiniteElement("DG",
                                       "interval",
                                       degree - 1,
                                       variant=variant)
                Ic_elt = FiniteElement("CG",
                                       "interval",
                                       degree,
                                       variant=variant)

                return EnrichedElement(
                    HDiv(TensorProductElement(Qc_elt, Id_elt, cell=cell)),
                    HDiv(TensorProductElement(Qd_elt, Ic_elt, cell=cell)))

            elif family == "NCE":
                cell_h, cell_v = cell.sub_cells()
                if cell_h.cellname() != "quadrilateral":
                    error(
                        "%s is available on TensorProductCell(quadrilateral, interval) only."
                        % family)
                if cell_v.cellname() != "interval":
                    error(
                        "%s is available on TensorProductCell(quadrilateral, interval) only."
                        % family)

                Qc_elt = FiniteElement("Q",
                                       "quadrilateral",
                                       degree,
                                       variant=variant)
                Qd_elt = FiniteElement("RTCE",
                                       "quadrilateral",
                                       degree,
                                       variant=variant)

                Id_elt = FiniteElement("DG",
                                       "interval",
                                       degree - 1,
                                       variant=variant)
                Ic_elt = FiniteElement("CG",
                                       "interval",
                                       degree,
                                       variant=variant)

                return EnrichedElement(
                    HCurl(TensorProductElement(Qc_elt, Id_elt, cell=cell)),
                    HCurl(TensorProductElement(Qd_elt, Ic_elt, cell=cell)))

            elif family == "Q":
                return TensorProductElement(*[
                    FiniteElement("CG", c, degree, variant=variant)
                    for c in cell.sub_cells()
                ],
                                            cell=cell)

            elif family == "DQ":

                def dq_family(cell):
                    return "DG" if cell.cellname() in simplices else "DQ"

                return TensorProductElement(*[
                    FiniteElement(dq_family(c), c, degree, variant=variant)
                    for c in cell.sub_cells()
                ],
                                            cell=cell)

        return super(FiniteElement, cls).__new__(cls)
예제 #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
예제 #15
0
파일: finiteelement.py 프로젝트: FEniCS/ufl
    def __new__(cls,
                family,
                cell=None,
                degree=None,
                form_degree=None,
                quad_scheme=None,
                variant=None):
        """Intercepts construction to expand CG, DG, RTCE and RTCF
        spaces on TensorProductCells."""
        if cell is not None:
            cell = as_cell(cell)

        if isinstance(cell, TensorProductCell):
            # Delay import to avoid circular dependency at module load time
            from ufl.finiteelement.tensorproductelement import TensorProductElement
            from ufl.finiteelement.enrichedelement import EnrichedElement
            from ufl.finiteelement.hdivcurl import HDivElement as HDiv, HCurlElement as HCurl

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

            if family in ["RTCF", "RTCE"]:
                cell_h, cell_v = cell.sub_cells()
                if cell_h.cellname() != "interval":
                    error("%s is available on TensorProductCell(interval, interval) only." % family)
                if cell_v.cellname() != "interval":
                    error("%s is available on TensorProductCell(interval, interval) only." % family)

                C_elt = FiniteElement("CG", "interval", degree, variant=variant)
                D_elt = FiniteElement("DG", "interval", degree - 1, variant=variant)

                CxD_elt = TensorProductElement(C_elt, D_elt, cell=cell)
                DxC_elt = TensorProductElement(D_elt, C_elt, cell=cell)

                if family == "RTCF":
                    return EnrichedElement(HDiv(CxD_elt), HDiv(DxC_elt))
                if family == "RTCE":
                    return EnrichedElement(HCurl(CxD_elt), HCurl(DxC_elt))

            elif family == "NCF":
                cell_h, cell_v = cell.sub_cells()
                if cell_h.cellname() != "quadrilateral":
                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)
                if cell_v.cellname() != "interval":
                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)

                Qc_elt = FiniteElement("RTCF", "quadrilateral", degree, variant=variant)
                Qd_elt = FiniteElement("DQ", "quadrilateral", degree - 1, variant=variant)

                Id_elt = FiniteElement("DG", "interval", degree - 1, variant=variant)
                Ic_elt = FiniteElement("CG", "interval", degree, variant=variant)

                return EnrichedElement(HDiv(TensorProductElement(Qc_elt, Id_elt, cell=cell)),
                                       HDiv(TensorProductElement(Qd_elt, Ic_elt, cell=cell)))

            elif family == "NCE":
                cell_h, cell_v = cell.sub_cells()
                if cell_h.cellname() != "quadrilateral":
                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)
                if cell_v.cellname() != "interval":
                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)

                Qc_elt = FiniteElement("Q", "quadrilateral", degree, variant=variant)
                Qd_elt = FiniteElement("RTCE", "quadrilateral", degree, variant=variant)

                Id_elt = FiniteElement("DG", "interval", degree - 1, variant=variant)
                Ic_elt = FiniteElement("CG", "interval", degree, variant=variant)

                return EnrichedElement(HCurl(TensorProductElement(Qc_elt, Id_elt, cell=cell)),
                                       HCurl(TensorProductElement(Qd_elt, Ic_elt, cell=cell)))

            elif family == "Q":
                return TensorProductElement(*[FiniteElement("CG", c, degree, variant=variant)
                                              for c in cell.sub_cells()],
                                            cell=cell)

            elif family == "DQ":
                def dq_family(cell):
                    return "DG" if cell.cellname() in simplices else "DQ"
                return TensorProductElement(*[FiniteElement(dq_family(c), c, degree, variant=variant)
                                              for c in cell.sub_cells()],
                                            cell=cell)

        return super(FiniteElement, cls).__new__(cls)
예제 #16
0
파일: mixedelement.py 프로젝트: FEniCS/ufl
    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))
예제 #17
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)