From fde2c8ce59b0ad1526afb406026514d3b89853d0 Mon Sep 17 00:00:00 2001 From: Martin Bauer <bauer_martin@gmx.de> Date: Sat, 21 Jan 2017 12:40:41 +0100 Subject: [PATCH] lbmpy: boundary index list creation with Cython --- boundaries/__init__.py | 0 boundaries/boundaryconditions.py | 8 ++-- boundaries/createindexlist.py | 40 +++++++++++++++++++ boundaries/createindexlistcython.pyx | 58 ++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 boundaries/__init__.py create mode 100644 boundaries/createindexlist.py create mode 100644 boundaries/createindexlistcython.pyx diff --git a/boundaries/__init__.py b/boundaries/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/boundaries/boundaryconditions.py b/boundaries/boundaryconditions.py index 48ab5c89..b80a281b 100644 --- a/boundaries/boundaryconditions.py +++ b/boundaries/boundaryconditions.py @@ -2,14 +2,14 @@ import sympy as sp from lbmpy.boundaries.boundaryhandling import offsetFromDir, weightOfDirection, invDir -def noSlip(pdfField, direction, latticeModel): - neighbor = offsetFromDir(direction, latticeModel.dim) +def noSlip(pdfField, direction, lbmMethod): + neighbor = offsetFromDir(direction, lbmMethod.dim) inverseDir = invDir(direction) return [sp.Eq(pdfField[neighbor](inverseDir), pdfField(direction))] -def ubb(pdfField, direction, latticeModel, velocity): - neighbor = offsetFromDir(direction, latticeModel.dim) +def ubb(pdfField, direction, lbmMethod, velocity): + neighbor = offsetFromDir(direction, lbmMethod.dim) inverseDir = invDir(direction) velTerm = 6 * sum([d_i * v_i for d_i, v_i in zip(neighbor, velocity)]) * weightOfDirection(direction) diff --git a/boundaries/createindexlist.py b/boundaries/createindexlist.py new file mode 100644 index 00000000..8f3fb6e7 --- /dev/null +++ b/boundaries/createindexlist.py @@ -0,0 +1,40 @@ +import numpy as np +import itertools + +#try: +if True: + import pyximport; + pyximport.install() + from lbmpy.boundaries.createindexlistcython import createBoundaryIndexList2D, createBoundaryIndexList3D + cythonFuncsAvailable = True +#except Exception: +# cythonFuncsAvailable = False +# createBoundaryIndexList2D = None +# createBoundaryIndexList3D = None + + +def _createBoundaryIndexListPython(flagFieldArr, nrOfGhostLayers, boundaryMask, fluidMask, stencil): + result = [] + gl = nrOfGhostLayers + for cell in itertools.product(*[range(gl, i-gl) for i in flagFieldArr.shape]): + if not flagFieldArr[cell] & fluidMask: + continue + for dirIdx, direction in enumerate(stencil): + neighborCell = tuple([cell_i + dir_i for cell_i, dir_i in zip(cell, direction)]) + if flagFieldArr[neighborCell] & boundaryMask: + result.append(list(cell) + [dirIdx]) + + return np.array(result, dtype=np.int32) + + +def createBoundaryIndexList(flagField, stencil, boundaryMask, fluidMask, nrOfGhostLayers=1): + if cythonFuncsAvailable: + stencil = np.array(stencil, dtype=np.int32) + if len(flagField.shape) == 2: + return np.array(createBoundaryIndexList2D(flagField, nrOfGhostLayers, boundaryMask, fluidMask, stencil)) + elif len(flagField.shape) == 3: + return np.array(createBoundaryIndexList3D(flagField, nrOfGhostLayers, boundaryMask, fluidMask, stencil)) + else: + raise ValueError("Flag field has to be a 2 or 3 dimensional numpy array") + else: + return _createBoundaryIndexListPython(flagField, nrOfGhostLayers, boundaryMask, fluidMask, stencil) diff --git a/boundaries/createindexlistcython.pyx b/boundaries/createindexlistcython.pyx new file mode 100644 index 00000000..02034844 --- /dev/null +++ b/boundaries/createindexlistcython.pyx @@ -0,0 +1,58 @@ +import cython + +ctypedef fused IntegerType: + short + int + long + unsigned short + unsigned int + unsigned long + +@cython.boundscheck(False) # turn off bounds-checking for entire function +@cython.wraparound(False) # turn off negative index wrapping for entire function +def createBoundaryIndexList2D(object[IntegerType, ndim=2] flagField, + int nrOfGhostLayers, IntegerType boundaryMask, IntegerType fluidMask, + object[int, ndim=2] stencil): + cdef int xs, ys, x, y + cdef int dirIdx, numDirections, dx, dy + + xs, ys = flagField.shape + boundaryIndexList = [] + numDirections = stencil.shape[0] + + for x in range(nrOfGhostLayers,xs-nrOfGhostLayers): + for y in range(nrOfGhostLayers,ys-nrOfGhostLayers): + if flagField[x,y] & fluidMask: + for dirIdx in range(1, numDirections): + dx = stencil[dirIdx,0] + dy = stencil[dirIdx,1] + if flagField[x+dx, y+dy] & boundaryMask: + boundaryIndexList.append((x,y, dirIdx)) + return boundaryIndexList + + +@cython.boundscheck(False) # turn off bounds-checking for entire function +@cython.wraparound(False) # turn off negative index wrapping for entire function +def createBoundaryIndexList3D(object[IntegerType, ndim=3] flagField, + int nrOfGhostLayers, IntegerType boundaryMask, IntegerType fluidMask, + object[int, ndim=2] stencil): + cdef int xs, ys, zs, x, y, z + cdef int dirIdx, numDirections, dx, dy, dz + + xs, ys, zs = flagField.shape + boundaryIndexList = [] + numDirections = stencil.shape[0] + + for x in range(nrOfGhostLayers,xs-nrOfGhostLayers): + for y in range(nrOfGhostLayers,ys-nrOfGhostLayers): + for z in range(nrOfGhostLayers, zs-nrOfGhostLayers): + if flagField[x, y, z] & fluidMask: + for dirIdx in range(1, numDirections): + dx = stencil[dirIdx,0] + dy = stencil[dirIdx,1] + dz = stencil[dirIdx,2] + if flagField[x + dx, y + dy, z + dz] & boundaryMask: + boundaryIndexList.append((x,y,z, dirIdx)) + return boundaryIndexList + + -- GitLab