Exemplo n.º 1
0
    def __init__(self, *elements):
        "Create TensorProductElement from a given list of elements."

        self._sub_elements = list(elements)
        ufl_assert(
            len(self._sub_elements) > 0,
            "Cannot create TensorProductElement from empty list.")
        self._repr = "TensorProductElement(*%r)" % self._sub_elements
        family = "TensorProductElement"

        # Define cell as the product of each subcell
        cell = ProductCell(*[e.cell() for e in self._sub_elements])
        domain = as_domain(
            cell)  # FIXME: figure out what this is supposed to mean :)

        # Define polynomial degree as the maximal of each subelement
        degree = max(e.degree() for e in self._sub_elements)

        # No quadrature scheme defined
        quad_scheme = None

        # For now, check that all subelements have the same value
        # shape, and use this.
        # TODO: Not sure if this makes sense, what kind of product is used to build the basis?
        value_shape = self._sub_elements[0].value_shape()
        ufl_assert(
            all(e.value_shape() == value_shape for e in self._sub_elements),
            "All subelements in must have same value shape")

        super(TensorProductElement, self).__init__(family, domain, degree,
                                                   quad_scheme, value_shape)
    def __init__(self, *elements):
        "Create TensorProductElement from a given list of elements."

        self._sub_elements = list(elements)
        ufl_assert(len(self._sub_elements) > 0,
                   "Cannot create TensorProductElement from empty list.")
        self._repr = "TensorProductElement(*%r)" % self._sub_elements
        family = "TensorProductElement"

        # Define cell as the product of each subcell
        cell = ProductCell(*[e.cell() for e in self._sub_elements])
        domain = as_domain(cell) # FIXME: figure out what this is supposed to mean :)

        # Define polynomial degree as the maximal of each subelement
        degree = max(e.degree() for e in self._sub_elements)

        # No quadrature scheme defined
        quad_scheme = None

        # For now, check that all subelements have the same value
        # shape, and use this.
        # TODO: Not sure if this makes sense, what kind of product is used to build the basis?
        value_shape = self._sub_elements[0].value_shape()
        ufl_assert(all(e.value_shape() == value_shape
                       for e in self._sub_elements),
                   "All subelements in must have same value shape")

        super(TensorProductElement, self).__init__(family, domain, degree,
                                                   quad_scheme, value_shape)
Exemplo n.º 3
0
    def __init__(self, family, domain, degree, dim=None, quad_scheme=None,
                 form_degree=None):
        """
        Create vector element (repeated mixed element)

        *Arguments*
            family (string)
               The finite element family
            domain
               The geometric domain
            degree (int)
               The polynomial degree
            dim (int)
               The value dimension of the element (optional)
            quad_scheme
               The quadrature scheme (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form)
        """
        if domain is not None:
            domain = as_domain(domain)

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

        # Create mixed element from list of finite elements
        sub_element = FiniteElement(family, domain, degree, quad_scheme,
                                    form_degree)
        sub_elements = [sub_element]*dim

        # Get common family name (checked in FiniteElement.__init__)
        family = sub_element.family()

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

        # Initialize element data
        super(VectorElement, self).__init__(sub_elements, value_shape=value_shape)
        self._family = family
        self._degree = degree
        self._sub_element = sub_element

        # Cache repr string
        self._repr = "VectorElement(%r, %r, %r, %d, %r)" % \
            (self._family, self._domain, self._degree,
             len(self._sub_elements), quad_scheme)
