From fa121c19ded68e3d798c9b44322935bfc7d3c376 Mon Sep 17 00:00:00 2001
From: Markus Holzer <markus.holzer@fau.de>
Date: Thu, 11 Nov 2021 07:09:08 +0000
Subject: [PATCH] Testing

---
 .gitignore                                    |  1 +
 doc/notebooks/03_tutorial_datahandling.ipynb  | 85 ++++++++++++++-----
 pystencils/backends/cbackend.py               |  2 +-
 pystencils/cpu/cpujit.py                      |  9 +-
 pystencils/gpucuda/cudajit.py                 |  2 +-
 pystencils/utils.py                           | 22 +----
 .../test_datahandling_parallel.py             | 67 ++++++++-------
 7 files changed, 111 insertions(+), 77 deletions(-)

diff --git a/.gitignore b/.gitignore
index 41879ab79..d87144f7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ test-report
 pystencils/boundaries/createindexlistcython.c
 pystencils/boundaries/createindexlistcython.*.so
 pystencils_tests/tmp
+pystencils_tests/var
 pystencils_tests/kerncraft_inputs/.2d-5pt.c_kerncraft/
 pystencils_tests/kerncraft_inputs/.3d-7pt.c_kerncraft/
 report.xml
diff --git a/doc/notebooks/03_tutorial_datahandling.ipynb b/doc/notebooks/03_tutorial_datahandling.ipynb
index 8922efbec..da0162392 100644
--- a/doc/notebooks/03_tutorial_datahandling.ipynb
+++ b/doc/notebooks/03_tutorial_datahandling.ipynb
@@ -823,15 +823,10 @@
    "metadata": {},
    "outputs": [
     {
-     "ename": "ValueError",
-     "evalue": "Cannot create parallel data handling because walberla module is not available",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
-      "\u001b[0;32m/var/folders/07/0d7kq8fd0sx24cs53zz90_qc0000gp/T/ipykernel_12833/1198112608.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdh\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mps\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcreate_data_handling\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdomain_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m30\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m30\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparallel\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      2\u001b[0m \u001b[0mfield\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdh\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_array\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'field'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mblock\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdh\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0miterate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;31m# offset is in global coordinates, where first inner cell has coordiante (0,0)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;31m# and ghost layers have negative coordinates\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m~/pystencils/pystencils/pystencils/datahandling/__init__.py\u001b[0m in \u001b[0;36mcreate_data_handling\u001b[0;34m(domain_size, periodicity, default_layout, default_target, parallel, default_ghost_layers, opencl_queue)\u001b[0m\n\u001b[1;32m     46\u001b[0m         \u001b[0;32massert\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mopencl_queue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"OpenCL is only supported for SerialDataHandling\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     47\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mwlb\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 48\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Cannot create parallel data handling because walberla module is not available\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     49\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     50\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mperiodicity\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mFalse\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mperiodicity\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;31mValueError\u001b[0m: Cannot create parallel data handling because walberla module is not available"
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(-1, -1) (32, 32)\n"
      ]
     }
    ],
