From ceb4b14f023d557fe84cafb2893abc19d4b6b80b Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Wed, 7 Dec 2016 23:11:09 +0100
Subject: [PATCH] Redesign signature generation to split types and arg names

---
 python/dune/perftool/interactive.py          |   3 +-
 python/dune/perftool/pdelab/localoperator.py | 106 +---
 python/dune/perftool/pdelab/signatures.py    | 584 +++++++------------
 3 files changed, 227 insertions(+), 466 deletions(-)

diff --git a/python/dune/perftool/interactive.py b/python/dune/perftool/interactive.py
index f64f9980..77094c75 100644
--- a/python/dune/perftool/interactive.py
+++ b/python/dune/perftool/interactive.py
@@ -3,7 +3,8 @@ from functools import partial
 
 from dune.perftool.generation import global_context
 from dune.perftool.loopy.transformations import get_loopy_transformations
-from dune.perftool.pdelab.localoperator import assembly_routine_signature, LoopyKernelMethod
+from dune.perftool.pdelab.localoperator import LoopyKernelMethod
+from dune.perftool.pdelab.signatures import assembly_routine_signature
 
 import os
 
diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/perftool/pdelab/localoperator.py
index c3dbd024..1c16edb8 100644
--- a/python/dune/perftool/pdelab/localoperator.py
+++ b/python/dune/perftool/pdelab/localoperator.py
@@ -114,13 +114,6 @@ def define_initree(name):
     return "const Dune::ParameterTree& {};".format(name)
 
 
-def ufl_measure_to_pdelab_measure(which):
-    return {'cell': 'Volume',
-            'exterior_facet': 'Boundary',
-            'interior_facet': 'Skeleton',
-            }.get(which)
-
-
 @class_member(classtag="operator")
 def _enum_pattern(which):
     return "enum {{ doPattern{} = true }};".format(which)
@@ -129,6 +122,7 @@ def _enum_pattern(which):
 def enum_pattern():
     from dune.perftool.generation import get_global_context_value
     integral_type = get_global_context_value("integral_type")
+    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
     return _enum_pattern(ufl_measure_to_pdelab_measure(integral_type))
 
 
@@ -139,6 +133,7 @@ def _pattern_baseclass(measure):
 def pattern_baseclass():
     from dune.perftool.generation import get_global_context_value
     integral_type = get_global_context_value("integral_type")
+    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
     return _pattern_baseclass(ufl_measure_to_pdelab_measure(integral_type))
 
 
@@ -150,6 +145,7 @@ def _enum_alpha(which):
 def enum_alpha():
     from dune.perftool.generation import get_global_context_value
     integral_type = get_global_context_value("integral_type")
+    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
     return _enum_alpha(ufl_measure_to_pdelab_measure(integral_type))
 
 
@@ -181,89 +177,6 @@ def class_type_from_cache(classtag):
     return basename, basename + tparam_str
 
 
