From 2ebe64b3fba8586c9fe16ab8329d17626652e527 Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Mon, 25 Apr 2016 11:13:14 +0200
Subject: [PATCH] Working poisson_symdiff system test

---
 python/dune/perftool/generation/cpp.py       | 14 +++++------
 python/dune/perftool/generation/loopy.py     | 20 ++++++++--------
 python/dune/perftool/loopy/transformer.py    | 25 +++++++++++++++-----
 python/dune/perftool/pdelab/argument.py      |  5 ++++
 python/dune/perftool/pdelab/geometry.py      |  4 ++--
 python/dune/perftool/pdelab/localoperator.py |  2 +-
 test/poisson/CMakeLists.txt                  | 14 ++++++-----
 7 files changed, 52 insertions(+), 32 deletions(-)

diff --git a/python/dune/perftool/generation/cpp.py b/python/dune/perftool/generation/cpp.py
index 5affeabf..c23550a1 100644
--- a/python/dune/perftool/generation/cpp.py
+++ b/python/dune/perftool/generation/cpp.py
@@ -13,13 +13,13 @@ preamble = generator_factory(item_tags=("preamble",), counted=True)
 def include_file(include, filetag=None):
     assert filetag
     from cgen import Include
-    gen = generator_factory(on_store=lambda i: Include(i), item_tags=(filetag, "include"), no_deco=True)
+    gen = generator_factory(on_store=lambda i: Include(i), item_tags=("file", filetag, "include"), no_deco=True)
     return gen(include)
 
 
 def initializer_list(obj, params, classtag=None):
     assert classtag
-    gen = generator_factory(item_tags=(classtag, "initializer"), counted=True, no_deco=True, cache_key_generator=lambda *a: a[0])
+    gen = generator_factory(item_tags=("clazz", classtag, "initializer"), counted=True, no_deco=True, cache_key_generator=lambda *a: a[0])
     return gen("{}({})".format(obj, ", ".join(params)))
 
 