@@ -856,9 +851,20 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 21,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(-1, -1, -1) (22, 12, 22)\n",
+      "(19, -1, -1) (22, 12, 22)\n",
+      "(-1, -1, 19) (22, 12, 22)\n",
+      "(19, -1, 19) (22, 12, 22)\n"
+     ]
+    }
+   ],
    "source": [
     "from waLBerla import createUniformBlockGrid\n",
     "from pystencils.datahandling import ParallelDataHandling\n",
@@ -881,9 +887,24 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 22,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGoAAAAVCAYAAACuVXuDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADhUlEQVRoBe2Z7W3bMBCGHaMDGO0G6gZJs0GygeNO0HiDFv1l/yvSDdpOUCQbJBsE9Qb2BnW8gfs+jE5lJUo2bIoS0BxwOvL4dXqPR1LUYLvdDnyezWaZn39J/4tPCjxCPhgOPJrP5x+VPfVUL8luEMhyXxSjnzBDIBWMJc4lPzlFzUPlOHIqOS1Xke4m1/2WfCu+kW5Vrhcrn9tyq/7OlN6E+k1tk9mQ23YwTmpP0Gwkv9OniyhlRkp/lmx0Eg1EAPPapbyH2v5S9pE+xF+Vpq97pTOv2tFJ9TcS34q/qbMf4tr+VSeJTTUvdRROsh0McTS+eXaUJJHAizeSGuHlCkl/LSUA3lmh0sxw8jv7tTb7SPoVX4mJ6J91bVSezKayDRo7Fk5g51Yp26Mm6tyFWHlQy6ucJQ/w4TJdSbEoK5V/FF+orZsVgfI2VZ3YFBOn3Cf4ZjTUg71pn33kfd4wBO6FlOtAgfVLeWrqyqbYOIHhhIi6FD80oSgHEcrBJQxvN7XNyyp72h5tDq7SlU0t4YRvLnHUO/GyDhUNnqmMfcGio1zVnBBaEq3uPs60ujFkcptaxAnfZDgKEEPLlgHGyaNx/7KKDfJNQ1lXRbFtagsnfOMcxewLRoMcxMkpuOR56DY52WY231UpKalNLePESjYiooKUhzJH7rolz7VTuTk5tLyZrrGPoAFHKFPalAAnF0ivhAezzwD14WFv4qaCDzefTpXhigP9SpIPWzY86pfJIqrxsFJuFCmfyqa2ccI3axzFbK+ALAfwohWApX9CL8l3ihFOs+sj0yHPxAvV3ZhSaaK0yJu+BZnEJr1LKzh5eDDZV0M9FuJzr2BXEg/DBclYDhtrSb7JHClNnYn4w7PG3Seie1IZVzsxyA4EFrlFnx3aZDYcjJN1kEs32U90pc5Sxt0Zl6i1pHIOFUSefbxyPcTdHndSA0kMI6o2Yg4POP+L9EyEgpS3T4Hai9Sick1CfdhyjC2MyxisDNwtFidUpZPZpLEdacwoOHn9gdfU/YuSs5Y4LMW/FsbQWGPxKNV4+4zTU5sy2bXEfpY+iEio/LZwJe08OKQQeX2iPtrEQe3vpWy+XHCSqxwqYiOpMViOUn9XNb5GT23CF/jELeUWUbwIp7hdH7fUO5auNbjb147tKGL7PtqEL4pVrvjDy0sLQLw47iGQmPffkPDnEvxOsrgo+AP8ixo954XzTQAAAABJRU5ErkJggg==\n",
+      "text/latex": [
+       "$\\displaystyle \\left( 40, \\  10, \\  40\\right)$"
+      ],
+      "text/plain": [
+       "(40, 10, 40)"
+      ]
+     },
+     "execution_count": 22,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
     "dh.gather_array('field').shape"
    ]