-def assembler_routine_name():
-    from dune.perftool.generation import get_global_context_value
-    integral_type = get_global_context_value("integral_type")
-    form_type = get_global_context_value("form_type")
-
-    part1 = {"residual": "alpha"}.get(form_type, form_type)
-    part2 = ufl_measure_to_pdelab_measure(integral_type).lower()
-
-    return "{}_{}".format(part1, part2)
-
-
-def kernel_name():
-    arn = assembler_routine_name()
-    facedir_s = get_global_context_value("facedir_s", None)
-    facedir_n = get_global_context_value("facedir_n", None)
-    facemod_s = get_global_context_value("facemod_s", None)
-    facemod_n = get_global_context_value("facemod_n", None)
-    suffix = "{}{}{}{}".format("_facedirs{}".format(facedir_s) if facedir_s is not None else "",
-                               "_facedirn{}".format(facedir_n) if facedir_n is not None else "",
-                               "_facemods{}".format(facemod_s) if facemod_s is not None else "",
-                               "_facemodn{}".format(facemod_n) if facemod_n is not None else "",
-                               )
-
-    return "{}{}".format(arn, suffix)
-
-
-def assembly_routine_signature():
-    from dune.perftool.generation import get_global_context_value
-    integral_type = get_global_context_value("integral_type")
-    form_type = get_global_context_value("form_type")
-    formdata = get_global_context_value("formdata")
-
-    # Check if form is linear
-    from dune.perftool.pdelab.driver import is_linear
-    linear = is_linear(formdata.original_form)
-
-    if form_type == 'residual':
-        if integral_type == 'cell':
-            from dune.perftool.pdelab.signatures import alpha_volume_signature
-            return alpha_volume_signature(kernel_name())
-        if integral_type == 'exterior_facet':
-            from dune.perftool.pdelab.signatures import alpha_boundary_signature
-            return alpha_boundary_signature(kernel_name())
-        if integral_type == 'interior_facet':
-            from dune.perftool.pdelab.signatures import alpha_skeleton_signature
-            return alpha_skeleton_signature(kernel_name())
-
-    if form_type == 'jacobian':
-        if integral_type == 'cell':
-            from dune.perftool.pdelab.signatures import jacobian_volume_signature
-            return jacobian_volume_signature(kernel_name())
-        if integral_type == 'exterior_facet':
-            from dune.perftool.pdelab.signatures import jacobian_boundary_signature
-            return jacobian_boundary_signature(kernel_name())
-        if integral_type == 'interior_facet':
-            from dune.perftool.pdelab.signatures import jacobian_skeleton_signature
-            return jacobian_skeleton_signature(kernel_name())
-
-    if form_type == 'jacobian_apply':
-        if linear:
-            if integral_type == 'cell':
-                from dune.perftool.pdelab.signatures import jacobian_apply_volume_signature
-                return jacobian_apply_volume_signature(kernel_name())
-            if integral_type == 'exterior_facet':
-                from dune.perftool.pdelab.signatures import jacobian_apply_boundary_signature
-                return jacobian_apply_boundary_signature(kernel_name())
-            if integral_type == 'interior_facet':
-                from dune.perftool.pdelab.signatures import jacobian_apply_skeleton_signature
-                return jacobian_apply_skeleton_signature(kernel_name())
-        else:
-            if integral_type == 'cell':
-                from dune.perftool.pdelab.signatures import nonlinear_jacobian_apply_volume_signature
-                return nonlinear_jacobian_apply_volume_signature(kernel_name())
-            if integral_type == 'exterior_facet':
-                from dune.perftool.pdelab.signatures import nonlinear_jacobian_apply_boundary_signature
-                return nonlinear_jacobian_apply_boundary_signature(kernel_name())
-            if integral_type == 'interior_facet':
-                from dune.perftool.pdelab.signatures import nonlinear_jacobian_apply_skeleton_signature
-                return nonlinear_jacobian_apply_skeleton_signature(kernel_name())
-
-    assert False
-
-
 class AccumulationSpace(Record):
     def __init__(self,
                  lfs=None,
@@ -578,6 +491,7 @@ def extract_kernel_from_cache(tag, wrap_in_cgen=True):
 
     if wrap_in_cgen:
         # Wrap the kernel in something which can generate code
+        from dune.perftool.pdelab.signatures import assembly_routine_signature
         signature = assembly_routine_signature()
         kernel = LoopyKernelMethod(signature, kernel)
 
@@ -658,6 +572,7 @@ class LoopyKernelMethod(ClassMember):
 
             # Start timer
             if add_timings and get_option('timer'):
+                from dune.perftool.pdelab.signatures import assembler_routine_name
                 timer_name = assembler_routine_name() + '_kernel'
                 name_example_kernel(name=timer_name)
                 post_include('HP_DECLARE_TIMER({});'.format(timer_name), filetag='operatorfile')
@@ -765,6 +680,8 @@ def generate_localoperator_kernels(formdata, data):
                 enum_pattern()
                 pattern_baseclass()
                 enum_alpha()
+
+                from dune.perftool.pdelab.signatures import assembler_routine_name
                 with global_context(kernel=assembler_routine_name()):
                     kernel = [k for k in get_backend(interface="generate_kernels_per_integral")(form.integrals_by_type(measure))]
 
@@ -775,6 +692,7 @@ def generate_localoperator_kernels(formdata, data):
 
                     # Numerical jacobian base class
                     _, loptype = class_type_from_cache("operator")
+                    from dune.perftool.pdelab.signatures import ufl_measure_to_pdelab_measure
                     which = ufl_measure_to_pdelab_measure(measure)
                     base_class("Dune::PDELab::NumericalJacobian{}<{}>".format(which, loptype), classtag="operator")
 
@@ -831,7 +749,9 @@ def generate_localoperator_kernels(formdata, data):
             alpha_measures = set(i.integral_type() for i in form.integrals())
             jacobian_measures = set(i.integral_type() for i in jacform.integrals())
             for it in alpha_measures - jacobian_measures:
-                operator_kernels[(it, 'jacobian')] = None
+                with global_context(integral_type=it):
+                    from dune.perftool.pdelab.signatures import assembly_routine_signature
+                    operator_kernels[(it, 'jacobian')] = [LoopyKernelMethod(assembly_routine_signature(), kernel=None)]
 
         # Jacobian apply methods for matrix-free computations
         if get_option("matrix_free"):
@@ -857,7 +777,9 @@ def generate_localoperator_kernels(formdata, data):
                     alpha_measures = set(i.integral_type() for i in form.integrals())
                     jacobian_apply_measures = set(i.integral_type() for i in jac_apply_form.integrals())
                     for it in alpha_measures - jacobian_apply_measures:
-                        operator_kernels[(it, 'jacobian_apply')] = None
+                        with global_context(integral_type=it):
+                            from dune.perftool.pdelab.signatures import assembly_routine_signature
+                            operator_kernels[(it, 'jacobian_apply')] = [LoopyKernelMethod(assembly_routine_signature(), kernel=None)]
 
     # Return the set of generated kernels
     return operator_kernels
diff --git a/python/dune/perftool/pdelab/signatures.py b/python/dune/perftool/pdelab/signatures.py
index cc11184e..d903f929 100644
--- a/python/dune/perftool/pdelab/signatures.py
+++ b/python/dune/perftool/pdelab/signatures.py
@@ -1,5 +1,5 @@
 """ Signatures for PDELab local opreator assembly functions """
-
+from dune.perftool.generation import get_global_context_value
 from dune.perftool.ufl.modified_terminals import Restriction
 from dune.perftool.pdelab.geometry import (name_geometry_wrapper,
                                            type_geometry_wrapper,
@@ -17,469 +17,307 @@ from dune.perftool.pdelab.spaces import (name_testfunctionspace,
                                          )
 
 
-def alpha_volume_signature(name):
+def ufl_measure_to_pdelab_measure(which):
+    return {'cell': 'Volume',
+            'exterior_facet': 'Boundary',
+            'interior_facet': 'Skeleton',
+            }.get(which)
+
+
+def assembler_routine_name():
+    from dune.perftool.generation import get_global_context_value
+    integral_type = get_global_context_value("integral_type")
+    form_type = get_global_context_value("form_type")
+
+    part1 = {"residual": "alpha"}.get(form_type, form_type)
+    part2 = ufl_measure_to_pdelab_measure(integral_type).lower()
+
+    return "{}_{}".format(part1, part2)
+
+
+def kernel_name():
+    arn = assembler_routine_name()
+    facedir_s = get_global_context_value("facedir_s", None)
+    facedir_n = get_global_context_value("facedir_n", None)
+    facemod_s = get_global_context_value("facemod_s", None)
+    facemod_n = get_global_context_value("facemod_n", None)
+    suffix = "{}{}{}{}".format("_facedirs{}".format(facedir_s) if facedir_s is not None else "",
+                               "_facedirn{}".format(facedir_n) if facedir_n is not None else "",
+                               "_facemods{}".format(facemod_s) if facemod_s is not None else "",
+                               "_facemodn{}".format(facemod_n) if facemod_n is not None else "",
+                               )
+
+    return "{}{}".format(arn, suffix)
+
+
+def assembly_routine_signature():
+    integral_type = get_global_context_value("integral_type")
+    form_type = get_global_context_value("form_type")
+    formdata = get_global_context_value("formdata")
+
+    templates, args = {('residual', 'cell'): (alpha_volume_templates, alpha_volume_args),
+              ('residual', 'exterior_facet'): (alpha_boundary_templates, alpha_boundary_args),
+              ('residual', 'interior_facet'): (alpha_skeleton_templates, alpha_skeleton_args),
+              ('jacobian', 'cell'): (jacobian_volume_templates, jacobian_volume_args),
+              ('jacobian', 'exterior_facet'): (jacobian_boundary_templates, jacobian_boundary_args),
+              ('jacobian', 'interior_facet'): (jacobian_skeleton_templates, jacobian_skeleton_args),
+              }.get((form_type, integral_type), (None, None))
+
+    if templates is None:
+        # Check if form is linear
+        from dune.perftool.pdelab.driver import is_linear
+        linear = is_linear(formdata.original_form)
+
+        templates, args = {('jacobian_apply', 'cell', True): (jacobian_apply_volume_templates, jacobian_apply_volume_args),
+                  ('jacobian_apply', 'exterior_facet', True): (jacobian_apply_boundary_templates, jacobian_apply_boundary_args),
+                  ('jacobian_apply', 'interior_facet', True): (jacobian_apply_skeleton_templates, jacobian_apply_skeleton_args),
+                  ('jacobian_apply', 'cell', False): (nonlinear_jacobian_apply_volume_templates, nonlinear_jacobian_apply_volume_args),
+                  ('jacobian_apply', 'exterior_facet', False): (nonlinear_jacobian_apply_boundary_templates, nonlinear_jacobian_apply_boundary_args),
+                  ('jacobian_apply', 'interior_facet', False): (nonlinear_jacobian_apply_skeleton_templates, nonlinear_jacobian_apply_skeleton_args),
+                  }.get((form_type, integral_type, linear), None)
+
+    return construct_signature(templates(), args(), kernel_name())
+
+
+def construct_signature(types, args, name):
+    templates = "template<{}>".format(", ".join("typename {}".format(t) for t in set(types)))
+    func = "void {}({}) const".format(name, ", ".join("{}{}& {}".format("const " if c else "", t, a) for t, (c, a) in zip(types, args)))
+    return [templates, func]
+
+
+def alpha_volume_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NONE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NONE)
     cct = type_coefficientcontainer()
-    cc = name_coefficientcontainer(Restriction.NONE)
     avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, avt)
