From 1c4765189dec0b3b8d14a606b2bc73deeccb21a7 Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Thu, 8 Dec 2016 22:49:38 +0100
Subject: [PATCH] Add simplification of variants for YaspGrid

Not all variants appear in YaspGrids. The number of variant
reduces from 4*d*d -> 2*d for skeleton integrals.
---
 python/dune/perftool/sumfact/switch.py | 41 +++++++++++++++++++-------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/python/dune/perftool/sumfact/switch.py b/python/dune/perftool/sumfact/switch.py
index d46d5d75..4fa63064 100644
--- a/python/dune/perftool/sumfact/switch.py
+++ b/python/dune/perftool/sumfact/switch.py
@@ -10,6 +10,7 @@ from dune.perftool.pdelab.signatures import (assembly_routine_args,
                                              assembly_routine_signature,
                                              kernel_name,
                                              )
+from dune.perftool.options import get_option
 from dune.perftool.cgen.clazz import ClassMember
 
 
@@ -37,8 +38,9 @@ def generate_kernels_per_integral(integrals):
             for facemod_s in range(2):
                 for facedir_n in range(dim):
                     for facemod_n in range(2):
-                        with global_context(facedir_s=facedir_s, facemod_s=facemod_s, facedir_n=facedir_n, facemod_n=facemod_n):
-                            yield generate_kernel(integrals)
+                        if decide_if_kernel_is_necessary(facedir_s, facemod_s, facedir_n, facemod_n):
+                            with global_context(facedir_s=facedir_s, facemod_s=facemod_s, facedir_n=facedir_n, facemod_n=facemod_n):
+                                yield generate_kernel(integrals)
 
         # Generate switch statement
         yield generate_interior_facet_switch()
@@ -49,6 +51,24 @@ def get_kernel_name(facedir_s=None, facemod_s=None, facedir_n=None, facemod_n=No
         return kernel_name()
 
 
+def decide_if_kernel_is_necessary(facedir_s, facemod_s, facedir_n, facemod_n):
+    # If we are not using YaspGrid, all variants need to be realized
+    if not get_option("diagonal_transformation_matrix"):
+        return True
+
+    # A codim1 entity is can never be on the upper resp. lower side of the ref element
+    # in both inside and outside cell in a YaspGrid
+    if facemod_n == facemod_s:
+        return False
+
+    # A codim1 entity has the same orientation in both the embedding in the inside
+    # and outside cell for a YaspGrid
+    if facedir_n != facedir_s:
+        return False
+
+    return True
+
+
 def generate_exterior_facet_switch():
     # Extract the signature
     signature = assembly_routine_signature()
@@ -85,7 +105,7 @@ def generate_interior_facet_switch():
     # Construct the switch statement
     block = []
     block.append("{")
-    block.append("  size_t variant = ig.indexInOutside() + 6 * ig.indexInInside();")
+    block.append("  size_t variant = ig.indexInOutside() + {} * ig.indexInInside();".format(2 * dim))
     block.append("  switch(variant)")
     block.append("  {")
 
@@ -93,13 +113,14 @@ def generate_interior_facet_switch():
         for facemod_s in range(2):
             for facedir_n in range(dim):
                 for facemod_n in range(2):
-                    block.append("    case {}: {}({}); break;".format((dim * facedir_s + facemod_s) * (2 * dim) + dim * facedir_n + facemod_n,
-                                                                      get_kernel_name(facedir_s=facedir_s,
-                                                                                      facemod_s=facemod_s,
-                                                                                      facedir_n=facedir_n,
-                                                                                      facemod_n=facemod_n,
-                                                                                      ),
-                                                                      args))
+                    if decide_if_kernel_is_necessary(facedir_s, facemod_s, facedir_n, facemod_n):
+                        block.append("    case {}: {}({}); break;".format((dim * facedir_s + facemod_s) * (2 * dim) + dim * facedir_n + facemod_n,
+                                                                          get_kernel_name(facedir_s=facedir_s,
+                                                                                          facemod_s=facemod_s,
+                                                                                          facedir_n=facedir_n,
+                                                                                          facemod_n=facemod_n,
+                                                                                          ),
+                                                                          args))
 
     block.append("  }")
     block.append("}")
-- 
GitLab