@@ -899,7 +920,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 23,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -926,9 +947,22 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 24,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 1152x432 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
    "source": [
     "dh.fill('src', 0.0)\n",
     "for block in dh.iterate(ghost_layers=False, inner_ghost_layers=False):\n",
@@ -947,7 +981,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 25,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -960,9 +994,22 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 26,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 1152x432 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
    "source": [
     "plt.scalar_field( dh.gather_array('src') );"
    ]
diff --git a/pystencils/backends/cbackend.py b/pystencils/backends/cbackend.py
index c4d178639..d590fd87c 100644
--- a/pystencils/backends/cbackend.py
+++ b/pystencils/backends/cbackend.py
@@ -123,7 +123,7 @@ def get_headers(ast_node: Node) -> Set[str]:
     for h in headers:
         assert HEADER_REGEX.match(h), f'header /{h}/ does not follow the pattern /"..."/ or /<...>/'
 
-    return sorted(headers)
+    return headers
 
 
 # --------------------------------------- Backend Specific Nodes -------------------------------------------------------
diff --git a/pystencils/cpu/cpujit.py b/pystencils/cpu/cpujit.py
index 7144a58bd..ac1e8ac4f 100644
--- a/pystencils/cpu/cpujit.py
+++ b/pystencils/cpu/cpujit.py
@@ -63,7 +63,7 @@ from pystencils.backends.cbackend import generate_c, get_headers, CFunction
 from pystencils.data_types import cast_func, VectorType, vector_memory_access
 from pystencils.include import get_pystencils_include_path
 from pystencils.kernel_wrapper import KernelWrapper
-from pystencils.utils import atomic_file_write, file_handle_for_atomic_write, recursive_dict_update
+from pystencils.utils import atomic_file_write, recursive_dict_update
 
 
 def make_python_function(kernel_function_node, custom_backend=None):
@@ -601,8 +601,11 @@ def compile_module(code, code_hash, base_dir, compile_flags=None):
     object_file = os.path.join(base_dir, code_hash + object_suffix)
 
     if not os.path.exists(object_file):
-        with file_handle_for_atomic_write(src_file) as f:
-            code.write_to_file(f)
+        try:
+            with open(src_file, 'x') as f:
+                code.write_to_file(f)
+        except FileExistsError:
+            pass
 
         if windows:
             compile_cmd = ['cl.exe', '/c', '/EHsc'] + compiler_config['flags'].split()
diff --git a/pystencils/gpucuda/cudajit.py b/pystencils/gpucuda/cudajit.py
index 03dfc8245..3f752700b 100644
--- a/pystencils/gpucuda/cudajit.py
+++ b/pystencils/gpucuda/cudajit.py
@@ -41,7 +41,7 @@ def make_python_function(kernel_function_node, argument_dict=None, custom_backen
         argument_dict = {}
 
     header_list = ['<cstdint>'] + list(get_headers(kernel_function_node))
-    includes = "\n".join(["#include %s" % (include_file,) for include_file in header_list])
+    includes = "\n".join([f"#include {include_file}" for include_file in header_list])
 
     code = includes + "\n"
     code += "#define FUNC_PREFIX __global__\n"
diff --git a/pystencils/utils.py b/pystencils/utils.py
index bdeab9536..3afdbc582 100644
--- a/pystencils/utils.py
+++ b/pystencils/utils.py
@@ -51,33 +51,13 @@ def recursive_dict_update(d, u):
     return d
 
 
-@contextmanager
-def file_handle_for_atomic_write(file_path):
-    """Open temporary file object that atomically moves to destination upon exiting.
-
-    Allows reading and writing to and from the same filename.
-    The file will not be moved to destination in case of an exception.
-
-    Args:
-        file_path: path to file to be opened
-    """
-    target_folder = os.path.dirname(os.path.abspath(file_path))
-    with NamedTemporaryFile(delete=False, dir=target_folder, mode='w') as f:
-        try:
-            yield f
-        finally:
-            f.flush()
-            os.fsync(f.fileno())
-    os.rename(f.name, file_path)
-
-
 @contextmanager
 def atomic_file_write(file_path):
     target_folder = os.path.dirname(os.path.abspath(file_path))
     with NamedTemporaryFile(delete=False, dir=target_folder) as f:
         f.file.close()
         yield f.name
-    os.rename(f.name, file_path)
+    os.replace(f.name, file_path)
 
 
 def fully_contains(l1, l2):
diff --git a/pystencils_tests/test_datahandling_parallel.py b/pystencils_tests/test_datahandling_parallel.py
index 82567fe45..dd18e4fb1 100644
--- a/pystencils_tests/test_datahandling_parallel.py
+++ b/pystencils_tests/test_datahandling_parallel.py
@@ -4,7 +4,6 @@ import waLBerla as wlb
 import pystencils
 from pystencils import make_slice
 
-from tempfile import TemporaryDirectory
 from pathlib import Path
 
 from pystencils.boundaries import BoundaryHandling, Neumann
@@ -39,9 +38,7 @@ def test_access_and_gather():
 
 
 def test_gpu():
-    if not hasattr(wlb, 'cuda'):
-        print("Skip GPU tests because walberla was built without CUDA")
-        return
+    pytest.importorskip('waLBerla.cuda')
 
     block_size = (4, 7, 1)
     num_blocks = (3, 2, 1)
@@ -59,24 +56,22 @@ def test_gpu():
         np.testing.assert_equal(b['v'], 42)
 
 
-def test_kernel():
-
-    for gpu in (True, False):
-        if gpu and not hasattr(wlb, 'cuda'):
-            print("Skipping CUDA tests because walberla was built without GPU support")
-            continue
+@pytest.mark.parametrize('target', (pystencils.Target.CPU, pystencils.Target.GPU))
+def test_kernel(target):
+    if target == pystencils.Target.GPU:
+        pytest.importorskip('waLBerla.cuda')
 
-        # 3D
-        blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 4), cellsPerBlock=(3, 2, 5), oneBlockPerProcess=False)
-        dh = ParallelDataHandling(blocks)
-        kernel_execution_jacobi(dh, pystencils.Target.GPU)
-        reduction(dh)
+    # 3D
+    blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 4), cellsPerBlock=(3, 2, 5), oneBlockPerProcess=False)
+    dh = ParallelDataHandling(blocks, default_target=target)
+    kernel_execution_jacobi(dh, target)
+    reduction(dh)
 