+
+
+def alpha_volume_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NONE)
+    lfsv = name_testfunctionspace(Restriction.NONE)
+    cc = name_coefficientcontainer(Restriction.NONE)
     av = name_accumulation_variable((Restriction.NONE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                cc,
-                lfsvt,
-                lfsv,
-                avt,
-                av,
-                )
-            ]
-
-
-def alpha_boundary_signature(name):
+    return ((True, geo), (True, lfsu), (True, cc), (True, lfsv), (False, av))
+
+
+def alpha_boundary_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
     cct = type_coefficientcontainer()
-    cc = name_coefficientcontainer(Restriction.NEGATIVE)
     avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, avt)
+
+
+def alpha_boundary_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
+    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
+    cc = name_coefficientcontainer(Restriction.NEGATIVE)
     av = name_accumulation_variable((Restriction.NEGATIVE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                cc,
-                lfsvt,
-                lfsv,
-                avt,
-                av,
-                )
-            ]
-
-
-def alpha_skeleton_signature(name):
+    return ((True, geo), (True, lfsu), (True, cc), (True, lfsv), (False, av))
+
+
+def alpha_skeleton_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
+    lfsvt = type_testfunctionspace()
+    cct = type_coefficientcontainer()
+    avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, lfsut, cct, lfsvt, avt, avt)
+
+
+def alpha_skeleton_args():
+    geo = name_geometry_wrapper()
     lfsu_s = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsu_n = name_trialfunctionspace(Restriction.POSITIVE)
