From 5ef2b1de08be8288d21417eea71baac240ef5644 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20He=C3=9F?= <rene.hess@iwr.uni-heidelberg.de>
Date: Mon, 26 Aug 2019 14:38:03 +0200
Subject: [PATCH] [skip ci] Big code cleanup and bugfix

---
 python/dune/codegen/pdelab/driver/error.py    |  55 +---
 .../codegen/pdelab/driver/instationary.py     |   5 +-
 .../dune/codegen/pdelab/driver/interpolate.py | 295 +++++++++---------
 3 files changed, 153 insertions(+), 202 deletions(-)

diff --git a/python/dune/codegen/pdelab/driver/error.py b/python/dune/codegen/pdelab/driver/error.py
index c9f3a6b8..523caeec 100644
--- a/python/dune/codegen/pdelab/driver/error.py
+++ b/python/dune/codegen/pdelab/driver/error.py
@@ -16,8 +16,8 @@ from dune.codegen.pdelab.driver.gridfunctionspace import (main_type_trial_gfs,
                                                           main_type_subgfs,
                                                           )
 from dune.codegen.pdelab.driver.interpolate import (interpolate_vector,
-                                                    main_name_boundary_grid_function,
-                                                    main_type_boundary_grid_function,
+                                                    main_name_grid_function,
+                                                    main_type_grid_function,
                                                     )
 from dune.codegen.pdelab.driver.solve import (define_vector,
                                               dune_solve,
@@ -38,46 +38,6 @@ def name_test_fail_variable():
     return name
 
 
-@preamble(section="error", kernel="main")
-def main_typedef_exact_solution_grid_function(name, treepath):
-    # palpo TODO
-    solution_type = main_type_boundary_grid_function()
-    # solution_type = "BoundaryGridFunction"
-    if len(treepath) > 0:
-        solution_type = "Dune::TypeTree::Child<{}, {}>;".format(solution_type, ", ".join(str(t) for t in treepath))
-    return "using {} = {};".format(name, solution_type)
-
-
-def main_type_exact_solution_grid_function(treepath):
-    name = "ExactSolution"
-    if len(treepath) > 0:
-        name = "{}_{}".format(name, "_".join(str(t) for t in treepath))
-    main_typedef_exact_solution_grid_function(name, treepath)
-    return name
-
-
-@preamble(section="error", kernel="main")
-def main_define_exact_solution_grid_function(name, treepath):
-    element = get_trial_element()
-    func = preprocess_leaf_data(element, "exact_solution")
-    # palpo TODO
-    # boundary_gf = "boundaryGridFunction"
-    boundary_gf = main_name_boundary_grid_function(element, func)
-    if len(treepath) == 0:
-        return "auto {} = *{};".format(name, boundary_gf)
-    else:
-        indices = ["Dune::Indices::_{}".format(str(t)) for t in treepath]
-        return "auto {} = child(*{}, {});".format(name, boundary_gf, ", ".join(i for i in indices))
-
-
-def main_name_exact_solution_grid_function(treepath):
-    name = "exactSolution"
-    if len(treepath) > 0:
-        name = "{}_{}".format(name, "_".join(str(t) for t in treepath))
-    main_define_exact_solution_grid_function(name, treepath)
-    return name
-
-
 def type_discrete_grid_function(treepath):
     name = "DiscreteGridFunction_{}".format("_".join(str(t) for t in treepath))
     return name
@@ -109,14 +69,7 @@ def name_discrete_grid_function(gfs, vector_name, treepath):
 
 @preamble(section="error", kernel="main")
 def typedef_difference_squared_adapter(name, treepath):
-    # Grid function representing exact solution
-    # element = get_trial_element()
-    # func = preprocess_leaf_data(element, "exact_solution")
-    # if isinstance(element, MixedElement):
-    #     index = treepath_to_index(element, treepath)
-    #     func = (func[index],)
-    #     element = element.extract_component(index)[1]
-    bgf_type = main_type_exact_solution_grid_function(treepath)
+    bgf_type = main_type_grid_function("exact_solution", treepath)
 
     # Discrete grid function (numerical solution)
     gfs = main_name_trial_subgfs(treepath)
@@ -136,7 +89,7 @@ def type_difference_squared_adapter(treepath):
 @preamble(section="error", kernel="main")
 def define_difference_squared_adapter(name, treepath):
     t = type_difference_squared_adapter(treepath)
-    sol = main_name_exact_solution_grid_function(treepath)
+    sol = main_name_grid_function("exact_solution", treepath)
     vector = main_name_vector(get_form_ident())
     gfs = main_name_trial_subgfs(treepath)
     dgf = name_discrete_grid_function(gfs, vector, treepath)
diff --git a/python/dune/codegen/pdelab/driver/instationary.py b/python/dune/codegen/pdelab/driver/instationary.py
index 3f203c86..c8edb474 100644
--- a/python/dune/codegen/pdelab/driver/instationary.py
+++ b/python/dune/codegen/pdelab/driver/instationary.py
@@ -19,7 +19,7 @@ from dune.codegen.pdelab.driver.constraints import (has_dirichlet_constraints,
                                                     name_constraintscontainer,
                                                     )
 from dune.codegen.pdelab.driver.interpolate import (interpolate_dirichlet_data,
-                                                    name_boundary_grid_function,
+                                                    name_grid_function_root,
                                                     )
 from dune.codegen.pdelab.driver.solve import (print_matrix,
                                               print_residual,
@@ -79,8 +79,7 @@ def time_loop():
     else:
         osm = name_onestepmethod()
     if has_dirichlet_constraints(is_dirichlet):
-        dirichlet = preprocess_leaf_data(element, "interpolate_expression")
-        boundary = name_boundary_grid_function(element, dirichlet)
+        boundary = name_boundary_grid_function_root("interpolate_expression")
         apply_call = "{}.apply(time, dt, {}, {}, {}new);".format(osm, vector, boundary, vector)
     else:
         apply_call = "{}.apply(time, dt, {}, {}new);".format(osm, vector, vector)
diff --git a/python/dune/codegen/pdelab/driver/interpolate.py b/python/dune/codegen/pdelab/driver/interpolate.py
index 40fddda5..6a52f485 100644
--- a/python/dune/codegen/pdelab/driver/interpolate.py
+++ b/python/dune/codegen/pdelab/driver/interpolate.py
@@ -21,109 +21,155 @@ from dune.codegen.pdelab.driver.gridfunctionspace import (name_trial_gfs,
 from ufl import FiniteElement, MixedElement, TensorElement, VectorElement, TensorProductElement
 
 
+@preamble(section="vector", kernel="driver_block")
+def interpolate_vector(func, gfs, name):
+    return "Dune::PDELab::interpolate(*{}, *{}, *{});".format(func,
+                                                              gfs,
+                                                              name,
+                                                              )
+
+
 def interpolate_dirichlet_data(name):
     element = get_trial_element()
     func = preprocess_leaf_data(element, "interpolate_expression", applyZeroDefault=False)
     if func is not None:
-        bf = name_boundary_grid_function(element, func)
+        bf = name_grid_function_root("interpolate_expression")
         gfs = name_trial_gfs()
         interpolate_vector(bf, gfs, name)
 
 
-@preamble(section="vector", kernel="driver_block")
-def interpolate_vector(func, gfs, name):
-    return "Dune::PDELab::interpolate(*{}, *{}, *{});".format(func,
-                                                              gfs,
-                                                              name,
-                                                              )
+def _grid_function_root_type(identifier):
+    name_dict = {"exact_solution": "ExactSolution",
+                 "interpolate_expression": "BoundaryGridFunction"}
+    return name_dict[identifier]
+
+
+def _grid_function_root_name(identifier):
+    name_dict = {"exact_solution": "exactSolution",
+                 "interpolate_expression": "boundaryGridFunction"}
+    return name_dict[identifier]
+
+
+def _get_grid_function_method_name(identifier):
+    name_dict = {"exact_solution": "getExactSolution",
+                 "interpolate_expression": "getBoundaryGridFunction"}
+    return name_dict[identifier]
 
 
 @class_member(classtag="driver_block")
-def typedef_composite_boundary_grid_function(name, children):
+def typedef_composite_grid_function(name, children):
     templates = ','.join('std::decay_t<decltype(*{})>'.format(c) for c in children)
     return "using {} = Dune::PDELab::CompositeGridFunction<{}>;".format(name, templates)
 
 
-def type_composite_boundary_grid_function(children, root):
+def type_composite_grid_function(identifier, children, root):
     if root:
-        name = "BoundaryGridFunction"
+        name = _grid_function_root_type(identifier)
     else:
         name = "CompositeGridFunction_{}".format('_'.join(c for c in children))
-    typedef_composite_boundary_grid_function(name, children)
+    typedef_composite_grid_function(name, children)
     return name
 
 
 @class_member(classtag="driver_block")
-def declare_composite_boundary_grid_function(name, children, root):
-    composite_gfs_type = type_composite_boundary_grid_function(children, root)
+def declare_composite_grid_function(identifier, name, children, root):
+    composite_gfs_type = type_composite_grid_function(identifier, children, root)
     return "std::shared_ptr<{}> {};".format(composite_gfs_type, name)
 
 
 @preamble(section="vector", kernel="driver_block")
-def define_composite_boundary_grid_function(name, children, root=False):
-    declare_composite_boundary_grid_function(name, children, root)
-    composite_gfs_type = type_composite_boundary_grid_function(children, root)
+def define_composite_grid_function(identifier, name, children, root=True):
+    declare_composite_grid_function(identifier, name, children, root)
+    composite_gfs_type = type_composite_grid_function(identifier, children, root)
     return "{} = std::make_shared<{}>({});".format(name, composite_gfs_type, ', '.join('*{}'.format(c) for c in children))
 
 
-def _is_local(func):
-    # palpo TODO
-    return True
-    # return False
-    # assert isinstance(func, tuple)
-    # if len(func) == 2:
-    #     return True
-    # else:
-    #     try:
-    #         assert len(func) == 1
-    #     except:
-    #         from pudb import set_trace; set_trace()
-    #     return False
+def function_lambda(func):
+    assert isinstance(func, tuple)
+    func = func[0]
+    if func is None:
+        func = 0.0
+
+    if isinstance(func, (int, float)):
+        return "[&](const auto& is, const auto& xl){{ return {}; }}".format(float(func))
+    else:
+        from ufl.classes import Expr
+        assert isinstance(func, Expr)
+        from dune.codegen.pdelab.driver.visitor import ufl_to_code
+        return "[&](const auto& is, const auto& xl){{ {}; }}".format(ufl_to_code(func))
 
 
 @class_member(classtag="driver_block")
-def typedef_boundary_grid_function(name, local):
+def typedef_function(name):
+    range_type = type_range()
+    leafview_type = type_leafview()
+    entity = "typename {}::template Codim<0>::Entity".format(leafview_type)
+    coordinate = "typename {}::template Codim<0>::Entity::Geometry::LocalCoordinate".format(leafview_type)
+    return "using {} = std::function<{}({}, {})>;".format(name, range_type, entity, coordinate)
+
+
+def type_function():
+    name = "FunctionExpression"
+    typedef_function(name)
+    return name
+
+
+@class_member(classtag="driver_block")
+def declare_function(name):
+    function_type = type_function()
+    return "std::shared_ptr<{}> {};".format(function_type, name)
+
+
+@preamble(section="vector", kernel="driver_block")
+def define_function(name, func):
+    declare_function(name)
+    function_type = type_function()
+    fct_lambda = function_lambda(func)
+    return "{} = std::make_shared<{}> ({});".format(name, function_type, fct_lambda)
+
+
+@cached
+def name_function(func):
+    name = get_counted_variable("functionExpression")
+    define_function(name, func)
+    return name
+
+
+@class_member(classtag="driver_block")
+def typedef_grid_function(name):
     leafview_type = type_leafview()
     range_type = type_range()
-    boundary_function_type = type_boundary_function(local)
-    # palpo TODO: 1 in the format below!
+    function_type = type_function()
     return "using {} = Dune::PDELab::LocalCallableToGridFunctionAdapter<{}, {}, {}, {}>;".format(name,
                                                                                                  leafview_type,
                                                                                                  range_type,
                                                                                                  1,
-                                                                                                 boundary_function_type)
+                                                                                                 function_type)
 
 
-def type_boundary_grid_function(local, root):
-    # TODO: remove local stuff
-    # if local:
-    #     name = "BoundaryGridFunctionLocal"
-    # else:
-    #     name = "BoundaryGridFunctionGlobal"
+def type_grid_function(identifier, root):
+    name = "GridFunctionLeaf"
     if root:
-        name = "BoundaryGridFunction"
-    else:
-        name = "BoundaryGridFunctionLeaf"
-    typedef_boundary_grid_function(name, local)
+        name = _grid_function_root_type(identifier)
+    typedef_grid_function(name)
     return name
 
 
 @class_member(classtag="driver_block")
-def declare_boundary_grid_function(name, local, root):
-    bgf_type = type_boundary_grid_function(local, root)
-    return "std::shared_ptr<{}> {};".format(bgf_type, name)
+def declare_grid_function(identifier, name, root):
+    grid_function_type = type_grid_function(identifier, root)
+    return "std::shared_ptr<{}> {};".format(grid_function_type, name)
 
 
 @preamble(section="vector", kernel="driver_block")
-def define_boundary_grid_function(name, func, root=False):
-    local = _is_local(func)
-    declare_boundary_grid_function(name, local, root)
+def define_grid_function(identifier, name, func, root=True):
+    declare_grid_function(identifier, name, root)
     gv = name_leafview()
-    boundary_function = name_boundary_function(func, local)
-    bgf_type = type_boundary_grid_function(local, root)
+    function_name = name_function(func)
+    grid_function_type = type_grid_function(identifier, root)
     include_file('dune/pdelab/function/callableadapter.hh', filetag='driver')
     if is_stationary():
-        return "{} = std::make_shared<{}>({}, *{});".format(name, bgf_type, gv, boundary_function)
+        return "{} = std::make_shared<{}>({}, *{});".format(name, grid_function_type, gv, function_name)
     else:
         # palpo TODO
         assert False
@@ -136,134 +182,87 @@ def define_boundary_grid_function(name, func, root=False):
                                                                                                       )
 
 
-@cached
-def name_boundary_grid_function(element, func, root=True):
+
+def name_grid_function(identifier, element, func, root=True):
     assert isinstance(func, tuple)
 
     if isinstance(element, MixedElement):
         k = 0
         childs = []
         for subel in element.sub_elements():
-            childs.append(name_boundary_grid_function(subel, func[k:k + subel.value_size()], root=False))
+            childs.append(name_grid_function(identifier, subel, func[k:k + subel.value_size()], root=False))
             k = k + subel.value_size()
         name = "_".join(childs)
         if len(childs) == 1:
             name = "{}_dummy".format(name)
         if root:
-            name = "boundary_grid_function"
-        define_composite_boundary_grid_function(name, tuple(childs), root=root)
+            name = identifier
+        define_composite_grid_function(identifier, name, tuple(childs), root=root)
     else:
         assert isinstance(element, (FiniteElement, TensorProductElement))
-        name = get_counted_variable("boundary_grid_function")
+        name = get_counted_variable(identifier)
         if root:
-            name = "boundary_grid_function"
-        define_boundary_grid_function(name, func, root=root)
-    if root:
-        print("palpo 1 element: {}".format(element))
-        driver_block_get_boundarygridfunction(element, func, name=name)
+            name = identifier
+        define_grid_function(identifier, name, func, root=root)
     return name
 
 
-def boundary_lambda(func, local):
-    # palpo TODO
-    assert isinstance(func, tuple)
-    func = func[0]
-    if func is None:
-        func = 0.0
-
-    if isinstance(func, (int, float)):
-        return "[&](const auto& is, const auto& x){{ return {}; }}".format(float(func))
-    else:
-        from ufl.classes import Expr
-        assert isinstance(func, Expr)
-        from dune.codegen.pdelab.driver.visitor import ufl_to_code
-        return "[&](const auto& is, const auto& xl){{ {}; }}".format(ufl_to_code(func))
-
-
-@class_member(classtag="driver_block")
-def typedef_boundary_function(name, local):
-    range_type = type_range()
-    leafview_type = type_leafview()
-    if not local:
-        coordinate = "typename {}::template Codim<0>::Entity::Geometry::GlobalCoordinate".format(leafview_type)
-        return "using {} = std::function<{}({})>;".format(name, range_type, coordinate)
-    else:
-        entity = "typename {}::template Codim<0>::Entity".format(leafview_type)
-        coordinate = "typename {}::template Codim<0>::Entity::Geometry::LocalCoordinate".format(leafview_type)
-        return "using {} = std::function<{}({}, {})>;".format(name, range_type, entity, coordinate)
-
-
-def type_boundary_function(local):
-    name = "BoundaryFunction"
-    if not local:
-        name = name + "Global"
-    else:
-        name = name + "Local"
-    typedef_boundary_function(name, local)
+def name_grid_function_root(identifier):
+    element = get_trial_element()
+    func = preprocess_leaf_data(element, identifier)
+    name = name_grid_function(identifier, element, func, root=True)
     return name
 
 
-@class_member(classtag="driver_block")
-def declare_boundary_function(name, local):
-    bf_type = type_boundary_function(local)
-    return "std::shared_ptr<{}> {};".format(bf_type, name)
-
-
-@preamble(section="vector", kernel="driver_block")
-def define_boundary_function(name, func, local):
-    declare_boundary_function(name, local)
-    bf_type = type_boundary_function(local)
-    bf_lambda = boundary_lambda(func, local)
-    return "{} = std::make_shared<{}> ({});".format(name, bf_type, bf_lambda)
-
-
-@cached
-def name_boundary_function(func, local):
-    name = get_counted_variable("boundary_function")
-    define_boundary_function(name, func, local)
-    return name
+@preamble(section="postprocessing", kernel="main")
+def main_typedef_grid_function(name, identifier, treepath):
+    if len(treepath) == 0:
+        driver_block_type = type_driver_block()
+        gf_type = _grid_function_root_type(identifier)
+        type_name = "{}::{}".format(driver_block_type, gf_type)
+    else:
+        root_type = main_type_grid_function(identifier, ())
+        type_name = "Dune::TypeTree::Child<{}, {}>;".format(root_type, ", ".join(str(t) for t in treepath))
+    return "using {} = {};".format(name, type_name)
 
 
-@preamble(section="postprocessing", kernel="main")
-def main_typedef_boundary_grid_function(name):
-    driver_block_type = type_driver_block()
-    # palpo TODO
-    local = True
-    # bgf_type = type_boundary_grid_function(local, True)
-    bgf_type = "BoundaryGridFunction"
-    print("palpo name: {}".format(name))
-    return "using {} = {}::{};".format(name, driver_block_type, bgf_type)
-
-
-def main_type_boundary_grid_function():
-    name = "BoundaryGridFunction"
-    main_typedef_boundary_grid_function(name)
+def main_type_grid_function(identifier, treepath):
+    name = _grid_function_root_type(identifier)
+    if len(treepath) > 0:
+        name = "{}_{}".format(name, "_".join(str(t) for t in treepath))
+    main_typedef_grid_function(name, identifier, treepath)
     return name
 
 
 @class_member(classtag="driver_block")
-def driver_block_get_boundarygridfunction(element, func, name=None):
+def driver_block_get_grid_function(identifier, name=None):
+    assert identifier in ["exact_solution", "interpolate_expression"]
     if not name:
-        name = name_boundary_grid_function(element, func)
-    # bgf_type = type_boundary_grid_function(True, True)
-    bgf_type = "BoundaryGridFunction"
-    return ["std::shared_ptr<{}> getBoundaryGridFunction(){{".format(bgf_type),
+        name = name_grid_function_root(identifier)
+    gf_type = _grid_function_root_type(identifier)
+    method_name = _get_grid_function_method_name(identifier)
+    return ["std::shared_ptr<{}> {}(){{".format(gf_type, method_name),
             "  return {};".format(name),
             "}"]
 
 
 @preamble(section="postprocessing", kernel="main")
-def main_define_boundary_grid_function(name, element, func):
-    driver_block_name = name_driver_block()
-    # palpo TODO
-    # driver_block_get_boundarygridfunction(element, func)
-    return "auto {} = {}.getBoundaryGridFunction();".format(name, driver_block_name)
+def main_define_grid_function(name, identifier, treepath):
+    if len(treepath) == 0:
+        driver_block_get_grid_function(identifier)
+        driver_block_name = name_driver_block()
+        method_name = _get_grid_function_method_name(identifier)
+        return "auto {} = {}.{}();".format(name, driver_block_name, method_name)
+    else:
+        root_name = main_name_grid_function(identifier, ())
+        indices = ["Dune::Indices::_{}".format(str(t)) for t in treepath]
+        return "auto {} = child(*{}, {});".format(name, root_name, ", ".join(i for i in indices))
 
 
-@cached
-def main_name_boundary_grid_function(element, func):
-    # palpo TODO func rauswerfen?
-    assert isinstance(func, tuple)
-    name = "boundaryGridFunction"
-    main_define_boundary_grid_function(name, element, func)
+
+def main_name_grid_function(identifier, treepath):
+    name = _grid_function_root_name(identifier)
+    if len(treepath) > 0:
+        name = "{}_{}".format(name, "_".join(str(t) for t in treepath))
+    main_define_grid_function(name, identifier, treepath)
     return name
-- 
GitLab