From fc2f341f63d095272b9ef4a076190cec1baf24dc Mon Sep 17 00:00:00 2001 From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de> Date: Wed, 5 Oct 2016 17:42:48 +0200 Subject: [PATCH] move transformer to ufl and remove separated pymbolic visitor --- python/dune/perftool/pdelab/localoperator.py | 2 +- python/dune/perftool/pymbolic/__init__.py | 0 python/dune/perftool/pymbolic/uflmapper.py | 48 --------------- .../{loopy/transformer.py => ufl/visitor.py} | 61 ++++++++++++++++--- 4 files changed, 55 insertions(+), 56 deletions(-) delete mode 100644 python/dune/perftool/pymbolic/__init__.py delete mode 100644 python/dune/perftool/pymbolic/uflmapper.py rename python/dune/perftool/{loopy/transformer.py => ufl/visitor.py} (89%) diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/perftool/pdelab/localoperator.py index 6773ca1a..b7ad0e72 100644 --- a/python/dune/perftool/pdelab/localoperator.py +++ b/python/dune/perftool/pdelab/localoperator.py @@ -257,7 +257,7 @@ def generate_kernel(integrals): accterms = split_into_accumulation_terms(integrand) # Get a transformer instance for this kernel - from dune.perftool.loopy.transformer import UFL2LoopyVisitor + from dune.perftool.ufl.visitor import UFL2LoopyVisitor visitor = UFL2LoopyVisitor(measure, subdomain_id, dimension_indices) # Iterate over the terms and generate a kernel diff --git a/python/dune/perftool/pymbolic/__init__.py b/python/dune/perftool/pymbolic/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python/dune/perftool/pymbolic/uflmapper.py b/python/dune/perftool/pymbolic/uflmapper.py deleted file mode 100644 index c8f10c79..00000000 --- a/python/dune/perftool/pymbolic/uflmapper.py +++ /dev/null @@ -1,48 +0,0 @@ -""" A multi function mapping UFL expressions to pymbolic expressions - -This mapper only defines handler for those UFL expression types that have an -equivalent in pymbolic (mainly algebraic operations). - -This is mainly intended as a base class for anything mapping ufl to pymbolic. -""" - -from __future__ import absolute_import -from ufl.algorithms import MultiFunction -from pymbolic.primitives import Product, Quotient, Subscript, Sum, Variable, Call - -# The constructed pymbolic expressions use n-ary operators instead of ufls binary operators -from dune.perftool.ufl.flatoperators import get_operands - - -class UFL2PymbolicMapper(MultiFunction): - def __init__(self): - super(UFL2PymbolicMapper, self).__init__() - - call = MultiFunction.__call__ - - def product(self, o): - return Product(tuple(self.call(op) for op in get_operands(o))) - - def float_value(self, o): - return o.value() - - def int_value(self, o): - return o.value() - - def division(self, o): - assert len(o.ufl_operands) == 2 - - return Quotient(self.call(o.ufl_operands[0]), self.call(o.ufl_operands[1])) - - def sum(self, o): - return Sum(tuple(self.call(op) for op in get_operands(o))) - - def zero(self, o): - return 0 - - def abs(self, o): - from ufl.classes import JacobianDeterminant - if isinstance(o.ufl_operands[0], JacobianDeterminant): - return self.call(o.ufl_operands[0]) - else: - return Call('abs', self.call(o.ufl_operands[0])) diff --git a/python/dune/perftool/loopy/transformer.py b/python/dune/perftool/ufl/visitor.py similarity index 89% rename from python/dune/perftool/loopy/transformer.py rename to python/dune/perftool/ufl/visitor.py index a99121b2..cfc03a1f 100644 --- a/python/dune/perftool/loopy/transformer.py +++ b/python/dune/perftool/ufl/visitor.py @@ -1,13 +1,10 @@ """ -This is the module that contains the main transformation from ufl to loopy -(with pdelab as the hardcoded generation target) +This module defines the main visitor algorithm transforming ufl expressions +to pymbolic and loopy. """ -from __future__ import absolute_import - from dune.perftool import Restriction from dune.perftool.ufl.modified_terminals import ModifiedTerminalTracker -from dune.perftool.pymbolic.uflmapper import UFL2PymbolicMapper from dune.perftool.pdelab.geometry import GeometryMapper from dune.perftool.generation import (domain, get_temporary_name, @@ -27,9 +24,9 @@ from dune.perftool.pdelab.basis import (lfs_iname, ) from dune.perftool.pdelab.quadrature import quadrature_iname from pymbolic.primitives import Subscript, Variable +from ufl.algorithms import MultiFunction - -class UFL2LoopyVisitor(ModifiedTerminalTracker, UFL2PymbolicMapper, GeometryMapper): +class UFL2LoopyVisitor(ModifiedTerminalTracker, GeometryMapper): def __init__(self, measure, subdomain_id, dimension_indices): # Some variables describing the integral measure of this integral self.measure = measure @@ -39,6 +36,9 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker, UFL2PymbolicMapper, GeometryMapp # Call base class constructors super(UFL2LoopyVisitor, self).__init__() + # Allow recursion through self.call(..) + call = MultiFunction.__call__ + def __call__(self, o): # Reset some state variables that are reinitialized for each accumulation term self.argshape = 0 @@ -166,6 +166,11 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker, UFL2PymbolicMapper, GeometryMapp predicates=predicates ) + # + # Form argument/coefficients handlers: + # This is where the actual domain specific work happens + # + def argument(self, o): # Correct the restriction on boundary integrals restriction = self.restriction @@ -260,6 +265,10 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker, UFL2PymbolicMapper, GeometryMapp # And return a symbol return Variable(name) + # + # Handlers for all indexing related stuff + # + def indexed(self, o): """ Although indexed is something that we want to handle in the pymbolic mapper we need to handle it here, as we have to give special treatment to indices into vector @@ -334,3 +343,41 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker, UFL2PymbolicMapper, GeometryMapp def index(self, o): return self._index_or_fixed_index(o) + + # + # Handlers for arithmetic operators and functions + # Those handlers would be valid in any code going from UFL to pymbolic + # + + def product(self, o): + from dune.perftool.ufl.flatoperators import get_operands + from pymbolic.primitives import Product + return Product(tuple(self.call(op) for op in get_operands(o))) + + def float_value(self, o): + return o.value() + + def int_value(self, o): + return o.value() + + def division(self, o): + assert len(o.ufl_operands) == 2 + + from pymbolic.primitives import Quotient + return Quotient(self.call(o.ufl_operands[0]), self.call(o.ufl_operands[1])) + + def sum(self, o): + from dune.perftool.ufl.flatoperators import get_operands + from pymbolic.primitives import Sum + return Sum(tuple(self.call(op) for op in get_operands(o))) + + def zero(self, o): + return 0 + + def abs(self, o): + from ufl.classes import JacobianDeterminant + if isinstance(o.ufl_operands[0], JacobianDeterminant): + return self.call(o.ufl_operands[0]) + else: + from pymbolic.primitives import Call + return Call('abs', self.call(o.ufl_operands[0])) -- GitLab