-    lfsvt = type_testfunctionspace()
     lfsv_s = name_testfunctionspace(Restriction.NEGATIVE)
     lfsv_n = name_testfunctionspace(Restriction.POSITIVE)
-    cct = type_coefficientcontainer()
     cc_s = name_coefficientcontainer(Restriction.NEGATIVE)
     cc_n = name_coefficientcontainer(Restriction.POSITIVE)
-    avt = type_accumulation_variable()
     av_s = name_accumulation_variable((Restriction.NEGATIVE,))
     av_n = name_accumulation_variable((Restriction.POSITIVE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu_s,
-                cct,
-                cc_s,
-                lfsvt,
-                lfsv_s,
-                lfsut,
-                lfsu_n,
-                cct,
-                cc_n,
-                lfsvt,
-                lfsv_n,
-                avt,
-                av_s,
-                avt,
-                av_n,
-                )
-            ]
-
-
-def jacobian_volume_signature(name):
+    return ((True, geo), (True, lfsu_s), (True, cc_s), (True, lfsv_s), (True, lfsu_n), (True, cc_n), (True, lfsv_n), (False, av_s), (False, av_n))
+
+
+def jacobian_volume_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NONE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NONE)
     cct = type_coefficientcontainer()
-    cc = name_coefficientcontainer(Restriction.NONE)
     avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, avt)