@@ -27,7 +27,7 @@ def base_class(baseclass, classtag=None, access=AccessModifier.PUBLIC, construct
     assert classtag
 
     from dune.perftool.cgen.clazz import BaseClass
-    gen = generator_factory(item_tags=("baseclass", classtag), on_store=lambda n: BaseClass(n, inheritance=access), counted=True, no_deco=True)
+    gen = generator_factory(item_tags=("clazz", "baseclass", classtag), on_store=lambda n: BaseClass(n, inheritance=access), counted=True, no_deco=True)
 
     if construction:
         initializer_list(baseclass, construction, classtag=classtag)
@@ -40,7 +40,7 @@ def class_member(classtag=None, access=AccessModifier.PRIVATE):
     from cgen import Value
     from dune.perftool.cgen.clazz import ClassMember
 
-    return generator_factory(item_tags=(classtag, "member"), on_store=lambda m: ClassMember(m, access=access), counted=True)
+    return generator_factory(item_tags=("clazz", classtag, "member"), on_store=lambda m: ClassMember(m, access=access), counted=True)
 
 
 def constructor_parameter(_type, name, classtag=None, constructortag="default"):
@@ -48,17 +48,17 @@ def constructor_parameter(_type, name, classtag=None, constructortag="default"):
     assert constructortag
     from cgen import Value
 
-    gen = generator_factory(item_tags=(classtag, constructortag, "constructor_param"), counted=True, no_deco=True)
+    gen = generator_factory(item_tags=("clazz", classtag, constructortag, "constructor_param"), counted=True, no_deco=True)
     return gen(Value(_type, name))
 
 
 def template_parameter(classtag=None):
     assert classtag
 
-    return generator_factory(item_tags=(classtag, "template_param"), counted=True)
+    return generator_factory(item_tags=("clazz", classtag, "template_param"), counted=True)
 
 
 def class_basename(classtag=None):
     assert classtag
 
-    return generator_factory(item_tags=(classtag, "basename"))
+    return generator_factory(item_tags=("clazz", classtag, "basename"))
diff --git a/python/dune/perftool/generation/loopy.py b/python/dune/perftool/generation/loopy.py
index 8214ec76..b99ea877 100644
--- a/python/dune/perftool/generation/loopy.py
+++ b/python/dune/perftool/generation/loopy.py
@@ -8,13 +8,13 @@ from dune.perftool.generation import (generator_factory,
 import loopy
 import numpy
 
-iname = generator_factory(item_tags=("loopy", "kernel", "iname"))
-valuearg = generator_factory(item_tags=("loopy", "kernel", "argument", "valuearg"), on_store=lambda n: loopy.ValueArg(n), no_deco=True)
-pymbolic_expr = generator_factory(item_tags=("loopy", "kernel", "pymbolic"))
-constantarg = generator_factory(item_tags=("loopy", "kernel", "argument", "constantarg"), on_store=lambda n: loopy.ConstantArg(n))
+iname = generator_factory(item_tags=("iname",))
+valuearg = generator_factory(item_tags=("argument", "valuearg"), on_store=lambda n: loopy.ValueArg(n), no_deco=True)
+pymbolic_expr = generator_factory(item_tags=("kernel", "pymbolic"))
+constantarg = generator_factory(item_tags=("kernel", "argument", "constantarg"), on_store=lambda n: loopy.ConstantArg(n))
 
 
-@generator_factory(item_tags=("loopy", "kernel", "argument", "globalarg"),
+@generator_factory(item_tags=("argument", "globalarg"),
                    cache_key_generator=lambda n, **kw: n)
 def globalarg(name, shape=loopy.auto, **kw):
     if isinstance(shape, str):
@@ -22,7 +22,7 @@ def globalarg(name, shape=loopy.auto, **kw):
     return loopy.GlobalArg(name, dtype=numpy.float64, shape=shape, **kw)
 
 
-@generator_factory(item_tags=("loopy", "kernel", "domain"))
+@generator_factory(item_tags=("domain",))
 def domain(iname, shape):
     if isinstance(shape, str):
         valuearg(shape)
@@ -59,7 +59,7 @@ def default_declaration(name, shape, shape_impl):
         return '{} {}(0.0);'.format(t, name)
 
 
-@generator_factory(item_tags=("loopy", "kernel", "temporary"), cache_key_generator=lambda n, **kw: n)
+@generator_factory(item_tags=("temporary",), cache_key_generator=lambda n, **kw: n)
 def temporary_variable(name, **kwargs):
     if 'dtype' not in kwargs:
         kwargs['dtype'] = numpy.float64
@@ -79,7 +79,7 @@ def temporary_variable(name, **kwargs):
 # actually adds the instruction. Hashing is done based on the code snippet.
 
 
-@generator_factory(item_tags=("loopy", "kernel", "instruction", "cinstruction"),
+@generator_factory(item_tags=("instruction", "cinstruction"),
                    cache_key_generator=lambda *a, **kw: kw['code'],
                    )
 def c_instruction_impl(**kw):
@@ -89,7 +89,7 @@ def c_instruction_impl(**kw):
     return loopy.CInstruction(inames, **kw)
 
 
-@generator_factory(item_tags=("loopy", "kernel", "instruction", "exprinstruction"),
+@generator_factory(item_tags=("instruction", "exprinstruction"),
                    cache_key_generator=lambda *a, **kw: kw['expression'],
                    )
 def expr_instruction_impl(**kw):
@@ -108,7 +108,7 @@ def _insn_cache_key(code=None, expression=None, **kwargs):
     raise ValueError("Please specify either code or expression for instruction!")
 
 
-@generator_factory(item_tags=("insn_id"), cache_key_generator=_insn_cache_key)
+@generator_factory(item_tags=("insn_id",), cache_key_generator=_insn_cache_key)
 def instruction(code=None, expression=None, **kwargs):
     assert code or expression
     assert not (code and expression)
diff --git a/python/dune/perftool/loopy/transformer.py b/python/dune/perftool/loopy/transformer.py
index 96477b8e..682812e3 100644
--- a/python/dune/perftool/loopy/transformer.py
+++ b/python/dune/perftool/loopy/transformer.py
@@ -158,23 +158,36 @@ def transform_accumulation_term(term):
         # Determine the shape
         residual_shape[arg.argexpr.number()] = name_lfs_bound(name_lfs(arg.argexpr.element()))
 
-    from dune.perftool.pdelab.argument import name_residual
-    residual = name_residual()
+    from dune.perftool.pdelab.argument import name_jacobian, name_residual
+    if len(test_ma) == 1:
+        accumvar = name_residual()
+    else:
+        accumvar = name_jacobian()
 
     # The residual/the jacobian should be represented through a loopy global argument
     # TODO this seems still a bit hacky, esp. w.r.t. systems
     shape = tuple(v for k, v in sorted(residual_shape.items(), key=lambda (k, v): k))
-    globalarg(residual, shape=shape)
+    globalarg(accumvar, shape=shape)
+
+    # In the jacobian case we might need to enforce the second loop!
+    if len(test_ma) == 2:
+        def _get_element(test_ma):
+            for ma in test_ma:
+                if ma.argexpr.count() == 1:
+                    return ma.argexpr.element()
+
+        acc_inames = acc_inames.union(frozenset({lfs_iname(_get_element(test_ma), argcount=1)}))
+
 
     from dune.perftool.pdelab.quadrature import name_factor
     factor = name_factor()
-    instruction(code="{}.accumulate({}, {}*{});".format(residual,
+    instruction(code="{}.accumulate({}, {}*{});".format(accumvar,
                                                         ", ".join(accumargs),
                                                         expr_tv_name,
                                                         factor,
                                                         ),
-                assignees=frozenset({residual}),
-                read_variables=frozenset({residual, factor, expr_tv_name}),
+                assignees=frozenset({accumvar}),
+                read_variables=frozenset({accumvar, factor, expr_tv_name}),
                 forced_iname_deps=acc_inames,
                 forced_iname_deps_is_final=True,
                 )
diff --git a/python/dune/perftool/pdelab/argument.py b/python/dune/perftool/pdelab/argument.py
index bb06887b..86e1ccba 100644
--- a/python/dune/perftool/pdelab/argument.py
+++ b/python/dune/perftool/pdelab/argument.py
@@ -105,6 +105,11 @@ def pymbolic_argument(ma):
     assert False
 
 
+@symbol
+def name_jacobian():
+    return "jac"
+
+
 @symbol
 def name_residual():
     return "r"
diff --git a/python/dune/perftool/pdelab/geometry.py b/python/dune/perftool/pdelab/geometry.py
index d6c54214..bc42d0af 100644
--- a/python/dune/perftool/pdelab/geometry.py
+++ b/python/dune/perftool/pdelab/geometry.py
@@ -78,5 +78,5 @@ def define_jacobian_inverse_transposed(name):
 
 @symbol
 def name_jacobian_inverse_transposed():
-    define_jacobian_inverse_transposed("J")
-    return "J"
+    define_jacobian_inverse_transposed("jit")
+    return "jit"
diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/perftool/pdelab/localoperator.py
index 95aa96f6..5289f829 100644
--- a/python/dune/perftool/pdelab/localoperator.py
+++ b/python/dune/perftool/pdelab/localoperator.py
@@ -168,7 +168,7 @@ def generate_kernel(integrand=None, measure=None):
 
     # All items with the kernel tags can be destroyed once a kernel has been generated
     from dune.perftool.generation import delete_cache_items
-    delete_cache_items("kernel")
+    delete_cache_items("(not file) and (not clazz)")
 
     # Return the actual code (might instead return kernels...)
     return kernel
diff --git a/test/poisson/CMakeLists.txt b/test/poisson/CMakeLists.txt
index 634f7f9a..71fe4fcf 100644
--- a/test/poisson/CMakeLists.txt
+++ b/test/poisson/CMakeLists.txt
@@ -12,9 +12,11 @@ dune_add_system_test(TARGET poisson_numdiff
 dune_symlink_to_source_files(FILES poisson_ref.vtu)
 
 
-#add_generated_executable(UFLFILE poisson.ufl
-#                         TARGET poisson_symdiff
-#                         )
-#
-#dune_add_system_test(TARGET poisson_symdiff
-#                     INIFILE poisson.mini)
+add_generated_executable(UFLFILE poisson.ufl
+                         TARGET poisson_symdiff
+                         )
+
+dune_add_system_test(TARGET poisson_symdiff
+                     INIFILE poisson.mini
+                     SCRIPT dune_vtkcompare.py
+                     )
-- 
GitLab