-        # 2D
-        blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 1), cellsPerBlock=(3, 2, 1), oneBlockPerProcess=False)
-        dh = ParallelDataHandling(blocks, dim=2)
-        kernel_execution_jacobi(dh, pystencils.Target.GPU)
-        reduction(dh)
+    # 2D
+    blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 1), cellsPerBlock=(3, 2, 1), oneBlockPerProcess=False)
+    dh = ParallelDataHandling(blocks, dim=2, default_target=target)
+    kernel_execution_jacobi(dh, target)
+    reduction(dh)
 
 
 def test_vtk_output():
@@ -90,7 +85,7 @@ def test_block_iteration():
     num_blocks = (2, 2, 2)
     blocks = wlb.createUniformBlockGrid(blocks=num_blocks, cellsPerBlock=block_size, oneBlockPerProcess=False)
     dh = ParallelDataHandling(blocks, default_ghost_layers=2)
-    dh.add_array('v', values_per_cell=1, dtype=np.int64, ghost_layers=2, gpu=True)
+    dh.add_array('v', values_per_cell=1, dtype=np.int64, ghost_layers=2)
 
     for b in dh.iterate():
         b['v'].fill(1)
@@ -113,10 +108,12 @@ def test_block_iteration():
 
 
 def test_getter_setter():
+    pytest.importorskip('waLBerla.cuda')
+
     block_size = (2, 2, 2)
     num_blocks = (2, 2, 2)
     blocks = wlb.createUniformBlockGrid(blocks=num_blocks, cellsPerBlock=block_size, oneBlockPerProcess=False)
-    dh = ParallelDataHandling(blocks, default_ghost_layers=2)
+    dh = ParallelDataHandling(blocks, default_ghost_layers=2, default_target=pystencils.Target.GPU)
     dh.add_array('v', values_per_cell=1, dtype=np.int64, ghost_layers=2, gpu=True)
 
     assert dh.shape == (4, 4, 4)
@@ -135,14 +132,19 @@ def test_getter_setter():
 
 def test_parallel_datahandling_boundary_conditions():
     pytest.importorskip('waLBerla.cuda')
-    dh = create_data_handling(domain_size=(7, 7), periodicity=True, parallel=True, default_target=pystencils.Target.GPU)
-    src = dh.add_array('src')
-    src2 = dh.add_array('src2')
-    dh.fill("src", 0.0, ghost_layers=True)
-    dh.fill("src", 1.0, ghost_layers=False)
-    src_cpu = dh.add_array('src_cpu', gpu=False)
-    dh.fill("src_cpu", 0.0, ghost_layers=True)
-    dh.fill("src_cpu", 1.0, ghost_layers=False)
+
+    dh = create_data_handling(domain_size=(7, 7), periodicity=True, parallel=True,
+                              default_target=pystencils.Target.GPU)
+
+    src = dh.add_array('src', values_per_cell=1)
+    dh.fill(src.name, 0.0, ghost_layers=True)
+    dh.fill(src.name, 1.0, ghost_layers=False)
+
+    src2 = dh.add_array('src2', values_per_cell=1)
+
+    src_cpu = dh.add_array('src_cpu', values_per_cell=1, gpu=False)
+    dh.fill(src_cpu.name, 0.0, ghost_layers=True)
+    dh.fill(src_cpu.name, 1.0, ghost_layers=False)
 
     boundary_stencil = [(1, 0), (-1, 0), (0, 1), (0, -1)]
     boundary_handling_cpu = BoundaryHandling(dh, src_cpu.name, boundary_stencil,
@@ -165,10 +167,11 @@ def test_parallel_datahandling_boundary_conditions():
     boundary_handling()
     dh.all_to_cpu()
     for block in dh.iterate():
-        np.testing.assert_almost_equal(block["src_cpu"], block["src"])
+        np.testing.assert_almost_equal(block[src_cpu.name], block[src.name])
 
     assert dh.custom_data_names == ('boundary_handling_cpuIndexArrays', 'boundary_handling_gpuIndexArrays')
-    dh.swap("src", "src2", gpu=True)
+    dh.swap(src.name, src2.name, gpu=True)
+
 
 def test_save_data():
     domain_shape = (2, 2)
-- 
GitLab