+
+
+def jacobian_volume_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NONE)
+    lfsv = name_testfunctionspace(Restriction.NONE)
+    cc = name_coefficientcontainer(Restriction.NONE)
     av = name_accumulation_variable((Restriction.NONE, Restriction.NONE))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                cc,
-                lfsvt,
-                lfsv,
-                avt,
-                av,
-                )
-            ]
-
-
-def jacobian_boundary_signature(name):
+    return ((True, geo), (True, lfsu), (True, cc), (True, lfsv), (False, av))
+
+
+def jacobian_boundary_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
     cct = type_coefficientcontainer()
-    cc = name_coefficientcontainer(Restriction.NEGATIVE)
     avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, avt)
+
+
+def jacobian_boundary_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
+    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
+    cc = name_coefficientcontainer(Restriction.NEGATIVE)
     av = name_accumulation_variable((Restriction.NEGATIVE, Restriction.NEGATIVE))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                cc,
-                lfsvt,
-                lfsv,
-                avt,
-                av,
-                )
-            ]
-
-
-def jacobian_skeleton_signature(name):
+    return ((True, geo), (True, lfsu), (True, cc), (True, lfsv), (False, av))
+
+
+def jacobian_skeleton_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
+    lfsvt = type_testfunctionspace()
+    cct = type_coefficientcontainer()
+    avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, lfsut, cct, lfsvt, avt, avt, avt, avt)
+
+
+def jacobian_skeleton_args():
+    geo = name_geometry_wrapper()
     lfsu_s = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsu_n = name_trialfunctionspace(Restriction.POSITIVE)
-    lfsvt = type_testfunctionspace()
     lfsv_s = name_testfunctionspace(Restriction.NEGATIVE)
     lfsv_n = name_testfunctionspace(Restriction.POSITIVE)
-    cct = type_coefficientcontainer()
     cc_s = name_coefficientcontainer(Restriction.NEGATIVE)
     cc_n = name_coefficientcontainer(Restriction.POSITIVE)
