Source code for ufl.algorithms.balancing

# -*- coding: utf-8 -*-
# Copyright (C) 2011-2017 Martin Sandve Alnæs
#
# This file is part of UFL (https://www.fenicsproject.org)
#
# SPDX-License-Identifier:    LGPL-3.0-or-later

from ufl.classes import (CellAvg, FacetAvg, Grad, Indexed, NegativeRestricted,
                         PositiveRestricted, ReferenceGrad, ReferenceValue)
from ufl.corealg.map_dag import map_expr_dag
from ufl.corealg.multifunction import MultiFunction

modifier_precedence = [
    ReferenceValue, ReferenceGrad, Grad, CellAvg, FacetAvg, PositiveRestricted,
    NegativeRestricted, Indexed
]

modifier_precedence = {
    m._ufl_handler_name_: i
    for i, m in enumerate(modifier_precedence)
}


[docs]def balance_modified_terminal(expr): # NB! Assuming e.g. grad(cell_avg(expr)) does not occur, # i.e. it is simplified to 0 immediately. if expr._ufl_is_terminal_: return expr assert expr._ufl_is_terminal_modifier_ orig = expr # Build list of modifier layers layers = [expr] while not expr._ufl_is_terminal_: assert expr._ufl_is_terminal_modifier_ expr = expr.ufl_operands[0] layers.append(expr) assert layers[-1] is expr assert expr._ufl_is_terminal_ # Apply modifiers in order layers = sorted( layers[:-1], key=lambda e: modifier_precedence[e._ufl_handler_name_]) for op in layers: ops = (expr, ) + op.ufl_operands[1:] expr = op._ufl_expr_reconstruct_(*ops) # Preserve id if nothing has changed return orig if expr == orig else expr
[docs]class BalanceModifiers(MultiFunction):
[docs] def expr(self, expr, *ops): return expr._ufl_expr_reconstruct_(*ops)
[docs] def terminal(self, expr): return expr
def _modifier(self, expr, *ops): return balance_modified_terminal(expr) reference_value = _modifier reference_grad = _modifier grad = _modifier cell_avg = _modifier facet_avg = _modifier positive_restricted = _modifier negative_restricted = _modifier
[docs]def balance_modifiers(expr): mf = BalanceModifiers() return map_expr_dag(mf, expr)