From 3b25ffbab6cb6edf0c0ce4f8e08101f03284ce34 Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Thu, 1 Feb 2018 13:25:00 +0100
Subject: [PATCH] Allow construction of higher diffOrder grid functions

---
 python/dune/perftool/pdelab/__init__.py      |  4 +++
 python/dune/perftool/pdelab/basis.py         | 21 ++++++++++++
 python/dune/perftool/pdelab/localoperator.py | 35 ++++++++++++++------
 python/dune/perftool/ufl/visitor.py          | 12 +++----
 4 files changed, 55 insertions(+), 17 deletions(-)

diff --git a/python/dune/perftool/pdelab/__init__.py b/python/dune/perftool/pdelab/__init__.py
index 929a5879..3a224222 100644
--- a/python/dune/perftool/pdelab/__init__.py
+++ b/python/dune/perftool/pdelab/__init__.py
@@ -12,6 +12,7 @@ from dune.perftool.pdelab.argument import (pymbolic_apply_function,
                                            )
 from dune.perftool.pdelab.basis import (pymbolic_basis,
                                         pymbolic_reference_gradient,
+                                        pymbolic_evaluate_gridfunction,
                                         )
 from dune.perftool.pdelab.geometry import (component_iname,
                                            pymbolic_cell_volume,
@@ -98,6 +99,9 @@ class PDELabInterface(object):
     def pymbolic_apply_function(self, element, restriction, index):
         return pymbolic_apply_function(self.visitor, element, restriction, index)
 
+    def pymbolic_evaluate_gridfunction(self, coeff, restriction, grad):
+        return pymbolic_evaluate_gridfunction(self.visitor, coeff, restriction, grad)
+
     #
     # Tensor expression related generator functions
     #
diff --git a/python/dune/perftool/pdelab/basis.py b/python/dune/perftool/pdelab/basis.py
index 53917205..b2593874 100644
--- a/python/dune/perftool/pdelab/basis.py
+++ b/python/dune/perftool/pdelab/basis.py
@@ -6,6 +6,7 @@ from dune.perftool.generation import (backend,
                                       include_file,
                                       instruction,
                                       kernel_cached,
+                                      preamble,
                                       temporary_variable,
                                       )
 from dune.perftool.options import (option_switch,
@@ -23,6 +24,7 @@ from dune.perftool.pdelab.geometry import (component_iname,
                                            world_dimension,
                                            name_jacobian_inverse_transposed,
                                            to_cell_coordinates,
+                                           name_cell,
                                            )
 from dune.perftool.pdelab.localoperator import (lop_template_ansatz_gfs,
                                                 lop_template_test_gfs,
@@ -227,3 +229,22 @@ def evaluate_coefficient_gradient(visitor, element, name, container, restriction
                 forced_iname_deps=frozenset(get_backend("quad_inames")()).union(frozenset({dimindex})),
                 forced_iname_deps_is_final=True,
                 )
+
+
+@preamble
+def bind_gridfunction_to_element(gf, restriction):
+    element = name_cell(restriction)
+    return "localFunction({}).bind({});".format(gf, element)
+
+
+def pymbolic_evaluate_gridfunction(visitor, coeff, restriction, grad):
+    diffOrder = 1 if grad else 0
+
+    from dune.perftool.pdelab.localoperator import name_gridfunction_member
+    gridfunction = name_gridfunction_member(coeff, diffOrder)
+
+    bind_gridfunction_to_element(gridfunction, restriction)
+
+    # Foobar!
+    visitor.indices = None
+    return 1
diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/perftool/pdelab/localoperator.py
index 336062fc..dffc7c88 100644
--- a/python/dune/perftool/pdelab/localoperator.py
+++ b/python/dune/perftool/pdelab/localoperator.py
@@ -157,24 +157,37 @@ def localoperator_basename(form_ident):
     return get_form_option("classname", form_ident)
 
 
-def name_gridfunction_member(coeff):
-    name = "gridfunction_{}".format(coeff.count())
-    define_gridfunction_member(name)
+def name_gridfunction_member(coeff, diffOrder=0):
+    name = "gridfunction_coeff{}_diff{}".format(coeff.count(), diffOrder)
+    define_gridfunction_member(name, coeff, diffOrder)
+    return name
+
+
+def name_gridfunction_constructor_argument(coeff):
+    _type = type_gridfunction_template_parameter(coeff)
+    name = "gridfunction_coeff{}_".format(coeff.count())
+    constructor_parameter("const {}&".format(_type), name, classtag="operator")
     return name
 
 
 @class_member(classtag="operator")
-def define_gridfunction_member(name):
-    _type = type_gridfunction_template_parameter(name)
-    param = "{}_".format(name)
-    constructor_parameter("const {}&".format(_type), param, classtag="operator")
-    initializer_list(name, [param], classtag="operator")
-    return "const {}& {};".format(_type, name)
+def define_gridfunction_member(name, coeff, diffOrder):
+    _type = type_gridfunction_template_parameter(coeff)
+    param = name_gridfunction_constructor_argument(coeff)
+    if diffOrder > 0:
+        include_file("dune/pdelab/function/discretegridviewfunction.hh", filetag="operatorfile")
+        newtype = "Dune::PDELab::DiscreteGridViewFunction<typename {0}::GridFunctionSpace, typename {0}::Vector, {1}>".format(_type, diffOrder)
+        params = ["{}.gridFunctionSpace()".format(param), "{}.dofs()".format(param)]
+        initializer_list(name, params, classtag="operator")
+        return "{} {};".format(_type, name)
+    else:
+        initializer_list(name, [param], classtag="operator")
+        return "const {}& {};".format(_type, name)
 
 
 @template_parameter(classtag="operator")
-def type_gridfunction_template_parameter(name):
-    return name.upper()
+def type_gridfunction_template_parameter(coeff):
+    return "GRIDFUNCTION_COEFF{}".format(coeff.count())
 
 
 def class_type_from_cache(classtag):
diff --git a/python/dune/perftool/ufl/visitor.py b/python/dune/perftool/ufl/visitor.py
index 6b4db02f..153f9713 100644
--- a/python/dune/perftool/ufl/visitor.py
+++ b/python/dune/perftool/ufl/visitor.py
@@ -127,13 +127,13 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker):
             return self.interface.pymbolic_basis(leaf_element, restriction, o.number())
 
     def coefficient(self, o):
+        # Correct the restriction on boundary integrals
+        restriction = self.restriction
+        if self.measure == 'exterior_facet':
+            restriction = Restriction.NEGATIVE
+
         # Do something different for trial function and coefficients from jacobian apply
         if o.count() == 0 or o.count() == 1:
-            # Correct the restriction on boundary integrals
-            restriction = self.restriction
-            if self.measure == 'exterior_facet':
-                restriction = Restriction.NEGATIVE
-
             self.interface.initialize_function_spaces(o, self)
 
             index = None
@@ -164,7 +164,7 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker):
             # and exports it through a getter method 'getTime'
             return prim.Call(prim.Variable("getTime"), ())
         else:
-            raise NotImplementedError("General Coefficients")
+            return self.interface.pymbolic_evaluate_gridfunction(o, restriction, self.reference_grad)
 
     #
     # Handlers for all indexing related stuff
-- 
GitLab