Skip to content
Snippets Groups Projects
Commit 0e2c793a authored by Martin Bauer's avatar Martin Bauer
Browse files

Removed flag array support

because boundary handling does its own flag management
parent 032f1be5
No related merge requests found
......@@ -4,7 +4,6 @@ from abc import ABC, abstractmethod, abstractproperty
from collections import defaultdict
from contextlib import contextmanager
from lbmpy.boundaries.periodicityhandling import PeriodicityHandling
from lbmpy.stencils import getStencil
from pystencils import Field, makeSlice
from pystencils.parallel.blockiteration import BlockIterationInfo
......@@ -16,62 +15,6 @@ try:
except ImportError:
gpuarray = None
class WalberlaFlagInterface:
def __init__(self, flagField):
self.flagField = flagField
def registerFlag(self, flagName):
return self.flagField.registerFlag(flagName)
def flag(self, flagName):
return self.flagField.flag(flagName)
def flagName(self, flag):
return self.flagField.flagName(flag)
@property
def flags(self):
return self.flagField.flags
class PythonFlagInterface:
def __init__(self):
self.nameToFlag = {}
self.flagToName = {}
self.nextFreeBit = 0
def registerFlag(self, flagName):
assert flagName not in self.nameToFlag
flag = 1 << self.nextFreeBit
self.nextFreeBit += 1
self.flagToName[flag] = flagName
self.nameToFlag[flagName] = flag
return flag
def flag(self, flagName):
return self.nameToFlag[flagName]
def flagName(self, flag):
return self.flagToName[flag]
@property
def flags(self):
return tuple(self.nameToFlag.keys())
class FlagArray(np.ndarray):
def __new__(cls, inputArray, flagInterface):
obj = np.asarray(inputArray).view(cls)
obj.flagInterface = flagInterface
assert inputArray.dtype.kind in ('u', 'i'), "FlagArrays can only be created from integer arrays"
return obj
def __array_finalize__(self, obj):
if obj is None: return
self.flagInterface = getattr(obj, 'flagInterface', None)
class DataHandling(ABC):
"""
Manages the storage of arrays and maps them to a symbolic field.
......@@ -113,6 +56,12 @@ class DataHandling(ABC):
:param gpu: allocate field on the GPU
"""
@abstractmethod
def hasData(self, name):
"""
Returns true if a field or custom data element with this name was added
"""
@abstractmethod
def addLike(self, name, nameOfTemplateField, latexName=None, cpu=True, gpu=False):
"""
......@@ -124,13 +73,6 @@ class DataHandling(ABC):
:param gpu: see 'add' method
"""
def addFlagArray(self, name, dtype=np.int32, latexName=None, ghostLayers=None):
"""
Adds a flag array (of integer type) where each bit is interpreted as a boolean
Flag arrays additionally store a mapping of name to bit nr, which is accessible as arr.flagInterface.
For parameter documentation see 'add()' function.
"""
@property
@abstractmethod
def fields(self):
......@@ -297,13 +239,10 @@ class SerialDataHandling(DataHandling):
self.fields[name] = Field.createFixedSize(latexName, shape=kwargs['shape'], indexDimensions=indexDimensions,
dtype=kwargs['dtype'], layout=kwargs['order'])
def addFlagArray(self, name, dtype=np.int32, latexName=None, ghostLayers=None):
self.add(name, 1, dtype, latexName, ghostLayers, layout='AoS', cpu=True, gpu=False)
self.cpuArrays[name] = FlagArray(self.cpuArrays[name], PythonFlagInterface())
def hasData(self, name):
return name in self.fields
def addLike(self, name, nameOfTemplateField, latexName=None, cpu=True, gpu=False):
if hasattr(self.fields[nameOfTemplateField], 'flagInterface'):
raise ValueError("addLike() does not work for flag arrays")
self.add(name,latexName=latexName, cpu=cpu, gpu=gpu, **self._fieldInformation[nameOfTemplateField])
def access(self, name, sliceObj=None, outerGhostLayers='all', **kwargs):
......
......@@ -465,7 +465,7 @@ def layoutStringToTuple(layoutStr, dim):
elif layoutStr == 'zyxf' or layoutStr == 'aos':
assert dim <= 4
return tuple(reversed(range(dim - 1))) + (dim-1,)
elif layoutStr == 'f' or layoutStr == 'reverseNumpy':
elif layoutStr == 'f' or layoutStr == 'reversenumpy':
return tuple(reversed(range(dim)))
elif layoutStr == 'c' or layoutStr == 'numpy':
return tuple(range(dim))
......
import numpy as np
from pystencils import Field, makeSlice
from pystencils.datahandling import DataHandling, FlagArray, WalberlaFlagInterface
from pystencils.datahandling import DataHandling
from pystencils.parallel.blockiteration import slicedBlockIteration
from pystencils.utils import DotDict
import waLBerla as wlb
......@@ -42,14 +42,51 @@ class ParallelDataHandling(DataHandling):
return self._fields
def add(self, name, fSize=1, dtype=np.float64, latexName=None, ghostLayers=None, layout=None, cpu=True, gpu=False):
return self._add(name, fSize, dtype, latexName, ghostLayers, layout, cpu, gpu, flagField=False)
if ghostLayers is None:
ghostLayers = self.defaultGhostLayers
if layout is None:
layout = self.defaultLayout
if latexName is None:
latexName = name
if len(self.blocks) == 0:
raise ValueError("Data handling expects that each process has at least one block")
if hasattr(dtype, 'type'):
dtype = dtype.type
if name in self.blocks[0] or self.GPU_DATA_PREFIX + name in self.blocks[0]:
raise ValueError("Data with this name has already been added")
def addLike(self, name, nameOfTemplateField, latexName=None, cpu=True, gpu=False):
assert not self._fieldInformation[nameOfTemplateField]['flagField']
self._add(name,latexName=latexName, cpu=cpu, gpu=gpu, **self._fieldInformation[nameOfTemplateField])
self._fieldInformation[name] = {'ghostLayers': ghostLayers,
'fSize': fSize,
'layout': layout,
'dtype': dtype}
def addFlagArray(self, name, dtype=np.int32, latexName=None, ghostLayers=None):
return self._add(name, dtype=dtype, latexName=latexName, ghostLayers=ghostLayers, flagField=True)
layoutMap = {'fzyx': wlb.field.Layout.fzyx, 'zyxf': wlb.field.Layout.zyxf,
'SoA': wlb.field.Layout.fzyx, 'AoS': wlb.field.Layout.zyxf}
if cpu:
wlb.field.addToStorage(self.blocks, name, dtype, fSize=fSize, layout=layoutMap[layout],
ghostLayers=ghostLayers)
if gpu:
wlb.cuda.addGpuFieldToStorage(self.blocks, self.GPU_DATA_PREFIX+name, dtype, fSize=fSize,
usePitchedMem=False, ghostLayers=ghostLayers, layout=layoutMap[layout])
if cpu and gpu:
self._cpuGpuPairs.append((name, self.GPU_DATA_PREFIX + name))
blockBB = self.blocks.getBlockCellBB(self.blocks[0])
shape = tuple(s + 2 * ghostLayers for s in blockBB.size)
indexDimensions = 1 if fSize > 1 else 0
if indexDimensions == 1:
shape += (fSize, )
assert all(f.name != latexName for f in self.fields.values()), "Symbolic field with this name already exists"
self.fields[name] = Field.createFixedSize(latexName, shape, indexDimensions, dtype, layout)
def hasData(self, name):
return name in self._fields
def addLike(self, name, nameOfTemplateField, latexName=None, cpu=True, gpu=False):
self.add(name,latexName=latexName, cpu=cpu, gpu=gpu, **self._fieldInformation[nameOfTemplateField])
def swap(self, name1, name2, gpu=False):
if gpu:
......@@ -68,8 +105,6 @@ class ParallelDataHandling(DataHandling):
for iterInfo in slicedBlockIteration(self.blocks, sliceObj, innerGhostLayers, outerGhostLayers):
arr = wlb.field.toArray(iterInfo.block[name], withGhostLayers=innerGhostLayers)[iterInfo.localSlice]
if fieldInfo['flagField']:
arr = FlagArray(arr, WalberlaFlagInterface(iterInfo.block[name]))
if self.fields[name].indexDimensions == 0:
arr = arr[..., 0]
if self.dim == 2:
......@@ -107,55 +142,6 @@ class ParallelDataHandling(DataHandling):
def synchronizationFunctionGPU(self, names, stencil=None, buffered=True, **kwargs):
return self._synchronizationFunction(names, stencil, buffered, 'gpu')
def _add(self, name, fSize=1, dtype=np.float64, latexName=None, ghostLayers=None, layout=None,
cpu=True, gpu=False, flagField=False):
if ghostLayers is None:
ghostLayers = self.defaultGhostLayers
if layout is None:
layout = self.defaultLayout
if latexName is None:
latexName = name
if len(self.blocks) == 0:
raise ValueError("Data handling expects that each process has at least one block")
if hasattr(dtype, 'type'):
dtype = dtype.type
if name in self.blocks[0] or self.GPU_DATA_PREFIX + name in self.blocks[0]:
raise ValueError("Data with this name has already been added")
self._fieldInformation[name] = {'ghostLayers': ghostLayers,
'fSize': fSize,
'layout': layout,
'dtype': dtype,
'flagField': flagField}
layoutMap = {'fzyx': wlb.field.Layout.fzyx, 'zyxf': wlb.field.Layout.zyxf,
'SoA': wlb.field.Layout.fzyx, 'AoS': wlb.field.Layout.zyxf}
if flagField:
assert not gpu
assert np.dtype(dtype).kind in ('u', 'i'), "FlagArrays can only be created from integer arrays"
nrOfBits = np.dtype(dtype).itemsize * 8
wlb.field.addFlagFieldToStorage(self.blocks, name, nrOfBits, ghostLayers)
else:
if cpu:
wlb.field.addToStorage(self.blocks, name, dtype, fSize=fSize, layout=layoutMap[layout],
ghostLayers=ghostLayers)
if gpu:
wlb.cuda.addGpuFieldToStorage(self.blocks, self.GPU_DATA_PREFIX+name, dtype, fSize=fSize,
usePitchedMem=False, ghostLayers=ghostLayers, layout=layoutMap[layout])
if cpu and gpu:
self._cpuGpuPairs.append((name, self.GPU_DATA_PREFIX + name))
blockBB = self.blocks.getBlockCellBB(self.blocks[0])
shape = tuple(s + 2 * ghostLayers for s in blockBB.size)
indexDimensions = 1 if fSize > 1 else 0
if indexDimensions == 1:
shape += (fSize, )
assert all(f.name != latexName for f in self.fields.values()), "Symbolic field with this name already exists"
self.fields[name] = Field.createFixedSize(latexName, shape, indexDimensions, dtype, layout)
def _synchronizationFunction(self, names, stencil, buffered, target):
if stencil is None:
stencil = 'D3Q27' if self.dim == 3 else 'D2Q9'
......
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