Example #1
0
def derivative(form, coefficient, argument=None, coefficient_derivatives=None):
    """UFL form operator:
    Compute the Gateaux derivative of *form* w.r.t. *coefficient* in direction
    of *argument*.

    If the argument is omitted, a new ``Argument`` is created
    in the same space as the coefficient, with argument number
    one higher than the highest one in the form.

    The resulting form has one additional ``Argument``
    in the same finite element space as the coefficient.

    A tuple of ``Coefficient`` s may be provided in place of
    a single ``Coefficient``, in which case the new ``Argument``
    argument is based on a ``MixedElement`` created from this tuple.

    An indexed ``Coefficient`` from a mixed space may be provided,
    in which case the argument should be in the corresponding
    subspace of the coefficient space.

    If provided, *coefficient_derivatives* should be a mapping from
    ``Coefficient`` instances to their derivatives w.r.t. *coefficient*.
    """

    coefficients, arguments = _handle_derivative_arguments(form, coefficient,
                                                           argument)

    if coefficient_derivatives is None:
        coefficient_derivatives = ExprMapping()
    else:
        cd = []
        for k in sorted_expr(coefficient_derivatives.keys()):
            cd += [as_ufl(k), as_ufl(coefficient_derivatives[k])]
        coefficient_derivatives = ExprMapping(*cd)

    # Got a form? Apply derivatives to the integrands in turn.
    if isinstance(form, Form):
        integrals = []
        for itg in form.integrals():
            if not isinstance(coefficient, SpatialCoordinate):
                fd = CoefficientDerivative(itg.integrand(), coefficients,
                                           arguments, coefficient_derivatives)
            else:
                fd = CoordinateDerivative(itg.integrand(), coefficients,
                                          arguments, coefficient_derivatives)
            integrals.append(itg.reconstruct(fd))
        return Form(integrals)

    elif isinstance(form, Expr):
        # What we got was in fact an integrand
        if not isinstance(coefficient, SpatialCoordinate):
            return CoefficientDerivative(form, coefficients,
                                         arguments, coefficient_derivatives)
        else:
            return CoordinateDerivative(form, coefficients,
                                        arguments, coefficient_derivatives)

    error("Invalid argument type %s." % str(type(form)))
 def coordinate_derivative(self, o, f, dummy_w, dummy_v, dummy_cd):
     o_ = o.ufl_operands
     key = (CoordinateDerivative, o_[0])
     return CoordinateDerivative(map_expr_dag(self, o_[0],
                                              vcache=self.vcaches[key],
                                              rcache=self.rcaches[key]),
                                 o_[1], o_[2], o_[3])
Example #3
0
 def scale_coordinate_derivative(o, scale):
     o_ = o.ufl_operands
     if isinstance(o, CoordinateDerivative):
         return CoordinateDerivative(
             scale_coordinate_derivative(o_[0], scale), o_[1], o_[2],
             o_[3])
     else:
         return scale * o
def attach_coordinate_derivatives(integral, coordinate_derivatives):
    if coordinate_derivatives is None:
        return integral

    if isinstance(integral, Integral):
        integrand = integral.integrand()
        # apply the stored coordinate derivatives back onto the integrand
        for tup in reversed(coordinate_derivatives):
            integrand = CoordinateDerivative(integrand, tup[0], tup[1], tup[2])
        return integral.reconstruct(integrand=integrand)
    else:
        error("Invalid type %s" % (integral.__class__.__name__,))
Example #5
0
def attach_coordinate_derivatives(form, coordinate_derivatives):
    if coordinate_derivatives is None:
        return form

    if isinstance(form, Form):
        cds = coordinate_derivatives
        new_integrals = [attach_coordinate_derivatives(integ, cds) for integ in form.integrals()]
        return Form(new_integrals)

    elif isinstance(form, Integral):
        integral = form
        integrand = integral.integrand()
        # apply the stored coordinate derivatives back onto the integrand
        for tup in reversed(coordinate_derivatives):
            integrand = CoordinateDerivative(integrand, tup[0], tup[1], tup[2])
        return integral.reconstruct(integrand=integrand)
    else:
        error("Invalid type %s" % (form.__class__.__name__,))
Example #6
0
 def coordinate_derivative(self, o, f, dummy_w, dummy_v, dummy_cd):
     o_ = o.ufl_operands
     return CoordinateDerivative(map_expr_dag(self, o_[0]), o_[1], o_[2],
                                 o_[3])
Example #7
0
 def coordinate_derivative(self, o):
     o = o.ufl_operands
     return CoordinateDerivative(map_expr_dag(self, o[0]), o[1], o[2], o[3])