From ae8884d6f78ce016da5e21b57f67970686a81f62 Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Mon, 5 Feb 2018 16:06:49 +0100
Subject: [PATCH] Add sections in generated drivers for much better reading

---
 python/dune/perftool/generation/cache.py      |  3 ++
 .../dune/perftool/pdelab/driver/__init__.py   | 33 ++++++++++++---
 .../perftool/pdelab/driver/constraints.py     | 14 +++----
 python/dune/perftool/pdelab/driver/error.py   | 16 ++++----
 .../pdelab/driver/gridfunctionspace.py        | 40 +++++++++----------
 .../perftool/pdelab/driver/gridoperator.py    | 14 +++----
 .../perftool/pdelab/driver/instationary.py    | 20 +++++-----
 .../perftool/pdelab/driver/interpolate.py     |  8 ++--
 python/dune/perftool/pdelab/driver/solve.py   | 24 +++++------
 python/dune/perftool/pdelab/driver/timings.py | 12 +++---
 python/dune/perftool/pdelab/driver/vtk.py     | 18 ++++-----
 11 files changed, 113 insertions(+), 89 deletions(-)

diff --git a/python/dune/perftool/generation/cache.py b/python/dune/perftool/generation/cache.py
index 474e0e10..b4ae54f2 100644
--- a/python/dune/perftool/generation/cache.py
+++ b/python/dune/perftool/generation/cache.py
@@ -69,6 +69,7 @@ class _RegisteredFunction(object):
                  on_store=lambda x: x,
                  item_tags=(),
                  context_tags=(),
+                 section=None,
                  **kwargs
                  ):
         self.func = func
@@ -78,6 +79,8 @@ class _RegisteredFunction(object):
         self.item_tags = item_tags
         self.context_tags = context_tags
         self.kwargs = kwargs
+        if section:
+            self.item_tags = self.item_tags + (section,)
 
         # Initialize the memoization cache
         self._memoize_cache = {}
diff --git a/python/dune/perftool/pdelab/driver/__init__.py b/python/dune/perftool/pdelab/driver/__init__.py
index ab34d8d8..aed507b1 100644
--- a/python/dune/perftool/pdelab/driver/__init__.py
+++ b/python/dune/perftool/pdelab/driver/__init__.py
@@ -195,7 +195,7 @@ def name_inifile():
     return "argv[1]"
 
 
-@preamble
+@preamble(section="init")
 def parse_initree(varname):
     include_file("dune/common/parametertree.hh", filetag="driver")
     include_file("dune/common/parametertreeparser.hh", filetag="driver")
@@ -209,7 +209,7 @@ def name_initree():
     return "initree"
 
 
-@preamble
+@preamble(section="init")
 def define_mpihelper(name):
     include_file("dune/common/parallel/mpihelper.hh", filetag="driver")
     return "Dune::MPIHelper& {} = Dune::MPIHelper::instance(argc, argv);".format(name)
@@ -221,7 +221,7 @@ def name_mpihelper():
     return name
 
 
-@preamble
+@preamble(section="init")
 def check_parallel_execution():
     from dune.perftool.pdelab.driver.gridfunctionspace import name_leafview
     gv = name_leafview()
@@ -272,11 +272,32 @@ def generate_driver():
     return_statement()
 
     from dune.perftool.generation import retrieve_cache_items
-    from cgen import FunctionDeclaration, FunctionBody, Block, Value
+    from cgen import FunctionDeclaration, FunctionBody, Block, Value, LineComment, Line
     driver_signature = FunctionDeclaration(Value('bool', 'driver'), [Value('int', 'argc'), Value('char**', 'argv')])
-    contents = [i for i in retrieve_cache_items("preamble", make_generable=True)]
 
