From 75b1d916b7b970083a0f2a70edd58acb7ffefa68 Mon Sep 17 00:00:00 2001 From: Martin Bauer <martin.bauer@fau.de> Date: Wed, 1 Nov 2017 18:47:59 +0100 Subject: [PATCH] Simple functions to compute force on boundary - added functions to compute force on boundary for generic boundary and NoSlip - simple calculations for serial scenarios - to distinguish between different obstacles, NoSlip boundaries can now be named --- boundaries/boundaryconditions.py | 20 ++++++++++-- boundaries/forceevaluation.py | 52 ++++++++++++++++++++++++++++++++ boundaries/handlinginterface.py | 4 +++ scenarios.py | 17 +++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 boundaries/forceevaluation.py diff --git a/boundaries/boundaryconditions.py b/boundaries/boundaryconditions.py index 19d2d690..e7146e3f 100644 --- a/boundaries/boundaryconditions.py +++ b/boundaries/boundaryconditions.py @@ -51,6 +51,11 @@ class Boundary(object): class NoSlip(Boundary): + + def __init__(self, name=None): + """Set an optional name here, to mark boundaries, for example for force evaluations""" + self._name = name + """No-Slip, (half-way) simple bounce back boundary condition, enforcing zero velocity at obstacle""" def __call__(self, pdfField, directionSymbol, lbMethod, **kwargs): neighbor = offsetFromDir(directionSymbol, lbMethod.dim) @@ -58,11 +63,20 @@ class NoSlip(Boundary): return [sp.Eq(pdfField[neighbor](inverseDir), pdfField(directionSymbol))] def __hash__(self): - # All boundaries of these class behave equal -> should also be equal - return hash("NoSlip") + # All boundaries of these class behave equal -> should also be equal (as long as name is equal) + return hash(self.name) def __eq__(self, other): - return type(other) == NoSlip + if not isinstance(other, NoSlip): + return False + return self.name == other.name + + @property + def name(self): + if self._name: + return self._name + else: + return type(self).__name__ class NoSlipFullWay(Boundary): diff --git a/boundaries/forceevaluation.py b/boundaries/forceevaluation.py new file mode 100644 index 00000000..3e741d73 --- /dev/null +++ b/boundaries/forceevaluation.py @@ -0,0 +1,52 @@ +import numpy as np +from lbmpy.stencils import inverseDirection + + +def calculateForceOnNoSlipBoundary(boundaryObject, boundaryHandling, pdfArray): + indArr = boundaryHandling.getBoundaryIndexArray(boundaryObject) + method = boundaryHandling.lbMethod + + stencil = np.array(method.stencil) + + if method.dim == 2: + x, y = indArr['x'], indArr['y'] + values = 2 * pdfArray[x, y, indArr['dir']] + else: + assert method.dim == 3 + x, y, z = indArr['x'], indArr['y'], indArr['z'] + values = 2 * pdfArray[x, y, z, indArr['dir']] + + forces = stencil[indArr['dir']] * values[:, np.newaxis] + return forces.sum(axis=0) + + +def calculateForceOnBoundary(boundaryObject, boundaryHandling, pdfArray): + indArr = boundaryHandling.getBoundaryIndexArray(boundaryObject) + method = boundaryHandling.lbMethod + + stencil = np.array(method.stencil) + invDirection = np.array([method.stencil.index(inverseDirection(d)) + for d in method.stencil]) + + if method.dim == 2: + x, y = indArr['x'], indArr['y'] + offsets = stencil[indArr['dir']] + + fluidValues = pdfArray[x, y, indArr['dir']] + boundaryValues = pdfArray[x + offsets[:, 0], + y + offsets[:, 1], + invDirection[indArr['dir']]] + else: + assert method.dim == 3 + x, y, z = indArr['x'], indArr['y'], indArr['z'] + offsets = stencil[indArr['dir']] + + fluidValues = pdfArray[x, y, z, indArr['dir']] + boundaryValues = pdfArray[x + offsets[:, 0], + y + offsets[:, 1], + z + offsets[:, 2], + invDirection[indArr['dir']]] + + values = fluidValues + boundaryValues + forces = stencil[indArr['dir']] * values[:, np.newaxis] + return forces.sum(axis=0) diff --git a/boundaries/handlinginterface.py b/boundaries/handlinginterface.py index de3f28fb..ba768e4c 100644 --- a/boundaries/handlinginterface.py +++ b/boundaries/handlinginterface.py @@ -113,6 +113,10 @@ class GenericBoundaryHandling(object): if target not in ('cpu', 'gpu'): raise ValueError("Invalid target '%s' . Allowed values: 'cpu' or 'gpu'" % (target,)) + @property + def lbMethod(self): + return self._lbMethod + def getBoundaryNameToFlagDict(self): result = {self._flagFieldInterface.getName(o): self._flagFieldInterface.getFlag(o) for o in self._boundaryInfos} result['fluid'] = self._flagFieldInterface.getFlag('fluid') diff --git a/scenarios.py b/scenarios.py index d1ab830f..0687bb27 100644 --- a/scenarios.py +++ b/scenarios.py @@ -26,6 +26,7 @@ that defines the viscosity of the fluid (valid values being between 0 and 2). import numpy as np import sympy as sp +from lbmpy.boundaries.forceevaluation import calculateForceOnBoundary, calculateForceOnNoSlipBoundary from lbmpy.geometry import setupChannelWalls, addParabolicVelocityInflow from pystencils.field import getLayoutOfArray, createNumpyArrayWithLayout from pystencils.slicing import sliceFromDirection, addGhostLayers, removeGhostLayers, normalizeSlice, makeSlice @@ -346,6 +347,14 @@ class Scenario(object): """Equation collection defining the LBM update rule (already in simplified form)""" return self._lbmKernel.updateRule + def calculateForceOnBoundary(self, boundaryObject): + """Computes force on boundary using simple momentum exchange method""" + if isinstance(boundaryObject, NoSlip): + return calculateForceOnNoSlipBoundary(boundaryObject, self.boundaryHandling, self._pdfArrays[0]) + else: + self.runBoundaryHandlingOnly() + return calculateForceOnBoundary(boundaryObject, self.boundaryHandling, self._pdfArrays[0]) + def animateVelocity(self, steps=10, **kwargs): import lbmpy.plot2d as plt @@ -415,3 +424,11 @@ class Scenario(object): self._getMacroscopic(pdfs=self._pdfArrays[0], density=self._density, velocity=self._velocity, **self.kernelParams) + def runBoundaryHandlingOnly(self): + isGpuSimulation = len(self._pdfGpuArrays) > 0 + if isGpuSimulation: + self._pdfGpuArrays[0].set(self._pdfArrays[0]) + self._boundaryHandling(pdfs=self._pdfGpuArrays[0], **self.kernelParams) + self._pdfGpuArrays[0].get(self._pdfArrays[0]) + else: + self._boundaryHandling(pdfs=self._pdfArrays[0], **self.kernelParams) -- GitLab