From a52302dbe0d9d1b175c73ac0d55825b0b30531cf Mon Sep 17 00:00:00 2001
From: Martin Bauer <martin.bauer@fau.de>
Date: Mon, 13 Feb 2017 15:52:49 +0100
Subject: [PATCH] lbmpy: bugfixes in macroscopic value computation

---
 boundaries/boundaryconditions.py        |  8 ++++++--
 boundaries/boundaryhandling.py          |  1 +
 forcemodels.py                          | 24 ++++++++++++++----------
 macroscopicValueKernels.py              | 17 +++++++++++++----
 methods/conservedquantitycomputation.py |  2 +-
 5 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/boundaries/boundaryconditions.py b/boundaries/boundaryconditions.py
index 459c8799..26785bb8 100644
--- a/boundaries/boundaryconditions.py
+++ b/boundaries/boundaryconditions.py
@@ -12,7 +12,7 @@ def noSlip(pdfField, direction, lbMethod):
     return [sp.Eq(pdfField[neighbor](inverseDir), pdfField(direction))]
 
 
-def ubb(pdfField, direction, lbMethod, velocity):
+def ubb(pdfField, direction, lbMethod, velocity, adaptVelocityToForce=False):
     """Velocity bounce back boundary condition, enforcing specified velocity at obstacle"""
 
     assert len(velocity) == lbMethod.dim, \
@@ -20,7 +20,11 @@ def ubb(pdfField, direction, lbMethod, velocity):
     neighbor = offsetFromDir(direction, lbMethod.dim)
     inverseDir = invDir(direction)
 
-    # TODO adapt velocity to force
+    if adaptVelocityToForce:
+        cqc = lbMethod.conservedQuantityComputation
+        shiftedVelEqs = cqc.equilibriumInputEquationsFromInitValues(velocity=velocity)
+        velocity = [eq.rhs for eq in shiftedVelEqs.extract(cqc.firstOrderMomentSymbols).mainEquations]
+
     c_s_sq = sp.Rational(1, 3)
     velTerm = 2 / c_s_sq * sum([d_i * v_i for d_i, v_i in zip(neighbor, velocity)]) * weightOfDirection(direction)
 
diff --git a/boundaries/boundaryhandling.py b/boundaries/boundaryhandling.py
index 14e40146..213fc1f6 100644
--- a/boundaries/boundaryhandling.py
+++ b/boundaries/boundaryhandling.py
@@ -140,6 +140,7 @@ def generateBoundaryHandling(pdfField, indexArr, lbMethod, boundaryFunctor):
     cellLoop = LoopOverCoordinate(cellLoopBody, coordinateToLoopOver=0, start=0, stop=indexArr.shape[0])
 
     indexField = Field.createFromNumpyArray("indexField", indexArr, indexDimensions=1)
+    indexField.isIndexField = True
 
     coordinateSymbols = [TypedSymbol(name, "int") for name in ['x', 'y', 'z']]
     for d in range(dim):
diff --git a/forcemodels.py b/forcemodels.py
index 5b7fe308..ca0c4203 100644
--- a/forcemodels.py
+++ b/forcemodels.py
@@ -16,10 +16,14 @@ class Simple:
     def __init__(self, force):
         self._force = force
 
-    def __call__(self, lbmMethod, **kwargs):
-        assert len(self._force) == lbmMethod.dim
-        return [3 * w_i * sum([d_i * f_i for d_i, f_i in zip(direction, self._force)])
-                for direction, w_i in zip(lbmMethod.stencil, lbmMethod.weights)]
+    def __call__(self, lbMethod, **kwargs):
+        assert len(self._force) == lbMethod.dim
+
+        def scalarProduct(a, b):
+            return sum(a_i * b_i for a_i, b_i in zip(a, b))
+
+        return [3 * w_i * scalarProduct(self._force, direction)
+                for direction, w_i in zip(lbMethod.stencil, lbMethod.weights)]
 
 
 class Luo:
@@ -35,12 +39,12 @@ class Luo:
     def __init__(self, force):
         self._force = force
 