Exemplo n.º 4
0
def build_element_mapping(element_mapping, common_cell, arguments,
                          coefficients):
    """Complete an element mapping for all elements used by
    arguments and coefficients, using a well defined common cell."""

    # Build a new dict to avoid modifying the dict passed from non-ufl code
    new_element_mapping = {}

    # Check that the given initial mapping has no invalid entries as values
    for v in element_mapping.itervalues():
        ufl_assert(
            v.cell() is not None,
            "Found incomplete element with undefined cell in element mapping.")
        ufl_assert(
            v.family() is not None,
            "Found incomplete element with undefined family in element mapping."
        )

    common_domain = as_domain(common_cell)  # FIXME: handle better somehow?

    # Reconstruct all elements we need to map
    for f in chain(arguments, coefficients):
        e = f.element()
        # Prefer the given mapping:
        new_e = element_mapping.get(e)
        if new_e is None:
            if e.cell() is None:
                # Otherwise complete with domain by reconstructing if cell is missing
                new_e = e.reconstruct(domain=common_domain)
            else:
                # Or just use the original element
                new_e = e
        new_element_mapping[e] = new_e

    # Check that the new mapping has no invalid entries as values
    for v in new_element_mapping.itervalues():
        ufl_assert(
            v.cell() is not None,
            "Found incomplete element with undefined cell in new element mapping."
        )
        ufl_assert(
            v.family() is not None,
            "Found incomplete element with undefined family in new element mapping."
        )

    return new_element_mapping
 def __init__(self, family, domain, degree, quad_scheme, value_shape):
     "Initialize basic finite element data"
     ufl_assert(isinstance(family, str), "Invalid family type.")
     ufl_assert(isinstance(degree, int) or degree is None, "Invalid degree type.")
     ufl_assert(isinstance(value_shape, tuple), "Invalid value_shape type.")
     if domain is None:
         self._domain = None
         self._cell = None
     else:
         self._domain = as_domain(domain)
         self._cell = self._domain.cell()
         ufl_assert(isinstance(self._domain, DomainDescription), "Invalid domain type.")
         ufl_assert(isinstance(self._cell, Cell), "Invalid cell type.")
     self._family = family
     self._degree = degree
     self._value_shape = value_shape
     self._quad_scheme = quad_scheme
 def __init__(self, family, domain, degree, quad_scheme, value_shape):
     "Initialize basic finite element data"
     ufl_assert(isinstance(family, str), "Invalid family type.")
     ufl_assert(
         isinstance(degree, int) or degree is None, "Invalid degree type.")
     ufl_assert(isinstance(value_shape, tuple), "Invalid value_shape type.")
     if domain is None:
         self._domain = None
         self._cell = None
     else:
         self._domain = as_domain(domain)
         self._cell = self._domain.cell()
         ufl_assert(isinstance(self._domain, DomainDescription),
                    "Invalid domain type.")
         ufl_assert(isinstance(self._cell, Cell), "Invalid cell type.")
     self._family = family
     self._degree = degree
     self._value_shape = value_shape
     self._quad_scheme = quad_scheme
Exemplo n.º 7
0
def build_element_mapping(element_mapping, common_cell, arguments, coefficients):
    """Complete an element mapping for all elements used by
    arguments and coefficients, using a well defined common cell."""

    # Build a new dict to avoid modifying the dict passed from non-ufl code
    new_element_mapping = {}

    # Check that the given initial mapping has no invalid entries as values
    for v in element_mapping.itervalues():
        ufl_assert(v.cell() is not None,
                   "Found incomplete element with undefined cell in element mapping.")
        ufl_assert(v.family() is not None,
                   "Found incomplete element with undefined family in element mapping.")

    common_domain = as_domain(common_cell) # FIXME: handle better somehow?

    # Reconstruct all elements we need to map
    for f in chain(arguments, coefficients):
        e = f.element()
        # Prefer the given mapping:
        new_e = element_mapping.get(e)
        if new_e is None:
            if e.cell() is None:
                # Otherwise complete with domain by reconstructing if cell is missing
                new_e = e.reconstruct(domain=common_domain)
            else:
                # Or just use the original element
                new_e = e
        new_element_mapping[e] = new_e

    # Check that the new mapping has no invalid entries as values
    for v in new_element_mapping.itervalues():
        ufl_assert(v.cell() is not None,
                   "Found incomplete element with undefined cell in new element mapping.")
        ufl_assert(v.family() is not None,
                   "Found incomplete element with undefined family in new element mapping.")

    return new_element_mapping
