diff --git a/python/dune/perftool/generation/cpp.py b/python/dune/perftool/generation/cpp.py index 5affeabff3b863a2109430dc987fdbdde3b0f593..c23550a13b2714bea08c7404f932d8ab96f667f7 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 8214ec765843f038b4c4bad7d868ee7b78c3ba06..b99ea877dbfb679f24844a8f8dc7fc9f8d1cd778 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 96477b8ec6b8c901bf977f632761fe03d87ca60c..682812e34f838f8633f6baecee5ac46d9b4f2f9a 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 bb06887bda178553fc2a079983f9d9e73b510b0a..86e1ccbad0596af5e27277cce1d51b716291219f 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 d6c54214fd0038e817d5d3f9e140edfaefb73b5b..bc42d0af6651082e86e852b0260d0b9274f8e7f9 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 95aa96f6bc8191e6b5f8905c4aebd9150f252c63..5289f829a9260a96215b9a34b89ec2ec6b65d0f2 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 634f7f9ac5fc55020d9e4fac2597d7ddb8cc829b..71fe4fcfa6a41c9ef2a1c7494654223b64898739 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 + )