-    from cgen import Line
+    contents = []
+    def add_section(tag, comment):
+        tagcontents = [i for i in retrieve_cache_items("preamble and {}".format(tag), make_generable=True)]
+        if tagcontents:
+            contents.append(LineComment(comment))
+            contents.append(Line("\n"))
+            contents.extend(tagcontents)
+            contents.append(Line("\n"))
+
+    add_section("init", "Initialize basic stuff...")
+    add_section("grid", "Setup grid (view)...")
+    add_section("fem", "Set up finite element maps...")
+    add_section("gfs", "Set up grid function spaces...")
+    add_section("constraints", "Set up constraints container...")
+    add_section("gridoperator", "Set up grid grid operators...")
+    add_section("vector", "Set up solution vectors...")
+    add_section("solver", "Set up (non)linear solvers...")
+    add_section("instat", "Set up instationary stuff...")
+    add_section("vtk", "Do visualization...")
+    add_section("timings", "Maybe take performance measurements...")
+    add_section("print", "Maybe print residuals and matrices to stdout...")
+    add_section("error", "Maybe calculate errors for test results...")
+
     if get_option("instrumentation_level") >= 1:
         from dune.perftool.generation import post_include
         post_include("HP_DECLARE_TIMER(driver);\n", filetag="driver")
diff --git a/python/dune/perftool/pdelab/driver/constraints.py b/python/dune/perftool/pdelab/driver/constraints.py
index 6e9d7e7a..e3a96df4 100644
--- a/python/dune/perftool/pdelab/driver/constraints.py
+++ b/python/dune/perftool/pdelab/driver/constraints.py
@@ -30,7 +30,7 @@ def has_dirichlet_constraints(is_dirichlet):
         return bool(is_dirichlet)
 
 
-@preamble
+@preamble(section="constraints")
 def assemble_constraints(name):
     element = get_trial_element()
     gfs = name_trial_gfs()
@@ -70,7 +70,7 @@ def name_bctype_function(element, is_dirichlet):
         return name
 
 
-@preamble
+@preamble(section="constraints")
 def define_bctype_function(element, is_dirichlet, name):
     gv = name_leafview()
     bctype_lambda = name_bctype_lambda(name, is_dirichlet)
@@ -81,13 +81,13 @@ def define_bctype_function(element, is_dirichlet, name):
                                                                                        )
 
 
-@preamble
+@preamble(section="constraints")
 def define_power_bctype_function(element, name, subgfs):
     include_file('dune/pdelab/constraints/common/constraintsparameters.hh', filetag='driver')
     return "Dune::PDELab::PowerConstraintsParameters<decltype({}), {}> {}({});".format(subgfs, element.num_sub_elements(), name, subgfs)
 
 
