Commit 7f8d6873 authored by Martin Bauer's avatar Martin Bauer
Browse files

Bugfixes in LBM phase field code

- 3 phase model works now with step sytem
parent af40fa99
......@@ -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)
......
......@@ -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).
......
......@@ -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'
......
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)
......@@ -136,3 +136,5 @@ def createdIndexedCUDAKernel(listOfEquations, indexFields, functionName="kernel"
ast.indexing = indexing
ast.compile = partial(makePythonFunction, ast)
return ast
......@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment