Ejemplo n.º 1
0
def expression_replace(expression, replacements):
    replaced_expression = replace(expression, replacements)
    replaced_expression_domains = extract_domains(replaced_expression)
    assert len(replaced_expression_domains) in (0, 1)
    expression_domains = extract_domains(expression)
    assert len(expression_domains) in (0, 1)
    assert len(expression_domains) == len(replaced_expression_domains)
    if len(expression_domains) == 1:
        assert replaced_expression_domains[0] is not expression_domains[0]
    return replaced_expression
Ejemplo n.º 2
0
def _generate_space(expression: Operator):
    # Extract mesh from expression (from dolfin/fem/projection.py, _extract_function_space function)
    meshes = set(
        [ufl_domain.ufl_cargo() for ufl_domain in extract_domains(expression)])
    for t in traverse_unique_terminals(
            expression):  # from ufl/domain.py, extract_domains
        if hasattr(t, "_mesh"):
            meshes.add(t._mesh)
    assert len(meshes) == 1
    mesh = meshes.pop()
    # The EIM algorithm will evaluate the expression at vertices. However, since the Operator expression may
    # contain e.g. a gradient of a solution defined in a C^0 space, we resort to DG1 spaces.
    shape = expression.ufl_shape
    assert len(shape) in (0, 1, 2)
    if len(shape) == 0:
        space = FunctionSpace(mesh, "Discontinuous Lagrange", 1)
    elif len(shape) == 1:
        space = VectorFunctionSpace(mesh,
                                    "Discontinuous Lagrange",
                                    1,
                                    dim=shape[0])
    elif len(shape) == 2:
        space = TensorFunctionSpace(mesh,
                                    "Discontinuous Lagrange",
                                    1,
                                    shape=shape)
    else:
        raise ValueError(
            "Invalid expression in ParametrizedExpressionFactory.__init__().")
    return space
Ejemplo n.º 3
0
def form_replace(form, replacements, replacement_type="nodes"):
    assert replacement_type in ("nodes", "measures")
    if replacement_type == "nodes":
        replaced_form = replace(form, replacements)
        for (integral, replaced_integral) in zip(form.integrals(), replaced_form.integrals()):
            replaced_integral_domains = extract_domains(replaced_integral.integrand())
            assert len(replaced_integral_domains) == 1
            integral_domains = extract_domains(integral.integrand())
            assert len(integral_domains) == 1
            assert replaced_integral_domains[0] is not integral_domains[0]
        return replaced_form
    elif replacement_type == "measures":
        replaced_form = 0
        for integral in form.integrals():
            measure = replacements[integral.integrand(), integral.integral_type(), integral.subdomain_id()]
            replaced_form += integral.integrand() * measure
        return replaced_form
    else:
        raise ValueError("Invalid replacement type")
Ejemplo n.º 4
0
def jump(v, n=None):
    "UFL operator: Take the jump of *v* across a facet."
    v = as_ufl(v)
    is_constant = len(extract_domains(v)) > 0
    if is_constant:
        if n is None:
            return v('+') - v('-')
        r = len(v.ufl_shape)
        if r == 0:
            return v('+') * n('+') + v('-') * n('-')
        else:
            return dot(v('+'), n('+')) + dot(v('-'), n('-'))
    else:
        warning("Returning zero from jump of expression without a domain. This may be erroneous if a dolfin.Expression is involved.")
        # FIXME: Is this right? If v has no domain, it doesn't depend
        # on anything spatially variable or any form arguments, and
        # thus the jump is zero. In other words, I'm assuming that "v
        # has no geometric domains" is equivalent with "v is a spatial
        # constant".  Update: This is NOT true for
        # jump(Expression("x[0]")) from dolfin.
        return Zero(v.ufl_shape, v.ufl_free_indices, v.ufl_index_dimensions)
Ejemplo n.º 5
0
def jump(v, n=None):
    "UFL operator: Take the jump of *v* across a facet."
    v = as_ufl(v)
    is_constant = len(extract_domains(v)) > 0
    if is_constant:
        if n is None:
            return v('+') - v('-')
        r = len(v.ufl_shape)
        if r == 0:
            return v('+') * n('+') + v('-') * n('-')
        else:
            return dot(v('+'), n('+')) + dot(v('-'), n('-'))
    else:
        warning("Returning zero from jump of expression without a domain. This may be erroneous if a dolfin.Expression is involved.")
        # FIXME: Is this right? If v has no domain, it doesn't depend
        # on anything spatially variable or any form arguments, and
        # thus the jump is zero. In other words, I'm assuming that "v
        # has no geometric domains" is equivalent with "v is a spatial
        # constant".  Update: This is NOT true for
        # jump(Expression("x[0]")) from dolfin.
        return Zero(v.ufl_shape, v.ufl_free_indices, v.ufl_index_dimensions)
Ejemplo n.º 6
0
    def __rmul__(self, integrand):
        """Multiply a scalar expression with measure to construct a form with
        a single integral.

        This is to implement the notation

            form = integrand * self

        Integration properties are taken from this Measure object.

        """
        # Avoid circular imports
        from ufl.integral import Integral
        from ufl.form import Form

        # Allow python literals: 1*dx and 1.0*dx
        if isinstance(integrand, (int, float)):
            integrand = as_ufl(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("Can only integrate scalar expressions. The integrand is a "
                  "tensor expression with value shape %s and free indices with labels %s." %
                  (integrand.ufl_shape, integrand.ufl_free_indices))

        # If we have a tuple of domain ids, delegate composition to
        # Integral.__add__:
        subdomain_id = self.subdomain_id()
        if isinstance(subdomain_id, tuple):
            return sum(integrand*self.reconstruct(subdomain_id=d) for d in subdomain_id)

        # Check that we have an integer subdomain or a string
        # ("everywhere" or "otherwise", any more?)
        if not isinstance(subdomain_id, (str, numbers.Integral,)):
            error("Expecting integer or string domain id.")

        # If we don't have an integration domain, try to find one in
        # integrand
        domain = self.ufl_domain()
        if domain is None:
            domains = extract_domains(integrand)
            if len(domains) == 1:
                domain, = domains
            elif len(domains) == 0:
                error("This integral is missing an integration domain.")
            else:
                error("Multiple domains found, making the choice of integration domain ambiguous.")

        # Otherwise create and return a one-integral form
        integral = Integral(integrand=integrand,
                            integral_type=self.integral_type(),
                            domain=domain,
                            subdomain_id=subdomain_id,
                            metadata=self.metadata(),
                            subdomain_data=self.subdomain_data())
        return Form([integral])
Ejemplo n.º 7
0
 def ufl_domains(
         self):  # TODO: Deprecate this and use extract_domains(expr)
     "Return all domains this expression is defined on."
     from ufl.domain import extract_domains
     return extract_domains(self)
Ejemplo n.º 8
0
Archivo: expr.py Proyecto: FEniCS/ufl
 def ufl_domains(self):  # TODO: Deprecate this and use extract_domains(expr)
     "Return all domains this expression is defined on."
     from ufl.domain import extract_domains
     return extract_domains(self)