-@preamble
+@preamble(section="constraints")
 def define_composite_bctype_function(element, is_dirichlet, name, subgfs):
     include_file('dune/pdelab/constraints/common/constraintsparameters.hh', filetag='driver')
     return "Dune::PDELab::CompositeConstraintsParameters<{}> {}({});".format(', '.join('decltype({})'.format(c) for c in subgfs),
@@ -102,7 +102,7 @@ def name_bctype_lambda(name, func):
     return name
 
 
-@preamble
+@preamble(section="constraints")
 def define_intersection_lambda(name, func):
     from ufl.classes import Expr
     if func is None:
@@ -116,7 +116,7 @@ def define_intersection_lambda(name, func):
     raise ValueError("Expression not understood")
 
 
-@preamble
+@preamble(section="constraints")
 def typedef_constraintscontainer(name):
     gfs = type_trial_gfs()
     r = type_range()
@@ -129,7 +129,7 @@ def type_constraintscontainer():
     return name
 
 
-@preamble
+@preamble(section="constraints")
 def define_constraintscontainer(name):
     cctype = type_constraintscontainer()
     return ["{} {};".format(cctype, name), "{}.clear();".format(name)]
diff --git a/python/dune/perftool/pdelab/driver/error.py b/python/dune/perftool/pdelab/driver/error.py
index b210d61f..a4a7e2d4 100644
--- a/python/dune/perftool/pdelab/driver/error.py
+++ b/python/dune/perftool/pdelab/driver/error.py
@@ -24,7 +24,7 @@ from dune.perftool.pdelab.driver.solve import (define_vector,
 from ufl import MixedElement, TensorElement, VectorElement
 
 
-@preamble
+@preamble(section="error")
 def define_test_fail_variable(name):
     return 'bool {}(false);'.format(name)
 
@@ -49,7 +49,7 @@ def type_discrete_grid_function(gfs):
     return "{}_DGF".format(gfs.upper())
 
 
-@preamble
+@preamble(section="error")
 def define_discrete_grid_function(gfs, vector_name, dgf_name):
     dgf_type = type_discrete_grid_function(gfs)
     return ["using {} = Dune::PDELab::DiscreteGridFunction<decltype({}),decltype({})>;".format(dgf_type, gfs, vector_name),
@@ -62,7 +62,7 @@ def name_discrete_grid_function(gfs, vector_name):
     return dgf_name
 
 
-@preamble
+@preamble(section="error")
 def typedef_difference_squared_adapter(name, treepath):
     sol = name_exact_solution_gridfunction(treepath)
     vector = name_vector(get_form_ident())
@@ -78,7 +78,7 @@ def type_difference_squared_adapter(treepath):
     return name
 
 
-@preamble
+@preamble(section="error")
 def define_difference_squared_adapter(name, treepath):
     t = type_difference_squared_adapter(treepath)
     sol = name_exact_solution_gridfunction(treepath)
@@ -95,7 +95,7 @@ def name_difference_squared_adapter(treepath):
     return name
 
 
-@preamble
+@preamble(section="error")
 def _accumulate_L2_squared(treepath):
     dsa = name_difference_squared_adapter(treepath)
     accum_error = name_accumulated_L2_error()
@@ -158,7 +158,7 @@ def accumulate_L2_squared():
         _accumulate_L2_squared(())
 
 
-@preamble
+@preamble(section="error")
 def define_accumulated_L2_error(name):
     t = type_range()
     return "{} {}(0.0);".format(t, name)
@@ -170,7 +170,7 @@ def name_accumulated_L2_error():
     return name
 
 
-@preamble
+@preamble(section="error")
 def compare_L2_squared():
     accumulate_L2_squared()
     gv = name_leafview()
@@ -186,7 +186,7 @@ def compare_L2_squared():
             "  {} = true;".format(fail)]
 
 
-@preamble
+@preamble(section="error")
 def return_statement():
     from dune.perftool.pdelab.driver.error import name_test_fail_variable
     fail = name_test_fail_variable()
diff --git a/python/dune/perftool/pdelab/driver/gridfunctionspace.py b/python/dune/perftool/pdelab/driver/gridfunctionspace.py
index 62c3df84..a956855a 100644
--- a/python/dune/perftool/pdelab/driver/gridfunctionspace.py
+++ b/python/dune/perftool/pdelab/driver/gridfunctionspace.py
@@ -24,7 +24,7 @@ from dune.perftool.loopy.target import type_floatingpoint
 from ufl import FiniteElement, MixedElement, TensorElement, VectorElement, TensorProductElement
 
 
-@preamble
+@preamble(section="grid")
 def typedef_domainfield(name):
     gridt = type_grid()
     return "using {} = {}::ctype;".format(name, gridt)
@@ -35,7 +35,7 @@ def type_domainfield():
     return "DF"
 
 
-@preamble
+@preamble(section="init")
 def typedef_range(name):
     return "using {} = {};".format(name, type_floatingpoint())
 
@@ -46,7 +46,7 @@ def type_range():
     return name
 
 
-@preamble
+@preamble(section="grid")
 def typedef_grid(name):
     dim = get_dimension()
     if isQuadrilateral(get_trial_element().cell()):
@@ -73,7 +73,7 @@ def type_grid():
     return name
 
 
-@preamble
+@preamble(section="grid")
 def define_grid(name):
     include_file("dune/testtools/gridconstruction.hh", filetag="driver")
     ini = name_initree()
@@ -88,7 +88,7 @@ def name_grid():
     return name
 
 
-@preamble
+@preamble(section="grid")
 def typedef_leafview(name):
     grid = type_grid()
     return "using {} = {}::LeafGridView;".format(name, grid)
@@ -100,7 +100,7 @@ def type_leafview():
     return name
 
 
-@preamble
+@preamble(section="grid")
 def define_leafview(name):
     _type = type_leafview()
     grid = name_grid()
@@ -113,7 +113,7 @@ def name_leafview():
     return name
 
 
-@preamble
+@preamble(section="fem")
 def typedef_fem(element, name):
     gv = type_leafview()
     df = type_domainfield()
@@ -176,7 +176,7 @@ def type_fem(element):
     return name
 
 
-@preamble
+@preamble(section="fem")
 def define_fem(element, name):
     femtype = type_fem(element)
     from dune.perftool.pdelab.driver import isDG
@@ -286,7 +286,7 @@ def type_gfs(element, is_dirichlet, root=True):
         return name
 
 
-@preamble
+@preamble(section="gfs")
 def define_gfs(element, is_dirichlet, name, root):
     gfstype = type_gfs(element, is_dirichlet, root=root)
     gv = name_leafview()
@@ -295,7 +295,7 @@ def define_gfs(element, is_dirichlet, name, root):
             "{}.name(\"{}\");".format(name, name)]
 
 
-@preamble
+@preamble(section="gfs")
 def define_power_gfs(element, is_dirichlet, name, subgfs, root):
     gfstype = type_gfs(element, is_dirichlet, root=root)
     names = ["using namespace Dune::Indices;"]
@@ -303,14 +303,14 @@ def define_power_gfs(element, is_dirichlet, name, subgfs, root):
     return ["{} {}({});".format(gfstype, name, subgfs)] + names
 
 
-@preamble
+@preamble(section="gfs")
 def define_composite_gfs(element, is_dirichlet, name, subgfs, root):
     gfstype = type_gfs(element, is_dirichlet, root=root)
     return ["{} {}({});".format(gfstype, name, ", ".join(subgfs)),
             "{}.update();".format(name)]
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_gfs(element, is_dirichlet, name, root):
     vb = type_vectorbackend(element, root)
     gv = type_leafview()
@@ -319,7 +319,7 @@ def typedef_gfs(element, is_dirichlet, name, root):
     return "using {} = Dune::PDELab::GridFunctionSpace<{}, {}, {}, {}>;".format(name, gv, fem, cass, vb)
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_power_gfs(element, is_dirichlet, name, subgfs, root):
     include_file("dune/pdelab/gridfunctionspace/powergridfunctionspace.hh", filetag="driver")
     vb = type_vectorbackend(element, root)
@@ -328,7 +328,7 @@ def typedef_power_gfs(element, is_dirichlet, name, subgfs, root):
     return "using {} = Dune::PDELab::PowerGridFunctionSpace<{}, {}, {}, {}>;".format(name, subgfs, element.num_sub_elements(), vb, ot)
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_composite_gfs(element, name, subgfs, root):
     vb = type_vectorbackend(element, root)
     ot = type_orderingtag(isinstance(element, FiniteElement))
@@ -336,7 +336,7 @@ def typedef_composite_gfs(element, name, subgfs, root):
     return "using {} = Dune::PDELab::CompositeGridFunctionSpace<{}, {}, {}>;".format(name, vb, ot, args)
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_vectorbackend(name, element, root):
     include_file("dune/pdelab/backend/istl.hh", filetag="driver")
     if get_form_option("fastdg") and root:
@@ -366,25 +366,25 @@ def type_orderingtag(leaf):
         return "Dune::PDELab::EntityBlockedOrderingTag"
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_overlapping_dirichlet_constraintsassembler(name):
     include_file("dune/pdelab/constraints/conforming.hh", filetag="driver")
     return "using {} = Dune::PDELab::ConformingDirichletConstraints;".format(name)
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_p0parallel_constraintsassembler(name):
     include_file("dune/pdelab/constraints/p0.hh", filetag="driver")
     return "using {} = Dune::PDELab::P0ParallelConstraints;".format(name)
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_dirichlet_constraintsassembler(name):
     include_file("dune/pdelab/constraints/conforming.hh", filetag="driver")
     return "using {} = Dune::PDELab::ConformingDirichletConstraints;".format(name)
 
 
-@preamble
+@preamble(section="gfs")
 def typedef_no_constraintsassembler(name):
     return "using {} = Dune::PDELab::NoConstraints;".format(name)
 
@@ -422,7 +422,7 @@ def name_subgfs(treepath):
     return name
 
 
-@preamble
+@preamble(section="vtk")
 def define_subgfs(name, treepath):
     t = type_subgfs(treepath)
     gfs = name_trial_gfs()
diff --git a/python/dune/perftool/pdelab/driver/gridoperator.py b/python/dune/perftool/pdelab/driver/gridoperator.py
index 372f1bca..8b5c8c02 100644
--- a/python/dune/perftool/pdelab/driver/gridoperator.py
+++ b/python/dune/perftool/pdelab/driver/gridoperator.py
@@ -24,7 +24,7 @@ from dune.perftool.pdelab.localoperator import localoperator_basename
 from dune.perftool.options import get_form_option
 
 
-@preamble
+@preamble(section="gridoperator")
 def typedef_gridoperator(name, form_ident):
     ugfs = type_trial_gfs()
     vgfs = type_test_gfs()
@@ -49,7 +49,7 @@ def type_gridoperator(form_ident):
     return name
 
 
-@preamble
+@preamble(section="gridoperator")
 def define_gridoperator(name, form_ident):
     gotype = type_gridoperator(form_ident)
     ugfs = name_trial_gfs()
@@ -70,7 +70,7 @@ def name_gridoperator(form_ident):
     return name
 
 
-@preamble
+@preamble(section="gridoperator")
 def typedef_localoperator(name, form_ident):
     ugfs = type_trial_gfs()
     vgfs = type_test_gfs()
@@ -87,7 +87,7 @@ def type_localoperator(form_ident):
     return name
 
 
-@preamble
+@preamble(section="gridoperator")
 def define_localoperator(name, form_ident):
     trial_gfs = name_trial_gfs()
     test_gfs = name_test_gfs()
@@ -102,7 +102,7 @@ def name_localoperator(form_ident):
     return name
 
 
-@preamble
+@preamble(section="gridoperator")
 def define_dofestimate(name):
     # Provide a worstcase estimate for the number of entries per row based
     # on the given gridfunction space and cell geometry
@@ -129,7 +129,7 @@ def name_dofestimate():
     return name
 
 
-@preamble
+@preamble(section="gridoperator")
 def typedef_matrixbackend(name):
     include_file("dune/pdelab/backend/istl.hh", filetag="driver")
     return "using {} = Dune::PDELab::ISTL::BCRSMatrixBackend<>;".format(name)
@@ -141,7 +141,7 @@ def type_matrixbackend():
     return name
 
 
-@preamble
+@preamble(section="gridoperator")
 def define_matrixbackend(name):
     mbtype = type_matrixbackend()
     dof = name_dofestimate()
diff --git a/python/dune/perftool/pdelab/driver/instationary.py b/python/dune/perftool/pdelab/driver/instationary.py
index 13a47e4d..2995d66b 100644
--- a/python/dune/perftool/pdelab/driver/instationary.py
+++ b/python/dune/perftool/pdelab/driver/instationary.py
@@ -49,7 +49,7 @@ def solve_instationary():
     print_matrix()
 
 
-@preamble
+@preamble(section="instat")
 def time_loop():
     ini = name_initree()
     lop = name_localoperator(get_form_ident())
@@ -113,7 +113,7 @@ def time_loop():
             ""]
 
 