Exemplo n.º 8
0
    def __rmul__(self, integrand):
        # Let other types implement multiplication with Measure
        # if they want to (to support the dolfin-adjoint TimeMeasure)
        if not isinstance(integrand, Expr):
            return NotImplemented

        # Allow only scalar integrands
        if not is_true_ufl_scalar(integrand):
            error("Trying to integrate expression of rank %d with free indices %r." \
                  % (integrand.rank(), integrand.free_indices()))

        # Is the measure in a state where multiplication is not allowed?
        if self._domain_description == Measure.DOMAIN_ID_UNDEFINED:
            error("Missing domain id. You need to select a subdomain, " +\
                  "e.g. M = f*dx(0) for subdomain 0.")

        #else: # TODO: Do it this way instead, and move all logic below into preprocess:
        #    # Return a one-integral form:
        #    from ufl.form import Form
        #    return Form( [Integral(integrand, self.domain_type(), self.domain_id(), self.metadata(), self.domain_data())] )
        #    # or if we move domain data into Form instead:
        #    integrals = [Integral(integrand, self.domain_type(), self.domain_id(), self.metadata())]
        #    domain_data = { self.domain_type(): self.domain_data() }
        #    return Form(integrals, domain_data)

        # TODO: How to represent all kinds of domain descriptions is still a bit unclear
        # Create form if we have a sufficient domain description
        elif (# We have a complete measure with domain description
            isinstance(self._domain_description, DomainDescription)
            # Is the measure in a basic state 'foo*dx'?
            or self._domain_description == Measure.DOMAIN_ID_UNIQUE
            # Is the measure over everywhere?
            or self._domain_description == Measure.DOMAIN_ID_EVERYWHERE
            # Is the measure in a state not allowed prior to preprocessing?
            or self._domain_description == Measure.DOMAIN_ID_OTHERWISE
            ):
            # Create and return a one-integral form
            from ufl.form import Form
            return Form( [Integral(integrand, self.domain_type(), self.domain_id(), self.metadata(), self.domain_data())] )

        # Did we get several ids?
        elif isinstance(self._domain_description, tuple):
            # FIXME: Leave this analysis to preprocessing
            return sum(integrand*self.reconstruct(domain_id=d) for d in self._domain_description)

        # Did we get a name?
        elif isinstance(self._domain_description, str):
            # FIXME: Leave this analysis to preprocessing

            # Get all domains and regions from integrand to analyse
            domains = extract_domains(integrand)

            # Get domain or region with this name from integrand, error if multiple found
            name = self._domain_description
            candidates = set()
            for TD in domains:
                if TD.name() == name:
                    candidates.add(TD)
            ufl_assert(len(candidates) > 0,
                       "Found no domain with name '%s' in integrand." % name)
            ufl_assert(len(candidates) == 1,
                       "Multiple distinct domains with same name encountered in integrand.")
            D, = candidates

            # Reconstruct measure with the found named domain or region
            measure = self.reconstruct(domain_id=D)
            return integrand*measure

        # Did we get a number?
        elif isinstance(self._domain_description, int):
            # FIXME: Leave this analysis to preprocessing

            # Get all top level domains from integrand to analyse
            domains = extract_top_domains(integrand)

            # Get domain from integrand, error if multiple found
            if len(domains) == 0:
                # This is the partially defined integral from dolfin expression mess
                cell = integrand.cell()
                D = None if cell is None else as_domain(cell)
            elif len(domains) == 1:
                D, = domains
            else:
                error("Ambiguous reference to integer subdomain with multiple top domains in integrand.")

            if D is None:
                # We have a number but not a domain? Leave it to preprocess...
                # This is the case with badly formed forms which can occur from dolfin
                # Create and return a one-integral form
                from ufl.form import Form
                return Form( [Integral(integrand, self.domain_type(), self.domain_id(), self.metadata(), self.domain_data())] )
            else:
                # Reconstruct measure with the found numbered subdomain
                measure = self.reconstruct(domain_id=D[self._domain_description])
                return integrand*measure

        # Provide error to user
        else:
            error("Invalid domain id %s." % str(self._domain_description))
    def __init__(self,
                 family,
                 domain=None,
                 degree=None,
                 quad_scheme=None,
                 form_degree=None):
        """Create finite element

        *Arguments*
            family (string)
               The finite element family
            domain
               The geometric domain
            degree (int)
               The polynomial degree (optional)
            quad_scheme
               The quadrature scheme (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form)
        """
        if domain is None:
            cell = None
        else:
            domain = as_domain(domain)
            cell = domain.cell()
            ufl_assert(cell is not None, "Missing cell in given domain.")

        # Check whether this family is an alias for something else
        if family in aliases:
            (name, cell, r) = aliases[family](family, cell, degree,
                                              form_degree)
            #info_blue("%s, is an alias for %s " % (
            #        (family, cell, degree, form_degree),
            #        (name, cell, r)))

            # FIXME: Need to init here with domain instead of using cell from aliases, is that ok?
            ufl_assert(cell == domain.cell(),
                       "Breaking assumption in element alias mapping.")
            self.__init__(name, domain, r, quad_scheme)
            return

        # Check that the element family exists
        ufl_assert(family in ufl_elements,
                   'Unknown finite element "%s".' % family)

        # Check that element data is valid (and also get common family name)
        (family, self._short_name, value_rank, krange, cellnames) =\
            ufl_elements[family]

        # Validate cellname if a valid cell is specified
        cellname = None if cell is None else cell.cellname()
        ufl_assert(
            cellname in cellnames,
            'Cellname "%s" invalid for "%s" finite element.' %
            (cellname, family))

        # Validate degree if specified
        if degree is not None:
            ufl_assert(krange is not None,
                       'Degree "%s" invalid for "%s" finite element, '\
                           'should be None.' % (degree, family))
            kmin, kmax = krange
            ufl_assert(kmin is None or degree >= kmin,
                       'Degree "%s" invalid for "%s" finite element.' %\
                           (degree, family))
            ufl_assert(kmax is None or degree <= kmax,
                   'Degree "%s" invalid for "%s" finite element.' %\
                           (istr(degree), family))

        # Set value dimension (default to using geometric dimension in each axis)
        if value_rank == 0:
            value_shape = ()
        else:
            ufl_assert(
                domain is not None,
                "Cannot infer shape of element without a domain with geometric dimension."
            )
            dim = domain.geometric_dimension()
            value_shape = (dim, ) * value_rank

        # Initialize element data
        super(FiniteElement, self).__init__(family, domain, degree,
                                            quad_scheme, value_shape)

        # Cache repr string
        self._repr = "FiniteElement(%r, %r, %r, %r)" % (
            self.family(), self.domain(), self.degree(),
            self.quadrature_scheme())