-    avt = type_accumulation_variable()
     av_ss = name_accumulation_variable((Restriction.NEGATIVE, Restriction.NEGATIVE))
     av_sn = name_accumulation_variable((Restriction.NEGATIVE, Restriction.POSITIVE))
     av_ns = name_accumulation_variable((Restriction.POSITIVE, Restriction.NEGATIVE))
     av_nn = name_accumulation_variable((Restriction.POSITIVE, Restriction.POSITIVE))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}, {}& {}, {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu_s,
-                cct,
-                cc_s,
-                lfsvt,
-                lfsv_s,
-                lfsut,
-                lfsu_n,
-                cct,
-                cc_n,
-                lfsvt,
-                lfsv_n,
-                avt,
-                av_ss,
-                avt,
-                av_sn,
-                avt,
-                av_ns,
-                avt,
-                av_nn,
-                )
-            ]
-
-
-def jacobian_apply_volume_signature(name):
+    return ((True, geo), (True, lfsu_s), (True, cc_s), (True, lfsv_s), (True, lfsu_n), (True, cc_n), (True, lfsv_n), (False, av_ss), (False, av_sn), (False, av_ns), (False, av_nn))
+
+
+def jacobian_apply_volume_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NONE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NONE)
     cct = type_coefficientcontainer()
-    ac = name_applycontainer(Restriction.NONE)
     avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, avt)
+
+
+def jacobian_apply_volume_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NONE)
+    lfsv = name_testfunctionspace(Restriction.NONE)
+    ac = name_applycontainer(Restriction.NONE)
     av = name_accumulation_variable((Restriction.NONE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                ac,
-                lfsvt,
-                lfsv,
-                avt,
-                av,)
-            ]
-
-
-def jacobian_apply_boundary_signature(name):
+    return ((True, geo), (True, lfsu), (True, ac), (True, lfsv), (False, av))
+
+
+def jacobian_apply_boundary_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
     cct = type_coefficientcontainer()
-    ac = name_applycontainer(Restriction.NEGATIVE)
     avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, avt)
+
+
+def jacobian_apply_boundary_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
+    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
+    ac = name_applycontainer(Restriction.NEGATIVE)
     av = name_accumulation_variable((Restriction.NEGATIVE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                ac,
-                lfsvt,
-                lfsv,
-                avt,
-                av,)
-            ]
-
-
-def jacobian_apply_skeleton_signature(name):
+    return ((True, geo), (True, lfsu), (True, ac), (True, lfsv), (False, av))
+
+
+def jacobian_apply_skeleton_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
+    lfsvt = type_testfunctionspace()
+    cct = type_coefficientcontainer()
+    avt = type_accumulation_variable()
+    return (geot, lfsut, cct, lfsvt, lfsut, cct, lfsvt, avt)
+
+
+def jacobian_apply_skeleton_args():
+    geo = name_geometry_wrapper()
     lfsu_s = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsu_n = name_trialfunctionspace(Restriction.POSITIVE)
-    lfsvt = type_testfunctionspace()
     lfsv_s = name_testfunctionspace(Restriction.NEGATIVE)
     lfsv_n = name_testfunctionspace(Restriction.POSITIVE)
-    cct = type_coefficientcontainer()
     ac_s = name_applycontainer(Restriction.NEGATIVE)
     ac_n = name_applycontainer(Restriction.POSITIVE)
-    avt = type_accumulation_variable()
     av_s = name_accumulation_variable((Restriction.NEGATIVE,))
     av_n = name_accumulation_variable((Restriction.POSITIVE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu_s,
-                cct,
-                ac_s,
-                lfsvt,
-                lfsv_s,
-                lfsut,
-                lfsu_n,
-                cct,
-                ac_n,
-                lfsvt,
-                lfsv_n,
-                avt,
-                av_s,
-                avt,
-                av_n,)
-            ]
-
-
-def nonlinear_jacobian_apply_volume_signature(name):
+    return ((True, geo), (True, lfsu_s), (True, ac_s), (True, lfsv_s), (True, lfsu_n), (True, ac_n), (True, lfsv_n), (False, av_s), (False, av_n))
+
+
+def nonlinear_jacobian_apply_volume_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NONE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NONE)
     cct = type_coefficientcontainer()
+    avt = type_accumulation_variable()
+    return (geot, lfsut, cct, cct, lfsvt, avt)
+
+
+def nonlinear_jacobian_apply_volume_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NONE)
+    lfsv = name_testfunctionspace(Restriction.NONE)
     cc = name_coefficientcontainer(Restriction.NONE)
     ac = name_applycontainer(Restriction.NONE)