-@preamble
+@preamble(section="instat")
 def define_time(name):
     return "double {} = 0.0;".format(name)
 
@@ -123,7 +123,7 @@ def name_time():
     return "time"
 
 
-@preamble
+@preamble(section="instat")
 def typedef_timesteppingmethod(name):
     r_type = type_range()
     explicit = get_option('explicit_time_stepping')
@@ -138,7 +138,7 @@ def type_timesteppingmethod():
     return "TSM"
 
 
-@preamble
+@preamble(section="instat")
 def define_timesteppingmethod(name):
     tsm_type = type_timesteppingmethod()
     explicit = get_option('explicit_time_stepping')
@@ -154,7 +154,7 @@ def name_timesteppingmethod():
     return "tsm"
 
 
-@preamble
+@preamble(section="instat")
 def typedef_instationarygridoperator(name):
     include_file("dune/pdelab/gridoperator/onestep.hh", filetag="driver")
     go_type = type_gridoperator(get_form_ident())
@@ -171,7 +171,7 @@ def type_instationarygridoperator():
     return "IGO"
 
 
-@preamble
+@preamble(section="instat")
 def define_instationarygridoperator(name):
     igo_type = type_instationarygridoperator()
     go = name_gridoperator(get_form_ident())
@@ -184,7 +184,7 @@ def name_instationarygridoperator():
     return "igo"
 
 
