Source code for ufl.algorithms.map_integrands
"""Basic algorithms for applying functions to sub-expressions."""
# Copyright (C) 2008-2016 Martin Sandve Alnæs
#
# This file is part of UFL (https://www.fenicsproject.org)
#
# SPDX-License-Identifier: LGPL-3.0-or-later
# NOTE: Placing this under algorithms/ because I want corealg/ to stay clean
# as part of a careful refactoring process, and this file depends on ufl.form
# which drags in a lot of stuff.
from ufl.action import Action
from ufl.adjoint import Adjoint
from ufl.constantvalue import Zero
from ufl.core.expr import Expr
from ufl.corealg.map_dag import map_expr_dag
from ufl.form import BaseForm, Form, FormSum, ZeroBaseForm
from ufl.integral import Integral
[docs]def map_integrands(function, form, only_integral_type=None):
"""Map integrands.
Apply transform(expression) to each integrand expression in form, or
to form if it is an Expr.
"""
if isinstance(form, Form):
mapped_integrals = [
map_integrands(function, itg, only_integral_type) for itg in form.integrals()
]
nonzero_integrals = [
itg for itg in mapped_integrals if not isinstance(itg.integrand(), Zero)
]
return Form(nonzero_integrals)
elif isinstance(form, Integral):
itg = form
if (only_integral_type is None) or (itg.integral_type() in only_integral_type):
return itg.reconstruct(function(itg.integrand()))
else:
return itg
elif isinstance(form, FormSum):
mapped_components = [
map_integrands(function, component, only_integral_type)
for component in form.components()
]
nonzero_components = [
(component, w)
for component, w in zip(mapped_components, form.weights())
# Catch ufl.Zero and ZeroBaseForm
if component != 0
]
# Simplify case with one nonzero component and the corresponding weight is 1
if len(nonzero_components) == 1 and nonzero_components[0][1] == 1:
return nonzero_components[0][0]
if all(not isinstance(component, BaseForm) for component, _ in nonzero_components):
# Simplification of `BaseForm` objects may turn `FormSum` into a sum of `Expr` objects
# that are not `BaseForm`, i.e. into a `Sum` object.
# Example: `Action(Adjoint(c*), u)` with `c*` a `Coargument` and u a `Coefficient`.
return sum([component for component, _ in nonzero_components])
return FormSum(*nonzero_components)
elif isinstance(form, Adjoint):
# Zeros are caught inside `Adjoint.__new__`
return Adjoint(map_integrands(function, form._form, only_integral_type))
elif isinstance(form, Action):
left = map_integrands(function, form._left, only_integral_type)
right = map_integrands(function, form._right, only_integral_type)
# Zeros are caught inside `Action.__new__`
return Action(left, right)
elif isinstance(form, ZeroBaseForm):
arguments = tuple(
map_integrands(function, arg, only_integral_type) for arg in form._arguments
)
return ZeroBaseForm(arguments)
elif isinstance(form, (Expr, BaseForm)):
integrand = form
return function(integrand)
else:
raise ValueError("Expecting Form, Integral or Expr.")
[docs]def map_integrand_dags(function, form, only_integral_type=None, compress=True):
"""Map integrand dags."""
return map_integrands(
lambda expr: map_expr_dag(function, expr, compress), form, only_integral_type
)