-    avt = type_accumulation_variable()
     av = name_accumulation_variable((Restriction.NONE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                cc,
-                cct,
-                ac,
-                lfsvt,
-                lfsv,
-                avt,
-                av,)
-            ]
-
-
-def nonlinear_jacobian_apply_boundary_signature(name):
+    return ((True, geo), (True, lfsu), (True, cc), (True, ac), (True, lfsv), (False, av))
+
+
+def nonlinear_jacobian_apply_boundary_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
-    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsvt = type_testfunctionspace()
-    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
     cct = type_coefficientcontainer()
+    avt = type_accumulation_variable()
+    return (geot, lfsut, cct, cct, lfsvt, avt)
+
+
+def nonlinear_jacobian_apply_boundary_args():
+    geo = name_geometry_wrapper()
+    lfsu = name_trialfunctionspace(Restriction.NEGATIVE)
+    lfsv = name_testfunctionspace(Restriction.NEGATIVE)
     cc = name_coefficientcontainer(Restriction.NEGATIVE)
     ac = name_applycontainer(Restriction.NEGATIVE)
-    avt = type_accumulation_variable()
     av = name_accumulation_variable((Restriction.NEGATIVE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu,
-                cct,
-                cc,
-                cct,
-                ac,
-                lfsvt,
-                lfsv,
-                avt,
-                av,)
-            ]
-
-
-def nonlinear_jacobian_apply_skeleton_signature(name):
+    return ((True, geo), (True, lfsu), (True, cc), (True, ac), (True, lfsv), (False, av))
+
+
+def nonlinear_jacobian_apply_skeleton_templates():
     geot = type_geometry_wrapper()
-    geo = name_geometry_wrapper()
     lfsut = type_trialfunctionspace()
+    lfsvt = type_testfunctionspace()
+    cct = type_coefficientcontainer()
+    avt = type_accumulation_variable()
+    return (geot, lfsut, cct, cct, lfsvt, lfsut, cct, cct, lfsvt, avt, avt)
+
+
+def nonlinear_jacobian_apply_skeleton_args():
+    geo = name_geometry_wrapper()
     lfsu_s = name_trialfunctionspace(Restriction.NEGATIVE)
     lfsu_n = name_trialfunctionspace(Restriction.POSITIVE)
-    lfsvt = type_testfunctionspace()
     lfsv_s = name_testfunctionspace(Restriction.NEGATIVE)
     lfsv_n = name_testfunctionspace(Restriction.POSITIVE)
-    cct = type_coefficientcontainer()
     cc_s = name_coefficientcontainer(Restriction.NEGATIVE)
     cc_n = name_coefficientcontainer(Restriction.POSITIVE)
     ac_s = name_applycontainer(Restriction.NEGATIVE)
     ac_n = name_applycontainer(Restriction.POSITIVE)
-    avt = type_accumulation_variable()
     av_s = name_accumulation_variable((Restriction.NEGATIVE,))
     av_n = name_accumulation_variable((Restriction.POSITIVE,))
-    return ['template<typename {}, typename {}, typename {}, typename {}, typename {}>'.format(
-                geot,
-                lfsut,
-                cct,
-                lfsvt,
-                avt,
-                ),
-            'void {}(const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, const {}& {}, {}& {}, {}& {}) const'.format(
-                name,
-                geot,
-                geo,
-                lfsut,
-                lfsu_s,
-                cct,
-                cc_s,
-                cct,
-                ac_s,
-                lfsvt,
-                lfsv_s,
-                lfsut,
-                lfsu_n,
-                cct,
-                cc_n,
-                cct,
-                ac_n,
-                lfsvt,
-                lfsv_n,
-                avt,
-                av_s,
-                avt,
-                av_n,)
-            ]
+    return ((True, geo), (True, lfsu_s), (True, cc_s), (True, ac_s), (True, lfsv_s), (True, lfsu_n), (True, cc_n), (True, ac_n), (True, lfsv_n), (False, av_s), (False, av_n))
-- 
GitLab