-@preamble
+@preamble(section="instat")
 def typedef_onestepmethod(name):
     r_type = type_range()
     igo_type = type_instationarygridoperator()
@@ -198,7 +198,7 @@ def type_onestepmethod():
     return "OSM"
 
 
-@preamble
+@preamble(section="instat")
 def define_onestepmethod(name):
     ilptype = type_onestepmethod()
     tsm = name_timesteppingmethod()
@@ -213,7 +213,7 @@ def name_onestepmethod():
     return "osm"
 
 
-@preamble
+@preamble(section="instat")
 def typedef_explicitonestepmethod(name):
     r_type = type_range()
     igo_type = type_instationarygridoperator()
@@ -227,7 +227,7 @@ def type_explicitonestepmethod():
     return "EOSM"
 
 
-@preamble
+@preamble(section="instat")
 def define_explicitonestepmethod(name):
     eosm_type = type_explicitonestepmethod()
     tsm = name_timesteppingmethod()
diff --git a/python/dune/perftool/pdelab/driver/interpolate.py b/python/dune/perftool/pdelab/driver/interpolate.py
index 9e910ac3..75846a1f 100644
--- a/python/dune/perftool/pdelab/driver/interpolate.py
+++ b/python/dune/perftool/pdelab/driver/interpolate.py
@@ -25,7 +25,7 @@ def interpolate_dirichlet_data(name):
         interpolate_vector(bf, gfs, name)
 
 