Exemplo n.º 10
0
    def __init__(self, family, domain, degree, shape=None,
                 symmetry=None, quad_scheme=None):
        "Create tensor element (repeated mixed element with optional symmetries)"
        if domain is not None:
            domain = as_domain(domain)

        # Set default shape if not specified
        if shape is None:
            ufl_assert(domain is not None,
                       "Cannot infer vector dimension without a domain.")
            dim = domain.geometric_dimension()
            shape = (dim, dim)

        # Construct default symmetry for matrix elements
        if symmetry == True:
            ufl_assert(len(shape) == 2 and shape[0] == shape[1],
                       "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 )

        # Validate indices in symmetry dict
        if isinstance(symmetry, dict):
            for i,j in symmetry.iteritems():
                ufl_assert(len(i) == len(j),
                           "Non-matching length of symmetry index tuples.")
                for k in range(len(i)):
                    ufl_assert(i[k] >= 0 and j[k] >= 0 and
                               i[k] < shape[k] and j[k] < shape[k],
                               "Symmetry dimensions out of bounds.")
        else:
            ufl_assert(symmetry is None, "Expecting symmetry to be None, True, or dict.")

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

        # Compute sub elements and mapping from indices
        # to sub elements, accounting for symmetry
        sub_element = FiniteElement(family, domain, degree, quad_scheme)
        sub_elements = []
        sub_element_mapping = {}
        for index in indices:
            if symmetry and index in symmetry:
                continue
            sub_element_mapping[index] = len(sub_elements)
            sub_elements += [sub_element]

        # Update mapping for symmetry
        for index in indices:
            if symmetry and index in symmetry:
                sub_element_mapping[index] = sub_element_mapping[symmetry[index]]

        # Get common family name (checked in FiniteElement.__init__)
        family = sub_element.family()

        # Compute value shape
        value_shape = shape + sub_element.value_shape()

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

        # Cache repr string
        self._repr = "TensorElement(%r, %r, %r, %r, %r, %r)" % \
            (self._family, self._domain, self._degree, self._shape,
             self._symmetry, quad_scheme)
Exemplo n.º 11
0
    def __init__(self, family, domain=None, degree=None, quad_scheme=None,
                 form_degree=None):
        """Create finite element

        *Arguments*
            family (string)
               The finite element family
            domain
               The geometric domain
            degree (int)
               The polynomial degree (optional)
            quad_scheme
               The quadrature scheme (optional)
            form_degree (int)
               The form degree (FEEC notation, used when field is
               viewed as k-form)
        """
        if domain is None:
            cell = None
        else:
            domain = as_domain(domain)
            cell = domain.cell()
            ufl_assert(cell is not None, "Missing cell in given domain.")

        # Check whether this family is an alias for something else
        if family in aliases:
            (name, cell, r) = aliases[family](family, cell, degree, form_degree)
            #info_blue("%s, is an alias for %s " % (
            #        (family, cell, degree, form_degree),
            #        (name, cell, r)))

            # FIXME: Need to init here with domain instead of using cell from aliases, is that ok?
            ufl_assert(cell == domain.cell(),
                       "Breaking assumption in element alias mapping.")
            self.__init__(name, domain, r, quad_scheme)
            return

        # Check that the element family exists
        ufl_assert(family in ufl_elements,
                   'Unknown finite element "%s".' % family)

        # Check that element data is valid (and also get common family name)
        (family, self._short_name, value_rank, krange, cellnames) =\
            ufl_elements[family]

        # Validate cellname if a valid cell is specified
        cellname = None if cell is None else cell.cellname()
        ufl_assert(cellname in cellnames,
                   'Cellname "%s" invalid for "%s" finite element.' % (cellname, family))

        # Validate degree if specified
        if degree is not None:
            ufl_assert(krange is not None,
                       'Degree "%s" invalid for "%s" finite element, '\
                           'should be None.' % (degree, family))
            kmin, kmax = krange
            ufl_assert(kmin is None or degree >= kmin,
                       'Degree "%s" invalid for "%s" finite element.' %\
                           (degree, family))
            ufl_assert(kmax is None or degree <= kmax,
                   'Degree "%s" invalid for "%s" finite element.' %\
                           (istr(degree), family))

        # Set value dimension (default to using geometric dimension in each axis)
        if value_rank == 0:
            value_shape = ()
        else:
            ufl_assert(domain is not None,
                       "Cannot infer shape of element without a domain with geometric dimension.")
            dim = domain.geometric_dimension()
            value_shape = (dim,)*value_rank

        # Initialize element data
        super(FiniteElement, self).__init__(family, domain, degree,
                                            quad_scheme, value_shape)

        # Cache repr string
        self._repr = "FiniteElement(%r, %r, %r, %r)" % (
            self.family(), self.domain(), self.degree(), self.quadrature_scheme())
Exemplo n.º 12
0
    def __rmul__(self, integrand):
        # Let other types implement multiplication with Measure
        # if they want to (to support the dolfin-adjoint TimeMeasure)
        if not isinstance(integrand, Expr):
            return NotImplemented

        # Allow only scalar integrands
        if not is_true_ufl_scalar(integrand):
            error("Trying to integrate expression of rank %d with free indices %r." \
                  % (integrand.rank(), integrand.free_indices()))

        # Is the measure in a state where multiplication is not allowed?
        if self._domain_description == Measure.DOMAIN_ID_UNDEFINED:
            error("Missing domain id. You need to select a subdomain, " +\
                  "e.g. M = f*dx(0) for subdomain 0.")

        #else: # TODO: Do it this way instead, and move all logic below into preprocess:
        #    # Return a one-integral form:
        #    from ufl.form import Form
        #    return Form( [Integral(integrand, self.domain_type(), self.domain_id(), self.metadata(), self.domain_data())] )
        #    # or if we move domain data into Form instead:
        #    integrals = [Integral(integrand, self.domain_type(), self.domain_id(), self.metadata())]
        #    domain_data = { self.domain_type(): self.domain_data() }
        #    return Form(integrals, domain_data)

        # TODO: How to represent all kinds of domain descriptions is still a bit unclear
        # Create form if we have a sufficient domain description
        elif (  # We have a complete measure with domain description
                isinstance(self._domain_description, DomainDescription)
                # Is the measure in a basic state 'foo*dx'?
                or self._domain_description == Measure.DOMAIN_ID_UNIQUE
                # Is the measure over everywhere?
                or self._domain_description == Measure.DOMAIN_ID_EVERYWHERE
                # Is the measure in a state not allowed prior to preprocessing?
                or self._domain_description == Measure.DOMAIN_ID_OTHERWISE):
            # Create and return a one-integral form
            from ufl.form import Form
            return Form([
                Integral(integrand, self.domain_type(), self.domain_id(),
                         self.metadata(), self.domain_data())
            ])

        # Did we get several ids?
        elif isinstance(self._domain_description, tuple):
            # FIXME: Leave this analysis to preprocessing
            return sum(integrand * self.reconstruct(domain_id=d)
                       for d in self._domain_description)

        # Did we get a name?
        elif isinstance(self._domain_description, str):
            # FIXME: Leave this analysis to preprocessing

            # Get all domains and regions from integrand to analyse
            domains = extract_domains(integrand)

            # Get domain or region with this name from integrand, error if multiple found
            name = self._domain_description
            candidates = set()
            for TD in domains:
                if TD.name() == name:
                    candidates.add(TD)
            ufl_assert(
                len(candidates) > 0,
                "Found no domain with name '%s' in integrand." % name)
            ufl_assert(
                len(candidates) == 1,
                "Multiple distinct domains with same name encountered in integrand."
            )
            D, = candidates

            # Reconstruct measure with the found named domain or region
            measure = self.reconstruct(domain_id=D)
            return integrand * measure

        # Did we get a number?
        elif isinstance(self._domain_description, int):
            # FIXME: Leave this analysis to preprocessing

            # Get all top level domains from integrand to analyse
            domains = extract_top_domains(integrand)

            # Get domain from integrand, error if multiple found
            if len(domains) == 0:
                # This is the partially defined integral from dolfin expression mess
                cell = integrand.cell()
                D = None if cell is None else as_domain(cell)
            elif len(domains) == 1:
                D, = domains
            else:
                error(
                    "Ambiguous reference to integer subdomain with multiple top domains in integrand."
                )

            if D is None:
                # We have a number but not a domain? Leave it to preprocess...
                # This is the case with badly formed forms which can occur from dolfin
                # Create and return a one-integral form
                from ufl.form import Form
                return Form([
                    Integral(integrand, self.domain_type(), self.domain_id(),
                             self.metadata(), self.domain_data())
                ])
            else:
                # Reconstruct measure with the found numbered subdomain
                measure = self.reconstruct(
                    domain_id=D[self._domain_description])
                return integrand * measure

        # Provide error to user
        else:
            error("Invalid domain id %s." % str(self._domain_description))