def compute_form_with_arity(form, arity, arguments=None): """Compute parts of form of given arity.""" # Extract all arguments in form if arguments is None: arguments = form.arguments() parts = [arg.part() for arg in arguments] if set(parts) - {None}: error("compute_form_with_arity cannot handle parts.") if len(arguments) < arity: warning("Form has no parts with arity %d." % arity) return 0*form # Assuming that the form is not a sum of terms # that depend on different arguments, e.g. (u+v)*dx # would result in just v*dx. But that doesn't make # any sense anyway. sub_arguments = set(arguments[:arity]) pe = PartExtracter(sub_arguments) def _transform(e): e, provides = pe.visit(e) if provides == sub_arguments: return e return Zero() return map_integrands(_transform, form)
def compute_form_adjoint(form, reordered_arguments=None): """Compute the adjoint of a bilinear form. This works simply by swapping the number and part of the two arguments, but keeping their elements and places in the integrand expressions. """ arguments = form.arguments() parts = [arg.part() for arg in arguments] if set(parts) - {None}: error("compute_form_adjoint cannot handle parts.") if len(arguments) != 2: error("Expecting bilinear form.") v, u = arguments if v.number() >= u.number(): error("Mistaken assumption in code!") if reordered_arguments is None: reordered_u = Argument(u.ufl_function_space(), number=v.number(), part=v.part()) reordered_v = Argument(v.ufl_function_space(), number=u.number(), part=u.part()) else: reordered_u, reordered_v = reordered_arguments if reordered_u.number() >= reordered_v.number(): error("Ordering of new arguments is the same as the old arguments!") if reordered_u.part() != v.part(): error("Ordering of new arguments is the same as the old arguments!") if reordered_v.part() != u.part(): error("Ordering of new arguments is the same as the old arguments!") if reordered_u.ufl_function_space() != u.ufl_function_space(): error( "Element mismatch between new and old arguments (trial functions)." ) if reordered_v.ufl_function_space() != v.ufl_function_space(): error( "Element mismatch between new and old arguments (test functions).") return map_integrands(Conj, replace(form, { v: reordered_v, u: reordered_u }))
def diff(f, v): """UFL operator: Take the derivative of *f* with respect to the variable *v*. If *f* is a form, ``diff`` is applied to each integrand. """ # Apply to integrands if isinstance(f, Form): from ufl.algorithms.map_integrands import map_integrands return map_integrands(lambda e: diff(e, v), f) # Apply to expression f = as_ufl(f) if isinstance(v, SpatialCoordinate): return grad(f) elif isinstance(v, (Variable, Coefficient)): return VariableDerivative(f, v) else: error("Expecting a Variable or SpatialCoordinate in diff.")
def compute_form_adjoint(form, reordered_arguments=None): """Compute the adjoint of a bilinear form. This works simply by swapping the number and part of the two arguments, but keeping their elements and places in the integrand expressions. """ arguments = form.arguments() parts = [arg.part() for arg in arguments] if set(parts) - {None}: error("compute_form_adjoint cannot handle parts.") if len(arguments) != 2: error("Expecting bilinear form.") v, u = arguments if v.number() >= u.number(): error("Mistaken assumption in code!") if reordered_arguments is None: reordered_u = Argument(u.ufl_function_space(), number=v.number(), part=v.part()) reordered_v = Argument(v.ufl_function_space(), number=u.number(), part=u.part()) else: reordered_u, reordered_v = reordered_arguments if reordered_u.number() >= reordered_v.number(): error("Ordering of new arguments is the same as the old arguments!") if reordered_u.part() != v.part(): error("Ordering of new arguments is the same as the old arguments!") if reordered_v.part() != u.part(): error("Ordering of new arguments is the same as the old arguments!") if reordered_u.ufl_function_space() != u.ufl_function_space(): error("Element mismatch between new and old arguments (trial functions).") if reordered_v.ufl_function_space() != v.ufl_function_space(): error("Element mismatch between new and old arguments (test functions).") return map_integrands(Conj, replace(form, {v: reordered_v, u: reordered_u}))
def apply_transformer(e, transformer, integral_type=None): """Apply transformer.visit(expression) to each integrand expression in form, or to form if it is an Expr.""" return map_integrands(lambda expr: transformer.visit(expr), e, integral_type)