-@preamble
+@preamble(section="vector")
 def interpolate_vector(func, gfs, name):
     return "Dune::PDELab::interpolate({}, {}, {});".format(func,
                                                            gfs,
@@ -53,14 +53,14 @@ def name_boundary_function(element, func):
         return name
 
 
-@preamble
+@preamble(section="vector")
 def define_compositegfs_parameterfunction(name, children):
     return "Dune::PDELab::CompositeGridFunction<{}> {}({});".format(', '.join('decltype({})'.format(c) for c in children),
                                                                     name,
                                                                     ', '.join(children))
 
 
-@preamble
+@preamble(section="vector")
 def define_boundary_function(name, dirichlet):
     gv = name_leafview()
     lambdaname = name_boundary_lambda(dirichlet)
@@ -87,7 +87,7 @@ def name_boundary_lambda(boundary):
     return name
 
 
-@preamble
+@preamble(section="vector")
 def define_boundary_lambda(name, boundary):
     if boundary is None:
         boundary = 0.0
diff --git a/python/dune/perftool/pdelab/driver/solve.py b/python/dune/perftool/pdelab/driver/solve.py
index 29b0e268..4ecce62f 100644
--- a/python/dune/perftool/pdelab/driver/solve.py
+++ b/python/dune/perftool/pdelab/driver/solve.py
@@ -21,7 +21,7 @@ from dune.perftool.pdelab.driver.gridoperator import (name_gridoperator,
 from dune.perftool.pdelab.driver.interpolate import interpolate_dirichlet_data
 
 
-@preamble
+@preamble(section="solver")
 def dune_solve():
     form_ident = get_form_ident()
     # Test if form is linear in ansatzfunction
@@ -81,7 +81,7 @@ def name_vector(form_ident):
     return name
 
 
-@preamble
+@preamble(section="vector")
 def typedef_vector(name, form_ident):
     gfs = type_trial_gfs()
     df = type_domainfield()
@@ -94,14 +94,14 @@ def type_vector(form_ident):
     return name
 
 
-@preamble
+@preamble(section="vector")
 def define_vector(name, form_ident):
     vtype = type_vector(form_ident)
     gfs = name_trial_gfs()
     return ["{} {}({});".format(vtype, name, gfs), "{} = 0.0;".format(name)]
 
 
-@preamble
+@preamble(section="solver")
 def typedef_linearsolver(name):
     include_file("dune/pdelab/backend/istl.hh", filetag="driver")
     if get_option('overlapping'):
@@ -118,7 +118,7 @@ def type_linearsolver():
     return name
 
 
-@preamble
+@preamble(section="solver")
 def define_linearsolver(name):
     lstype = type_linearsolver()
     if get_option('overlapping'):
@@ -135,7 +135,7 @@ def name_linearsolver():
     return name
 
 
-@preamble
+@preamble(section="solver")
 def define_reduction(name):
     ini = name_initree()
     return "double {} = {}.get<double>(\"reduction\", 1e-12);".format(name, ini)
@@ -147,7 +147,7 @@ def name_reduction():
     return name
 
 
-@preamble
+@preamble(section="solver")
 def typedef_stationarylinearproblemsolver(name):
     include_file("dune/pdelab/stationary/linearproblem.hh", filetag="driver")
     gotype = type_gridoperator(get_form_ident())
@@ -161,7 +161,7 @@ def type_stationarylinearproblemsolver():
     return "SLP"
 
 
-@preamble
+@preamble(section="solver")
 def define_stationarylinearproblemsolver(name):
     slptype = type_stationarylinearproblemsolver()
     go = name_gridoperator(get_form_ident())
@@ -176,7 +176,7 @@ def name_stationarylinearproblemsolver():
     return "slp"
 
 
-@preamble
+@preamble(section="solver")
 def typedef_stationarynonlinearproblemsolver(name, go_type):
     include_file("dune/pdelab/newton/newton.hh", filetag="driver")
     ls_type = type_linearsolver()
@@ -190,7 +190,7 @@ def type_stationarynonlinearproblemssolver(go_type):
     return name
 
 
-@preamble
+@preamble(section="solver")
 def define_stationarynonlinearproblemsolver(name, go_type, go):
     snptype = type_stationarynonlinearproblemssolver(go_type)
     x = name_vector(get_form_ident())
@@ -204,7 +204,7 @@ def name_stationarynonlinearproblemsolver(go_type, go):
     return name
 
 
-@preamble
+@preamble(section="print")
 def print_residual():
     ini = name_initree()
     n_go = name_gridoperator(get_form_ident())
@@ -227,7 +227,7 @@ def print_residual():
             "}"]
 
 
-@preamble
+@preamble(section="print")
 def print_matrix():
     ini = name_initree()
     t_go = type_gridoperator(get_form_ident())
diff --git a/python/dune/perftool/pdelab/driver/timings.py b/python/dune/perftool/pdelab/driver/timings.py
index 6fcae37a..84f0ce83 100644
--- a/python/dune/perftool/pdelab/driver/timings.py
+++ b/python/dune/perftool/pdelab/driver/timings.py
@@ -24,7 +24,7 @@ from dune.perftool.pdelab.driver.solve import (name_vector,
                                                )
 
 
-@preamble
+@preamble(section="timings")
 def define_timing_identifier(name):
     ini = name_initree()
     return "auto {} = {}.get<std::string>(\"identifier\", std::string(argv[0]));".format(name, ini)
@@ -36,7 +36,7 @@ def name_timing_identifier():
     return name
 
 
-@preamble
+@preamble(section="timings")
 def dump_dof_numbers(stream):
     ident = name_timing_identifier()
     level = get_option("instrumentation_level")
@@ -51,7 +51,7 @@ def dump_dof_numbers(stream):
             ]
 
 