-    def __call__(self, lbmMethod):
-        u = sp.Matrix(lbmMethod.firstOrderEquilibriumMomentSymbols)
+    def __call__(self, lbMethod):
+        u = sp.Matrix(lbMethod.firstOrderEquilibriumMomentSymbols)
         force = sp.Matrix(self._force)
 
         result = []
-        for direction, w_i in zip(lbmMethod.stencil, lbmMethod.weights):
+        for direction, w_i in zip(lbMethod.stencil, lbMethod.weights):
             direction = sp.Matrix(direction)
             result.append(3 * w_i * force.dot(direction - u + 3 * direction * direction.dot(u)))
         return result
@@ -62,11 +66,11 @@ class Guo:
     def __init__(self, force):
         self._force = force
 
-    def __call__(self, lbmMethod):
+    def __call__(self, lbMethod):
         luo = Luo(self._force)
-        shearRelaxationRate = lbmMethod.getShearRelaxationRate()
+        shearRelaxationRate = lbMethod.getShearRelaxationRate()
         correctionFactor = (1 - sp.Rational(1, 2) * shearRelaxationRate)
-        return [correctionFactor * t for t in luo(lbmMethod)]
+        return [correctionFactor * t for t in luo(lbMethod)]
 
     def macroscopicVelocityShift(self, density):
         return defaultVelocityShift(density, self._force)
diff --git a/macroscopicValueKernels.py b/macroscopicValueKernels.py
index 084a6f6a..4061adfe 100644
--- a/macroscopicValueKernels.py
+++ b/macroscopicValueKernels.py
@@ -1,4 +1,3 @@
-import sympy as sp
 from copy import deepcopy
 from pystencils.field import Field, getLayoutFromNumpyArray
 from lbmpy.simplificationfactory import createSimplificationStrategy
@@ -30,14 +29,24 @@ def compileMacroscopicValuesGetter(lbMethod, outputQuantities, pdfArr=None, fiel
         pdfField = Field.createGeneric('pdfs', lbMethod.dim, indexDimensions=1, layout=fieldLayout)
     else:
         pdfField = Field.createFromNumpyArray('pdfs', pdfArr, indexDimensions=1)
-        fieldLayout = getLayoutFromNumpyArray(pdfArr, indexDimensionIds=[len(pdfField.shape)-1])
 
     outputMapping = {}
     for outputQuantity in outputQuantities:
         numberOfElements = cqc.conservedQuantities[outputQuantity]
         assert numberOfElements >= 1
-        outputField = Field.createGeneric(outputQuantity, lbMethod.dim, layout=fieldLayout,
-                                          indexDimensions=0 if numberOfElements <= 1 else 1)
+
+        indDims = 0 if numberOfElements <= 1 else 1
+        if pdfArr is None:
+            fieldLayout = getLayoutFromNumpyArray(pdfArr, indexDimensionIds=[len(pdfField.shape) - 1])
+            outputField = Field.createGeneric(outputQuantity, lbMethod.dim, layout=fieldLayout, indexDimensions=indDims)
+        else:
+            outputFieldShape = pdfArr.shape[:-1]
+            if indDims > 0:
+                outputFieldShape += (numberOfElements,)
+                fieldLayout = getLayoutFromNumpyArray(pdfArr)
+            else:
+                fieldLayout = getLayoutFromNumpyArray(pdfArr, indexDimensionIds=[len(pdfField.shape) - 1])
+            outputField = Field.createFixedSize(outputQuantity, outputFieldShape, indDims, pdfArr.dtype, fieldLayout)
 
         outputMapping[outputQuantity] = [outputField(i) for i in range(numberOfElements)]
         if len(outputMapping[outputQuantity]) == 1:
diff --git a/methods/conservedquantitycomputation.py b/methods/conservedquantitycomputation.py
index 34060528..41f31460 100644
--- a/methods/conservedquantitycomputation.py
+++ b/methods/conservedquantitycomputation.py
@@ -90,7 +90,7 @@ class DensityVelocityComputation(AbstractConservedQuantityComputation):
     @property
     def conservedQuantities(self):
         return {'density': 1,
-                'velocity': 3}
+                'velocity': len(self._stencil[0])}
 
     def definedSymbols(self, order='all'):
         if order == 'all':
-- 
GitLab