From 7f8d6873ee200f8b8453cf93b673d531ead94515 Mon Sep 17 00:00:00 2001
From: Martin Bauer <martin.bauer@fau.de>
Date: Mon, 5 Feb 2018 12:42:52 +0100
Subject: [PATCH] Bugfixes in LBM phase field code

- 3 phase model works now with step sytem
---
 cpu/kernelcreation.py                  |  2 +-
 datahandling/datahandling_interface.py |  9 +++------
 datahandling/parallel_datahandling.py  | 11 ++++++-----
 datahandling/serial_datahandling.py    | 17 +++++++++++------
 gpucuda/kernelcreation.py              |  2 ++
 timeloop.py                            | 14 +++++++++-----
 6 files changed, 32 insertions(+), 23 deletions(-)

diff --git a/cpu/kernelcreation.py b/cpu/kernelcreation.py
index f290942ce..af2ddae9c 100644
--- a/cpu/kernelcreation.py
+++ b/cpu/kernelcreation.py
@@ -136,7 +136,7 @@ def createIndexedKernel(listOfEquations, indexFields, functionName="kernel", typ
         loopBody.append(assignment)
 
     functionBody = Block([loopNode])
-    ast = KernelFunction(functionBody, "cpu", functionName=functionName)
+    ast = KernelFunction(functionBody, backend="cpu", functionName=functionName)
 
     fixedCoordinateMapping = {f.name: coordinateTypedSymbols for f in nonIndexFields}
     resolveFieldAccesses(ast, set(['indexField']), fieldToFixedCoordinates=fixedCoordinateMapping)
diff --git a/datahandling/datahandling_interface.py b/datahandling/datahandling_interface.py
index 3d1ad21be..d4d1f428c 100644
--- a/datahandling/datahandling_interface.py
+++ b/datahandling/datahandling_interface.py
@@ -181,22 +181,19 @@ class DataHandling(ABC):
 
     # ------------------------------- Communication --------------------------------------------------------------------
 
-    def synchronizationFunctionCPU(self, names, stencil=None, **kwargs):
+    @abstractmethod
+    def synchronizationFunction(self, names, stencil, target, **kwargs):
         """
         Synchronizes ghost layers for distributed arrays - for serial scenario this has to be called
         for correct periodicity handling
         :param names: what data to synchronize: name of array or sequence of names
         :param stencil: stencil as string defining which neighbors are synchronized e.g. 'D2Q9', 'D3Q19'
                         if None, a full synchronization (i.e. D2Q9 or D3Q27) is done
+        :param target: either 'cpu' or 'gpu
         :param kwargs: implementation specific, optional optimization parameters for communication
         :return: function object to run the communication
         """
 
-    def synchronizationFunctionGPU(self, names, stencil=None, **kwargs):
-        """
-        Synchronization of GPU fields, for documentation see CPU version above
-        """
-
     def reduceFloatSequence(self, sequence, operation, allReduce=False):
         """Takes a sequence of floating point values on each process and reduces it element wise to all
         processes (allReduce=True) or only to the root process (allReduce=False).
diff --git a/datahandling/parallel_datahandling.py b/datahandling/parallel_datahandling.py
index d35dbd3b0..2b1007434 100644
--- a/datahandling/parallel_datahandling.py
+++ b/datahandling/parallel_datahandling.py
@@ -205,7 +205,7 @@ class ParallelDataHandling(DataHandling):
             nameMap = self._fieldNameToCpuDataName
             toArray = wlb.field.toArray
         dataUsedInKernel = [(nameMap[p.fieldName], self.fields[p.fieldName])
-                            for p in kernelFunc.parameters if p.isFieldPtrArgument]
+                            for p in kernelFunc.parameters if p.isFieldPtrArgument and p.fieldName not in kwargs]
         for block in self.blocks:
             fieldArgs = {}
             for dataName, f in dataUsedInKernel:
@@ -229,10 +229,11 @@ class ParallelDataHandling(DataHandling):
             for block in self.blocks:
                 transferFunc(block[self.GPU_DATA_PREFIX + name], block[name])
         else:
+            print("trying to transfer ", self.GPU_DATA_PREFIX + name)
             wlb.cuda.copyFieldToGpu(self.blocks, self.GPU_DATA_PREFIX + name, name)
 
     def isOnGpu(self, name):
-        return name, self.GPU_DATA_PREFIX + name in self._cpuGpuPairs
+        return (name, self.GPU_DATA_PREFIX + name) in self._cpuGpuPairs
 
     def allToCpu(self):
         for cpuName, gpuName in self._cpuGpuPairs:
@@ -247,12 +248,12 @@ class ParallelDataHandling(DataHandling):
             self.toGpu(name)
 
     def synchronizationFunctionCPU(self, names, stencil=None, buffered=True, **kwargs):
-        return self._synchronizationFunction(names, stencil, buffered, 'cpu')
+        return self.synchronizationFunction(names, stencil, 'cpu',  buffered,)
 
     def synchronizationFunctionGPU(self, names, stencil=None, buffered=True, **kwargs):
-        return self._synchronizationFunction(names, stencil, buffered, 'gpu')
+        return self.synchronizationFunction(names, stencil, 'gpu', buffered)
 
-    def _synchronizationFunction(self, names, stencil, buffered, target):
+    def synchronizationFunction(self, names, stencil=None, target='cpu', buffered=True):
         if stencil is None:
             stencil = 'D3Q27' if self.dim == 3 else 'D2Q9'
 
diff --git a/datahandling/serial_datahandling.py b/datahandling/serial_datahandling.py
index caf446719..a70b48de1 100644
--- a/datahandling/serial_datahandling.py
+++ b/datahandling/serial_datahandling.py
@@ -1,11 +1,13 @@
-import numpy as np
 import itertools
+
+import numpy as np
+
 from pystencils import Field
+from pystencils.datahandling.datahandling_interface import DataHandling
 from pystencils.field import layoutStringToTuple, spatialLayoutStringToTuple, createNumpyArrayWithLayout
 from pystencils.parallel.blockiteration import SerialBlock
 from pystencils.slicing import normalizeSlice, removeGhostLayers
 from pystencils.utils import DotDict
-from pystencils.datahandling.datahandling_interface import DataHandling
 
 try:
     import pycuda.gpuarray as gpuarray
@@ -96,6 +98,8 @@ class SerialDataHandling(DataHandling):
 
         # cpuArr is always created - since there is no createPycudaArrayWithLayout()
         cpuArr = createNumpyArrayWithLayout(layout=layoutTuple, **kwargs)
+        cpuArr.fill(np.inf)
+
         if cpu:
             if name in self.cpuArrays:
                 raise ValueError("CPU Field with this name already exists")
@@ -195,7 +199,7 @@ class SerialDataHandling(DataHandling):
 
     def runKernel(self, kernelFunc, *args, **kwargs):
         dataUsedInKernel = [self._fieldLatexNameToDataName[p.fieldName]
-                            for p in kernelFunc.parameters if p.isFieldPtrArgument]
+                            for p in kernelFunc.parameters if p.isFieldPtrArgument and p.fieldName not in kwargs]
         arrays = self.gpuArrays if kernelFunc.ast.backend == 'gpucuda' else self.cpuArrays
         arrayParams = {name: arrays[name] for name in dataUsedInKernel}
         arrayParams.update(kwargs)
@@ -219,12 +223,12 @@ class SerialDataHandling(DataHandling):
         return name in self.gpuArrays
 
     def synchronizationFunctionCPU(self, names, stencilName=None, **kwargs):
-        return self._synchronizationFunctor(names, stencilName, 'cpu')
+        return self.synchronizationFunction(names, stencilName, 'cpu')
 
     def synchronizationFunctionGPU(self, names, stencilName=None, **kwargs):
-        return self._synchronizationFunctor(names, stencilName, 'gpu')
+        return self.synchronizationFunction(names, stencilName, 'gpu')
 
-    def _synchronizationFunctor(self, names, stencil, target):
+    def synchronizationFunction(self, names, stencil=None, target='cpu'):
         assert target in ('cpu', 'gpu')
         if not hasattr(names, '__len__') or type(names) is str:
             names = [names]
@@ -337,3 +341,4 @@ class SerialDataHandling(DataHandling):
         indDims = 1 if self._fieldInformation[name]['fSize'] > 1 else 0
         return removeGhostLayers(self.cpuArrays[name], indDims, glToRemove)
 
+
diff --git a/gpucuda/kernelcreation.py b/gpucuda/kernelcreation.py
index 7797b46a3..2c25243d3 100644
--- a/gpucuda/kernelcreation.py
+++ b/gpucuda/kernelcreation.py
@@ -136,3 +136,5 @@ def createdIndexedCUDAKernel(listOfEquations, indexFields, functionName="kernel"
     ast.indexing = indexing
     ast.compile = partial(makePythonFunction, ast)
     return ast
+
+
diff --git a/timeloop.py b/timeloop.py
index b6f3cfd51..c5c88a04f 100644
--- a/timeloop.py
+++ b/timeloop.py
@@ -6,6 +6,7 @@ class TimeLoop:
         self._preRunFunctions = []
         self._postRunFunctions = []
         self._timeStepFunctions = []
+        self._functionNames = []
         self.timeStepsRun = 0
 
     def addStep(self, stepObj):
@@ -13,13 +14,16 @@ class TimeLoop:
             self.addPreRunFunction(stepObj.preRun)
         if hasattr(stepObj, 'postRun'):
             self.addPostRunFunction(stepObj.postRun)
-        self.add(stepObj.timeStep)
+        self.add(stepObj.timeStep, stepObj.name)
 
-    def add(self, timeStepFunction):
+    def add(self, timeStepFunction, name=None):
+        if name is None:
+            name = str(timeStepFunction)
         self._timeStepFunctions.append(timeStepFunction)
+        self._functionNames.append(name)
 
-    def addKernel(self, dataHandling, kernelFunc):
-        self._timeStepFunctions.append(lambda: dataHandling.runKernel(kernelFunc))
+    def addKernel(self, dataHandling, kernelFunc, name=None):
+        self.add(lambda: dataHandling.runKernel(kernelFunc), name)
 
     def addPreRunFunction(self, f):
         self._preRunFunctions.append(f)
@@ -27,7 +31,7 @@ class TimeLoop:
     def addPostRunFunction(self, f):
         self._postRunFunctions.append(f)
 
-    def run(self, timeSteps=0):
+    def run(self, timeSteps=1):
         self.preRun()
 
         try:
-- 
GitLab