-@preamble
+@preamble(section="timings")
 def define_timing_stream(name):
     include_file('fstream', filetag='driver', system=True)
     include_file('sstream', filetag='driver', system=True)
@@ -81,7 +81,7 @@ def setup_timer():
     include_file("dune/perftool/common/timer.hh", filetag="driver")
 
 
-@preamble
+@preamble(section="timings")
 def evaluate_residual_timer():
     n_go = name_gridoperator(get_form_ident())
     v = name_vector(get_form_ident())
@@ -113,7 +113,7 @@ def evaluate_residual_timer():
     return evaluation
 
 
-@preamble
+@preamble(section="timings")
 def apply_jacobian_timer():
     n_go = name_gridoperator(get_form_ident())
     v = name_vector(get_form_ident())
@@ -145,7 +145,7 @@ def apply_jacobian_timer():
     return evaluation
 
 
-@preamble
+@preamble(section="timings")
 def assemble_matrix_timer():
     t_go = type_gridoperator(get_form_ident())
     n_go = name_gridoperator(get_form_ident())
diff --git a/python/dune/perftool/pdelab/driver/vtk.py b/python/dune/perftool/pdelab/driver/vtk.py
index 22b7e1fc..3004c489 100644
--- a/python/dune/perftool/pdelab/driver/vtk.py
+++ b/python/dune/perftool/pdelab/driver/vtk.py
@@ -15,7 +15,7 @@ from dune.perftool.pdelab.driver.gridfunctionspace import (name_leafview,
 from dune.perftool.pdelab.driver.solve import name_vector
 
 
-@preamble
+@preamble(section="vtk")
 def define_vtkfile(name):
     ini = name_initree()
     include_file("string", filetag="driver")
@@ -27,7 +27,7 @@ def name_vtkfile():
     return "vtkfile"
 
 
-@preamble
+@preamble(section="vtk")
 def typedef_vtkwriter(name):
     include_file("dune/grid/io/file/vtk/subsamplingvtkwriter.hh", filetag="driver")
     gv = type_leafview()
@@ -39,7 +39,7 @@ def type_vtkwriter():
     return "VTKWriter"
 
 
-@preamble
+@preamble(section="vtk")
 def define_subsamplinglevel(name):
     ini = name_initree()
     degree = get_trial_element().degree()
@@ -55,7 +55,7 @@ def name_subsamplingintervals():
     return "subint"
 
 
-@preamble
+@preamble(section="vtk")
 def define_vtkwriter(name):
     _type = type_vtkwriter()
     gv = name_leafview()
@@ -68,7 +68,7 @@ def name_vtkwriter():
     return "vtkwriter"
 
 
-@preamble
+@preamble(section="vtk")
 def vtkoutput():
     include_file("dune/pdelab/gridfunctionspace/vtk.hh", filetag="driver")
     vtkwriter = name_vtkwriter()
@@ -86,7 +86,7 @@ def type_predicate():
     return "CuttingPredicate"
 
 
-@preamble
+@preamble(section="vtk")
 def define_predicate(name):
     t = type_predicate()
     return "{} {};".format(t, name)
@@ -97,7 +97,7 @@ def name_predicate():
     return "predicate"
 
 
-@preamble
+@preamble(section="vtk")
 def typedef_vtk_sequence_writer(name):
     include_file("dune/grid/io/file/vtk/vtksequencewriter.hh", filetag="driver")
     gv_type = type_leafview()
@@ -109,7 +109,7 @@ def type_vtk_sequence_writer():
     return "VTKSW"
 
 
-@preamble
+@preamble(section="vtk")
 def define_vtk_sequence_writer(name):
     vtksw_type = type_vtk_sequence_writer()
     vtkw_type = type_vtkwriter()
@@ -123,7 +123,7 @@ def name_vtk_sequence_writer():
     return "vtkSequenceWriter"
 
 
-@preamble
+@preamble(section="vtk")
 def visualize_initial_condition():
     include_file("dune/pdelab/gridfunctionspace/vtk.hh", filetag="driver")
     vtkwriter = name_vtk_sequence_writer()
-- 
GitLab