diff --git a/apps/gpu/LBM/BoundaryLayer/BoundaryLayer.cpp b/apps/gpu/LBM/BoundaryLayer/BoundaryLayer.cpp
index c9378bd18925419cefa6621bb3e7c9b77e9dfd8a..a3915c07d5bdbd32a047763ad130de7893202589 100644
--- a/apps/gpu/LBM/BoundaryLayer/BoundaryLayer.cpp
+++ b/apps/gpu/LBM/BoundaryLayer/BoundaryLayer.cpp
@@ -50,6 +50,7 @@
 #include "VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h"
 #include "VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.h"
 #include "VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.h"
+#include "VirtualFluids_GPU/TurbulenceModels/TurbulenceModelFactory.h"
 
 #include "VirtualFluids_GPU/GPU/CudaMemoryManager.h"
 
@@ -161,10 +162,7 @@ void multipleLevel(const std::string& configPath)
     para->setViscosityRatio( dx*dx/dt );
     para->setDensityRatio( 1.0 );
 
-    if(para->getUseAMD())
-        para->setMainKernel("TurbulentViscosityCumulantK17CompChim");
-    else
-        para->setMainKernel("CumulantK17CompChim");
+    para->setMainKernel("TurbulentViscosityCumulantK17CompChim");
 
     para->setIsBodyForce( config.getValue<bool>("bodyForce") );
 
@@ -172,15 +170,22 @@ void multipleLevel(const std::string& configPath)
     para->setTimestepOut( uint(tOut/dt) );
     para->setTimestepEnd( uint(tEnd/dt) );
 
-    // para->setTimestepOut( 100 );
-    // para->setTimestepEnd( 100000 );
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    SPtr<TurbulenceModelFactory> tmFactory = SPtr<TurbulenceModelFactory>( new TurbulenceModelFactory(para) );
+    tmFactory->readConfigFile( config );
+    
+    // tmFactory->setTurbulenceModel(TurbulenceModel::AMD);
+    // tmFactory->setModelConstant(config.getValue<real>("SGSconstant"));
 
     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
     gridBuilder->addCoarseGrid(0.0, 0.0, 0.0,
                                 L_x,  L_y,  L_z, dx);
-    // gridBuilder->setNumberOfLayers(0,0);
-    // gridBuilder->addGrid( new Cuboid( 300., 300., 300., 1000. , 1000., 600.), 1 );
+    // gridBuilder->setNumberOfLayers(12, 8);
+
+    // gridBuilder->addGrid( new Cuboid( 0.0, 0.0, 0.0, L_x,  L_y,  0.3*L_z) , 1 );
+    // para->setMaxLevel(2);
 
     gridBuilder->setPeriodicBoundaryCondition(true, true, false);
 
@@ -192,18 +197,17 @@ void multipleLevel(const std::string& configPath)
                                             0.0, 0.0, 1.0,              // wall normals
                                             samplingOffset, z0/dx);     // wall model settinng
     para->setHasWallModelMonitor(true);
-    bcFactory.setStressBoundaryCondition(BoundaryConditionFactory::StressBC::StressBounceBack);
-
+    bcFactory.setStressBoundaryCondition(BoundaryConditionFactory::StressBC::StressPressureBounceBack);
 
-    // gridBuilder->setVelocityBoundaryCondition(SideType::PZ, 0.0, 0.0, 0.0);
     gridBuilder->setSlipBoundaryCondition(SideType::PZ,  0.0,  0.0, 0.0);
-    bcFactory.setSlipBoundaryCondition(BoundaryConditionFactory::SlipBC::SlipCompressible);
+    bcFactory.setSlipBoundaryCondition(BoundaryConditionFactory::SlipBC::SlipBounceBack); 
+    
 
     real cPi = 3.1415926535897932384626433832795;
     para->setInitialCondition([&](real coordX, real coordY, real coordZ, real &rho, real &vx, real &vy, real &vz) {
         rho = (real)0.0;
-        vx  = (u_star/0.4 * log(coordZ/z0) + 2.0*sin(cPi*16.0f*coordX/L_x)*sin(cPi*8.0f*coordZ/H)/(pow(coordZ/H,c2o1)+c1o1))  * dt / dx;
-        vy  =  2.0*sin(cPi*16.0f*coordX/L_x)*sin(cPi*8.0f*coordZ/H)/(pow(coordZ/H,c2o1)+c1o1)  * dt / dx;
+        vx  = (u_star/0.4 * log(coordZ/z0) + 2.0*sin(cPi*16.0f*coordX/L_x)*sin(cPi*8.0f*coordZ/H)/(pow(coordZ/H,c2o1)+c1o1))  * dt / dx; 
+        vy  = 2.0*sin(cPi*16.0f*coordX/L_x)*sin(cPi*8.0f*coordZ/H)/(pow(coordZ/H,c2o1)+c1o1)  * dt / dx; 
         vz  = 8.0*u_star/0.4*(sin(cPi*8.0*coordY/H)*sin(cPi*8.0*coordZ/H)+sin(cPi*8.0*coordX/L_x))/(pow(L_z/2.0-coordZ, c2o1)+c1o1) * dt / dx;
     });
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -225,7 +229,7 @@ void multipleLevel(const std::string& configPath)
     auto cudaMemoryManager = std::make_shared<CudaMemoryManager>(para);
     auto gridGenerator = GridProvider::makeGridGenerator(gridBuilder, para, cudaMemoryManager, communicator);
 
-    Simulation sim(para, cudaMemoryManager, communicator, *gridGenerator, &bcFactory);
+    Simulation sim(para, cudaMemoryManager, communicator, *gridGenerator, &bcFactory, tmFactory);
     sim.run();
 }
 
diff --git a/pythonbindings/src/gpu/submodules/parameter.cpp b/pythonbindings/src/gpu/submodules/parameter.cpp
index 0ea87924bd0a2fc2b3a6bc343cad5948febe2ffe..7b4e67f101e3928abbd4262557864ea1d0f45b02 100644
--- a/pythonbindings/src/gpu/submodules/parameter.cpp
+++ b/pythonbindings/src/gpu/submodules/parameter.cpp
@@ -41,6 +41,9 @@ namespace parameter
         .def("set_density_ratio", &Parameter::setDensityRatio)
         .def("set_devices", &Parameter::setDevices)
         .def("set_is_body_force", &Parameter::setIsBodyForce)
+        .def("set_use_AMD", &Parameter::setUseAMD)
+        .def("set_use_Wale", &Parameter::setUseWale)
+        .def("set_SGS_constant", &Parameter::setSGSConstant)
         .def("set_main_kernel", &Parameter::setMainKernel)
         .def("set_AD_kernel", &Parameter::setADKernel)
         .def("set_use_AMD", &Parameter::setUseAMD)
diff --git a/src/gpu/GridGenerator/grid/GridBuilder/LevelGridBuilder.cpp b/src/gpu/GridGenerator/grid/GridBuilder/LevelGridBuilder.cpp
index b81ecd13cb42a13a055a92ce4643480c7f5ad4df..083b9a51e0b151f49922df456e968c4b204e4af7 100644
--- a/src/gpu/GridGenerator/grid/GridBuilder/LevelGridBuilder.cpp
+++ b/src/gpu/GridGenerator/grid/GridBuilder/LevelGridBuilder.cpp
@@ -77,20 +77,23 @@ std::shared_ptr<LevelGridBuilder> LevelGridBuilder::makeShared()
 
 void LevelGridBuilder::setSlipBoundaryCondition(SideType sideType, real normalX, real normalY, real normalZ)
 {
-    if(sideType == SideType::GEOMETRY){
-        setSlipGeometryBoundaryCondition(normalX, normalY, normalZ);
-    }else{
-        SPtr<SlipBoundaryCondition> slipBoundaryCondition = SlipBoundaryCondition::make(normalX, normalY, normalZ);
+    for (uint level = 0; level < getNumberOfGridLevels(); level++)
+    {
+        if(sideType == SideType::GEOMETRY){
+            setSlipGeometryBoundaryCondition(normalX, normalY, normalZ);
+        }else{
+            SPtr<SlipBoundaryCondition> slipBoundaryCondition = SlipBoundaryCondition::make(normalX, normalY, normalZ);
 
-        auto side = SideFactory::make(sideType);
+            auto side = SideFactory::make(sideType);
 
-        slipBoundaryCondition->side = side;
-        slipBoundaryCondition->side->addIndices(grids, 0, slipBoundaryCondition);
+            slipBoundaryCondition->side = side;
+            slipBoundaryCondition->side->addIndices(grids, level, slipBoundaryCondition);
 
-        slipBoundaryCondition->fillSlipNormalLists();
-        boundaryConditions[0]->slipBoundaryConditions.push_back(slipBoundaryCondition);
+            slipBoundaryCondition->fillSlipNormalLists();
+            boundaryConditions[level]->slipBoundaryConditions.push_back(slipBoundaryCondition);
 
-        *logging::out << logging::Logger::INFO_INTERMEDIATE << "Set Slip BC on level " << 0 << " with " << (int)slipBoundaryCondition->indices.size() << "\n";
+            *logging::out << logging::Logger::INFO_INTERMEDIATE << "Set Slip BC on level " << level << " with " << (int)slipBoundaryCondition->indices.size() << "\n";
+        }
     }
 }
 
@@ -118,21 +121,24 @@ void LevelGridBuilder::setStressBoundaryCondition(  SideType sideType,
                                                     real nomalX, real normalY, real normalZ, 
                                                     uint samplingOffset, real z0)
 {
-    SPtr<StressBoundaryCondition> stressBoundaryCondition = StressBoundaryCondition::make(nomalX, normalY, normalZ, samplingOffset, z0);
+    for (uint level = 0; level < getNumberOfGridLevels(); level++)
+    {
+        SPtr<StressBoundaryCondition> stressBoundaryCondition = StressBoundaryCondition::make(nomalX, normalY, normalZ, samplingOffset, z0);
 
-    auto side = SideFactory::make(sideType);
+        auto side = SideFactory::make(sideType);
 
-    stressBoundaryCondition->side = side;
-    stressBoundaryCondition->side->addIndices(grids, 0, stressBoundaryCondition);
+        stressBoundaryCondition->side = side;
+        stressBoundaryCondition->side->addIndices(grids, level, stressBoundaryCondition);
 
-    stressBoundaryCondition->fillStressNormalLists();
-    stressBoundaryCondition->fillSamplingOffsetLists();
-    stressBoundaryCondition->fillZ0Lists();
-    // stressBoundaryCondition->fillSamplingIndices(grids, 0, samplingOffset); //redundant with Side::setStressSamplingIndices but potentially a better approach for cases with complex geometries
+        stressBoundaryCondition->fillStressNormalLists();
+        stressBoundaryCondition->fillSamplingOffsetLists();
+        stressBoundaryCondition->fillZ0Lists();
+        // stressBoundaryCondition->fillSamplingIndices(grids, 0, samplingOffset); //redundant with Side::setStressSamplingIndices but potentially a better approach for cases with complex geometries
 
-    boundaryConditions[0]->stressBoundaryConditions.push_back(stressBoundaryCondition);
+        boundaryConditions[level]->stressBoundaryConditions.push_back(stressBoundaryCondition);
 
-    *logging::out << logging::Logger::INFO_INTERMEDIATE << "Set Stress BC on level " << 0 << " with " << (int)stressBoundaryCondition->indices.size() << "\n";
+        *logging::out << logging::Logger::INFO_INTERMEDIATE << "Set Stress BC on level " << level << " with " << (int)stressBoundaryCondition->indices.size() << "\n";
+    }
 }
 
 void LevelGridBuilder::setVelocityBoundaryCondition(SideType sideType, real vx, real vy, real vz)
diff --git a/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.cpp b/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.cpp
index a461eb5f67b9a42a02779cc53000f765aac5e93b..bff054eb174a0f5fa34119deedde6f1c9733d83c 100644
--- a/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.cpp
+++ b/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.cpp
@@ -99,9 +99,15 @@ boundaryCondition BoundaryConditionFactory::getSlipBoundaryConditionPost(bool is
         case SlipBC::SlipCompressible:
             return QSlipDevComp27;
             break;
+        case SlipBC::SlipBounceBack:
+            return BBSlipDevComp27;
+            break;
         case SlipBC::SlipCompressibleTurbulentViscosity:
             return QSlipDevCompTurbulentViscosity27;
             break;
+        case SlipBC::SlipPressureCompressibleTurbulentViscosity:
+            return QSlipPressureDevCompTurbulentViscosity27;
+            break;
         default:
             return nullptr;
     }
@@ -137,6 +143,9 @@ boundaryConditionWithParameter BoundaryConditionFactory::getStressBoundaryCondit
         case StressBC::StressBounceBack:
             return BBStressDev27;
             break;
+        case StressBC::StressPressureBounceBack:
+            return BBStressPressureDev27;
+            break;
         case StressBC::StressCompressible:
             return QStressDevComp27;
             break;
diff --git a/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.h b/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.h
index 1c0797daa97b913ae746e717c62642cb8eac5f85..52df58744641344c97e1b6f8ff964b75c22fec48 100644
--- a/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.h
+++ b/src/gpu/VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.h
@@ -87,9 +87,12 @@ public:
         SlipIncompressible,
         //! - SlipCompressible = interpolated slip boundary condition, based on subgrid distances
         SlipCompressible,
-        //! - SlipCompressible = interpolated slip boundary condition, based on subgrid distances.
+        //! - SlipBounceBack = simple bounce-back slip boundary condition.
+        SlipBounceBack,
         //! With turbulent viscosity -> para->setUseTurbulentViscosity(true) has to be set to true
         SlipCompressibleTurbulentViscosity,
+        //! With turbulent viscosity -> para->setUseTurbulentViscosity(true) has to be set to true
+        SlipPressureCompressibleTurbulentViscosity,
         //! - NotSpecified =  the user did not set a boundary condition
         NotSpecified
     };
@@ -116,6 +119,8 @@ public:
         StressCompressible,
         //! - StressBounceBack
         StressBounceBack,
+        //! - StressPressureBounceBack
+        StressPressureBounceBack,
         //! - NotSpecified =  the user did not set a boundary condition
         NotSpecified
     };
diff --git a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp
index 0a310e500ad0b5ee262b3d5519591e0b5c4c9c8c..4f08c0cc9b4e5ac4af0d11b5eebcbc275e07cdad 100644
--- a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp
+++ b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp
@@ -4,10 +4,10 @@
 
 #include "Communication/ExchangeData27.h"
 #include "Parameter/CudaStreamManager.h"
-#include "GPU/TurbulentViscosity.h"
 #include "KernelManager/BCKernelManager.h"
 #include "KernelManager/ADKernelManager.h"
 #include "KernelManager/GridScalingKernelManager.h"
+#include "TurbulenceModels/TurbulenceModelFactory.h"
 #include "Kernel/Kernel.h"
 
 #include "CollisionStrategy.h"
@@ -36,11 +36,10 @@ void UpdateGrid27::updateGrid(int level, unsigned int t)
 
     //////////////////////////////////////////////////////////////////////////
 
-    if (para->getUseWale())
+    if (para->getUseWale()) //TODO: make WALE consistent with structure of other turbulence models
         calcMacroscopicQuantities(level);
 
-    if (para->getUseTurbulentViscosity())
-        calcTurbulentViscosity(level);
+    calcTurbulentViscosity(level);
 
     //////////////////////////////////////////////////////////////////////////
 
@@ -364,8 +363,7 @@ void  UpdateGrid27::interactWithProbes(int level, unsigned int t)
 
 void  UpdateGrid27::calcTurbulentViscosity(int level)
 {
-    if(para->getUseAMD())
-        calcTurbulentViscosityAMD(para.get(), level);
+    this->tmFactory->runTurbulenceModelKernel(level);
 }
 
 void UpdateGrid27::exchangeData(int level)
@@ -374,8 +372,8 @@ void UpdateGrid27::exchangeData(int level)
 }
 
 UpdateGrid27::UpdateGrid27(SPtr<Parameter> para, vf::gpu::Communicator &comm, SPtr<CudaMemoryManager> cudaMemoryManager,
-                           std::vector<std::shared_ptr<PorousMedia>> &pm, std::vector<SPtr<Kernel>> &kernels , BoundaryConditionFactory* bcFactory)
-    : para(para), comm(comm), cudaMemoryManager(cudaMemoryManager), pm(pm), kernels(kernels)
+                           std::vector<std::shared_ptr<PorousMedia>> &pm, std::vector<SPtr<Kernel>> &kernels , BoundaryConditionFactory* bcFactory, SPtr<TurbulenceModelFactory>  tmFactory)
+    : para(para), comm(comm), cudaMemoryManager(cudaMemoryManager), pm(pm), kernels(kernels), tmFactory(tmFactory)
 {
     this->collision = getFunctionForCollisionAndExchange(para->getUseStreams(), para->getNumprocs(), para->getKernelNeedsFluidNodeIndicesToRun());
     this->refinement = getFunctionForRefinementAndExchange(para->getUseStreams(), para->getNumprocs(), para->getMaxLevel(), para->useReducedCommunicationAfterFtoC);
diff --git a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h
index 9001b3db2e7c1b8f9e790a7686090d3af89484a4..f1fb3476313718e120bb5ee167445e50a319facb 100644
--- a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h
+++ b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h
@@ -13,6 +13,7 @@ class ADKernelManager;
 class GridScalingKernelManager;
 class Kernel;
 class BoundaryConditionFactory;
+class TurbulenceModelFactory;
 
 class UpdateGrid27;
 using CollisionStrategy = std::function<void (UpdateGrid27* updateGrid, Parameter* para, int level, unsigned int t)>;
@@ -23,7 +24,7 @@ class UpdateGrid27
 {
 public:
     UpdateGrid27(SPtr<Parameter> para, vf::gpu::Communicator &comm, SPtr<CudaMemoryManager> cudaMemoryManager,
-                 std::vector<std::shared_ptr<PorousMedia>> &pm, std::vector<SPtr<Kernel>> &kernels, BoundaryConditionFactory* bcFactory);
+                 std::vector<std::shared_ptr<PorousMedia>> &pm, std::vector<SPtr<Kernel>> &kernels, BoundaryConditionFactory* bcFactory, SPtr<TurbulenceModelFactory> tmFactory);
     void updateGrid(int level, unsigned int t);
     void exchangeData(int level);
 
@@ -79,6 +80,8 @@ private:
     std::shared_ptr<ADKernelManager> adKernelManager;
     //! \property gridScalingKernelManager is a shared pointer to an object of GridScalingKernelManager
     std::shared_ptr<GridScalingKernelManager> gridScalingKernelManager;
+    //! \property tmFactory is a shared pointer to an object of TurbulenceModelFactory
+    std::shared_ptr<TurbulenceModelFactory> tmFactory;
 };
 
 #endif
diff --git a/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp b/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp
index 06448c854ba2a8b1c3884c2c909029fd93cfb3d4..22192216927f91c33fafc23c54c3fae334abdd34 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp
+++ b/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp
@@ -30,6 +30,18 @@ void CudaMemoryManager::cudaCopyPrint(int lev)
     checkCudaErrors( cudaMemcpy(parameter->getParH(lev)->velocityZ   , parameter->getParD(lev)->velocityZ   , parameter->getParH(lev)->mem_size_real_SP , cudaMemcpyDeviceToHost));
     checkCudaErrors( cudaMemcpy(parameter->getParH(lev)->rho  , parameter->getParD(lev)->rho  , parameter->getParH(lev)->mem_size_real_SP , cudaMemcpyDeviceToHost));
     checkCudaErrors( cudaMemcpy(parameter->getParH(lev)->pressure, parameter->getParD(lev)->pressure, parameter->getParH(lev)->mem_size_real_SP , cudaMemcpyDeviceToHost));
+
+    if(parameter->getIsBodyForce())
+    {
+        checkCudaErrors( cudaMemcpy(parameter->getParH(lev)->forceX_SP   , parameter->getParD(lev)->forceX_SP   , parameter->getParH(lev)->mem_size_real_SP , cudaMemcpyDeviceToHost));
+        checkCudaErrors( cudaMemcpy(parameter->getParH(lev)->forceY_SP   , parameter->getParD(lev)->forceY_SP   , parameter->getParH(lev)->mem_size_real_SP , cudaMemcpyDeviceToHost));
+        checkCudaErrors( cudaMemcpy(parameter->getParH(lev)->forceZ_SP   , parameter->getParD(lev)->forceZ_SP   , parameter->getParH(lev)->mem_size_real_SP , cudaMemcpyDeviceToHost));
+    }
+
+    if(parameter->getUseTurbulentViscosity())
+    {
+        checkCudaErrors( cudaMemcpy(parameter->getParH(lev)->turbViscosity   , parameter->getParD(lev)->turbViscosity   , parameter->getParH(lev)->mem_size_real_SP , cudaMemcpyDeviceToHost));
+    }
 }
 void CudaMemoryManager::cudaCopyMedianPrint(int lev)
 {
diff --git a/src/gpu/VirtualFluids_GPU/GPU/GPU_Interface.h b/src/gpu/VirtualFluids_GPU/GPU/GPU_Interface.h
index f77967b46352cc95d95d4e3fa6db206e4308da73..f611075bf5d04e7c47837718cba562cdc4335515 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/GPU_Interface.h
+++ b/src/gpu/VirtualFluids_GPU/GPU/GPU_Interface.h
@@ -831,8 +831,12 @@ void QSlipDev27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions*
 
 void QSlipDevComp27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition);
 
+void BBSlipDevComp27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition);
+
 void QSlipDevCompTurbulentViscosity27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition);
 
+void QSlipPressureDevCompTurbulentViscosity27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition);
+
 void QSlipGeomDevComp27( unsigned int numberOfThreads,
 									real* DD, 
 									int* k_Q, 
@@ -867,6 +871,8 @@ void QStressDevComp27(Parameter *para,  QforBoundaryConditions* boundaryConditio
 
 void BBStressDev27(Parameter *para,  QforBoundaryConditions* boundaryCondition, const int level);
 
+void BBStressPressureDev27(Parameter *para,  QforBoundaryConditions* boundaryCondition, const int level);
+
 void QPressDev27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition);
 
 void QPressDevFixBackflow27(unsigned int numberOfThreads,
diff --git a/src/gpu/VirtualFluids_GPU/GPU/GPU_Kernels.cuh b/src/gpu/VirtualFluids_GPU/GPU/GPU_Kernels.cuh
index 5363a5c4ed3fe8de9dc6c0511d82f6ed04cb855e..4cb2867f322856c2e1ece4a60e70588a79ddc8a7 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/GPU_Kernels.cuh
+++ b/src/gpu/VirtualFluids_GPU/GPU/GPU_Kernels.cuh
@@ -882,17 +882,31 @@ __global__ void QSlipDeviceComp27(real* DD,
 											 unsigned int size_Mat,
 											 bool isEvenTimestep);
 
-__global__ void QSlipDeviceComp27TurbViscosity(real* DD,
-											 int* k_Q,
-											 real* QQ,
-											 unsigned int numberOfBCnodes,
-											 real om1,
-											 unsigned int* neighborX,
-											 unsigned int* neighborY,
-											 unsigned int* neighborZ,
-											 real* turbViscosity,
-											 unsigned int size_Mat,
-											 bool isEvenTimestep);
+__global__ void QSlipDeviceComp27TurbViscosity(
+                                    real* distributions, 
+                                    int* subgridDistanceIndices, 
+                                    real* subgridDistances,
+                                    unsigned int numberOfBCnodes,
+                                    real omega, 
+                                    unsigned int* neighborX,
+                                    unsigned int* neighborY,
+                                    unsigned int* neighborZ,
+                                    real* turbViscosity,
+                                    unsigned int numberOfLBnodes, 
+                                    bool isEvenTimestep);
+
+__global__ void QSlipPressureDeviceComp27TurbViscosity(
+                                    real* distributions, 
+                                    int* subgridDistanceIndices, 
+                                    real* subgridDistances,
+                                    unsigned int numberOfBCnodes,
+                                    real omega, 
+                                    unsigned int* neighborX,
+                                    unsigned int* neighborY,
+                                    unsigned int* neighborZ,
+                                    real* turbViscosity,
+                                    unsigned int numberOfLBnodes, 
+                                    bool isEvenTimestep);
 
 __global__ void QSlipGeomDeviceComp27(real* DD,
 												 int* k_Q,
@@ -985,6 +999,36 @@ __global__ void BBStressDevice27( real* DD,
 												unsigned int size_Mat,
 												bool isEvenTimestep);
 
+__global__ void BBStressPressureDevice27( real* DD,
+											            int* k_Q,
+                                             int* k_N,
+                                             real* QQ,
+                                             unsigned int  numberOfBCnodes,
+                                             real* vx,
+                                             real* vy,
+                                             real* vz,
+                                             real* normalX,
+                                             real* normalY,
+                                             real* normalZ,
+                                             real* vx_el,
+                                             real* vy_el,
+                                             real* vz_el,
+                                             real* vx_w_mean,
+                                             real* vy_w_mean,
+                                             real* vz_w_mean,
+                                             int* samplingOffset,
+                                             real* z0,
+                                             bool  hasWallModelMonitor,
+                                             real* u_star_monitor,
+                                             real* Fx_monitor,
+                                             real* Fy_monitor,
+                                             real* Fz_monitor,
+                                             unsigned int* neighborX,
+                                             unsigned int* neighborY,
+                                             unsigned int* neighborZ,
+                                             unsigned int size_Mat,
+                                             bool isEvenTimestep);
+
 //Pressure BCs
 __global__ void QPressDevice27( real* rhoBC,
                                            real* DD,
diff --git a/src/gpu/VirtualFluids_GPU/GPU/KernelUtilities.h b/src/gpu/VirtualFluids_GPU/GPU/KernelUtilities.h
index e80e36aa29a2d8965445cb334a49fec9d5379b91..2f6a11aa17398b65858508c3f94b241c16551b37 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/KernelUtilities.h
+++ b/src/gpu/VirtualFluids_GPU/GPU/KernelUtilities.h
@@ -148,6 +148,13 @@ __inline__ __device__ real getInterpolatedDistributionForVeloBC(const real& q, c
            + (q * (f + fInverse) - c6o1 * weight * velocity) / (c1o1 + q);
 }
 
+__inline__ __device__ real getBounceBackDistributionForVeloBC(  const real& f, 
+                                                                const real& velocity, const real weight)
+{
+
+    return f - (c6o1 * weight * velocity);
+}
+
 __inline__ __device__ real getInterpolatedDistributionForNoSlipBC(const real& q, const real& f, const real& fInverse, const real& feq, 
                                                                   const real& omega)
 {
diff --git a/src/gpu/VirtualFluids_GPU/GPU/LBMKernel.cu b/src/gpu/VirtualFluids_GPU/GPU/LBMKernel.cu
index 316a49c420eaf76dcee49e23591bf166d1859f2e..ff70727d52286d287039e88f7b1956c10a6900f9 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/LBMKernel.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/LBMKernel.cu
@@ -3371,6 +3371,26 @@ void QSlipDevCompTurbulentViscosity27(LBMSimulationParameter* parameterDevice, Q
    getLastCudaError("QSlipDeviceComp27TurbViscosity execution failed");
 }
 //////////////////////////////////////////////////////////////////////////
+void QSlipPressureDevCompTurbulentViscosity27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition)
+{
+   dim3 grid = vf::cuda::getCudaGrid( parameterDevice->numberofthreads, boundaryCondition->numberOfBCnodes);
+   dim3 threads(parameterDevice->numberofthreads, 1, 1 );
+
+   QSlipPressureDeviceComp27TurbViscosity<<< grid, threads >>> (
+         parameterDevice->distributions.f[0],
+         boundaryCondition->k,
+         boundaryCondition->q27[0],
+         boundaryCondition->numberOfBCnodes,
+         parameterDevice->omega,
+         parameterDevice->neighborX,
+         parameterDevice->neighborY,
+         parameterDevice->neighborZ,
+         parameterDevice->turbViscosity,
+         parameterDevice->numberOfNodes,
+         parameterDevice->isEvenTimestep);
+   getLastCudaError("QSlipDeviceComp27TurbViscosity execution failed");
+}
+//////////////////////////////////////////////////////////////////////////
 void QSlipDevComp27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition)
 {
    dim3 grid = vf::cuda::getCudaGrid( parameterDevice->numberofthreads, boundaryCondition->numberOfBCnodes);
@@ -3390,6 +3410,25 @@ void QSlipDevComp27(LBMSimulationParameter* parameterDevice, QforBoundaryConditi
    getLastCudaError("QSlipDeviceComp27 execution failed");
 }
 //////////////////////////////////////////////////////////////////////////
+void BBSlipDevComp27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition)
+{
+   dim3 grid = vf::cuda::getCudaGrid( parameterDevice->numberofthreads, boundaryCondition->numberOfBCnodes);
+   dim3 threads(parameterDevice->numberofthreads, 1, 1 );
+
+   QSlipDeviceComp27<<< grid, threads >>> (
+         parameterDevice->distributions.f[0],
+         boundaryCondition->k,
+         boundaryCondition->q27[0],
+         boundaryCondition->numberOfBCnodes,
+         parameterDevice->omega,
+         parameterDevice->neighborX,
+         parameterDevice->neighborY,
+         parameterDevice->neighborZ,
+         parameterDevice->numberOfNodes,
+         parameterDevice->isEvenTimestep);
+   getLastCudaError("BBSlipDeviceComp27 execution failed");
+}
+//////////////////////////////////////////////////////////////////////////
 void QSlipGeomDevComp27(unsigned int numberOfThreads,
 								   real* DD,
 								   int* k_Q,
@@ -3560,6 +3599,46 @@ void BBStressDev27(Parameter *para,  QforBoundaryConditions* boundaryCondition,
       para->getParD(level)->isEvenTimestep);
       getLastCudaError("BBStressDevice27 execution failed");
 }
+
+//////////////////////////////////////////////////////////////////////////
+void BBStressPressureDev27(Parameter *para,  QforBoundaryConditions* boundaryCondition, const int level)
+{
+   dim3 grid = vf::cuda::getCudaGrid( para->getParD(level)->numberofthreads, boundaryCondition->numberOfBCnodes);
+   dim3 threads(para->getParD(level)->numberofthreads, 1, 1 );
+
+   BBStressPressureDevice27<<< grid, threads >>> (
+      para->getParD(level)->distributions.f[0],
+      boundaryCondition->k,
+      boundaryCondition->kN,
+      boundaryCondition->q27[0],
+      boundaryCondition->numberOfBCnodes,
+      para->getParD(level)->velocityX,
+      para->getParD(level)->velocityY,
+      para->getParD(level)->velocityY,
+      boundaryCondition->normalX,
+      boundaryCondition->normalY,
+      boundaryCondition->normalZ,
+      boundaryCondition->Vx,
+      boundaryCondition->Vy,
+      boundaryCondition->Vz,
+      boundaryCondition->Vx1,
+      boundaryCondition->Vy1,
+      boundaryCondition->Vz1,
+      para->getParD(level)->wallModel.samplingOffset,
+      para->getParD(level)->wallModel.z0,
+      para->getHasWallModelMonitor(),
+      para->getParD(level)->wallModel.u_star,
+      para->getParD(level)->wallModel.Fx,
+      para->getParD(level)->wallModel.Fy,
+      para->getParD(level)->wallModel.Fz,
+      para->getParD(level)->neighborX,
+      para->getParD(level)->neighborY,
+      para->getParD(level)->neighborZ,
+      para->getParD(level)->numberOfNodes,
+      para->getParD(level)->isEvenTimestep);
+      getLastCudaError("BBStressDevice27 execution failed");
+}
+
 //////////////////////////////////////////////////////////////////////////
 void QPressDev27(LBMSimulationParameter* parameterDevice, QforBoundaryConditions* boundaryCondition)
 {
diff --git a/src/gpu/VirtualFluids_GPU/GPU/NoSlipBCs27.cu b/src/gpu/VirtualFluids_GPU/GPU/NoSlipBCs27.cu
index c348f0fb41dc203f7b6d4b35ca2bbbb31669b6cd..314687c4b29a32962b386d7c083f72b754388e5b 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/NoSlipBCs27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/NoSlipBCs27.cu
@@ -1773,7 +1773,6 @@ __global__ void QDeviceComp27(
       if (q>=c0o1 && q<=c1o1)
       {
          velocityLB = -vx1;
-         
          feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
          (dist.f[DIR_P00])[ke] = getInterpolatedDistributionForNoSlipBC(q, f_W, f_E, feq, omega);
       }
diff --git a/src/gpu/VirtualFluids_GPU/GPU/SlipBCs27.cu b/src/gpu/VirtualFluids_GPU/GPU/SlipBCs27.cu
index 57ab1d87ca22f402e0f95c17b99c47cab9429e11..0079c927373e90c1e408d2c57ace0595bcfdff15 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/SlipBCs27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/SlipBCs27.cu
@@ -1168,145 +1168,70 @@ __global__ void QSlipDeviceComp27(
    }
 }
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
 //////////////////////////////////////////////////////////////////////////////
-__global__ void QSlipDeviceComp27TurbViscosity(real* DD, 
-											 int* k_Q, 
-											 real* QQ,
-											 unsigned int numberOfBCnodes,
-											 real om1, 
-											 unsigned int* neighborX,
-											 unsigned int* neighborY,
-											 unsigned int* neighborZ,
-                                  real* turbViscosity,
-											 unsigned int size_Mat, 
-											 bool isEvenTimestep)
+__global__ void BBSlipDeviceComp27(
+                                    real* distributions, 
+                                    int* subgridDistanceIndices, 
+                                    real* subgridDistances,
+                                    unsigned int numberOfBCnodes,
+                                    real omega, 
+                                    unsigned int* neighborX,
+                                    unsigned int* neighborY,
+                                    unsigned int* neighborZ,
+                                    unsigned int numberOfLBnodes, 
+                                    bool isEvenTimestep)
 {
-   Distributions27 D;
-   if (isEvenTimestep==true)
-   {
-      D.f[DIR_P00   ] = &DD[DIR_P00   *size_Mat];
-      D.f[DIR_M00   ] = &DD[DIR_M00   *size_Mat];
-      D.f[DIR_0P0   ] = &DD[DIR_0P0   *size_Mat];
-      D.f[DIR_0M0   ] = &DD[DIR_0M0   *size_Mat];
-      D.f[DIR_00P   ] = &DD[DIR_00P   *size_Mat];
-      D.f[DIR_00M   ] = &DD[DIR_00M   *size_Mat];
-      D.f[DIR_PP0  ] = &DD[DIR_PP0  *size_Mat];
-      D.f[DIR_MM0  ] = &DD[DIR_MM0  *size_Mat];
-      D.f[DIR_PM0  ] = &DD[DIR_PM0  *size_Mat];
-      D.f[DIR_MP0  ] = &DD[DIR_MP0  *size_Mat];
-      D.f[DIR_P0P  ] = &DD[DIR_P0P  *size_Mat];
-      D.f[DIR_M0M  ] = &DD[DIR_M0M  *size_Mat];
-      D.f[DIR_P0M  ] = &DD[DIR_P0M  *size_Mat];
-      D.f[DIR_M0P  ] = &DD[DIR_M0P  *size_Mat];
-      D.f[DIR_0PP  ] = &DD[DIR_0PP  *size_Mat];
-      D.f[DIR_0MM  ] = &DD[DIR_0MM  *size_Mat];
-      D.f[DIR_0PM  ] = &DD[DIR_0PM  *size_Mat];
-      D.f[DIR_0MP  ] = &DD[DIR_0MP  *size_Mat];
-      D.f[DIR_000] = &DD[DIR_000*size_Mat];
-      D.f[DIR_PPP ] = &DD[DIR_PPP *size_Mat];
-      D.f[DIR_MMP ] = &DD[DIR_MMP *size_Mat];
-      D.f[DIR_PMP ] = &DD[DIR_PMP *size_Mat];
-      D.f[DIR_MPP ] = &DD[DIR_MPP *size_Mat];
-      D.f[DIR_PPM ] = &DD[DIR_PPM *size_Mat];
-      D.f[DIR_MMM ] = &DD[DIR_MMM *size_Mat];
-      D.f[DIR_PMM ] = &DD[DIR_PMM *size_Mat];
-      D.f[DIR_MPM ] = &DD[DIR_MPM *size_Mat];
-   } 
-   else
-   {
-      D.f[DIR_M00   ] = &DD[DIR_P00   *size_Mat];
-      D.f[DIR_P00   ] = &DD[DIR_M00   *size_Mat];
-      D.f[DIR_0M0   ] = &DD[DIR_0P0   *size_Mat];
-      D.f[DIR_0P0   ] = &DD[DIR_0M0   *size_Mat];
-      D.f[DIR_00M   ] = &DD[DIR_00P   *size_Mat];
-      D.f[DIR_00P   ] = &DD[DIR_00M   *size_Mat];
-      D.f[DIR_MM0  ] = &DD[DIR_PP0  *size_Mat];
-      D.f[DIR_PP0  ] = &DD[DIR_MM0  *size_Mat];
-      D.f[DIR_MP0  ] = &DD[DIR_PM0  *size_Mat];
-      D.f[DIR_PM0  ] = &DD[DIR_MP0  *size_Mat];
-      D.f[DIR_M0M  ] = &DD[DIR_P0P  *size_Mat];
-      D.f[DIR_P0P  ] = &DD[DIR_M0M  *size_Mat];
-      D.f[DIR_M0P  ] = &DD[DIR_P0M  *size_Mat];
-      D.f[DIR_P0M  ] = &DD[DIR_M0P  *size_Mat];
-      D.f[DIR_0MM  ] = &DD[DIR_0PP  *size_Mat];
-      D.f[DIR_0PP  ] = &DD[DIR_0MM  *size_Mat];
-      D.f[DIR_0MP  ] = &DD[DIR_0PM  *size_Mat];
-      D.f[DIR_0PM  ] = &DD[DIR_0MP  *size_Mat];
-      D.f[DIR_000] = &DD[DIR_000*size_Mat];
-      D.f[DIR_PPP ] = &DD[DIR_MMM *size_Mat];
-      D.f[DIR_MMP ] = &DD[DIR_PPM *size_Mat];
-      D.f[DIR_PMP ] = &DD[DIR_MPM *size_Mat];
-      D.f[DIR_MPP ] = &DD[DIR_PMM *size_Mat];
-      D.f[DIR_PPM ] = &DD[DIR_MMP *size_Mat];
-      D.f[DIR_MMM ] = &DD[DIR_PPP *size_Mat];
-      D.f[DIR_PMM ] = &DD[DIR_MPP *size_Mat];
-      D.f[DIR_MPM ] = &DD[DIR_PMP *size_Mat];
-   }
+   //! The slip boundary condition is executed in the following steps
+   //!
    ////////////////////////////////////////////////////////////////////////////////
-   const unsigned  x = threadIdx.x;  // Globaler x-Index 
-   const unsigned  y = blockIdx.x;   // Globaler y-Index 
-   const unsigned  z = blockIdx.y;   // Globaler z-Index 
+   //! - Get node index coordinates from threadIdx, blockIdx, blockDim and gridDim.
+   //!
+   const unsigned  x = threadIdx.x;  // global x-index 
+   const unsigned  y = blockIdx.x;   // global y-index 
+   const unsigned  z = blockIdx.y;   // global z-index 
 
    const unsigned nx = blockDim.x;
    const unsigned ny = gridDim.x;
 
    const unsigned k = nx*(ny*z + y) + x;
-   //////////////////////////////////////////////////////////////////////////
 
-   if(k<numberOfBCnodes)
+   if(k < numberOfBCnodes)
    {
+      //////////////////////////////////////////////////////////////////////////
+      //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on timestep is based on the esoteric twist algorithm \ref
+      //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), DOI:10.3390/computation5020019 ]</b></a>
+      //!
+      Distributions27 dist;
+      getPointersToDistributions(dist, distributions, numberOfLBnodes, isEvenTimestep);
+
       ////////////////////////////////////////////////////////////////////////////////
-      real *q_dirE,   *q_dirW,   *q_dirN,   *q_dirS,   *q_dirT,   *q_dirB, 
-            *q_dirNE,  *q_dirSW,  *q_dirSE,  *q_dirNW,  *q_dirTE,  *q_dirBW,
-            *q_dirBE,  *q_dirTW,  *q_dirTN,  *q_dirBS,  *q_dirBN,  *q_dirTS,
-            *q_dirTNE, *q_dirTSW, *q_dirTSE, *q_dirTNW, *q_dirBNE, *q_dirBSW,
-            *q_dirBSE, *q_dirBNW; 
-      q_dirE   = &QQ[DIR_P00   * numberOfBCnodes];
-      q_dirW   = &QQ[DIR_M00   * numberOfBCnodes];
-      q_dirN   = &QQ[DIR_0P0   * numberOfBCnodes];
-      q_dirS   = &QQ[DIR_0M0   * numberOfBCnodes];
-      q_dirT   = &QQ[DIR_00P   * numberOfBCnodes];
-      q_dirB   = &QQ[DIR_00M   * numberOfBCnodes];
-      q_dirNE  = &QQ[DIR_PP0  * numberOfBCnodes];
-      q_dirSW  = &QQ[DIR_MM0  * numberOfBCnodes];
-      q_dirSE  = &QQ[DIR_PM0  * numberOfBCnodes];
-      q_dirNW  = &QQ[DIR_MP0  * numberOfBCnodes];
-      q_dirTE  = &QQ[DIR_P0P  * numberOfBCnodes];
-      q_dirBW  = &QQ[DIR_M0M  * numberOfBCnodes];
-      q_dirBE  = &QQ[DIR_P0M  * numberOfBCnodes];
-      q_dirTW  = &QQ[DIR_M0P  * numberOfBCnodes];
-      q_dirTN  = &QQ[DIR_0PP  * numberOfBCnodes];
-      q_dirBS  = &QQ[DIR_0MM  * numberOfBCnodes];
-      q_dirBN  = &QQ[DIR_0PM  * numberOfBCnodes];
-      q_dirTS  = &QQ[DIR_0MP  * numberOfBCnodes];
-      q_dirTNE = &QQ[DIR_PPP * numberOfBCnodes];
-      q_dirTSW = &QQ[DIR_MMP * numberOfBCnodes];
-      q_dirTSE = &QQ[DIR_PMP * numberOfBCnodes];
-      q_dirTNW = &QQ[DIR_MPP * numberOfBCnodes];
-      q_dirBNE = &QQ[DIR_PPM * numberOfBCnodes];
-      q_dirBSW = &QQ[DIR_MMM * numberOfBCnodes];
-      q_dirBSE = &QQ[DIR_PMM * numberOfBCnodes];
-      q_dirBNW = &QQ[DIR_MPM * numberOfBCnodes];
+      //! - Set local subgrid distances (q's)
+      //!
+      SubgridDistances27 subgridD;
+      getPointersToSubgridDistances(subgridD, subgridDistances, numberOfBCnodes);
+      
       ////////////////////////////////////////////////////////////////////////////////
-      //index
-      unsigned int KQK  = k_Q[k];
-      unsigned int kzero= KQK;
-      unsigned int ke   = KQK;
-      unsigned int kw   = neighborX[KQK];
-      unsigned int kn   = KQK;
-      unsigned int ks   = neighborY[KQK];
-      unsigned int kt   = KQK;
-      unsigned int kb   = neighborZ[KQK];
+      //! - Set neighbor indices (necessary for indirect addressing)
+      //!
+      unsigned int indexOfBCnode  = subgridDistanceIndices[k];
+      unsigned int kzero= indexOfBCnode;
+      unsigned int ke   = indexOfBCnode;
+      unsigned int kw   = neighborX[indexOfBCnode];
+      unsigned int kn   = indexOfBCnode;
+      unsigned int ks   = neighborY[indexOfBCnode];
+      unsigned int kt   = indexOfBCnode;
+      unsigned int kb   = neighborZ[indexOfBCnode];
       unsigned int ksw  = neighborY[kw];
-      unsigned int kne  = KQK;
+      unsigned int kne  = indexOfBCnode;
       unsigned int kse  = ks;
       unsigned int knw  = kw;
       unsigned int kbw  = neighborZ[kw];
-      unsigned int kte  = KQK;
+      unsigned int kte  = indexOfBCnode;
       unsigned int kbe  = kb;
       unsigned int ktw  = kw;
       unsigned int kbs  = neighborZ[ks];
-      unsigned int ktn  = KQK;
+      unsigned int ktn  = indexOfBCnode;
       unsigned int kbn  = kb;
       unsigned int kts  = ks;
       unsigned int ktse = ks;
@@ -1315,527 +1240,2106 @@ __global__ void QSlipDeviceComp27TurbViscosity(real* DD,
       unsigned int kbse = kbs;
       unsigned int ktsw = ksw;
       unsigned int kbne = kb;
-      unsigned int ktne = KQK;
+      unsigned int ktne = indexOfBCnode;
       unsigned int kbsw = neighborZ[ksw];
       
       ////////////////////////////////////////////////////////////////////////////////
-      real f_W    = (D.f[DIR_P00   ])[ke   ];
-      real f_E    = (D.f[DIR_M00   ])[kw   ];
-      real f_S    = (D.f[DIR_0P0   ])[kn   ];
-      real f_N    = (D.f[DIR_0M0   ])[ks   ];
-      real f_B    = (D.f[DIR_00P   ])[kt   ];
-      real f_T    = (D.f[DIR_00M   ])[kb   ];
-      real f_SW   = (D.f[DIR_PP0  ])[kne  ];
-      real f_NE   = (D.f[DIR_MM0  ])[ksw  ];
-      real f_NW   = (D.f[DIR_PM0  ])[kse  ];
-      real f_SE   = (D.f[DIR_MP0  ])[knw  ];
-      real f_BW   = (D.f[DIR_P0P  ])[kte  ];
-      real f_TE   = (D.f[DIR_M0M  ])[kbw  ];
-      real f_TW   = (D.f[DIR_P0M  ])[kbe  ];
-      real f_BE   = (D.f[DIR_M0P  ])[ktw  ];
-      real f_BS   = (D.f[DIR_0PP  ])[ktn  ];
-      real f_TN   = (D.f[DIR_0MM  ])[kbs  ];
-      real f_TS   = (D.f[DIR_0PM  ])[kbn  ];
-      real f_BN   = (D.f[DIR_0MP  ])[kts  ];
-      real f_BSW  = (D.f[DIR_PPP ])[ktne ];
-      real f_BNE  = (D.f[DIR_MMP ])[ktsw ];
-      real f_BNW  = (D.f[DIR_PMP ])[ktse ];
-      real f_BSE  = (D.f[DIR_MPP ])[ktnw ];
-      real f_TSW  = (D.f[DIR_PPM ])[kbne ];
-      real f_TNE  = (D.f[DIR_MMM ])[kbsw ];
-      real f_TNW  = (D.f[DIR_PMM ])[kbse ];
-      real f_TSE  = (D.f[DIR_MPM ])[kbnw ];
+      //! - Set local distributions
+      //!
+      real f_W    = (dist.f[DIR_P00   ])[ke   ];
+      real f_E    = (dist.f[DIR_M00   ])[kw   ];
+      real f_S    = (dist.f[DIR_0P0   ])[kn   ];
+      real f_N    = (dist.f[DIR_0M0   ])[ks   ];
+      real f_B    = (dist.f[DIR_00P   ])[kt   ];
+      real f_T    = (dist.f[DIR_00M   ])[kb   ];
+      real f_SW   = (dist.f[DIR_PP0  ])[kne  ];
+      real f_NE   = (dist.f[DIR_MM0  ])[ksw  ];
+      real f_NW   = (dist.f[DIR_PM0  ])[kse  ];
+      real f_SE   = (dist.f[DIR_MP0  ])[knw  ];
+      real f_BW   = (dist.f[DIR_P0P  ])[kte  ];
+      real f_TE   = (dist.f[DIR_M0M  ])[kbw  ];
+      real f_TW   = (dist.f[DIR_P0M  ])[kbe  ];
+      real f_BE   = (dist.f[DIR_M0P  ])[ktw  ];
+      real f_BS   = (dist.f[DIR_0PP  ])[ktn  ];
+      real f_TN   = (dist.f[DIR_0MM  ])[kbs  ];
+      real f_TS   = (dist.f[DIR_0PM  ])[kbn  ];
+      real f_BN   = (dist.f[DIR_0MP  ])[kts  ];
+      real f_BSW  = (dist.f[DIR_PPP ])[ktne ];
+      real f_BNE  = (dist.f[DIR_MMP ])[ktsw ];
+      real f_BNW  = (dist.f[DIR_PMP ])[ktse ];
+      real f_BSE  = (dist.f[DIR_MPP ])[ktnw ];
+      real f_TSW  = (dist.f[DIR_PPM ])[kbne ];
+      real f_TNE  = (dist.f[DIR_MMM ])[kbsw ];
+      real f_TNW  = (dist.f[DIR_PMM ])[kbse ];
+      real f_TSE  = (dist.f[DIR_MPM ])[kbnw ];
+
       ////////////////////////////////////////////////////////////////////////////////
-      real vx1, vx2, vx3, drho, feq, q;
-      drho   =  f_TSE + f_TNW + f_TNE + f_TSW + f_BSE + f_BNW + f_BNE + f_BSW +
-                f_BN + f_TS + f_TN + f_BS + f_BE + f_TW + f_TE + f_BW + f_SE + f_NW + f_NE + f_SW + 
-                f_T + f_B + f_N + f_S + f_E + f_W + ((D.f[DIR_000])[kzero]); 
+      //! - Calculate macroscopic quantities
+      //!
+      real drho = f_TSE + f_TNW + f_TNE + f_TSW + f_BSE + f_BNW + f_BNE + f_BSW +
+                  f_BN + f_TS + f_TN + f_BS + f_BE + f_TW + f_TE + f_BW + f_SE + f_NW + f_NE + f_SW + 
+                  f_T + f_B + f_N + f_S + f_E + f_W + ((dist.f[DIR_000])[kzero]); 
 
-      vx1    =  (((f_TSE - f_BNW) - (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
-                ((f_BE - f_TW)   + (f_TE - f_BW))   + ((f_SE - f_NW)   + (f_NE - f_SW)) +
-                (f_E - f_W)) / (c1o1 + drho); 
-         
+      real vx1  = (((f_TSE - f_BNW) - (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                   ((f_BE - f_TW)   + (f_TE - f_BW))   + ((f_SE - f_NW)   + (f_NE - f_SW)) +
+                   (f_E - f_W)) / (c1o1 + drho);
 
-      vx2    =   ((-(f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
-                 ((f_BN - f_TS)   + (f_TN - f_BS))    + (-(f_SE - f_NW)  + (f_NE - f_SW)) +
-                 (f_N - f_S)) / (c1o1 + drho); 
+      real vx2  = ((-(f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                   ((f_BN - f_TS)   + (f_TN - f_BS))    + (-(f_SE - f_NW)  + (f_NE - f_SW)) +
+                   (f_N - f_S)) / (c1o1 + drho);
 
-      vx3    =   (((f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) + (f_TSW - f_BNE)) +
-                 (-(f_BN - f_TS)  + (f_TN - f_BS))   + ((f_TE - f_BW)   - (f_BE - f_TW)) +
-                 (f_T - f_B)) / (c1o1 + drho); 
+      real vx3  = (((f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) + (f_TSW - f_BNE)) +
+                   (-(f_BN - f_TS)  + (f_TN - f_BS))   + ((f_TE - f_BW)   - (f_BE - f_TW)) +
+                   (f_T - f_B)) / (c1o1 + drho);
 
-      real cu_sq=c3o2*(vx1*vx1+vx2*vx2+vx3*vx3) * (c1o1 + drho);
+      real cu_sq = c3o2 * (vx1 * vx1 + vx2 * vx2 + vx3 * vx3) * (c1o1 + drho);
 
-      //////////////////////////////////////////////////////////////////////////
-      if (isEvenTimestep==false)
-      {
-         D.f[DIR_P00   ] = &DD[DIR_P00   *size_Mat];
-         D.f[DIR_M00   ] = &DD[DIR_M00   *size_Mat];
-         D.f[DIR_0P0   ] = &DD[DIR_0P0   *size_Mat];
-         D.f[DIR_0M0   ] = &DD[DIR_0M0   *size_Mat];
-         D.f[DIR_00P   ] = &DD[DIR_00P   *size_Mat];
-         D.f[DIR_00M   ] = &DD[DIR_00M   *size_Mat];
-         D.f[DIR_PP0  ] = &DD[DIR_PP0  *size_Mat];
-         D.f[DIR_MM0  ] = &DD[DIR_MM0  *size_Mat];
-         D.f[DIR_PM0  ] = &DD[DIR_PM0  *size_Mat];
-         D.f[DIR_MP0  ] = &DD[DIR_MP0  *size_Mat];
-         D.f[DIR_P0P  ] = &DD[DIR_P0P  *size_Mat];
-         D.f[DIR_M0M  ] = &DD[DIR_M0M  *size_Mat];
-         D.f[DIR_P0M  ] = &DD[DIR_P0M  *size_Mat];
-         D.f[DIR_M0P  ] = &DD[DIR_M0P  *size_Mat];
-         D.f[DIR_0PP  ] = &DD[DIR_0PP  *size_Mat];
-         D.f[DIR_0MM  ] = &DD[DIR_0MM  *size_Mat];
-         D.f[DIR_0PM  ] = &DD[DIR_0PM  *size_Mat];
-         D.f[DIR_0MP  ] = &DD[DIR_0MP  *size_Mat];
-         D.f[DIR_000] = &DD[DIR_000*size_Mat];
-         D.f[DIR_PPP ] = &DD[DIR_PPP *size_Mat];
-         D.f[DIR_MMP ] = &DD[DIR_MMP *size_Mat];
-         D.f[DIR_PMP ] = &DD[DIR_PMP *size_Mat];
-         D.f[DIR_MPP ] = &DD[DIR_MPP *size_Mat];
-         D.f[DIR_PPM ] = &DD[DIR_PPM *size_Mat];
-         D.f[DIR_MMM ] = &DD[DIR_MMM *size_Mat];
-         D.f[DIR_PMM ] = &DD[DIR_PMM *size_Mat];
-         D.f[DIR_MPM ] = &DD[DIR_MPM *size_Mat];
-      } 
-      else
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - change the pointer to write the results in the correct array
+      //!
+      getPointersToDistributions(dist, distributions, numberOfLBnodes, !isEvenTimestep);
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Multiply the local velocities by the slipLength
+      //!
+      real slipLength = c1o1;
+      real VeloX = slipLength*vx1;
+      real VeloY = slipLength*vx2;
+      real VeloZ = slipLength*vx3;
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Update distributions with subgrid distance (q) between zero and one
+      //!
+      real q, velocityBC;
+
+      bool x = false;
+      bool y = false;
+      bool z = false;
+
+      q = (subgridD.q[DIR_P00])[k];
+      if (q>=c0o1 && q<=c1o1)  // only update distribution for q between zero and one
+      {
+         VeloX = c0o1;
+         x = true;
+
+         velocityBC = VeloX;
+         (dist.f[DIR_M00])[kw] = getBounceBackDistributionForVeloBC(f_W, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_M00])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = c0o1;
+         x = true;
+
+         velocityBC = -VeloX;
+         (dist.f[DIR_P00])[ke] = getBounceBackDistributionForVeloBC(f_E, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_0P0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = c0o1;
+         y = true;
+
+         velocityBC = VeloY;
+         (dist.f[DIR_0M0])[ks] = getBounceBackDistributionForVeloBC(f_S, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_0M0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = c0o1;
+         y = true;
+
+         velocityBC = -VeloY;
+         (dist.f[DIR_0P0])[kn] = getBounceBackDistributionForVeloBC(f_N, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_00P])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloZ = c0o1;
+         z = true;
+
+         velocityBC = VeloZ;
+         (dist.f[DIR_00M])[kb] = getBounceBackDistributionForVeloBC(f_B, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_00M])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloZ = c0o1;
+         z = true;
+
+         velocityBC = -VeloZ;
+         (dist.f[DIR_00P])[kt] = getBounceBackDistributionForVeloBC(f_T, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_PP0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityBC = VeloX + VeloY;
+         (dist.f[DIR_MM0])[ksw] = getBounceBackDistributionForVeloBC(f_SW, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_MM0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityBC = -VeloX - VeloY;
+         (dist.f[DIR_PP0])[kne] = getBounceBackDistributionForVeloBC(f_NE, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_PM0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityBC = VeloX - VeloY;
+         (dist.f[DIR_MP0])[knw] = getBounceBackDistributionForVeloBC(f_NW, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_MP0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityBC = -VeloX + VeloY;
+         (dist.f[DIR_PM0])[kse] = getBounceBackDistributionForVeloBC(f_SE, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_P0P])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloX + VeloZ;
+         (dist.f[DIR_M0M])[kbw] = getBounceBackDistributionForVeloBC(f_BW, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_M0M])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+        VeloX = slipLength*vx1;
+        VeloZ = slipLength*vx3;
+        if (x == true) VeloX = c0o1;
+        if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloX - VeloZ;
+         (dist.f[DIR_P0P])[kte] = getBounceBackDistributionForVeloBC(f_TE, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_P0M])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloX - VeloZ;
+         (dist.f[DIR_M0P])[ktw] = getBounceBackDistributionForVeloBC(f_TW, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_M0P])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloX + VeloZ;
+         (dist.f[DIR_P0M])[kbe] = getBounceBackDistributionForVeloBC(f_BE, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_0PP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloY + VeloZ;
+         (dist.f[DIR_0MM])[kbs] = getBounceBackDistributionForVeloBC(f_BS, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_0MM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloY - VeloZ;
+         (dist.f[DIR_0PP])[ktn] = getBounceBackDistributionForVeloBC(f_TN, velocityBC, c1o54);
+      }
+
+
+      q = (subgridD.q[DIR_0PM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloY - VeloZ;
+         (dist.f[DIR_0MP])[kts] = getBounceBackDistributionForVeloBC(f_TS, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_0MP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloY + VeloZ;
+         (dist.f[DIR_0PM])[kbn] = getBounceBackDistributionForVeloBC(f_BN, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_PPP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloX + VeloY + VeloZ;
+         (dist.f[DIR_MMM])[kbsw] = getBounceBackDistributionForVeloBC(f_TNE, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MMM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloX - VeloY - VeloZ;
+         (dist.f[DIR_PPP])[ktne] = getBounceBackDistributionForVeloBC(f_TNE, velocityBC, c1o216);
+      }
+
+
+      q = (subgridD.q[DIR_PPM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloX + VeloY - VeloZ;
+         (dist.f[DIR_MMP])[ktsw] = getBounceBackDistributionForVeloBC(f_TSW, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MMP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloX - VeloY + VeloZ;
+         (dist.f[DIR_PPM])[kbne] = getBounceBackDistributionForVeloBC(f_BNE, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_PMP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloX - VeloY + VeloZ;
+         (dist.f[DIR_MPM])[kbnw] = getBounceBackDistributionForVeloBC(f_BNW, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MPM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloX + VeloY - VeloZ;
+         (dist.f[DIR_PMP])[ktse] = getBounceBackDistributionForVeloBC(f_TSE, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_PMM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = VeloX - VeloY - VeloZ;
+         (dist.f[DIR_MPP])[ktnw] = getBounceBackDistributionForVeloBC(f_TNW, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MPP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityBC = -VeloX + VeloY + VeloZ;
+         (dist.f[DIR_PMM])[kbse] = getBounceBackDistributionForVeloBC(f_BSE, velocityBC, c1o216);
+      }
+   }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////
+__global__ void QSlipDeviceComp27TurbViscosity(
+                                    real* distributions, 
+                                    int* subgridDistanceIndices, 
+                                    real* subgridDistances,
+                                    unsigned int numberOfBCnodes,
+                                    real omega, 
+                                    unsigned int* neighborX,
+                                    unsigned int* neighborY,
+                                    unsigned int* neighborZ,
+                                    real* turbViscosity,
+                                    unsigned int numberOfLBnodes, 
+                                    bool isEvenTimestep)
+{
+   //! The slip boundary condition is executed in the following steps
+   //!
+   ////////////////////////////////////////////////////////////////////////////////
+   //! - Get node index coordinates from threadIdx, blockIdx, blockDim and gridDim.
+   //!
+   const unsigned  x = threadIdx.x;  // global x-index 
+   const unsigned  y = blockIdx.x;   // global y-index 
+   const unsigned  z = blockIdx.y;   // global z-index 
+
+   const unsigned nx = blockDim.x;
+   const unsigned ny = gridDim.x;
+
+   const unsigned k = nx*(ny*z + y) + x;
+
+   if(k < numberOfBCnodes)
+   {
+      //////////////////////////////////////////////////////////////////////////
+      //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on timestep is based on the esoteric twist algorithm \ref
+      //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), DOI:10.3390/computation5020019 ]</b></a>
+      //!
+      Distributions27 dist;
+      getPointersToDistributions(dist, distributions, numberOfLBnodes, isEvenTimestep);
+      
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Set local subgrid distances (q's)
+      //!
+      SubgridDistances27 subgridD;
+      getPointersToSubgridDistances(subgridD, subgridDistances, numberOfBCnodes);
+      
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Set neighbor indices (necessary for indirect addressing)
+      //!
+      unsigned int indexOfBCnode  = subgridDistanceIndices[k];
+      unsigned int kzero= indexOfBCnode;
+      unsigned int ke   = indexOfBCnode;
+      unsigned int kw   = neighborX[indexOfBCnode];
+      unsigned int kn   = indexOfBCnode;
+      unsigned int ks   = neighborY[indexOfBCnode];
+      unsigned int kt   = indexOfBCnode;
+      unsigned int kb   = neighborZ[indexOfBCnode];
+      unsigned int ksw  = neighborY[kw];
+      unsigned int kne  = indexOfBCnode;
+      unsigned int kse  = ks;
+      unsigned int knw  = kw;
+      unsigned int kbw  = neighborZ[kw];
+      unsigned int kte  = indexOfBCnode;
+      unsigned int kbe  = kb;
+      unsigned int ktw  = kw;
+      unsigned int kbs  = neighborZ[ks];
+      unsigned int ktn  = indexOfBCnode;
+      unsigned int kbn  = kb;
+      unsigned int kts  = ks;
+      unsigned int ktse = ks;
+      unsigned int kbnw = kbw;
+      unsigned int ktnw = kw;
+      unsigned int kbse = kbs;
+      unsigned int ktsw = ksw;
+      unsigned int kbne = kb;
+      unsigned int ktne = indexOfBCnode;
+      unsigned int kbsw = neighborZ[ksw];
+      
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Set local distributions
+      //!
+      real f_W    = (dist.f[DIR_P00   ])[ke   ];
+      real f_E    = (dist.f[DIR_M00   ])[kw   ];
+      real f_S    = (dist.f[DIR_0P0   ])[kn   ];
+      real f_N    = (dist.f[DIR_0M0   ])[ks   ];
+      real f_B    = (dist.f[DIR_00P   ])[kt   ];
+      real f_T    = (dist.f[DIR_00M   ])[kb   ];
+      real f_SW   = (dist.f[DIR_PP0  ])[kne  ];
+      real f_NE   = (dist.f[DIR_MM0  ])[ksw  ];
+      real f_NW   = (dist.f[DIR_PM0  ])[kse  ];
+      real f_SE   = (dist.f[DIR_MP0  ])[knw  ];
+      real f_BW   = (dist.f[DIR_P0P  ])[kte  ];
+      real f_TE   = (dist.f[DIR_M0M  ])[kbw  ];
+      real f_TW   = (dist.f[DIR_P0M  ])[kbe  ];
+      real f_BE   = (dist.f[DIR_M0P  ])[ktw  ];
+      real f_BS   = (dist.f[DIR_0PP  ])[ktn  ];
+      real f_TN   = (dist.f[DIR_0MM  ])[kbs  ];
+      real f_TS   = (dist.f[DIR_0PM  ])[kbn  ];
+      real f_BN   = (dist.f[DIR_0MP  ])[kts  ];
+      real f_BSW  = (dist.f[DIR_PPP ])[ktne ];
+      real f_BNE  = (dist.f[DIR_MMP ])[ktsw ];
+      real f_BNW  = (dist.f[DIR_PMP ])[ktse ];
+      real f_BSE  = (dist.f[DIR_MPP ])[ktnw ];
+      real f_TSW  = (dist.f[DIR_PPM ])[kbne ];
+      real f_TNE  = (dist.f[DIR_MMM ])[kbsw ];
+      real f_TNW  = (dist.f[DIR_PMM ])[kbse ];
+      real f_TSE  = (dist.f[DIR_MPM ])[kbnw ];
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Calculate macroscopic quantities
+      //!
+      real drho = f_TSE + f_TNW + f_TNE + f_TSW + f_BSE + f_BNW + f_BNE + f_BSW +
+                  f_BN + f_TS + f_TN + f_BS + f_BE + f_TW + f_TE + f_BW + f_SE + f_NW + f_NE + f_SW + 
+                  f_T + f_B + f_N + f_S + f_E + f_W + ((dist.f[DIR_000])[kzero]); 
+
+      real vx1  = (((f_TSE - f_BNW) - (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                   ((f_BE - f_TW)   + (f_TE - f_BW))   + ((f_SE - f_NW)   + (f_NE - f_SW)) +
+                   (f_E - f_W)) / (c1o1 + drho);
+
+      real vx2  = ((-(f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                   ((f_BN - f_TS)   + (f_TN - f_BS))    + (-(f_SE - f_NW)  + (f_NE - f_SW)) +
+                   (f_N - f_S)) / (c1o1 + drho);
+
+      real vx3  = (((f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) + (f_TSW - f_BNE)) +
+                   (-(f_BN - f_TS)  + (f_TN - f_BS))   + ((f_TE - f_BW)   - (f_BE - f_TW)) +
+                   (f_T - f_B)) / (c1o1 + drho);
+
+      real cu_sq = c3o2 * (vx1 * vx1 + vx2 * vx2 + vx3 * vx3) * (c1o1 + drho);
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - change the pointer to write the results in the correct array
+      //!
+      getPointersToDistributions(dist, distributions, numberOfLBnodes, !isEvenTimestep);
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - compute local relaxation rate
+      //!
+      real om_turb = omega / (c1o1 + c3o1* omega* max(c0o1, turbViscosity[indexOfBCnode]) );
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Multiply the local velocities by the slipLength
+      //!
+      real slipLength = c1o1;
+      real VeloX = slipLength*vx1;
+      real VeloY = slipLength*vx2;
+      real VeloZ = slipLength*vx3;
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Update distributions with subgrid distance (q) between zero and one
+      //!
+      real feq, q, velocityLB, velocityBC;
+
+      bool x = false;
+      bool y = false;
+      bool z = false;
+
+      q = (subgridD.q[DIR_P00])[k];
+      if (q>=c0o1 && q<=c1o1)  // only update distribution for q between zero and one
+      {
+         VeloX = c0o1;
+         x = true;
+
+         velocityLB = vx1;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = VeloX;
+         (dist.f[DIR_M00])[kw] = getInterpolatedDistributionForVeloBC(q, f_E, f_W, feq, om_turb, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_M00])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = c0o1;
+         x = true;
+
+         velocityLB = -vx1;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = -VeloX;
+         (dist.f[DIR_P00])[ke] = getInterpolatedDistributionForVeloBC(q, f_W, f_E, feq, om_turb, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_0P0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = c0o1;
+         y = true;
+
+         velocityLB = vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = VeloY;
+         (dist.f[DIR_0M0])[ks] = getInterpolatedDistributionForVeloBC(q, f_N, f_S, feq, om_turb, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_0M0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = c0o1;
+         y = true;
+
+         velocityLB = -vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = -VeloY;
+         (dist.f[DIR_0P0])[kn] = getInterpolatedDistributionForVeloBC(q, f_S, f_N, feq, om_turb, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_00P])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloZ = c0o1;
+         z = true;
+
+         velocityLB = vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = VeloZ;
+         (dist.f[DIR_00M])[kb] = getInterpolatedDistributionForVeloBC(q, f_T, f_B, feq, om_turb, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_00M])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloZ = c0o1;
+         z = true;
+
+         velocityLB = -vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = -VeloZ;
+         (dist.f[DIR_00P])[kt] = getInterpolatedDistributionForVeloBC(q, f_B, f_T, feq, om_turb, velocityBC, c2o27);
+      }
+
+      q = (subgridD.q[DIR_PP0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = vx1 + vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX + VeloY;
+         (dist.f[DIR_MM0])[ksw] = getInterpolatedDistributionForVeloBC(q, f_NE, f_SW, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_MM0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = -vx1 - vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX - VeloY;
+         (dist.f[DIR_PP0])[kne] = getInterpolatedDistributionForVeloBC(q, f_SW, f_NE, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_PM0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = vx1 - vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX - VeloY;
+         (dist.f[DIR_MP0])[knw] = getInterpolatedDistributionForVeloBC(q, f_SE, f_NW, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_MP0])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = -vx1 + vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX + VeloY;
+         (dist.f[DIR_PM0])[kse] = getInterpolatedDistributionForVeloBC(q, f_NW, f_SE, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_P0P])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx1 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX + VeloZ;
+         (dist.f[DIR_M0M])[kbw] = getInterpolatedDistributionForVeloBC(q, f_TE, f_BW, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_M0M])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+        VeloX = slipLength*vx1;
+        VeloZ = slipLength*vx3;
+        if (x == true) VeloX = c0o1;
+        if (z == true) VeloZ = c0o1;
+
+         velocityLB = -vx1 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX - VeloZ;
+         (dist.f[DIR_P0P])[kte] = getInterpolatedDistributionForVeloBC(q, f_BW, f_TE, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_P0M])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx1 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX - VeloZ;
+         (dist.f[DIR_M0P])[ktw] = getInterpolatedDistributionForVeloBC(q, f_BE, f_TW, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_M0P])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = -vx1 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX + VeloZ;
+         (dist.f[DIR_P0M])[kbe] = getInterpolatedDistributionForVeloBC(q, f_TW, f_BE, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_0PP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloY + VeloZ;
+         (dist.f[DIR_0MM])[kbs] = getInterpolatedDistributionForVeloBC(q, f_TN, f_BS, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_0MM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = -vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloY - VeloZ;
+         (dist.f[DIR_0PP])[ktn] = getInterpolatedDistributionForVeloBC(q, f_BS, f_TN, feq, om_turb, velocityBC, c1o54);
+      }
+
+
+      q = (subgridD.q[DIR_0PM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloY - VeloZ;
+         (dist.f[DIR_0MP])[kts] = getInterpolatedDistributionForVeloBC(q, f_BN, f_TS, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_0MP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = -vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloY + VeloZ;
+         (dist.f[DIR_0PM])[kbn] = getInterpolatedDistributionForVeloBC(q, f_TS, f_BN, feq, om_turb, velocityBC, c1o54);
+      }
+
+      q = (subgridD.q[DIR_PPP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 + vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX + VeloY + VeloZ;
+         (dist.f[DIR_MMM])[kbsw] = getInterpolatedDistributionForVeloBC(q, f_TNE, f_BSW, feq, om_turb, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MMM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 - vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX - VeloY - VeloZ;
+         (dist.f[DIR_PPP])[ktne] = getInterpolatedDistributionForVeloBC(q, f_BSW, f_TNE, feq, om_turb, velocityBC, c1o216);
+      }
+
+
+      q = (subgridD.q[DIR_PPM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 + vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX + VeloY - VeloZ;
+         (dist.f[DIR_MMP])[ktsw] = getInterpolatedDistributionForVeloBC(q, f_BNE, f_TSW, feq, om_turb, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MMP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 - vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX - VeloY + VeloZ;
+         (dist.f[DIR_PPM])[kbne] = getInterpolatedDistributionForVeloBC(q, f_TSW, f_BNE, feq, om_turb, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_PMP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 - vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX - VeloY + VeloZ;
+         (dist.f[DIR_MPM])[kbnw] = getInterpolatedDistributionForVeloBC(q, f_TSE, f_BNW, feq, om_turb, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MPM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 + vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX + VeloY - VeloZ;
+         (dist.f[DIR_PMP])[ktse] = getInterpolatedDistributionForVeloBC(q, f_BNW, f_TSE, feq, om_turb, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_PMM])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 - vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX - VeloY - VeloZ;
+         (dist.f[DIR_MPP])[ktnw] = getInterpolatedDistributionForVeloBC(q, f_BSE, f_TNW, feq, om_turb, velocityBC, c1o216);
+      }
+
+      q = (subgridD.q[DIR_MPP])[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 + vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX + VeloY + VeloZ;
+         (dist.f[DIR_PMM])[kbse] = getInterpolatedDistributionForVeloBC(q, f_TNW, f_BSE, feq, om_turb, velocityBC, c1o216);
+      }
+   }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+__global__ void QSlipPressureDeviceComp27TurbViscosity(
+                                    real* distributions, 
+                                    int* subgridDistanceIndices, 
+                                    real* subgridDistances,
+                                    unsigned int numberOfBCnodes,
+                                    real omega, 
+                                    unsigned int* neighborX,
+                                    unsigned int* neighborY,
+                                    unsigned int* neighborZ,
+                                    real* turbViscosity,
+                                    unsigned int numberOfLBnodes, 
+                                    bool isEvenTimestep)
+{
+   //! The slip boundary condition is executed in the following steps
+   //!
+   ////////////////////////////////////////////////////////////////////////////////
+   //! - Get node index coordinates from threadIdx, blockIdx, blockDim and gridDim.
+   //!
+   const unsigned  x = threadIdx.x;  // global x-index 
+   const unsigned  y = blockIdx.x;   // global y-index 
+   const unsigned  z = blockIdx.y;   // global z-index 
+
+   const unsigned nx = blockDim.x;
+   const unsigned ny = gridDim.x;
+
+   const unsigned k = nx*(ny*z + y) + x;
+
+   if(k < numberOfBCnodes)
+   {
+      //////////////////////////////////////////////////////////////////////////
+      //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on timestep is based on the esoteric twist algorithm \ref
+      //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), DOI:10.3390/computation5020019 ]</b></a>
+      //!
+      Distributions27 dist;
+      getPointersToDistributions(dist, distributions, numberOfLBnodes, isEvenTimestep);
+      
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Set local subgrid distances (q's)
+      //!
+      SubgridDistances27 subgridD;
+      getPointersToSubgridDistances(subgridD, subgridDistances, numberOfBCnodes);
+      
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Set neighbor indices (necessary for indirect addressing)
+      //!
+      unsigned int indexOfBCnode  = subgridDistanceIndices[k];
+      unsigned int kzero= indexOfBCnode;
+      unsigned int ke   = indexOfBCnode;
+      unsigned int kw   = neighborX[indexOfBCnode];
+      unsigned int kn   = indexOfBCnode;
+      unsigned int ks   = neighborY[indexOfBCnode];
+      unsigned int kt   = indexOfBCnode;
+      unsigned int kb   = neighborZ[indexOfBCnode];
+      unsigned int ksw  = neighborY[kw];
+      unsigned int kne  = indexOfBCnode;
+      unsigned int kse  = ks;
+      unsigned int knw  = kw;
+      unsigned int kbw  = neighborZ[kw];
+      unsigned int kte  = indexOfBCnode;
+      unsigned int kbe  = kb;
+      unsigned int ktw  = kw;
+      unsigned int kbs  = neighborZ[ks];
+      unsigned int ktn  = indexOfBCnode;
+      unsigned int kbn  = kb;
+      unsigned int kts  = ks;
+      unsigned int ktse = ks;
+      unsigned int kbnw = kbw;
+      unsigned int ktnw = kw;
+      unsigned int kbse = kbs;
+      unsigned int ktsw = ksw;
+      unsigned int kbne = kb;
+      unsigned int ktne = indexOfBCnode;
+      unsigned int kbsw = neighborZ[ksw];
+      
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Set local distributions
+      //!
+      real f_W    = (dist.f[DIR_P00   ])[ke   ];
+      real f_E    = (dist.f[DIR_M00   ])[kw   ];
+      real f_S    = (dist.f[DIR_0P0   ])[kn   ];
+      real f_N    = (dist.f[DIR_0M0   ])[ks   ];
+      real f_B    = (dist.f[DIR_00P   ])[kt   ];
+      real f_T    = (dist.f[DIR_00M   ])[kb   ];
+      real f_SW   = (dist.f[DIR_PP0  ])[kne  ];
+      real f_NE   = (dist.f[DIR_MM0  ])[ksw  ];
+      real f_NW   = (dist.f[DIR_PM0  ])[kse  ];
+      real f_SE   = (dist.f[DIR_MP0  ])[knw  ];
+      real f_BW   = (dist.f[DIR_P0P  ])[kte  ];
+      real f_TE   = (dist.f[DIR_M0M  ])[kbw  ];
+      real f_TW   = (dist.f[DIR_P0M  ])[kbe  ];
+      real f_BE   = (dist.f[DIR_M0P  ])[ktw  ];
+      real f_BS   = (dist.f[DIR_0PP  ])[ktn  ];
+      real f_TN   = (dist.f[DIR_0MM  ])[kbs  ];
+      real f_TS   = (dist.f[DIR_0PM  ])[kbn  ];
+      real f_BN   = (dist.f[DIR_0MP  ])[kts  ];
+      real f_BSW  = (dist.f[DIR_PPP ])[ktne ];
+      real f_BNE  = (dist.f[DIR_MMP ])[ktsw ];
+      real f_BNW  = (dist.f[DIR_PMP ])[ktse ];
+      real f_BSE  = (dist.f[DIR_MPP ])[ktnw ];
+      real f_TSW  = (dist.f[DIR_PPM ])[kbne ];
+      real f_TNE  = (dist.f[DIR_MMM ])[kbsw ];
+      real f_TNW  = (dist.f[DIR_PMM ])[kbse ];
+      real f_TSE  = (dist.f[DIR_MPM ])[kbnw ];
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Calculate macroscopic quantities
+      //!
+      real drho = f_TSE + f_TNW + f_TNE + f_TSW + f_BSE + f_BNW + f_BNE + f_BSW +
+                  f_BN + f_TS + f_TN + f_BS + f_BE + f_TW + f_TE + f_BW + f_SE + f_NW + f_NE + f_SW + 
+                  f_T + f_B + f_N + f_S + f_E + f_W + ((dist.f[DIR_000])[kzero]); 
+
+      real vx1  = (((f_TSE - f_BNW) - (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                   ((f_BE - f_TW)   + (f_TE - f_BW))   + ((f_SE - f_NW)   + (f_NE - f_SW)) +
+                   (f_E - f_W)) / (c1o1 + drho);
+
+      real vx2  = ((-(f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                   ((f_BN - f_TS)   + (f_TN - f_BS))    + (-(f_SE - f_NW)  + (f_NE - f_SW)) +
+                   (f_N - f_S)) / (c1o1 + drho);
+
+      real vx3  = (((f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) + (f_TSW - f_BNE)) +
+                   (-(f_BN - f_TS)  + (f_TN - f_BS))   + ((f_TE - f_BW)   - (f_BE - f_TW)) +
+                   (f_T - f_B)) / (c1o1 + drho);
+
+      real cu_sq = c3o2 * (vx1 * vx1 + vx2 * vx2 + vx3 * vx3) * (c1o1 + drho);
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - change the pointer to write the results in the correct array
+      //!
+      getPointersToDistributions(dist, distributions, numberOfLBnodes, !isEvenTimestep);
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - compute local relaxation rate
+      //!
+      real om_turb = omega / (c1o1 + c3o1* omega* max(c0o1, turbViscosity[indexOfBCnode]) );
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Multiply the local velocities by the slipLength
+      //!
+      real slipLength = c1o1;
+      real VeloX = slipLength*vx1;
+      real VeloY = slipLength*vx2;
+      real VeloZ = slipLength*vx3;
+
+      ////////////////////////////////////////////////////////////////////////////////
+      //! - Update distributions with subgrid distance (q) between zero and one
+      //!
+      real feq, q, velocityLB, velocityBC;
+
+      bool x = false;
+      bool y = false;
+      bool z = false;
+
+      q = (subgridD.q[DIR_P00])[k];
+      if (q>=c0o1 && q<=c1o1)  // only update distribution for q between zero and one
       {
-         D.f[DIR_M00   ] = &DD[DIR_P00   *size_Mat];
-         D.f[DIR_P00   ] = &DD[DIR_M00   *size_Mat];
-         D.f[DIR_0M0   ] = &DD[DIR_0P0   *size_Mat];
-         D.f[DIR_0P0   ] = &DD[DIR_0M0   *size_Mat];
-         D.f[DIR_00M   ] = &DD[DIR_00P   *size_Mat];
-         D.f[DIR_00P   ] = &DD[DIR_00M   *size_Mat];
-         D.f[DIR_MM0  ] = &DD[DIR_PP0  *size_Mat];
-         D.f[DIR_PP0  ] = &DD[DIR_MM0  *size_Mat];
-         D.f[DIR_MP0  ] = &DD[DIR_PM0  *size_Mat];
-         D.f[DIR_PM0  ] = &DD[DIR_MP0  *size_Mat];
-         D.f[DIR_M0M  ] = &DD[DIR_P0P  *size_Mat];
-         D.f[DIR_P0P  ] = &DD[DIR_M0M  *size_Mat];
-         D.f[DIR_M0P  ] = &DD[DIR_P0M  *size_Mat];
-         D.f[DIR_P0M  ] = &DD[DIR_M0P  *size_Mat];
-         D.f[DIR_0MM  ] = &DD[DIR_0PP  *size_Mat];
-         D.f[DIR_0PP  ] = &DD[DIR_0MM  *size_Mat];
-         D.f[DIR_0MP  ] = &DD[DIR_0PM  *size_Mat];
-         D.f[DIR_0PM  ] = &DD[DIR_0MP  *size_Mat];
-         D.f[DIR_000] = &DD[DIR_000*size_Mat];
-         D.f[DIR_PPP ] = &DD[DIR_MMM *size_Mat];
-         D.f[DIR_MMP ] = &DD[DIR_PPM *size_Mat];
-         D.f[DIR_PMP ] = &DD[DIR_MPM *size_Mat];
-         D.f[DIR_MPP ] = &DD[DIR_PMM *size_Mat];
-         D.f[DIR_PPM ] = &DD[DIR_MMP *size_Mat];
-         D.f[DIR_MMM ] = &DD[DIR_PPP *size_Mat];
-         D.f[DIR_PMM ] = &DD[DIR_MPP *size_Mat];
-         D.f[DIR_MPM ] = &DD[DIR_PMP *size_Mat];
+         VeloX = c0o1;
+         x = true;
+
+         velocityLB = vx1;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = VeloX;
+         (dist.f[DIR_M00])[kw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_E, f_W, feq, om_turb, drho, velocityBC, c2o27);
       }
-      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-      //Test
-      //(D.f[DIR_000])[k]=c1o10;
-      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-	  real om_turb = om1 / (c1o1 + c3o1*om1*max(c0o1, turbViscosity[k_Q[k]]));
-     
-     real fac = c1o1;//c99o100;
-	  real VeloX = fac*vx1;
-	  real VeloY = fac*vx2;
-	  real VeloZ = fac*vx3;
-	  bool x = false;
-	  bool y = false;
-	  bool z = false;
 
-      q = q_dirE[k];
+      q = (subgridD.q[DIR_M00])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = c0o1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 x = true;
-         feq=c2o27* (drho/*+three*( vx1        )*/+c9o2*( vx1        )*( vx1        ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_M00])[kw]=(c1o1-q)/(c1o1+q)*(f_E-f_W+(f_E+f_W-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_E+f_W)-c6o1*c2o27*( VeloX     ))/(c1o1+q) - c2o27 * drho;
-         //feq=c2over27* (drho+three*( vx1        )+c9over2*( vx1        )*( vx1        )-cu_sq); 
-         //(D.f[DIR_M00])[kw]=(one-q)/(one+q)*(f_E-feq*om1)/(one-om1)+(q*(f_E+f_W)-six*c2over27*( VeloX     ))/(one+q);
-         //(D.f[DIR_M00])[kw]=zero;
+         VeloX = c0o1;
+         x = true;
+
+         velocityLB = -vx1;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = -VeloX;
+         (dist.f[DIR_P00])[ke] = getInterpolatedDistributionForVeloWithPressureBC(q, f_W, f_E, feq, om_turb, drho, velocityBC, c2o27);
       }
 
-      q = q_dirW[k];
+      q = (subgridD.q[DIR_0P0])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = c0o1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 x = true;
-         feq=c2o27* (drho/*+three*(-vx1        )*/+c9o2*(-vx1        )*(-vx1        ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_P00])[ke]=(c1o1-q)/(c1o1+q)*(f_W-f_E+(f_W+f_E-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_W+f_E)-c6o1*c2o27*(-VeloX     ))/(c1o1+q) - c2o27 * drho;
-         //feq=c2over27* (drho+three*(-vx1        )+c9over2*(-vx1        )*(-vx1        )-cu_sq); 
-         //(D.f[DIR_P00])[ke]=(one-q)/(one+q)*(f_W-feq*om_turb)/(one-om_turb)+(q*(f_W+f_E)-six*c2over27*(-VeloX     ))/(one+q);
-         //(D.f[DIR_P00])[ke]=zero;
+         VeloY = c0o1;
+         y = true;
+
+         velocityLB = vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = VeloY;
+         (dist.f[DIR_0M0])[ks] = getInterpolatedDistributionForVeloWithPressureBC(q, f_N, f_S, feq, om_turb, drho, velocityBC, c2o27);
       }
 
-      q = q_dirN[k];
+      q = (subgridD.q[DIR_0M0])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-		 VeloY = c0o1;
-	     VeloZ = fac*vx3;
-		 y = true;
-         feq=c2o27* (drho/*+three*(    vx2     )*/+c9o2*(     vx2    )*(     vx2    ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_0M0])[ks]=(c1o1-q)/(c1o1+q)*(f_N-f_S+(f_N+f_S-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_N+f_S)-c6o1*c2o27*( VeloY     ))/(c1o1+q) - c2o27 * drho;
-         //feq=c2over27* (drho+three*(    vx2     )+c9over2*(     vx2    )*(     vx2    )-cu_sq); 
-         //(D.f[DIR_0M0])[ks]=(one-q)/(one+q)*(f_N-feq*om_turb)/(one-om_turb)+(q*(f_N+f_S)-six*c2over27*( VeloY     ))/(one+q);
-         //(D.f[DIR_0M0])[ks]=zero;
+         VeloY = c0o1;
+         y = true;
+
+         velocityLB = -vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = -VeloY;
+         (dist.f[DIR_0P0])[kn] = getInterpolatedDistributionForVeloWithPressureBC(q, f_S, f_N, feq, om_turb, drho, velocityBC, c2o27);
       }
 
-      q = q_dirS[k];
+      q = (subgridD.q[DIR_00P])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-		 VeloY = c0o1;
-	     VeloZ = fac*vx3;
-		 y = true;
-         feq=c2o27* (drho/*+three*(   -vx2     )*/+c9o2*(    -vx2    )*(    -vx2    ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_0P0])[kn]=(c1o1-q)/(c1o1+q)*(f_S-f_N+(f_S+f_N-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_S+f_N)-c6o1*c2o27*(-VeloY     ))/(c1o1+q) - c2o27 * drho;
-         //feq=c2over27* (drho+three*(   -vx2     )+c9over2*(    -vx2    )*(    -vx2    )-cu_sq); 
-         //(D.f[DIR_0P0])[kn]=(one-q)/(one+q)*(f_S-feq*om_turb)/(one-om_turb)+(q*(f_S+f_N)-six*c2over27*(-VeloY     ))/(one+q);
-         //(D.f[DIR_0P0])[kn]=zero;
+         VeloZ = c0o1;
+         z = true;
+
+         velocityLB = vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = VeloZ;
+         (dist.f[DIR_00M])[kb] = getInterpolatedDistributionForVeloWithPressureBC(q, f_T, f_B, feq, om_turb, drho, velocityBC, c2o27);
       }
 
-      q = q_dirT[k];
+      q = (subgridD.q[DIR_00M])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-		 VeloZ = c0o1;
-		 z = true;
-         feq=c2o27* (drho/*+three*(         vx3)*/+c9o2*(         vx3)*(         vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_00M])[kb]=(c1o1-q)/(c1o1+q)*(f_T-f_B+(f_T+f_B-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_T+f_B)-c6o1*c2o27*( VeloZ     ))/(c1o1+q) - c2o27 * drho;
-         //feq=c2over27* (drho+three*(         vx3)+c9over2*(         vx3)*(         vx3)-cu_sq); 
-         //(D.f[DIR_00M])[kb]=(one-q)/(one+q)*(f_T-feq*om_turb)/(one-om_turb)+(q*(f_T+f_B)-six*c2over27*( VeloZ     ))/(one+q);
-         //(D.f[DIR_00M])[kb]=one;
+         VeloZ = c0o1;
+         z = true;
+
+         velocityLB = -vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         velocityBC = -VeloZ;
+         (dist.f[DIR_00P])[kt] = getInterpolatedDistributionForVeloWithPressureBC(q, f_B, f_T, feq, om_turb, drho, velocityBC, c2o27);
       }
 
-      q = q_dirB[k];
+      q = (subgridD.q[DIR_PP0])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-		 VeloZ = c0o1;
-		 z = true;
-         feq=c2o27* (drho/*+three*(        -vx3)*/+c9o2*(        -vx3)*(        -vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_00P])[kt]=(c1o1-q)/(c1o1+q)*(f_B-f_T+(f_B+f_T-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_B+f_T)-c6o1*c2o27*(-VeloZ     ))/(c1o1+q) - c2o27 * drho;
-         //feq=c2over27* (drho+three*(        -vx3)+c9over2*(        -vx3)*(        -vx3)-cu_sq); 
-         //(D.f[DIR_00P])[kt]=(one-q)/(one+q)*(f_B-feq*om_turb)/(one-om_turb)+(q*(f_B+f_T)-six*c2over27*(-VeloZ     ))/(one+q);
-         //(D.f[DIR_00P])[kt]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = vx1 + vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX + VeloY;
+         (dist.f[DIR_MM0])[ksw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_NE, f_SW, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirNE[k];
+      q = (subgridD.q[DIR_MM0])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-         feq=c1o54* (drho/*+three*( vx1+vx2    )*/+c9o2*( vx1+vx2    )*( vx1+vx2    ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_MM0])[ksw]=(c1o1-q)/(c1o1+q)*(f_NE-f_SW+(f_NE+f_SW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_NE+f_SW)-c6o1*c1o54*(VeloX+VeloY))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*( vx1+vx2    )+c9over2*( vx1+vx2    )*( vx1+vx2    )-cu_sq); 
-         //(D.f[DIR_MM0])[ksw]=(one-q)/(one+q)*(f_NE-feq*om_turb)/(one-om_turb)+(q*(f_NE+f_SW)-six*c1over54*(VeloX+VeloY))/(one+q);
-         //(D.f[DIR_MM0])[ksw]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = -vx1 - vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX - VeloY;
+         (dist.f[DIR_PP0])[kne] = getInterpolatedDistributionForVeloWithPressureBC(q, f_SW, f_NE, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirSW[k];
+      q = (subgridD.q[DIR_PM0])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-         feq=c1o54* (drho/*+three*(-vx1-vx2    )*/+c9o2*(-vx1-vx2    )*(-vx1-vx2    ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_PP0])[kne]=(c1o1-q)/(c1o1+q)*(f_SW-f_NE+(f_SW+f_NE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_SW+f_NE)-c6o1*c1o54*(-VeloX-VeloY))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(-vx1-vx2    )+c9over2*(-vx1-vx2    )*(-vx1-vx2    )-cu_sq); 
-         //(D.f[DIR_PP0])[kne]=(one-q)/(one+q)*(f_SW-feq*om_turb)/(one-om_turb)+(q*(f_SW+f_NE)-six*c1over54*(-VeloX-VeloY))/(one+q);
-         //(D.f[DIR_PP0])[kne]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = vx1 - vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX - VeloY;
+         (dist.f[DIR_MP0])[knw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_SE, f_NW, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirSE[k];
+      q = (subgridD.q[DIR_MP0])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-         feq=c1o54* (drho/*+three*( vx1-vx2    )*/+c9o2*( vx1-vx2    )*( vx1-vx2    ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_MP0])[knw]=(c1o1-q)/(c1o1+q)*(f_SE-f_NW+(f_SE+f_NW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_SE+f_NW)-c6o1*c1o54*( VeloX-VeloY))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*( vx1-vx2    )+c9over2*( vx1-vx2    )*( vx1-vx2    )-cu_sq); 
-         //(D.f[DIR_MP0])[knw]=(one-q)/(one+q)*(f_SE-feq*om_turb)/(one-om_turb)+(q*(f_SE+f_NW)-six*c1over54*( VeloX-VeloY))/(one+q);
-         //(D.f[DIR_MP0])[knw]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+
+         velocityLB = -vx1 + vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX + VeloY;
+         (dist.f[DIR_PM0])[kse] = getInterpolatedDistributionForVeloWithPressureBC(q, f_NW, f_SE, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirNW[k];
+      q = (subgridD.q[DIR_P0P])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-         feq=c1o54* (drho/*+three*(-vx1+vx2    )*/+c9o2*(-vx1+vx2    )*(-vx1+vx2    ) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_PM0])[kse]=(c1o1-q)/(c1o1+q)*(f_NW-f_SE+(f_NW+f_SE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_NW+f_SE)-c6o1*c1o54*(-VeloX+VeloY))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(-vx1+vx2    )+c9over2*(-vx1+vx2    )*(-vx1+vx2    )-cu_sq); 
-         //(D.f[DIR_PM0])[kse]=(one-q)/(one+q)*(f_NW-feq*om_turb)/(one-om_turb)+(q*(f_NW+f_SE)-six*c1over54*(-VeloX+VeloY))/(one+q);
-         //(D.f[DIR_PM0])[kse]=zero;
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx1 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX + VeloZ;
+         (dist.f[DIR_M0M])[kbw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TE, f_BW, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirTE[k];
+      q = (subgridD.q[DIR_M0M])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (z == true) VeloZ = c0o1;
-      //  if (k==10000) printf("AFTER x: %u \t  y: %u \t z: %u \n  VeloX: %f \t VeloY: %f \t VeloZ: %f \n\n", x,y,z, VeloX,VeloY,VeloZ);
-         feq=c1o54* (drho/*+three*( vx1    +vx3)*/+c9o2*( vx1    +vx3)*( vx1    +vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_M0M])[kbw]=(c1o1-q)/(c1o1+q)*(f_TE-f_BW+(f_TE+f_BW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TE+f_BW)-c6o1*c1o54*( VeloX+VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*( vx1    +vx3)+c9over2*( vx1    +vx3)*( vx1    +vx3)-cu_sq); 
-         //(D.f[DIR_M0M])[kbw]=(one-q)/(one+q)*(f_TE-feq*om_turb)/(one-om_turb)+(q*(f_TE+f_BW)-six*c1over54*( VeloX+VeloZ))/(one+q);
-         //(D.f[DIR_M0M])[kbw]=zero;
+        VeloX = slipLength*vx1;
+        VeloZ = slipLength*vx3;
+        if (x == true) VeloX = c0o1;
+        if (z == true) VeloZ = c0o1;
+
+         velocityLB = -vx1 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX - VeloZ;
+         (dist.f[DIR_P0P])[kte] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BW, f_TE, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirBW[k];
+      q = (subgridD.q[DIR_P0M])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o54* (drho/*+three*(-vx1    -vx3)*/+c9o2*(-vx1    -vx3)*(-vx1    -vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_P0P])[kte]=(c1o1-q)/(c1o1+q)*(f_BW-f_TE+(f_BW+f_TE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BW+f_TE)-c6o1*c1o54*(-VeloX-VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(-vx1    -vx3)+c9over2*(-vx1    -vx3)*(-vx1    -vx3)-cu_sq); 
-         //(D.f[DIR_P0P])[kte]=(one-q)/(one+q)*(f_BW-feq*om_turb)/(one-om_turb)+(q*(f_BW+f_TE)-six*c1over54*(-VeloX-VeloZ))/(one+q);
-         //(D.f[DIR_P0P])[kte]=zero;
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx1 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloX - VeloZ;
+         (dist.f[DIR_M0P])[ktw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BE, f_TW, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirBE[k];
+      q = (subgridD.q[DIR_M0P])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o54* (drho/*+three*( vx1    -vx3)*/+c9o2*( vx1    -vx3)*( vx1    -vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_M0P])[ktw]=(c1o1-q)/(c1o1+q)*(f_BE-f_TW+(f_BE+f_TW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BE+f_TW)-c6o1*c1o54*( VeloX-VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*( vx1    -vx3)+c9over2*( vx1    -vx3)*( vx1    -vx3)-cu_sq); 
-         //(D.f[DIR_M0P])[ktw]=(one-q)/(one+q)*(f_BE-feq*om_turb)/(one-om_turb)+(q*(f_BE+f_TW)-six*c1over54*( VeloX-VeloZ))/(one+q);
-         //(D.f[DIR_M0P])[ktw]=zero;
-      }
+         VeloX = slipLength*vx1;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (z == true) VeloZ = c0o1;
 
-      q = q_dirTW[k];
-      if (q>=c0o1 && q<=c1o1)
-      {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o54* (drho/*+three*(-vx1    +vx3)*/+c9o2*(-vx1    +vx3)*(-vx1    +vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_P0M])[kbe]=(c1o1-q)/(c1o1+q)*(f_TW-f_BE+(f_TW+f_BE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TW+f_BE)-c6o1*c1o54*(-VeloX+VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(-vx1    +vx3)+c9over2*(-vx1    +vx3)*(-vx1    +vx3)-cu_sq); 
-         //(D.f[DIR_P0M])[kbe]=(one-q)/(one+q)*(f_TW-feq*om_turb)/(one-om_turb)+(q*(f_TW+f_BE)-six*c1over54*(-VeloX+VeloZ))/(one+q);
-         //(D.f[DIR_P0M])[kbe]=zero;
+         velocityLB = -vx1 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloX + VeloZ;
+         (dist.f[DIR_P0M])[kbe] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TW, f_BE, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirTN[k];
+      q = (subgridD.q[DIR_0PP])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o54* (drho/*+three*(     vx2+vx3)*/+c9o2*(     vx2+vx3)*(     vx2+vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_0MM])[kbs]=(c1o1-q)/(c1o1+q)*(f_TN-f_BS+(f_TN+f_BS-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TN+f_BS)-c6o1*c1o54*( VeloY+VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(     vx2+vx3)+c9over2*(     vx2+vx3)*(     vx2+vx3)-cu_sq); 
-         //(D.f[DIR_0MM])[kbs]=(one-q)/(one+q)*(f_TN-feq*om_turb)/(one-om_turb)+(q*(f_TN+f_BS)-six*c1over54*( VeloY+VeloZ))/(one+q);
-         //(D.f[DIR_0MM])[kbs]=zero;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloY + VeloZ;
+         (dist.f[DIR_0MM])[kbs] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TN, f_BS, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirBS[k];
+      q = (subgridD.q[DIR_0MM])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o54* (drho/*+three*(    -vx2-vx3)*/+c9o2*(    -vx2-vx3)*(    -vx2-vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_0PP])[ktn]=(c1o1-q)/(c1o1+q)*(f_BS-f_TN+(f_BS+f_TN-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BS+f_TN)-c6o1*c1o54*( -VeloY-VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(    -vx2-vx3)+c9over2*(    -vx2-vx3)*(    -vx2-vx3)-cu_sq); 
-         //(D.f[DIR_0PP])[ktn]=(one-q)/(one+q)*(f_BS-feq*om_turb)/(one-om_turb)+(q*(f_BS+f_TN)-six*c1over54*( -VeloY-VeloZ))/(one+q);
-         //(D.f[DIR_0PP])[ktn]=zero;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = -vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloY - VeloZ;
+         (dist.f[DIR_0PP])[ktn] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BS, f_TN, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirBN[k];
+
+      q = (subgridD.q[DIR_0PM])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o54* (drho/*+three*(     vx2-vx3)*/+c9o2*(     vx2-vx3)*(     vx2-vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_0MP])[kts]=(c1o1-q)/(c1o1+q)*(f_BN-f_TS+(f_BN+f_TS-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BN+f_TS)-c6o1*c1o54*( VeloY-VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(     vx2-vx3)+c9over2*(     vx2-vx3)*(     vx2-vx3)-cu_sq); 
-         //(D.f[DIR_0MP])[kts]=(one-q)/(one+q)*(f_BN-feq*om_turb)/(one-om_turb)+(q*(f_BN+f_TS)-six*c1over54*( VeloY-VeloZ))/(one+q);
-         //(D.f[DIR_0MP])[kts]=zero;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = VeloY - VeloZ;
+         (dist.f[DIR_0MP])[kts] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BN, f_TS, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirTS[k];
+      q = (subgridD.q[DIR_0MP])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o54* (drho/*+three*(    -vx2+vx3)*/+c9o2*(    -vx2+vx3)*(    -vx2+vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_0PM])[kbn]=(c1o1-q)/(c1o1+q)*(f_TS-f_BN+(f_TS+f_BN-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TS+f_BN)-c6o1*c1o54*( -VeloY+VeloZ))/(c1o1+q) - c1o54 * drho;
-         //feq=c1over54* (drho+three*(    -vx2+vx3)+c9over2*(    -vx2+vx3)*(    -vx2+vx3)-cu_sq); 
-         //(D.f[DIR_0PM])[kbn]=(one-q)/(one+q)*(f_TS-feq*om_turb)/(one-om_turb)+(q*(f_TS+f_BN)-six*c1over54*( -VeloY+VeloZ))/(one+q);
-         //(D.f[DIR_0PM])[kbn]=zero;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+
+         velocityLB = -vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         velocityBC = -VeloY + VeloZ;
+         (dist.f[DIR_0PM])[kbn] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TS, f_BN, feq, om_turb, drho, velocityBC, c1o54);
       }
 
-      q = q_dirTNE[k];
+      q = (subgridD.q[DIR_PPP])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*( vx1+vx2+vx3)*/+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_MMM])[kbsw]=(c1o1-q)/(c1o1+q)*(f_TNE-f_BSW+(f_TNE+f_BSW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TNE+f_BSW)-c6o1*c1o216*( VeloX+VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*( vx1+vx2+vx3)+c9over2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq); 
-         //(D.f[DIR_MMM])[kbsw]=(one-q)/(one+q)*(f_TNE-feq*om_turb)/(one-om_turb)+(q*(f_TNE+f_BSW)-six*c1over216*( VeloX+VeloY+VeloZ))/(one+q);
-         //(D.f[DIR_MMM])[kbsw]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 + vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX + VeloY + VeloZ;
+         (dist.f[DIR_MMM])[kbsw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TNE, f_BSW, feq, om_turb, drho, velocityBC, c1o216);
       }
 
-      q = q_dirBSW[k];
+      q = (subgridD.q[DIR_MMM])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*(-vx1-vx2-vx3)*/+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_PPP])[ktne]=(c1o1-q)/(c1o1+q)*(f_BSW-f_TNE+(f_BSW+f_TNE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BSW+f_TNE)-c6o1*c1o216*(-VeloX-VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*(-vx1-vx2-vx3)+c9over2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq); 
-         //(D.f[DIR_PPP])[ktne]=(one-q)/(one+q)*(f_BSW-feq*om_turb)/(one-om_turb)+(q*(f_BSW+f_TNE)-six*c1over216*(-VeloX-VeloY-VeloZ))/(one+q);
-         //(D.f[DIR_PPP])[ktne]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 - vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX - VeloY - VeloZ;
+         (dist.f[DIR_PPP])[ktne] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BSW, f_TNE, feq, om_turb, drho, velocityBC, c1o216);
       }
 
-      q = q_dirBNE[k];
+
+      q = (subgridD.q[DIR_PPM])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*( vx1+vx2-vx3)*/+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_MMP])[ktsw]=(c1o1-q)/(c1o1+q)*(f_BNE-f_TSW+(f_BNE+f_TSW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BNE+f_TSW)-c6o1*c1o216*( VeloX+VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*( vx1+vx2-vx3)+c9over2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq); 
-         //(D.f[DIR_MMP])[ktsw]=(one-q)/(one+q)*(f_BNE-feq*om_turb)/(one-om_turb)+(q*(f_BNE+f_TSW)-six*c1over216*( VeloX+VeloY-VeloZ))/(one+q);
-         //(D.f[DIR_MMP])[ktsw]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 + vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX + VeloY - VeloZ;
+         (dist.f[DIR_MMP])[ktsw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BNE, f_TSW, feq, om_turb, drho, velocityBC, c1o216);
       }
 
-      q = q_dirTSW[k];
+      q = (subgridD.q[DIR_MMP])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*(-vx1-vx2+vx3)*/+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_PPM])[kbne]=(c1o1-q)/(c1o1+q)*(f_TSW-f_BNE+(f_TSW+f_BNE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TSW+f_BNE)-c6o1*c1o216*(-VeloX-VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*(-vx1-vx2+vx3)+c9over2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq); 
-         //(D.f[DIR_PPM])[kbne]=(one-q)/(one+q)*(f_TSW-feq*om_turb)/(one-om_turb)+(q*(f_TSW+f_BNE)-six*c1over216*(-VeloX-VeloY+VeloZ))/(one+q);
-         //(D.f[DIR_PPM])[kbne]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 - vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX - VeloY + VeloZ;
+         (dist.f[DIR_PPM])[kbne] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TSW, f_BNE, feq, om_turb, drho, velocityBC, c1o216);
       }
 
-      q = q_dirTSE[k];
+      q = (subgridD.q[DIR_PMP])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*( vx1-vx2+vx3)*/+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_MPM])[kbnw]=(c1o1-q)/(c1o1+q)*(f_TSE-f_BNW+(f_TSE+f_BNW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TSE+f_BNW)-c6o1*c1o216*( VeloX-VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*( vx1-vx2+vx3)+c9over2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq); 
-         //(D.f[DIR_MPM])[kbnw]=(one-q)/(one+q)*(f_TSE-feq*om_turb)/(one-om_turb)+(q*(f_TSE+f_BNW)-six*c1over216*( VeloX-VeloY+VeloZ))/(one+q);
-         //(D.f[DIR_MPM])[kbnw]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 - vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX - VeloY + VeloZ;
+         (dist.f[DIR_MPM])[kbnw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TSE, f_BNW, feq, om_turb, drho, velocityBC, c1o216);
       }
 
-      q = q_dirBNW[k];
+      q = (subgridD.q[DIR_MPM])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*(-vx1+vx2-vx3)*/+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_PMP])[ktse]=(c1o1-q)/(c1o1+q)*(f_BNW-f_TSE+(f_BNW+f_TSE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BNW+f_TSE)-c6o1*c1o216*(-VeloX+VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*(-vx1+vx2-vx3)+c9over2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq); 
-         //(D.f[DIR_PMP])[ktse]=(one-q)/(one+q)*(f_BNW-feq*om_turb)/(one-om_turb)+(q*(f_BNW+f_TSE)-six*c1over216*(-VeloX+VeloY-VeloZ))/(one+q);
-         //(D.f[DIR_PMP])[ktse]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 + vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX + VeloY - VeloZ;
+         (dist.f[DIR_PMP])[ktse] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BNW, f_TSE, feq, om_turb, drho, velocityBC, c1o216);
       }
 
-      q = q_dirBSE[k];
+      q = (subgridD.q[DIR_PMM])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*( vx1-vx2-vx3)*/+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_MPP])[ktnw]=(c1o1-q)/(c1o1+q)*(f_BSE-f_TNW+(f_BSE+f_TNW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BSE+f_TNW)-c6o1*c1o216*( VeloX-VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*( vx1-vx2-vx3)+c9over2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq); 
-         //(D.f[DIR_MPP])[ktnw]=(one-q)/(one+q)*(f_BSE-feq*om_turb)/(one-om_turb)+(q*(f_BSE+f_TNW)-six*c1over216*( VeloX-VeloY-VeloZ))/(one+q);
-         //(D.f[DIR_MPP])[ktnw]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = vx1 - vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = VeloX - VeloY - VeloZ;
+         (dist.f[DIR_MPP])[ktnw] = getInterpolatedDistributionForVeloWithPressureBC(q, f_BSE, f_TNW, feq, om_turb, drho, velocityBC, c1o216);
       }
 
-      q = q_dirTNW[k];
+      q = (subgridD.q[DIR_MPP])[k];
       if (q>=c0o1 && q<=c1o1)
       {
-		 VeloX = fac*vx1;
-	     VeloY = fac*vx2;
-	     VeloZ = fac*vx3;
-		 if (x == true) VeloX = c0o1;
-		 if (y == true) VeloY = c0o1;
-		 if (z == true) VeloZ = c0o1;
-         feq=c1o216*(drho/*+three*(-vx1+vx2+vx3)*/+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3) * (c1o1 + drho)-cu_sq); 
-         (D.f[DIR_PMM])[kbse]=(c1o1-q)/(c1o1+q)*(f_TNW-f_BSE+(f_TNW+f_BSE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TNW+f_BSE)-c6o1*c1o216*(-VeloX+VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
-         //feq=c1over216*(drho+three*(-vx1+vx2+vx3)+c9over2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq); 
-         //(D.f[DIR_PMM])[kbse]=(one-q)/(one+q)*(f_TNW-feq*om_turb)/(one-om_turb)+(q*(f_TNW+f_BSE)-six*c1over216*(-VeloX+VeloY+VeloZ))/(one+q);
-         //(D.f[DIR_PMM])[kbse]=zero;
+         VeloX = slipLength*vx1;
+         VeloY = slipLength*vx2;
+         VeloZ = slipLength*vx3;
+         if (x == true) VeloX = c0o1;
+         if (y == true) VeloY = c0o1;
+         if (z == true) VeloZ = c0o1;
+         velocityLB = -vx1 + vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         velocityBC = -VeloX + VeloY + VeloZ;
+         (dist.f[DIR_PMM])[kbse] = getInterpolatedDistributionForVeloWithPressureBC(q, f_TNW, f_BSE, feq, om_turb, drho, velocityBC, c1o216);
       }
    }
 }
 
+// __global__ void QSlipDeviceComp27TurbViscosity(real* DD, 
+// 											 int* k_Q, 
+// 											 real* QQ,
+// 											 unsigned int numberOfBCnodes,
+// 											 real om1, 
+// 											 unsigned int* neighborX,
+// 											 unsigned int* neighborY,
+// 											 unsigned int* neighborZ,
+//                                   real* turbViscosity,
+// 											 unsigned int size_Mat, 
+// 											 bool isEvenTimestep)
+// {
+//    Distributions27 D;
+//    if (isEvenTimestep==true)
+//    {
+//       D.f[DIR_P00   ] = &DD[DIR_P00   *size_Mat];
+//       D.f[DIR_M00   ] = &DD[DIR_M00   *size_Mat];
+//       D.f[DIR_0P0   ] = &DD[DIR_0P0   *size_Mat];
+//       D.f[DIR_0M0   ] = &DD[DIR_0M0   *size_Mat];
+//       D.f[DIR_00P   ] = &DD[DIR_00P   *size_Mat];
+//       D.f[DIR_00M   ] = &DD[DIR_00M   *size_Mat];
+//       D.f[DIR_PP0  ] = &DD[DIR_PP0  *size_Mat];
+//       D.f[DIR_MM0  ] = &DD[DIR_MM0  *size_Mat];
+//       D.f[DIR_PM0  ] = &DD[DIR_PM0  *size_Mat];
+//       D.f[DIR_MP0  ] = &DD[DIR_MP0  *size_Mat];
+//       D.f[DIR_P0P  ] = &DD[DIR_P0P  *size_Mat];
+//       D.f[DIR_M0M  ] = &DD[DIR_M0M  *size_Mat];
+//       D.f[DIR_P0M  ] = &DD[DIR_P0M  *size_Mat];
+//       D.f[DIR_M0P  ] = &DD[DIR_M0P  *size_Mat];
+//       D.f[DIR_0PP  ] = &DD[DIR_0PP  *size_Mat];
+//       D.f[DIR_0MM  ] = &DD[DIR_0MM  *size_Mat];
+//       D.f[DIR_0PM  ] = &DD[DIR_0PM  *size_Mat];
+//       D.f[DIR_0MP  ] = &DD[DIR_0MP  *size_Mat];
+//       D.f[DIR_000] = &DD[DIR_000*size_Mat];
+//       D.f[DIR_PPP ] = &DD[DIR_PPP *size_Mat];
+//       D.f[DIR_MMP ] = &DD[DIR_MMP *size_Mat];
+//       D.f[DIR_PMP ] = &DD[DIR_PMP *size_Mat];
+//       D.f[DIR_MPP ] = &DD[DIR_MPP *size_Mat];
+//       D.f[DIR_PPM ] = &DD[DIR_PPM *size_Mat];
+//       D.f[DIR_MMM ] = &DD[DIR_MMM *size_Mat];
+//       D.f[DIR_PMM ] = &DD[DIR_PMM *size_Mat];
+//       D.f[DIR_MPM ] = &DD[DIR_MPM *size_Mat];
+//    } 
+//    else
+//    {
+//       D.f[DIR_M00   ] = &DD[DIR_P00   *size_Mat];
+//       D.f[DIR_P00   ] = &DD[DIR_M00   *size_Mat];
+//       D.f[DIR_0M0   ] = &DD[DIR_0P0   *size_Mat];
+//       D.f[DIR_0P0   ] = &DD[DIR_0M0   *size_Mat];
+//       D.f[DIR_00M   ] = &DD[DIR_00P   *size_Mat];
+//       D.f[DIR_00P   ] = &DD[DIR_00M   *size_Mat];
+//       D.f[DIR_MM0  ] = &DD[DIR_PP0  *size_Mat];
+//       D.f[DIR_PP0  ] = &DD[DIR_MM0  *size_Mat];
+//       D.f[DIR_MP0  ] = &DD[DIR_PM0  *size_Mat];
+//       D.f[DIR_PM0  ] = &DD[DIR_MP0  *size_Mat];
+//       D.f[DIR_M0M  ] = &DD[DIR_P0P  *size_Mat];
+//       D.f[DIR_P0P  ] = &DD[DIR_M0M  *size_Mat];
+//       D.f[DIR_M0P  ] = &DD[DIR_P0M  *size_Mat];
+//       D.f[DIR_P0M  ] = &DD[DIR_M0P  *size_Mat];
+//       D.f[DIR_0MM  ] = &DD[DIR_0PP  *size_Mat];
+//       D.f[DIR_0PP  ] = &DD[DIR_0MM  *size_Mat];
+//       D.f[DIR_0MP  ] = &DD[DIR_0PM  *size_Mat];
+//       D.f[DIR_0PM  ] = &DD[DIR_0MP  *size_Mat];
+//       D.f[DIR_000] = &DD[DIR_000*size_Mat];
+//       D.f[DIR_PPP ] = &DD[DIR_MMM *size_Mat];
+//       D.f[DIR_MMP ] = &DD[DIR_PPM *size_Mat];
+//       D.f[DIR_PMP ] = &DD[DIR_MPM *size_Mat];
+//       D.f[DIR_MPP ] = &DD[DIR_PMM *size_Mat];
+//       D.f[DIR_PPM ] = &DD[DIR_MMP *size_Mat];
+//       D.f[DIR_MMM ] = &DD[DIR_PPP *size_Mat];
+//       D.f[DIR_PMM ] = &DD[DIR_MPP *size_Mat];
+//       D.f[DIR_MPM ] = &DD[DIR_PMP *size_Mat];
+//    }
+//    ////////////////////////////////////////////////////////////////////////////////
+//    const unsigned  x = threadIdx.x;  // Globaler x-Index 
+//    const unsigned  y = blockIdx.x;   // Globaler y-Index 
+//    const unsigned  z = blockIdx.y;   // Globaler z-Index 
+
+//    const unsigned nx = blockDim.x;
+//    const unsigned ny = gridDim.x;
+
+//    const unsigned k = nx*(ny*z + y) + x;
+//    //////////////////////////////////////////////////////////////////////////
+
+//    if(k<numberOfBCnodes)
+//    {
+//       ////////////////////////////////////////////////////////////////////////////////
+//       real *q_dirE,   *q_dirW,   *q_dirN,   *q_dirS,   *q_dirT,   *q_dirB, 
+//             *q_dirNE,  *q_dirSW,  *q_dirSE,  *q_dirNW,  *q_dirTE,  *q_dirBW,
+//             *q_dirBE,  *q_dirTW,  *q_dirTN,  *q_dirBS,  *q_dirBN,  *q_dirTS,
+//             *q_dirTNE, *q_dirTSW, *q_dirTSE, *q_dirTNW, *q_dirBNE, *q_dirBSW,
+//             *q_dirBSE, *q_dirBNW; 
+//       q_dirE   = &QQ[DIR_P00   * numberOfBCnodes];
+//       q_dirW   = &QQ[DIR_M00   * numberOfBCnodes];
+//       q_dirN   = &QQ[DIR_0P0   * numberOfBCnodes];
+//       q_dirS   = &QQ[DIR_0M0   * numberOfBCnodes];
+//       q_dirT   = &QQ[DIR_00P   * numberOfBCnodes];
+//       q_dirB   = &QQ[DIR_00M   * numberOfBCnodes];
+//       q_dirNE  = &QQ[DIR_PP0  * numberOfBCnodes];
+//       q_dirSW  = &QQ[DIR_MM0  * numberOfBCnodes];
+//       q_dirSE  = &QQ[DIR_PM0  * numberOfBCnodes];
+//       q_dirNW  = &QQ[DIR_MP0  * numberOfBCnodes];
+//       q_dirTE  = &QQ[DIR_P0P  * numberOfBCnodes];
+//       q_dirBW  = &QQ[DIR_M0M  * numberOfBCnodes];
+//       q_dirBE  = &QQ[DIR_P0M  * numberOfBCnodes];
+//       q_dirTW  = &QQ[DIR_M0P  * numberOfBCnodes];
+//       q_dirTN  = &QQ[DIR_0PP  * numberOfBCnodes];
+//       q_dirBS  = &QQ[DIR_0MM  * numberOfBCnodes];
+//       q_dirBN  = &QQ[DIR_0PM  * numberOfBCnodes];
+//       q_dirTS  = &QQ[DIR_0MP  * numberOfBCnodes];
+//       q_dirTNE = &QQ[DIR_PPP * numberOfBCnodes];
+//       q_dirTSW = &QQ[DIR_MMP * numberOfBCnodes];
+//       q_dirTSE = &QQ[DIR_PMP * numberOfBCnodes];
+//       q_dirTNW = &QQ[DIR_MPP * numberOfBCnodes];
+//       q_dirBNE = &QQ[DIR_PPM * numberOfBCnodes];
+//       q_dirBSW = &QQ[DIR_MMM * numberOfBCnodes];
+//       q_dirBSE = &QQ[DIR_PMM * numberOfBCnodes];
+//       q_dirBNW = &QQ[DIR_MPM * numberOfBCnodes];
+//       ////////////////////////////////////////////////////////////////////////////////
+//       //index
+//       unsigned int KQK  = k_Q[k];
+//       unsigned int kzero= KQK;
+//       unsigned int ke   = KQK;
+//       unsigned int kw   = neighborX[KQK];
+//       unsigned int kn   = KQK;
+//       unsigned int ks   = neighborY[KQK];
+//       unsigned int kt   = KQK;
+//       unsigned int kb   = neighborZ[KQK];
+//       unsigned int ksw  = neighborY[kw];
+//       unsigned int kne  = KQK;
+//       unsigned int kse  = ks;
+//       unsigned int knw  = kw;
+//       unsigned int kbw  = neighborZ[kw];
+//       unsigned int kte  = KQK;
+//       unsigned int kbe  = kb;
+//       unsigned int ktw  = kw;
+//       unsigned int kbs  = neighborZ[ks];
+//       unsigned int ktn  = KQK;
+//       unsigned int kbn  = kb;
+//       unsigned int kts  = ks;
+//       unsigned int ktse = ks;
+//       unsigned int kbnw = kbw;
+//       unsigned int ktnw = kw;
+//       unsigned int kbse = kbs;
+//       unsigned int ktsw = ksw;
+//       unsigned int kbne = kb;
+//       unsigned int ktne = KQK;
+//       unsigned int kbsw = neighborZ[ksw];
+      
+//       ////////////////////////////////////////////////////////////////////////////////
+//       real f_W    = (D.f[DIR_P00   ])[ke   ];
+//       real f_E    = (D.f[DIR_M00   ])[kw   ];
+//       real f_S    = (D.f[DIR_0P0   ])[kn   ];
+//       real f_N    = (D.f[DIR_0M0   ])[ks   ];
+//       real f_B    = (D.f[DIR_00P   ])[kt   ];
+//       real f_T    = (D.f[DIR_00M   ])[kb   ];
+//       real f_SW   = (D.f[DIR_PP0  ])[kne  ];
+//       real f_NE   = (D.f[DIR_MM0  ])[ksw  ];
+//       real f_NW   = (D.f[DIR_PM0  ])[kse  ];
+//       real f_SE   = (D.f[DIR_MP0  ])[knw  ];
+//       real f_BW   = (D.f[DIR_P0P  ])[kte  ];
+//       real f_TE   = (D.f[DIR_M0M  ])[kbw  ];
+//       real f_TW   = (D.f[DIR_P0M  ])[kbe  ];
+//       real f_BE   = (D.f[DIR_M0P  ])[ktw  ];
+//       real f_BS   = (D.f[DIR_0PP  ])[ktn  ];
+//       real f_TN   = (D.f[DIR_0MM  ])[kbs  ];
+//       real f_TS   = (D.f[DIR_0PM  ])[kbn  ];
+//       real f_BN   = (D.f[DIR_0MP  ])[kts  ];
+//       real f_BSW  = (D.f[DIR_PPP ])[ktne ];
+//       real f_BNE  = (D.f[DIR_MMP ])[ktsw ];
+//       real f_BNW  = (D.f[DIR_PMP ])[ktse ];
+//       real f_BSE  = (D.f[DIR_MPP ])[ktnw ];
+//       real f_TSW  = (D.f[DIR_PPM ])[kbne ];
+//       real f_TNE  = (D.f[DIR_MMM ])[kbsw ];
+//       real f_TNW  = (D.f[DIR_PMM ])[kbse ];
+//       real f_TSE  = (D.f[DIR_MPM ])[kbnw ];
+//       ////////////////////////////////////////////////////////////////////////////////
+//       real vx1, vx2, vx3, drho, feq, q;
+//       drho   =  f_TSE + f_TNW + f_TNE + f_TSW + f_BSE + f_BNW + f_BNE + f_BSW +
+//                 f_BN + f_TS + f_TN + f_BS + f_BE + f_TW + f_TE + f_BW + f_SE + f_NW + f_NE + f_SW + 
+//                 f_T + f_B + f_N + f_S + f_E + f_W + ((D.f[DIR_000])[kzero]); 
+
+//       vx1    =  (((f_TSE - f_BNW) - (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+//                 ((f_BE - f_TW)   + (f_TE - f_BW))   + ((f_SE - f_NW)   + (f_NE - f_SW)) +
+//                 (f_E - f_W)) / (c1o1 + drho); 
+         
+
+//       vx2    =   ((-(f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+//                  ((f_BN - f_TS)   + (f_TN - f_BS))    + (-(f_SE - f_NW)  + (f_NE - f_SW)) +
+//                  (f_N - f_S)) / (c1o1 + drho); 
+
+//       vx3    =   (((f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) + (f_TSW - f_BNE)) +
+//                  (-(f_BN - f_TS)  + (f_TN - f_BS))   + ((f_TE - f_BW)   - (f_BE - f_TW)) +
+//                  (f_T - f_B)) / (c1o1 + drho); 
+
+//       real cu_sq=c3o2*(vx1*vx1+vx2*vx2+vx3*vx3) * (c1o1 + drho);
+
+//       //////////////////////////////////////////////////////////////////////////
+//       if (isEvenTimestep==false)
+//       {
+//          D.f[DIR_P00   ] = &DD[DIR_P00   *size_Mat];
+//          D.f[DIR_M00   ] = &DD[DIR_M00   *size_Mat];
+//          D.f[DIR_0P0   ] = &DD[DIR_0P0   *size_Mat];
+//          D.f[DIR_0M0   ] = &DD[DIR_0M0   *size_Mat];
+//          D.f[DIR_00P   ] = &DD[DIR_00P   *size_Mat];
+//          D.f[DIR_00M   ] = &DD[DIR_00M   *size_Mat];
+//          D.f[DIR_PP0  ] = &DD[DIR_PP0  *size_Mat];
+//          D.f[DIR_MM0  ] = &DD[DIR_MM0  *size_Mat];
+//          D.f[DIR_PM0  ] = &DD[DIR_PM0  *size_Mat];
+//          D.f[DIR_MP0  ] = &DD[DIR_MP0  *size_Mat];
+//          D.f[DIR_P0P  ] = &DD[DIR_P0P  *size_Mat];
+//          D.f[DIR_M0M  ] = &DD[DIR_M0M  *size_Mat];
+//          D.f[DIR_P0M  ] = &DD[DIR_P0M  *size_Mat];
+//          D.f[DIR_M0P  ] = &DD[DIR_M0P  *size_Mat];
+//          D.f[DIR_0PP  ] = &DD[DIR_0PP  *size_Mat];
+//          D.f[DIR_0MM  ] = &DD[DIR_0MM  *size_Mat];
+//          D.f[DIR_0PM  ] = &DD[DIR_0PM  *size_Mat];
+//          D.f[DIR_0MP  ] = &DD[DIR_0MP  *size_Mat];
+//          D.f[DIR_000] = &DD[DIR_000*size_Mat];
+//          D.f[DIR_PPP ] = &DD[DIR_PPP *size_Mat];
+//          D.f[DIR_MMP ] = &DD[DIR_MMP *size_Mat];
+//          D.f[DIR_PMP ] = &DD[DIR_PMP *size_Mat];
+//          D.f[DIR_MPP ] = &DD[DIR_MPP *size_Mat];
+//          D.f[DIR_PPM ] = &DD[DIR_PPM *size_Mat];
+//          D.f[DIR_MMM ] = &DD[DIR_MMM *size_Mat];
+//          D.f[DIR_PMM ] = &DD[DIR_PMM *size_Mat];
+//          D.f[DIR_MPM ] = &DD[DIR_MPM *size_Mat];
+//       } 
+//       else
+//       {
+//          D.f[DIR_M00   ] = &DD[DIR_P00   *size_Mat];
+//          D.f[DIR_P00   ] = &DD[DIR_M00   *size_Mat];
+//          D.f[DIR_0M0   ] = &DD[DIR_0P0   *size_Mat];
+//          D.f[DIR_0P0   ] = &DD[DIR_0M0   *size_Mat];
+//          D.f[DIR_00M   ] = &DD[DIR_00P   *size_Mat];
+//          D.f[DIR_00P   ] = &DD[DIR_00M   *size_Mat];
+//          D.f[DIR_MM0  ] = &DD[DIR_PP0  *size_Mat];
+//          D.f[DIR_PP0  ] = &DD[DIR_MM0  *size_Mat];
+//          D.f[DIR_MP0  ] = &DD[DIR_PM0  *size_Mat];
+//          D.f[DIR_PM0  ] = &DD[DIR_MP0  *size_Mat];
+//          D.f[DIR_M0M  ] = &DD[DIR_P0P  *size_Mat];
+//          D.f[DIR_P0P  ] = &DD[DIR_M0M  *size_Mat];
+//          D.f[DIR_M0P  ] = &DD[DIR_P0M  *size_Mat];
+//          D.f[DIR_P0M  ] = &DD[DIR_M0P  *size_Mat];
+//          D.f[DIR_0MM  ] = &DD[DIR_0PP  *size_Mat];
+//          D.f[DIR_0PP  ] = &DD[DIR_0MM  *size_Mat];
+//          D.f[DIR_0MP  ] = &DD[DIR_0PM  *size_Mat];
+//          D.f[DIR_0PM  ] = &DD[DIR_0MP  *size_Mat];
+//          D.f[DIR_000] = &DD[DIR_000*size_Mat];
+//          D.f[DIR_PPP ] = &DD[DIR_MMM *size_Mat];
+//          D.f[DIR_MMP ] = &DD[DIR_PPM *size_Mat];
+//          D.f[DIR_PMP ] = &DD[DIR_MPM *size_Mat];
+//          D.f[DIR_MPP ] = &DD[DIR_PMM *size_Mat];
+//          D.f[DIR_PPM ] = &DD[DIR_MMP *size_Mat];
+//          D.f[DIR_MMM ] = &DD[DIR_PPP *size_Mat];
+//          D.f[DIR_PMM ] = &DD[DIR_MPP *size_Mat];
+//          D.f[DIR_MPM ] = &DD[DIR_PMP *size_Mat];
+//       }
+//       ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//       //Test
+//       //(D.f[DIR_000])[k]=c1o10;
+//       ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 	  real om_turb = om1 / (c1o1 + c3o1*om1*max(c0o1, turbViscosity[k_Q[k]]));
+     
+//      real fac = c1o1;//c99o100;
+// 	  real VeloX = fac*vx1;
+// 	  real VeloY = fac*vx2;
+// 	  real VeloZ = fac*vx3;
+// 	  bool x = false;
+// 	  bool y = false;
+// 	  bool z = false;
+
+//       q = q_dirE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = c0o1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 x = true;
+//          feq=c2o27* (drho/*+three*( vx1        )*/+c9o2*( vx1        )*( vx1        ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_M00])[kw]=(c1o1-q)/(c1o1+q)*(f_E-f_W+(f_E+f_W-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_E+f_W)-c6o1*c2o27*( VeloX     ))/(c1o1+q) - c2o27 * drho;
+//          //feq=c2over27* (drho+three*( vx1        )+c9over2*( vx1        )*( vx1        )-cu_sq); 
+//          //(D.f[DIR_M00])[kw]=(one-q)/(one+q)*(f_E-feq*om1)/(one-om1)+(q*(f_E+f_W)-six*c2over27*( VeloX     ))/(one+q);
+//          //(D.f[DIR_M00])[kw]=zero;
+//       }
+
+//       q = q_dirW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = c0o1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 x = true;
+//          feq=c2o27* (drho/*+three*(-vx1        )*/+c9o2*(-vx1        )*(-vx1        ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_P00])[ke]=(c1o1-q)/(c1o1+q)*(f_W-f_E+(f_W+f_E-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_W+f_E)-c6o1*c2o27*(-VeloX     ))/(c1o1+q) - c2o27 * drho;
+//          //feq=c2over27* (drho+three*(-vx1        )+c9over2*(-vx1        )*(-vx1        )-cu_sq); 
+//          //(D.f[DIR_P00])[ke]=(one-q)/(one+q)*(f_W-feq*om_turb)/(one-om_turb)+(q*(f_W+f_E)-six*c2over27*(-VeloX     ))/(one+q);
+//          //(D.f[DIR_P00])[ke]=zero;
+//       }
+
+//       q = q_dirN[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 		 VeloY = c0o1;
+// 	     VeloZ = fac*vx3;
+// 		 y = true;
+//          feq=c2o27* (drho/*+three*(    vx2     )*/+c9o2*(     vx2    )*(     vx2    ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_0M0])[ks]=(c1o1-q)/(c1o1+q)*(f_N-f_S+(f_N+f_S-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_N+f_S)-c6o1*c2o27*( VeloY     ))/(c1o1+q) - c2o27 * drho;
+//          //feq=c2over27* (drho+three*(    vx2     )+c9over2*(     vx2    )*(     vx2    )-cu_sq); 
+//          //(D.f[DIR_0M0])[ks]=(one-q)/(one+q)*(f_N-feq*om_turb)/(one-om_turb)+(q*(f_N+f_S)-six*c2over27*( VeloY     ))/(one+q);
+//          //(D.f[DIR_0M0])[ks]=zero;
+//       }
+
+//       q = q_dirS[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 		 VeloY = c0o1;
+// 	     VeloZ = fac*vx3;
+// 		 y = true;
+//          feq=c2o27* (drho/*+three*(   -vx2     )*/+c9o2*(    -vx2    )*(    -vx2    ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_0P0])[kn]=(c1o1-q)/(c1o1+q)*(f_S-f_N+(f_S+f_N-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_S+f_N)-c6o1*c2o27*(-VeloY     ))/(c1o1+q) - c2o27 * drho;
+//          //feq=c2over27* (drho+three*(   -vx2     )+c9over2*(    -vx2    )*(    -vx2    )-cu_sq); 
+//          //(D.f[DIR_0P0])[kn]=(one-q)/(one+q)*(f_S-feq*om_turb)/(one-om_turb)+(q*(f_S+f_N)-six*c2over27*(-VeloY     ))/(one+q);
+//          //(D.f[DIR_0P0])[kn]=zero;
+//       }
+
+//       q = q_dirT[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 		 VeloZ = c0o1;
+// 		 z = true;
+//          feq=c2o27* (drho/*+three*(         vx3)*/+c9o2*(         vx3)*(         vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_00M])[kb]=(c1o1-q)/(c1o1+q)*(f_T-f_B+(f_T+f_B-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_T+f_B)-c6o1*c2o27*( VeloZ     ))/(c1o1+q) - c2o27 * drho;
+//          //feq=c2over27* (drho+three*(         vx3)+c9over2*(         vx3)*(         vx3)-cu_sq); 
+//          //(D.f[DIR_00M])[kb]=(one-q)/(one+q)*(f_T-feq*om_turb)/(one-om_turb)+(q*(f_T+f_B)-six*c2over27*( VeloZ     ))/(one+q);
+//          //(D.f[DIR_00M])[kb]=one;
+//       }
+
+//       q = q_dirB[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 		 VeloZ = c0o1;
+// 		 z = true;
+//          feq=c2o27* (drho/*+three*(        -vx3)*/+c9o2*(        -vx3)*(        -vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_00P])[kt]=(c1o1-q)/(c1o1+q)*(f_B-f_T+(f_B+f_T-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_B+f_T)-c6o1*c2o27*(-VeloZ     ))/(c1o1+q) - c2o27 * drho;
+//          //feq=c2over27* (drho+three*(        -vx3)+c9over2*(        -vx3)*(        -vx3)-cu_sq); 
+//          //(D.f[DIR_00P])[kt]=(one-q)/(one+q)*(f_B-feq*om_turb)/(one-om_turb)+(q*(f_B+f_T)-six*c2over27*(-VeloZ     ))/(one+q);
+//          //(D.f[DIR_00P])[kt]=zero;
+//       }
+
+//       q = q_dirNE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+//          feq=c1o54* (drho/*+three*( vx1+vx2    )*/+c9o2*( vx1+vx2    )*( vx1+vx2    ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_MM0])[ksw]=(c1o1-q)/(c1o1+q)*(f_NE-f_SW+(f_NE+f_SW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_NE+f_SW)-c6o1*c1o54*(VeloX+VeloY))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*( vx1+vx2    )+c9over2*( vx1+vx2    )*( vx1+vx2    )-cu_sq); 
+//          //(D.f[DIR_MM0])[ksw]=(one-q)/(one+q)*(f_NE-feq*om_turb)/(one-om_turb)+(q*(f_NE+f_SW)-six*c1over54*(VeloX+VeloY))/(one+q);
+//          //(D.f[DIR_MM0])[ksw]=zero;
+//       }
+
+//       q = q_dirSW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+//          feq=c1o54* (drho/*+three*(-vx1-vx2    )*/+c9o2*(-vx1-vx2    )*(-vx1-vx2    ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_PP0])[kne]=(c1o1-q)/(c1o1+q)*(f_SW-f_NE+(f_SW+f_NE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_SW+f_NE)-c6o1*c1o54*(-VeloX-VeloY))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(-vx1-vx2    )+c9over2*(-vx1-vx2    )*(-vx1-vx2    )-cu_sq); 
+//          //(D.f[DIR_PP0])[kne]=(one-q)/(one+q)*(f_SW-feq*om_turb)/(one-om_turb)+(q*(f_SW+f_NE)-six*c1over54*(-VeloX-VeloY))/(one+q);
+//          //(D.f[DIR_PP0])[kne]=zero;
+//       }
+
+//       q = q_dirSE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+//          feq=c1o54* (drho/*+three*( vx1-vx2    )*/+c9o2*( vx1-vx2    )*( vx1-vx2    ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_MP0])[knw]=(c1o1-q)/(c1o1+q)*(f_SE-f_NW+(f_SE+f_NW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_SE+f_NW)-c6o1*c1o54*( VeloX-VeloY))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*( vx1-vx2    )+c9over2*( vx1-vx2    )*( vx1-vx2    )-cu_sq); 
+//          //(D.f[DIR_MP0])[knw]=(one-q)/(one+q)*(f_SE-feq*om_turb)/(one-om_turb)+(q*(f_SE+f_NW)-six*c1over54*( VeloX-VeloY))/(one+q);
+//          //(D.f[DIR_MP0])[knw]=zero;
+//       }
+
+//       q = q_dirNW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+//          feq=c1o54* (drho/*+three*(-vx1+vx2    )*/+c9o2*(-vx1+vx2    )*(-vx1+vx2    ) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_PM0])[kse]=(c1o1-q)/(c1o1+q)*(f_NW-f_SE+(f_NW+f_SE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_NW+f_SE)-c6o1*c1o54*(-VeloX+VeloY))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(-vx1+vx2    )+c9over2*(-vx1+vx2    )*(-vx1+vx2    )-cu_sq); 
+//          //(D.f[DIR_PM0])[kse]=(one-q)/(one+q)*(f_NW-feq*om_turb)/(one-om_turb)+(q*(f_NW+f_SE)-six*c1over54*(-VeloX+VeloY))/(one+q);
+//          //(D.f[DIR_PM0])[kse]=zero;
+//       }
+
+//       q = q_dirTE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//       //  if (k==10000) printf("AFTER x: %u \t  y: %u \t z: %u \n  VeloX: %f \t VeloY: %f \t VeloZ: %f \n\n", x,y,z, VeloX,VeloY,VeloZ);
+//          feq=c1o54* (drho/*+three*( vx1    +vx3)*/+c9o2*( vx1    +vx3)*( vx1    +vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_M0M])[kbw]=(c1o1-q)/(c1o1+q)*(f_TE-f_BW+(f_TE+f_BW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TE+f_BW)-c6o1*c1o54*( VeloX+VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*( vx1    +vx3)+c9over2*( vx1    +vx3)*( vx1    +vx3)-cu_sq); 
+//          //(D.f[DIR_M0M])[kbw]=(one-q)/(one+q)*(f_TE-feq*om_turb)/(one-om_turb)+(q*(f_TE+f_BW)-six*c1over54*( VeloX+VeloZ))/(one+q);
+//          //(D.f[DIR_M0M])[kbw]=zero;
+//       }
+
+//       q = q_dirBW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o54* (drho/*+three*(-vx1    -vx3)*/+c9o2*(-vx1    -vx3)*(-vx1    -vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_P0P])[kte]=(c1o1-q)/(c1o1+q)*(f_BW-f_TE+(f_BW+f_TE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BW+f_TE)-c6o1*c1o54*(-VeloX-VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(-vx1    -vx3)+c9over2*(-vx1    -vx3)*(-vx1    -vx3)-cu_sq); 
+//          //(D.f[DIR_P0P])[kte]=(one-q)/(one+q)*(f_BW-feq*om_turb)/(one-om_turb)+(q*(f_BW+f_TE)-six*c1over54*(-VeloX-VeloZ))/(one+q);
+//          //(D.f[DIR_P0P])[kte]=zero;
+//       }
+
+//       q = q_dirBE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o54* (drho/*+three*( vx1    -vx3)*/+c9o2*( vx1    -vx3)*( vx1    -vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_M0P])[ktw]=(c1o1-q)/(c1o1+q)*(f_BE-f_TW+(f_BE+f_TW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BE+f_TW)-c6o1*c1o54*( VeloX-VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*( vx1    -vx3)+c9over2*( vx1    -vx3)*( vx1    -vx3)-cu_sq); 
+//          //(D.f[DIR_M0P])[ktw]=(one-q)/(one+q)*(f_BE-feq*om_turb)/(one-om_turb)+(q*(f_BE+f_TW)-six*c1over54*( VeloX-VeloZ))/(one+q);
+//          //(D.f[DIR_M0P])[ktw]=zero;
+//       }
+
+//       q = q_dirTW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o54* (drho/*+three*(-vx1    +vx3)*/+c9o2*(-vx1    +vx3)*(-vx1    +vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_P0M])[kbe]=(c1o1-q)/(c1o1+q)*(f_TW-f_BE+(f_TW+f_BE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TW+f_BE)-c6o1*c1o54*(-VeloX+VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(-vx1    +vx3)+c9over2*(-vx1    +vx3)*(-vx1    +vx3)-cu_sq); 
+//          //(D.f[DIR_P0M])[kbe]=(one-q)/(one+q)*(f_TW-feq*om_turb)/(one-om_turb)+(q*(f_TW+f_BE)-six*c1over54*(-VeloX+VeloZ))/(one+q);
+//          //(D.f[DIR_P0M])[kbe]=zero;
+//       }
+
+//       q = q_dirTN[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o54* (drho/*+three*(     vx2+vx3)*/+c9o2*(     vx2+vx3)*(     vx2+vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_0MM])[kbs]=(c1o1-q)/(c1o1+q)*(f_TN-f_BS+(f_TN+f_BS-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TN+f_BS)-c6o1*c1o54*( VeloY+VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(     vx2+vx3)+c9over2*(     vx2+vx3)*(     vx2+vx3)-cu_sq); 
+//          //(D.f[DIR_0MM])[kbs]=(one-q)/(one+q)*(f_TN-feq*om_turb)/(one-om_turb)+(q*(f_TN+f_BS)-six*c1over54*( VeloY+VeloZ))/(one+q);
+//          //(D.f[DIR_0MM])[kbs]=zero;
+//       }
+
+//       q = q_dirBS[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o54* (drho/*+three*(    -vx2-vx3)*/+c9o2*(    -vx2-vx3)*(    -vx2-vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_0PP])[ktn]=(c1o1-q)/(c1o1+q)*(f_BS-f_TN+(f_BS+f_TN-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BS+f_TN)-c6o1*c1o54*( -VeloY-VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(    -vx2-vx3)+c9over2*(    -vx2-vx3)*(    -vx2-vx3)-cu_sq); 
+//          //(D.f[DIR_0PP])[ktn]=(one-q)/(one+q)*(f_BS-feq*om_turb)/(one-om_turb)+(q*(f_BS+f_TN)-six*c1over54*( -VeloY-VeloZ))/(one+q);
+//          //(D.f[DIR_0PP])[ktn]=zero;
+//       }
+
+//       q = q_dirBN[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o54* (drho/*+three*(     vx2-vx3)*/+c9o2*(     vx2-vx3)*(     vx2-vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_0MP])[kts]=(c1o1-q)/(c1o1+q)*(f_BN-f_TS+(f_BN+f_TS-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BN+f_TS)-c6o1*c1o54*( VeloY-VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(     vx2-vx3)+c9over2*(     vx2-vx3)*(     vx2-vx3)-cu_sq); 
+//          //(D.f[DIR_0MP])[kts]=(one-q)/(one+q)*(f_BN-feq*om_turb)/(one-om_turb)+(q*(f_BN+f_TS)-six*c1over54*( VeloY-VeloZ))/(one+q);
+//          //(D.f[DIR_0MP])[kts]=zero;
+//       }
+
+//       q = q_dirTS[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o54* (drho/*+three*(    -vx2+vx3)*/+c9o2*(    -vx2+vx3)*(    -vx2+vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_0PM])[kbn]=(c1o1-q)/(c1o1+q)*(f_TS-f_BN+(f_TS+f_BN-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TS+f_BN)-c6o1*c1o54*( -VeloY+VeloZ))/(c1o1+q) - c1o54 * drho;
+//          //feq=c1over54* (drho+three*(    -vx2+vx3)+c9over2*(    -vx2+vx3)*(    -vx2+vx3)-cu_sq); 
+//          //(D.f[DIR_0PM])[kbn]=(one-q)/(one+q)*(f_TS-feq*om_turb)/(one-om_turb)+(q*(f_TS+f_BN)-six*c1over54*( -VeloY+VeloZ))/(one+q);
+//          //(D.f[DIR_0PM])[kbn]=zero;
+//       }
+
+//       q = q_dirTNE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*( vx1+vx2+vx3)*/+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_MMM])[kbsw]=(c1o1-q)/(c1o1+q)*(f_TNE-f_BSW+(f_TNE+f_BSW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TNE+f_BSW)-c6o1*c1o216*( VeloX+VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*( vx1+vx2+vx3)+c9over2*( vx1+vx2+vx3)*( vx1+vx2+vx3)-cu_sq); 
+//          //(D.f[DIR_MMM])[kbsw]=(one-q)/(one+q)*(f_TNE-feq*om_turb)/(one-om_turb)+(q*(f_TNE+f_BSW)-six*c1over216*( VeloX+VeloY+VeloZ))/(one+q);
+//          //(D.f[DIR_MMM])[kbsw]=zero;
+//       }
+
+//       q = q_dirBSW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*(-vx1-vx2-vx3)*/+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_PPP])[ktne]=(c1o1-q)/(c1o1+q)*(f_BSW-f_TNE+(f_BSW+f_TNE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BSW+f_TNE)-c6o1*c1o216*(-VeloX-VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*(-vx1-vx2-vx3)+c9over2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3)-cu_sq); 
+//          //(D.f[DIR_PPP])[ktne]=(one-q)/(one+q)*(f_BSW-feq*om_turb)/(one-om_turb)+(q*(f_BSW+f_TNE)-six*c1over216*(-VeloX-VeloY-VeloZ))/(one+q);
+//          //(D.f[DIR_PPP])[ktne]=zero;
+//       }
+
+//       q = q_dirBNE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*( vx1+vx2-vx3)*/+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_MMP])[ktsw]=(c1o1-q)/(c1o1+q)*(f_BNE-f_TSW+(f_BNE+f_TSW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BNE+f_TSW)-c6o1*c1o216*( VeloX+VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*( vx1+vx2-vx3)+c9over2*( vx1+vx2-vx3)*( vx1+vx2-vx3)-cu_sq); 
+//          //(D.f[DIR_MMP])[ktsw]=(one-q)/(one+q)*(f_BNE-feq*om_turb)/(one-om_turb)+(q*(f_BNE+f_TSW)-six*c1over216*( VeloX+VeloY-VeloZ))/(one+q);
+//          //(D.f[DIR_MMP])[ktsw]=zero;
+//       }
+
+//       q = q_dirTSW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*(-vx1-vx2+vx3)*/+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_PPM])[kbne]=(c1o1-q)/(c1o1+q)*(f_TSW-f_BNE+(f_TSW+f_BNE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TSW+f_BNE)-c6o1*c1o216*(-VeloX-VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*(-vx1-vx2+vx3)+c9over2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3)-cu_sq); 
+//          //(D.f[DIR_PPM])[kbne]=(one-q)/(one+q)*(f_TSW-feq*om_turb)/(one-om_turb)+(q*(f_TSW+f_BNE)-six*c1over216*(-VeloX-VeloY+VeloZ))/(one+q);
+//          //(D.f[DIR_PPM])[kbne]=zero;
+//       }
+
+//       q = q_dirTSE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*( vx1-vx2+vx3)*/+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_MPM])[kbnw]=(c1o1-q)/(c1o1+q)*(f_TSE-f_BNW+(f_TSE+f_BNW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TSE+f_BNW)-c6o1*c1o216*( VeloX-VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*( vx1-vx2+vx3)+c9over2*( vx1-vx2+vx3)*( vx1-vx2+vx3)-cu_sq); 
+//          //(D.f[DIR_MPM])[kbnw]=(one-q)/(one+q)*(f_TSE-feq*om_turb)/(one-om_turb)+(q*(f_TSE+f_BNW)-six*c1over216*( VeloX-VeloY+VeloZ))/(one+q);
+//          //(D.f[DIR_MPM])[kbnw]=zero;
+//       }
+
+//       q = q_dirBNW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*(-vx1+vx2-vx3)*/+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_PMP])[ktse]=(c1o1-q)/(c1o1+q)*(f_BNW-f_TSE+(f_BNW+f_TSE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BNW+f_TSE)-c6o1*c1o216*(-VeloX+VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*(-vx1+vx2-vx3)+c9over2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3)-cu_sq); 
+//          //(D.f[DIR_PMP])[ktse]=(one-q)/(one+q)*(f_BNW-feq*om_turb)/(one-om_turb)+(q*(f_BNW+f_TSE)-six*c1over216*(-VeloX+VeloY-VeloZ))/(one+q);
+//          //(D.f[DIR_PMP])[ktse]=zero;
+//       }
+
+//       q = q_dirBSE[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*( vx1-vx2-vx3)*/+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_MPP])[ktnw]=(c1o1-q)/(c1o1+q)*(f_BSE-f_TNW+(f_BSE+f_TNW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BSE+f_TNW)-c6o1*c1o216*( VeloX-VeloY-VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*( vx1-vx2-vx3)+c9over2*( vx1-vx2-vx3)*( vx1-vx2-vx3)-cu_sq); 
+//          //(D.f[DIR_MPP])[ktnw]=(one-q)/(one+q)*(f_BSE-feq*om_turb)/(one-om_turb)+(q*(f_BSE+f_TNW)-six*c1over216*( VeloX-VeloY-VeloZ))/(one+q);
+//          //(D.f[DIR_MPP])[ktnw]=zero;
+//       }
+
+//       q = q_dirTNW[k];
+//       if (q>=c0o1 && q<=c1o1)
+//       {
+// 		 VeloX = fac*vx1;
+// 	     VeloY = fac*vx2;
+// 	     VeloZ = fac*vx3;
+// 		 if (x == true) VeloX = c0o1;
+// 		 if (y == true) VeloY = c0o1;
+// 		 if (z == true) VeloZ = c0o1;
+//          feq=c1o216*(drho/*+three*(-vx1+vx2+vx3)*/+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3) * (c1o1 + drho)-cu_sq); 
+//          (D.f[DIR_PMM])[kbse]=(c1o1-q)/(c1o1+q)*(f_TNW-f_BSE+(f_TNW+f_BSE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TNW+f_BSE)-c6o1*c1o216*(-VeloX+VeloY+VeloZ))/(c1o1+q) - c1o216 * drho;
+//          //feq=c1over216*(drho+three*(-vx1+vx2+vx3)+c9over2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3)-cu_sq); 
+//          //(D.f[DIR_PMM])[kbse]=(one-q)/(one+q)*(f_TNW-feq*om_turb)/(one-om_turb)+(q*(f_TNW+f_BSE)-six*c1over216*(-VeloX+VeloY+VeloZ))/(one+q);
+//          //(D.f[DIR_PMM])[kbse]=zero;
+//       }
+//    }
+// }
+
 
 
 
diff --git a/src/gpu/VirtualFluids_GPU/GPU/StressBCs27.cu b/src/gpu/VirtualFluids_GPU/GPU/StressBCs27.cu
index b0d2796a6805455c3a5acf55af98ddaf944c22aa..74e2faa38638228aa5d499aa74226405ab109f7d 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/StressBCs27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/StressBCs27.cu
@@ -43,6 +43,7 @@
 #include "LBM/LB.h"
 #include "lbm/constants/D3Q27.h"
 #include <lbm/constants/NumericConstants.h>
+#include "KernelUtilities.h"
 
 using namespace vf::lbm::constant;
 using namespace vf::lbm::dir;
@@ -426,60 +427,68 @@ __global__ void QStressDeviceComp27(real* DD,
       real f_E_in = 0.0,  f_W_in = 0.0,  f_N_in = 0.0,  f_S_in = 0.0,  f_T_in = 0.0,  f_B_in = 0.0,   f_NE_in = 0.0,  f_SW_in = 0.0,  f_SE_in = 0.0,  f_NW_in = 0.0,  f_TE_in = 0.0,  f_BW_in = 0.0,  f_BE_in = 0.0, f_TW_in = 0.0, f_TN_in = 0.0, f_BS_in = 0.0, f_BN_in = 0.0, f_TS_in = 0.0, f_TNE_in = 0.0, f_TSW_in = 0.0, f_TSE_in = 0.0, f_TNW_in = 0.0, f_BNE_in = 0.0, f_BSW_in = 0.0, f_BSE_in = 0.0, f_BNW_in = 0.0;
       // momentum exchanged with wall at rest
       real wallMomentumX = 0.0, wallMomentumY = 0.0, wallMomentumZ = 0.0;
-
+      real velocityLB = 0.0;
+      
       q = q_dirE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c2o27* (drho/*+three*( vx1        )*/+c9o2*( vx1        )*( vx1        ) * (c1o1 + drho)-cu_sq);
-         f_W_in=(c1o1-q)/(c1o1+q)*(f_E-f_W+(f_E+f_W-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_E+f_W))/(c1o1+q) - c2o27 * drho;
+         velocityLB = vx1;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         f_W_in = getInterpolatedDistributionForNoSlipBC(q, f_E, f_W, feq, om_turb);
          wallMomentumX += f_E+f_W_in;
       }
 
       q = q_dirW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c2o27* (drho/*+three*(-vx1        )*/+c9o2*(-vx1        )*(-vx1        ) * (c1o1 + drho)-cu_sq);
-         f_E_in=(c1o1-q)/(c1o1+q)*(f_W-f_E+(f_W+f_E-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_W+f_E))/(c1o1+q) - c2o27 * drho;
+         velocityLB = -vx1;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         f_E_in = getInterpolatedDistributionForNoSlipBC(q, f_W, f_E, feq, om_turb);
          wallMomentumX -= f_W+f_E_in;
       }
 
       q = q_dirN[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c2o27* (drho/*+three*(    vx2     )*/+c9o2*(     vx2    )*(     vx2    ) * (c1o1 + drho)-cu_sq);
-         f_S_in=(c1o1-q)/(c1o1+q)*(f_N-f_S+(f_N+f_S-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_N+f_S))/(c1o1+q) - c2o27 * drho;
+         velocityLB = vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         f_S_in = getInterpolatedDistributionForNoSlipBC(q, f_N, f_S, feq, om_turb);
          wallMomentumY += f_N+f_S_in;
       }
 
       q = q_dirS[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c2o27* (drho/*+three*(   -vx2     )*/+c9o2*(    -vx2    )*(    -vx2    ) * (c1o1 + drho)-cu_sq);
-         f_N_in=(c1o1-q)/(c1o1+q)*(f_S-f_N+(f_S+f_N-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_S+f_N))/(c1o1+q) - c2o27 * drho;
+         velocityLB = -vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         f_N_in = getInterpolatedDistributionForNoSlipBC(q, f_S, f_N, feq, om_turb);
          wallMomentumY -= f_S+f_N_in;
       }
 
       q = q_dirT[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c2o27* (drho/*+three*(         vx3)*/+c9o2*(         vx3)*(         vx3) * (c1o1 + drho)-cu_sq);
-         f_B_in=(c1o1-q)/(c1o1+q)*(f_T-f_B+(f_T+f_B-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_T+f_B))/(c1o1+q) - c2o27 * drho;
+         velocityLB = vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         f_B_in = getInterpolatedDistributionForNoSlipBC(q, f_T, f_B, feq, om_turb);
          wallMomentumZ += f_T+f_B_in;
       }
 
       q = q_dirB[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c2o27* (drho/*+three*(        -vx3)*/+c9o2*(        -vx3)*(        -vx3) * (c1o1 + drho)-cu_sq);
-         f_T_in=(c1o1-q)/(c1o1+q)*(f_B-f_T+(f_B+f_T-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_B+f_T))/(c1o1+q) - c2o27 * drho;
+         velocityLB = -vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c2o27);
+         f_T_in = getInterpolatedDistributionForNoSlipBC(q, f_B, f_T, feq, om_turb);
          wallMomentumZ -= f_B+f_T_in;
       }
 
       q = q_dirNE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*( vx1+vx2    )*/+c9o2*( vx1+vx2    )*( vx1+vx2    ) * (c1o1 + drho)-cu_sq);
-         f_SW_in=(c1o1-q)/(c1o1+q)*(f_NE-f_SW+(f_NE+f_SW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_NE+f_SW))/(c1o1+q) - c1o54 * drho;
+         velocityLB = vx1 + vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_SW_in = getInterpolatedDistributionForNoSlipBC(q, f_NE, f_SW, feq, om_turb);
          wallMomentumX += f_NE+f_SW_in;
          wallMomentumY += f_NE+f_SW_in;
       }
@@ -487,8 +496,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirSW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(-vx1-vx2    )*/+c9o2*(-vx1-vx2    )*(-vx1-vx2    ) * (c1o1 + drho)-cu_sq);
-         f_NE_in=(c1o1-q)/(c1o1+q)*(f_SW-f_NE+(f_SW+f_NE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_SW+f_NE))/(c1o1+q) - c1o54 * drho;
+         velocityLB = -vx1 - vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_NE_in = getInterpolatedDistributionForNoSlipBC(q, f_SW, f_NE, feq, om_turb);
          wallMomentumX -= f_SW+f_NE_in;
          wallMomentumY -= f_SW+f_NE_in;
       }
@@ -496,8 +506,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirSE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*( vx1-vx2    )*/+c9o2*( vx1-vx2    )*( vx1-vx2    ) * (c1o1 + drho)-cu_sq);
-         f_NW_in=(c1o1-q)/(c1o1+q)*(f_SE-f_NW+(f_SE+f_NW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_SE+f_NW))/(c1o1+q) - c1o54 * drho;
+         velocityLB = vx1 - vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_NW_in = getInterpolatedDistributionForNoSlipBC(q, f_SE, f_NW, feq, om_turb);
          wallMomentumX += f_SE+f_NW_in;
          wallMomentumY -= f_SE+f_NW_in;
       }
@@ -505,8 +516,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirNW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(-vx1+vx2    )*/+c9o2*(-vx1+vx2    )*(-vx1+vx2    ) * (c1o1 + drho)-cu_sq);
-         f_SE_in=(c1o1-q)/(c1o1+q)*(f_NW-f_SE+(f_NW+f_SE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_NW+f_SE))/(c1o1+q) - c1o54 * drho;
+         velocityLB = -vx1 + vx2;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_SE_in = getInterpolatedDistributionForNoSlipBC(q, f_NW, f_SE, feq, om_turb);
          wallMomentumX -= f_NW+f_SE_in;
          wallMomentumY += f_NW+f_SE_in;
       }
@@ -514,8 +526,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*( vx1    +vx3)*/+c9o2*( vx1    +vx3)*( vx1    +vx3) * (c1o1 + drho)-cu_sq);
-         f_BW_in=(c1o1-q)/(c1o1+q)*(f_TE-f_BW+(f_TE+f_BW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TE+f_BW))/(c1o1+q) - c1o54 * drho;
+         velocityLB = vx1 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_BW_in = getInterpolatedDistributionForNoSlipBC(q, f_TE, f_BW, feq, om_turb);
          wallMomentumX += f_TE+f_BW_in;
          wallMomentumZ += f_TE+f_BW_in;
       }
@@ -523,8 +536,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(-vx1    -vx3)*/+c9o2*(-vx1    -vx3)*(-vx1    -vx3) * (c1o1 + drho)-cu_sq);
-         f_TE_in=(c1o1-q)/(c1o1+q)*(f_BW-f_TE+(f_BW+f_TE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BW+f_TE))/(c1o1+q) - c1o54 * drho;
+         velocityLB = -vx1 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_TE_in = getInterpolatedDistributionForNoSlipBC(q, f_BW, f_TE, feq, om_turb);
          wallMomentumX -= f_BW+f_TE_in;
          wallMomentumZ -= f_BW+f_TE_in;
       }
@@ -532,8 +546,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*( vx1    -vx3)*/+c9o2*( vx1    -vx3)*( vx1    -vx3) * (c1o1 + drho)-cu_sq);
-         f_TW_in=(c1o1-q)/(c1o1+q)*(f_BE-f_TW+(f_BE+f_TW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BE+f_TW))/(c1o1+q) - c1o54 * drho;
+         velocityLB = vx1 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_TW_in = getInterpolatedDistributionForNoSlipBC(q, f_BE, f_TW, feq, om_turb);
          wallMomentumX += f_BE+f_TW_in;
          wallMomentumZ -= f_BE+f_TW_in;
       }
@@ -541,8 +556,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(-vx1    +vx3)*/+c9o2*(-vx1    +vx3)*(-vx1    +vx3) * (c1o1 + drho)-cu_sq);
-         f_BE_in=(c1o1-q)/(c1o1+q)*(f_TW-f_BE+(f_TW+f_BE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TW+f_BE))/(c1o1+q) - c1o54 * drho;
+         velocityLB = -vx1 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_BE_in = getInterpolatedDistributionForNoSlipBC(q, f_TW, f_BE, feq, om_turb);
          wallMomentumX -= f_TW+f_BE_in;
          wallMomentumZ += f_TW+f_BE_in;
       }
@@ -550,8 +566,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTN[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(     vx2+vx3)*/+c9o2*(     vx2+vx3)*(     vx2+vx3) * (c1o1 + drho)-cu_sq);
-         f_BS_in=(c1o1-q)/(c1o1+q)*(f_TN-f_BS+(f_TN+f_BS-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TN+f_BS))/(c1o1+q) - c1o54 * drho;
+         velocityLB = vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_BS_in = getInterpolatedDistributionForNoSlipBC(q, f_TN, f_BS, feq, om_turb);
          wallMomentumY += f_TN+f_BS_in;
          wallMomentumZ += f_TN+f_BS_in;
       }
@@ -559,8 +576,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBS[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(    -vx2-vx3)*/+c9o2*(    -vx2-vx3)*(    -vx2-vx3) * (c1o1 + drho)-cu_sq);
-         f_TN_in=(c1o1-q)/(c1o1+q)*(f_BS-f_TN+(f_BS+f_TN-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BS+f_TN))/(c1o1+q) - c1o54 * drho;
+         velocityLB = -vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_TN_in = getInterpolatedDistributionForNoSlipBC(q, f_BS, f_TN, feq, om_turb);
          wallMomentumY -= f_BS+f_TN_in;
          wallMomentumZ -= f_BS+f_TN_in;
       }
@@ -568,8 +586,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBN[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(     vx2-vx3)*/+c9o2*(     vx2-vx3)*(     vx2-vx3) * (c1o1 + drho)-cu_sq);
-         f_TS_in=(c1o1-q)/(c1o1+q)*(f_BN-f_TS+(f_BN+f_TS-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BN+f_TS))/(c1o1+q) - c1o54 * drho;
+         velocityLB = vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_TS_in = getInterpolatedDistributionForNoSlipBC(q, f_BN, f_TS, feq, om_turb);
          wallMomentumY += f_BN+f_TS_in;
          wallMomentumZ -= f_BN+f_TS_in;
       }
@@ -577,8 +596,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTS[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o54* (drho/*+three*(    -vx2+vx3)*/+c9o2*(    -vx2+vx3)*(    -vx2+vx3) * (c1o1 + drho)-cu_sq);
-         f_BN_in=(c1o1-q)/(c1o1+q)*(f_TS-f_BN+(f_TS+f_BN-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TS+f_BN))/(c1o1+q) - c1o54 * drho;
+         velocityLB = -vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o54);
+         f_BN_in = getInterpolatedDistributionForNoSlipBC(q, f_TS, f_BN, feq, om_turb);
          wallMomentumY -= f_TS+f_BN_in;
          wallMomentumZ += f_TS+f_BN_in;
       }
@@ -586,8 +606,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTNE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*( vx1+vx2+vx3)*/+c9o2*( vx1+vx2+vx3)*( vx1+vx2+vx3) * (c1o1 + drho)-cu_sq);
-         f_BSW_in=(c1o1-q)/(c1o1+q)*(f_TNE-f_BSW+(f_TNE+f_BSW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TNE+f_BSW))/(c1o1+q) - c1o216 * drho;
+         velocityLB = vx1 + vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_BSW_in = getInterpolatedDistributionForNoSlipBC(q, f_TNE, f_BSW, feq, om_turb);
          wallMomentumX += f_TNE+f_BSW_in;
          wallMomentumY += f_TNE+f_BSW_in;
          wallMomentumZ += f_TNE+f_BSW_in;
@@ -596,8 +617,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBSW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*(-vx1-vx2-vx3)*/+c9o2*(-vx1-vx2-vx3)*(-vx1-vx2-vx3) * (c1o1 + drho)-cu_sq);
-         f_TNE_in=(c1o1-q)/(c1o1+q)*(f_BSW-f_TNE+(f_BSW+f_TNE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BSW+f_TNE))/(c1o1+q) - c1o216 * drho;
+         velocityLB = -vx1 - vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_TNE_in = getInterpolatedDistributionForNoSlipBC(q, f_BSW, f_TNE, feq, om_turb);
          wallMomentumX -= f_BSW+f_TNE_in;
          wallMomentumY -= f_BSW+f_TNE_in;
          wallMomentumZ -= f_BSW+f_TNE_in;
@@ -606,8 +628,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBNE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*( vx1+vx2-vx3)*/+c9o2*( vx1+vx2-vx3)*( vx1+vx2-vx3) * (c1o1 + drho)-cu_sq);
-         f_TSW_in=(c1o1-q)/(c1o1+q)*(f_BNE-f_TSW+(f_BNE+f_TSW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BNE+f_TSW))/(c1o1+q) - c1o216 * drho;
+         velocityLB = vx1 + vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_TSW_in = getInterpolatedDistributionForNoSlipBC(q, f_BNE, f_TSW, feq, om_turb);
          wallMomentumX += f_BNE+f_TSW_in;
          wallMomentumY += f_BNE+f_TSW_in;
          wallMomentumZ -= f_BNE+f_TSW_in;
@@ -616,8 +639,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTSW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*(-vx1-vx2+vx3)*/+c9o2*(-vx1-vx2+vx3)*(-vx1-vx2+vx3) * (c1o1 + drho)-cu_sq);
-         f_BNE_in=(c1o1-q)/(c1o1+q)*(f_TSW-f_BNE+(f_TSW+f_BNE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TSW+f_BNE))/(c1o1+q) - c1o216 * drho;
+         velocityLB = -vx1 - vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_BNE_in = getInterpolatedDistributionForNoSlipBC(q, f_TSW, f_BNE, feq, om_turb);
          wallMomentumX -= f_TSW+f_BNE_in;
          wallMomentumY -= f_TSW+f_BNE_in;
          wallMomentumZ += f_TSW+f_BNE_in;
@@ -626,8 +650,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTSE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*( vx1-vx2+vx3)*/+c9o2*( vx1-vx2+vx3)*( vx1-vx2+vx3) * (c1o1 + drho)-cu_sq);
-         f_BNW_in=(c1o1-q)/(c1o1+q)*(f_TSE-f_BNW+(f_TSE+f_BNW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TSE+f_BNW))/(c1o1+q) - c1o216 * drho;
+         velocityLB = vx1 - vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_BNW_in = getInterpolatedDistributionForNoSlipBC(q, f_TSE, f_BNW, feq, om_turb);
          wallMomentumX += f_TSE+f_BNW_in;
          wallMomentumY -= f_TSE+f_BNW_in;
          wallMomentumZ += f_TSE+f_BNW_in;
@@ -636,8 +661,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBNW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*(-vx1+vx2-vx3)*/+c9o2*(-vx1+vx2-vx3)*(-vx1+vx2-vx3) * (c1o1 + drho)-cu_sq);
-         f_TSE_in=(c1o1-q)/(c1o1+q)*(f_BNW-f_TSE+(f_BNW+f_TSE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BNW+f_TSE))/(c1o1+q) - c1o216 * drho;
+         velocityLB = -vx1 + vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_TSE_in = getInterpolatedDistributionForNoSlipBC(q, f_BNW, f_TSE, feq, om_turb);
          wallMomentumX -= f_BNW+f_TSE_in;
          wallMomentumY += f_BNW+f_TSE_in;
          wallMomentumZ -= f_BNW+f_TSE_in;
@@ -646,8 +672,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirBSE[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*( vx1-vx2-vx3)*/+c9o2*( vx1-vx2-vx3)*( vx1-vx2-vx3) * (c1o1 + drho)-cu_sq);
-         f_TNW_in=(c1o1-q)/(c1o1+q)*(f_BSE-f_TNW+(f_BSE+f_TNW-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_BSE+f_TNW))/(c1o1+q) - c1o216 * drho;
+         velocityLB = vx1 - vx2 - vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_TNW_in = getInterpolatedDistributionForNoSlipBC(q, f_BSE, f_TNW, feq, om_turb);
          wallMomentumX += f_BSE+f_TNW_in;
          wallMomentumY -= f_BSE+f_TNW_in;
          wallMomentumZ -= f_BSE+f_TNW_in;
@@ -656,8 +683,9 @@ __global__ void QStressDeviceComp27(real* DD,
       q = q_dirTNW[k];
       if (q>=c0o1 && q<=c1o1)
       {
-         feq=c1o216*(drho/*+three*(-vx1+vx2+vx3)*/+c9o2*(-vx1+vx2+vx3)*(-vx1+vx2+vx3) * (c1o1 + drho)-cu_sq);
-         f_BSE_in=(c1o1-q)/(c1o1+q)*(f_TNW-f_BSE+(f_TNW+f_BSE-c2o1*feq*om_turb)/(c1o1-om_turb))*c1o2+(q*(f_TNW+f_BSE))/(c1o1+q) - c1o216 * drho;
+         velocityLB = -vx1 + vx2 + vx3;
+         feq = getEquilibriumForBC(drho, velocityLB, cu_sq, c1o216);
+         f_BSE_in = getInterpolatedDistributionForNoSlipBC(q, f_TNW, f_BSE, feq, om_turb);
          wallMomentumX -= f_TNW+f_BSE_in;
          wallMomentumY += f_TNW+f_BSE_in;
          wallMomentumZ += f_TNW+f_BSE_in;
@@ -1657,4 +1685,751 @@ __global__ void BBStressDevice27( real* DD,
 
    }
 }
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+__global__ void BBStressPressureDevice27( real* DD,
+											            int* k_Q,
+                                             int* k_N,
+                                             real* QQ,
+                                             unsigned int  numberOfBCnodes,
+                                             real* vx,
+                                             real* vy,
+                                             real* vz,
+                                             real* normalX,
+                                             real* normalY,
+                                             real* normalZ,
+                                             real* vx_el,
+                                             real* vy_el,
+                                             real* vz_el,
+                                             real* vx_w_mean,
+                                             real* vy_w_mean,
+                                             real* vz_w_mean,
+                                             int* samplingOffset,
+                                             real* z0,
+                                             bool  hasWallModelMonitor,
+                                             real* u_star_monitor,
+                                             real* Fx_monitor,
+                                             real* Fy_monitor,
+                                             real* Fz_monitor,
+                                             unsigned int* neighborX,
+                                             unsigned int* neighborY,
+                                             unsigned int* neighborZ,
+                                             unsigned int size_Mat,
+                                             bool isEvenTimestep)
+{
+   Distributions27 D;
+   if (isEvenTimestep==true)
+   {
+      D.f[DIR_P00   ] = &DD[DIR_P00   *size_Mat];
+      D.f[DIR_M00   ] = &DD[DIR_M00   *size_Mat];
+      D.f[DIR_0P0   ] = &DD[DIR_0P0   *size_Mat];
+      D.f[DIR_0M0   ] = &DD[DIR_0M0   *size_Mat];
+      D.f[DIR_00P   ] = &DD[DIR_00P   *size_Mat];
+      D.f[DIR_00M   ] = &DD[DIR_00M   *size_Mat];
+      D.f[DIR_PP0  ] = &DD[DIR_PP0  *size_Mat];
+      D.f[DIR_MM0  ] = &DD[DIR_MM0  *size_Mat];
+      D.f[DIR_PM0  ] = &DD[DIR_PM0  *size_Mat];
+      D.f[DIR_MP0  ] = &DD[DIR_MP0  *size_Mat];
+      D.f[DIR_P0P  ] = &DD[DIR_P0P  *size_Mat];
+      D.f[DIR_M0M  ] = &DD[DIR_M0M  *size_Mat];
+      D.f[DIR_P0M  ] = &DD[DIR_P0M  *size_Mat];
+      D.f[DIR_M0P  ] = &DD[DIR_M0P  *size_Mat];
+      D.f[DIR_0PP  ] = &DD[DIR_0PP  *size_Mat];
+      D.f[DIR_0MM  ] = &DD[DIR_0MM  *size_Mat];
+      D.f[DIR_0PM  ] = &DD[DIR_0PM  *size_Mat];
+      D.f[DIR_0MP  ] = &DD[DIR_0MP  *size_Mat];
+      D.f[DIR_000] = &DD[DIR_000*size_Mat];
+      D.f[DIR_PPP ] = &DD[DIR_PPP *size_Mat];
+      D.f[DIR_MMP ] = &DD[DIR_MMP *size_Mat];
+      D.f[DIR_PMP ] = &DD[DIR_PMP *size_Mat];
+      D.f[DIR_MPP ] = &DD[DIR_MPP *size_Mat];
+      D.f[DIR_PPM ] = &DD[DIR_PPM *size_Mat];
+      D.f[DIR_MMM ] = &DD[DIR_MMM *size_Mat];
+      D.f[DIR_PMM ] = &DD[DIR_PMM *size_Mat];
+      D.f[DIR_MPM ] = &DD[DIR_MPM *size_Mat];
+   }
+   else
+   {
+      D.f[DIR_M00   ] = &DD[DIR_P00   *size_Mat];
+      D.f[DIR_P00   ] = &DD[DIR_M00   *size_Mat];
+      D.f[DIR_0M0   ] = &DD[DIR_0P0   *size_Mat];
+      D.f[DIR_0P0   ] = &DD[DIR_0M0   *size_Mat];
+      D.f[DIR_00M   ] = &DD[DIR_00P   *size_Mat];
+      D.f[DIR_00P   ] = &DD[DIR_00M   *size_Mat];
+      D.f[DIR_MM0  ] = &DD[DIR_PP0  *size_Mat];
+      D.f[DIR_PP0  ] = &DD[DIR_MM0  *size_Mat];
+      D.f[DIR_MP0  ] = &DD[DIR_PM0  *size_Mat];
+      D.f[DIR_PM0  ] = &DD[DIR_MP0  *size_Mat];
+      D.f[DIR_M0M  ] = &DD[DIR_P0P  *size_Mat];
+      D.f[DIR_P0P  ] = &DD[DIR_M0M  *size_Mat];
+      D.f[DIR_M0P  ] = &DD[DIR_P0M  *size_Mat];
+      D.f[DIR_P0M  ] = &DD[DIR_M0P  *size_Mat];
+      D.f[DIR_0MM  ] = &DD[DIR_0PP  *size_Mat];
+      D.f[DIR_0PP  ] = &DD[DIR_0MM  *size_Mat];
+      D.f[DIR_0MP  ] = &DD[DIR_0PM  *size_Mat];
+      D.f[DIR_0PM  ] = &DD[DIR_0MP  *size_Mat];
+      D.f[DIR_000] = &DD[DIR_000*size_Mat];
+      D.f[DIR_PPP ] = &DD[DIR_MMM *size_Mat];
+      D.f[DIR_MMP ] = &DD[DIR_PPM *size_Mat];
+      D.f[DIR_PMP ] = &DD[DIR_MPM *size_Mat];
+      D.f[DIR_MPP ] = &DD[DIR_PMM *size_Mat];
+      D.f[DIR_PPM ] = &DD[DIR_MMP *size_Mat];
+      D.f[DIR_MMM ] = &DD[DIR_PPP *size_Mat];
+      D.f[DIR_PMM ] = &DD[DIR_MPP *size_Mat];
+      D.f[DIR_MPM ] = &DD[DIR_PMP *size_Mat];
+   }
+   ////////////////////////////////////////////////////////////////////////////////
+   const unsigned  x = threadIdx.x;  // Globaler x-Index
+   const unsigned  y = blockIdx.x;   // Globaler y-Index
+   const unsigned  z = blockIdx.y;   // Globaler z-Index
+
+   const unsigned nx = blockDim.x;
+   const unsigned ny = gridDim.x;
+
+   const unsigned k = nx*(ny*z + y) + x;
+   //////////////////////////////////////////////////////////////////////////
+
+   if(k< numberOfBCnodes)
+   {
+      ////////////////////////////////////////////////////////////////////////////////
+      real *q_dirE,   *q_dirW,   *q_dirN,   *q_dirS,   *q_dirT,   *q_dirB,
+         *q_dirNE,  *q_dirSW,  *q_dirSE,  *q_dirNW,  *q_dirTE,  *q_dirBW,
+         *q_dirBE,  *q_dirTW,  *q_dirTN,  *q_dirBS,  *q_dirBN,  *q_dirTS,
+         *q_dirTNE, *q_dirTSW, *q_dirTSE, *q_dirTNW, *q_dirBNE, *q_dirBSW,
+         *q_dirBSE, *q_dirBNW;
+      q_dirE   = &QQ[DIR_P00   * numberOfBCnodes];
+      q_dirW   = &QQ[DIR_M00   * numberOfBCnodes];
+      q_dirN   = &QQ[DIR_0P0   * numberOfBCnodes];
+      q_dirS   = &QQ[DIR_0M0   * numberOfBCnodes];
+      q_dirT   = &QQ[DIR_00P   * numberOfBCnodes];
+      q_dirB   = &QQ[DIR_00M   * numberOfBCnodes];
+      q_dirNE  = &QQ[DIR_PP0  * numberOfBCnodes];
+      q_dirSW  = &QQ[DIR_MM0  * numberOfBCnodes];
+      q_dirSE  = &QQ[DIR_PM0  * numberOfBCnodes];
+      q_dirNW  = &QQ[DIR_MP0  * numberOfBCnodes];
+      q_dirTE  = &QQ[DIR_P0P  * numberOfBCnodes];
+      q_dirBW  = &QQ[DIR_M0M  * numberOfBCnodes];
+      q_dirBE  = &QQ[DIR_P0M  * numberOfBCnodes];
+      q_dirTW  = &QQ[DIR_M0P  * numberOfBCnodes];
+      q_dirTN  = &QQ[DIR_0PP  * numberOfBCnodes];
+      q_dirBS  = &QQ[DIR_0MM  * numberOfBCnodes];
+      q_dirBN  = &QQ[DIR_0PM  * numberOfBCnodes];
+      q_dirTS  = &QQ[DIR_0MP  * numberOfBCnodes];
+      q_dirTNE = &QQ[DIR_PPP * numberOfBCnodes];
+      q_dirTSW = &QQ[DIR_MMP * numberOfBCnodes];
+      q_dirTSE = &QQ[DIR_PMP * numberOfBCnodes];
+      q_dirTNW = &QQ[DIR_MPP * numberOfBCnodes];
+      q_dirBNE = &QQ[DIR_PPM * numberOfBCnodes];
+      q_dirBSW = &QQ[DIR_MMM * numberOfBCnodes];
+      q_dirBSE = &QQ[DIR_PMM * numberOfBCnodes];
+      q_dirBNW = &QQ[DIR_MPM * numberOfBCnodes];
+      ////////////////////////////////////////////////////////////////////////////////
+      //index
+      unsigned int KQK  = k_Q[k];
+      unsigned int kzero= KQK;
+      unsigned int ke   = KQK;
+      unsigned int kw   = neighborX[KQK];
+      unsigned int kn   = KQK;
+      unsigned int ks   = neighborY[KQK];
+      unsigned int kt   = KQK;
+      unsigned int kb   = neighborZ[KQK];
+      unsigned int ksw  = neighborY[kw];
+      unsigned int kne  = KQK;
+      unsigned int kse  = ks;
+      unsigned int knw  = kw;
+      unsigned int kbw  = neighborZ[kw];
+      unsigned int kte  = KQK;
+      unsigned int kbe  = kb;
+      unsigned int ktw  = kw;
+      unsigned int kbs  = neighborZ[ks];
+      unsigned int ktn  = KQK;
+      unsigned int kbn  = kb;
+      unsigned int kts  = ks;
+      unsigned int ktse = ks;
+      unsigned int kbnw = kbw;
+      unsigned int ktnw = kw;
+      unsigned int kbse = kbs;
+      unsigned int ktsw = ksw;
+      unsigned int kbne = kb;
+      unsigned int ktne = KQK;
+      unsigned int kbsw = neighborZ[ksw];
+
+      ////////////////////////////////////////////////////////////////////////////////
+      real f_E,  f_W,  f_N,  f_S,  f_T,  f_B,   f_NE,  f_SW,  f_SE,  f_NW,  f_TE,  f_BW,  f_BE,
+         f_TW, f_TN, f_BS, f_BN, f_TS, f_TNE, f_TSW, f_TSE, f_TNW, f_BNE, f_BSW, f_BSE, f_BNW;
+
+      f_W    = (D.f[DIR_P00   ])[ke   ];
+      f_E    = (D.f[DIR_M00   ])[kw   ];
+      f_S    = (D.f[DIR_0P0   ])[kn   ];
+      f_N    = (D.f[DIR_0M0   ])[ks   ];
+      f_B    = (D.f[DIR_00P   ])[kt   ];
+      f_T    = (D.f[DIR_00M   ])[kb   ];
+      f_SW   = (D.f[DIR_PP0  ])[kne  ];
+      f_NE   = (D.f[DIR_MM0  ])[ksw  ];
+      f_NW   = (D.f[DIR_PM0  ])[kse  ];
+      f_SE   = (D.f[DIR_MP0  ])[knw  ];
+      f_BW   = (D.f[DIR_P0P  ])[kte  ];
+      f_TE   = (D.f[DIR_M0M  ])[kbw  ];
+      f_TW   = (D.f[DIR_P0M  ])[kbe  ];
+      f_BE   = (D.f[DIR_M0P  ])[ktw  ];
+      f_BS   = (D.f[DIR_0PP  ])[ktn  ];
+      f_TN   = (D.f[DIR_0MM  ])[kbs  ];
+      f_TS   = (D.f[DIR_0PM  ])[kbn  ];
+      f_BN   = (D.f[DIR_0MP  ])[kts  ];
+      f_BSW  = (D.f[DIR_PPP ])[ktne ];
+      f_BNE  = (D.f[DIR_MMP ])[ktsw ];
+      f_BNW  = (D.f[DIR_PMP ])[ktse ];
+      f_BSE  = (D.f[DIR_MPP ])[ktnw ];
+      f_TSW  = (D.f[DIR_PPM ])[kbne ];
+      f_TNE  = (D.f[DIR_MMM ])[kbsw ];
+      f_TNW  = (D.f[DIR_PMM ])[kbse ];
+      f_TSE  = (D.f[DIR_MPM ])[kbnw ];
+
+      ////////////////////////////////////////////////////////////////////////////////
+      real vx1, vx2, vx3, drho;
+      drho   =  f_TSE + f_TNW + f_TNE + f_TSW + f_BSE + f_BNW + f_BNE + f_BSW +
+                f_BN + f_TS + f_TN + f_BS + f_BE + f_TW + f_TE + f_BW + f_SE + f_NW + f_NE + f_SW +
+                f_T + f_B + f_N + f_S + f_E + f_W + ((D.f[DIR_000])[kzero]);
+
+      vx1    =  (((f_TSE - f_BNW) - (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                ((f_BE - f_TW)   + (f_TE - f_BW))   + ((f_SE - f_NW)   + (f_NE - f_SW)) +
+                (f_E - f_W)) / (c1o1 + drho);
+
+
+      vx2    =   ((-(f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) - (f_TSW - f_BNE)) +
+                 ((f_BN - f_TS)   + (f_TN - f_BS))    + (-(f_SE - f_NW)  + (f_NE - f_SW)) +
+                 (f_N - f_S)) / (c1o1 + drho);
+
+      vx3    =   (((f_TSE - f_BNW) + (f_TNW - f_BSE)) + ((f_TNE - f_BSW) + (f_TSW - f_BNE)) +
+                 (-(f_BN - f_TS)  + (f_TN - f_BS))   + ((f_TE - f_BW)   - (f_BE - f_TW)) +
+                 (f_T - f_B)) / (c1o1 + drho);
+
+      //////////////////////////////////////////////////////////////////////////
+      if (isEvenTimestep==false)
+      {
+         D.f[DIR_P00   ] = &DD[DIR_P00   *size_Mat];
+         D.f[DIR_M00   ] = &DD[DIR_M00   *size_Mat];
+         D.f[DIR_0P0   ] = &DD[DIR_0P0   *size_Mat];
+         D.f[DIR_0M0   ] = &DD[DIR_0M0   *size_Mat];
+         D.f[DIR_00P   ] = &DD[DIR_00P   *size_Mat];
+         D.f[DIR_00M   ] = &DD[DIR_00M   *size_Mat];
+         D.f[DIR_PP0  ] = &DD[DIR_PP0  *size_Mat];
+         D.f[DIR_MM0  ] = &DD[DIR_MM0  *size_Mat];
+         D.f[DIR_PM0  ] = &DD[DIR_PM0  *size_Mat];
+         D.f[DIR_MP0  ] = &DD[DIR_MP0  *size_Mat];
+         D.f[DIR_P0P  ] = &DD[DIR_P0P  *size_Mat];
+         D.f[DIR_M0M  ] = &DD[DIR_M0M  *size_Mat];
+         D.f[DIR_P0M  ] = &DD[DIR_P0M  *size_Mat];
+         D.f[DIR_M0P  ] = &DD[DIR_M0P  *size_Mat];
+         D.f[DIR_0PP  ] = &DD[DIR_0PP  *size_Mat];
+         D.f[DIR_0MM  ] = &DD[DIR_0MM  *size_Mat];
+         D.f[DIR_0PM  ] = &DD[DIR_0PM  *size_Mat];
+         D.f[DIR_0MP  ] = &DD[DIR_0MP  *size_Mat];
+         D.f[DIR_000] = &DD[DIR_000*size_Mat];
+         D.f[DIR_PPP ] = &DD[DIR_PPP *size_Mat];
+         D.f[DIR_MMP ] = &DD[DIR_MMP *size_Mat];
+         D.f[DIR_PMP ] = &DD[DIR_PMP *size_Mat];
+         D.f[DIR_MPP ] = &DD[DIR_MPP *size_Mat];
+         D.f[DIR_PPM ] = &DD[DIR_PPM *size_Mat];
+         D.f[DIR_MMM ] = &DD[DIR_MMM *size_Mat];
+         D.f[DIR_PMM ] = &DD[DIR_PMM *size_Mat];
+         D.f[DIR_MPM ] = &DD[DIR_MPM *size_Mat];
+      }
+      else
+      {
+         D.f[DIR_M00   ] = &DD[DIR_P00   *size_Mat];
+         D.f[DIR_P00   ] = &DD[DIR_M00   *size_Mat];
+         D.f[DIR_0M0   ] = &DD[DIR_0P0   *size_Mat];
+         D.f[DIR_0P0   ] = &DD[DIR_0M0   *size_Mat];
+         D.f[DIR_00M   ] = &DD[DIR_00P   *size_Mat];
+         D.f[DIR_00P   ] = &DD[DIR_00M   *size_Mat];
+         D.f[DIR_MM0  ] = &DD[DIR_PP0  *size_Mat];
+         D.f[DIR_PP0  ] = &DD[DIR_MM0  *size_Mat];
+         D.f[DIR_MP0  ] = &DD[DIR_PM0  *size_Mat];
+         D.f[DIR_PM0  ] = &DD[DIR_MP0  *size_Mat];
+         D.f[DIR_M0M  ] = &DD[DIR_P0P  *size_Mat];
+         D.f[DIR_P0P  ] = &DD[DIR_M0M  *size_Mat];
+         D.f[DIR_M0P  ] = &DD[DIR_P0M  *size_Mat];
+         D.f[DIR_P0M  ] = &DD[DIR_M0P  *size_Mat];
+         D.f[DIR_0MM  ] = &DD[DIR_0PP  *size_Mat];
+         D.f[DIR_0PP  ] = &DD[DIR_0MM  *size_Mat];
+         D.f[DIR_0MP  ] = &DD[DIR_0PM  *size_Mat];
+         D.f[DIR_0PM  ] = &DD[DIR_0MP  *size_Mat];
+         D.f[DIR_000] = &DD[DIR_000*size_Mat];
+         D.f[DIR_PPP ] = &DD[DIR_MMM *size_Mat];
+         D.f[DIR_MMP ] = &DD[DIR_PPM *size_Mat];
+         D.f[DIR_PMP ] = &DD[DIR_MPM *size_Mat];
+         D.f[DIR_MPP ] = &DD[DIR_PMM *size_Mat];
+         D.f[DIR_PPM ] = &DD[DIR_MMP *size_Mat];
+         D.f[DIR_MMM ] = &DD[DIR_PPP *size_Mat];
+         D.f[DIR_PMM ] = &DD[DIR_MPP *size_Mat];
+         D.f[DIR_MPM ] = &DD[DIR_PMP *size_Mat];
+      }
+      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+      real f_E_in,  f_W_in,  f_N_in,  f_S_in,  f_T_in,  f_B_in,   f_NE_in,  f_SW_in,  f_SE_in,  f_NW_in,  f_TE_in,  f_BW_in,  f_BE_in,
+         f_TW_in, f_TN_in, f_BS_in, f_BN_in, f_TS_in, f_TNE_in, f_TSW_in, f_TSE_in, f_TNW_in, f_BNE_in, f_BSW_in, f_BSE_in, f_BNW_in;
+
+      // momentum exchanged with wall at rest
+      real wallMomentumX = 0.0, wallMomentumY = 0.0, wallMomentumZ = 0.0;
+
+      real q;
+      q = q_dirE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_W_in=f_E - c2o27 * drho;
+         wallMomentumX += f_E+f_W_in;
+      }
+
+      q = q_dirW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_E_in=f_W - c2o27 * drho;
+          wallMomentumX -= f_W+f_E_in;
+      }
+
+      q = q_dirN[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_S_in=f_N - c2o27 * drho;
+         wallMomentumY += f_N+f_S_in;
+      }
+
+      q = q_dirS[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_N_in=f_S - c2o27 * drho;
+         wallMomentumY -= f_S+f_N_in;
+      }
+
+      q = q_dirT[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_B_in=f_T - c2o27 * drho;
+         wallMomentumZ += f_T+f_B_in;
+      }
+
+      q = q_dirB[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_T_in=f_B - c2o27 * drho;
+         wallMomentumZ -= f_B+f_T_in;
+      }
+
+      q = q_dirNE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_SW_in=f_NE - c1o54 * drho;
+         wallMomentumX += f_NE+f_SW_in;
+         wallMomentumY += f_NE+f_SW_in;
+      }
+
+      q = q_dirSW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_NE_in=f_SW - c1o54 * drho;
+         wallMomentumX -= f_SW+f_NE_in;
+         wallMomentumY -= f_SW+f_NE_in;
+      }
+
+      q = q_dirSE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_NW_in=f_SE - c1o54 * drho;
+         wallMomentumX += f_SE+f_NW_in;
+         wallMomentumY -= f_SE+f_NW_in;
+      }
+
+      q = q_dirNW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_SE_in=f_NW - c1o54 * drho;
+         wallMomentumX -= f_NW+f_SE_in;
+         wallMomentumY += f_NW+f_SE_in;
+      }
+
+      q = q_dirTE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BW_in=f_TE - c1o54 * drho;
+         wallMomentumX += f_TE+f_BW_in;
+         wallMomentumZ += f_TE+f_BW_in;
+      }
+
+      q = q_dirBW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TE_in=f_BW - c1o54 * drho;
+         wallMomentumX -= f_BW+f_TE_in;
+         wallMomentumZ -= f_BW+f_TE_in;
+      }
+
+      q = q_dirBE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TW_in=f_BE - c1o54 * drho;
+         wallMomentumX += f_BE+f_TW_in;
+         wallMomentumZ -= f_BE+f_TW_in;
+      }
+
+      q = q_dirTW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BE_in=f_TW - c1o54 * drho;
+         wallMomentumX -= f_TW+f_BE_in;
+         wallMomentumZ += f_TW+f_BE_in;
+      }
+
+      q = q_dirTN[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BS_in=f_TN - c1o54 * drho;
+         wallMomentumY += f_TN+f_BS_in;
+         wallMomentumZ += f_TN+f_BS_in;
+      }
+
+      q = q_dirBS[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TN_in=f_BS - c1o54 * drho;
+         wallMomentumY -= f_BS+f_TN_in;
+         wallMomentumZ -= f_BS+f_TN_in;
+      }
+
+      q = q_dirBN[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TS_in=f_BN - c1o54 * drho;
+         wallMomentumY += f_BN+f_TS_in;
+         wallMomentumZ -= f_BN+f_TS_in;
+      }
+
+      q = q_dirTS[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BN_in=f_TS - c1o54 * drho;
+         wallMomentumY -= f_TS+f_BN_in;
+         wallMomentumZ += f_TS+f_BN_in;
+      }
+
+      q = q_dirTNE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BSW_in=f_TNE - c1o216 * drho;
+         wallMomentumX += f_TNE+f_BSW_in;
+         wallMomentumY += f_TNE+f_BSW_in;
+         wallMomentumZ += f_TNE+f_BSW_in;
+      }
+
+      q = q_dirBSW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TNE_in=f_BSW - c1o216 * drho;
+         wallMomentumX -= f_BSW+f_TNE_in;
+         wallMomentumY -= f_BSW+f_TNE_in;
+         wallMomentumZ -= f_BSW+f_TNE_in;
+      }
+
+      q = q_dirBNE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TSW_in=f_BNE - c1o216 * drho;
+         wallMomentumX += f_BNE+f_TSW_in;
+         wallMomentumY += f_BNE+f_TSW_in;
+         wallMomentumZ -= f_BNE+f_TSW_in;
+      }
+
+      q = q_dirTSW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BNE_in=f_TSW - c1o216 * drho;
+         wallMomentumX -= f_TSW+f_BNE_in;
+         wallMomentumY -= f_TSW+f_BNE_in;
+         wallMomentumZ += f_TSW+f_BNE_in;
+      }
+
+      q = q_dirTSE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BNW_in=f_TSE - c1o216 * drho;
+         wallMomentumX += f_TSE+f_BNW_in;
+         wallMomentumY -= f_TSE+f_BNW_in;
+         wallMomentumZ += f_TSE+f_BNW_in;
+      }
+
+      q = q_dirBNW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TSE_in=f_BNW - c1o216 * drho;
+         wallMomentumX -= f_BNW+f_TSE_in;
+         wallMomentumY += f_BNW+f_TSE_in;
+         wallMomentumZ -= f_BNW+f_TSE_in;
+      }
+
+      q = q_dirBSE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_TNW_in=f_BSE - c1o216 * drho;
+         wallMomentumX += f_BSE+f_TNW_in;
+         wallMomentumY -= f_BSE+f_TNW_in;
+         wallMomentumZ -= f_BSE+f_TNW_in;
+      }
+
+      q = q_dirTNW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         f_BSE_in=f_TNW - c1o216 * drho;
+         wallMomentumX -= f_TNW+f_BSE_in;
+         wallMomentumY += f_TNW+f_BSE_in;
+         wallMomentumZ += f_TNW+f_BSE_in;
+      }
+
+      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+      // //Compute wall velocity
+      // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+      real VeloX=0.0, VeloY=0.0, VeloZ=0.0;
+
+      q = 0.5f;
+      real eps = 0.001f;
+
+      iMEM( k, k_N[k],
+         normalX, normalY, normalZ,
+         vx, vy, vz,
+         vx_el,      vy_el,      vz_el,
+         vx_w_mean,  vy_w_mean,  vz_w_mean,
+         vx1,        vx2,        vx3,
+         c1o1+drho,
+         samplingOffset,
+         q,
+         1.0,
+         eps,
+         z0,
+         hasWallModelMonitor,
+         u_star_monitor,
+         wallMomentumX, wallMomentumY, wallMomentumZ,
+         VeloX, VeloY, VeloZ);
+
+      // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+      // //Add wall velocity and write f's
+      // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+      q = q_dirE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_M00])[kw] = f_W_in - (c6o1*c2o27*( VeloX     ));
+         wallMomentumX += -(c6o1*c2o27*( VeloX     ));
+      }
+
+      q = q_dirW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_P00])[ke] = f_E_in - (c6o1*c2o27*(-VeloX     ));
+         wallMomentumX -= - (c6o1*c2o27*(-VeloX     ));
+      }
+
+      q = q_dirN[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_0M0])[ks] = f_S_in - (c6o1*c2o27*( VeloY     ));
+         wallMomentumY += - (c6o1*c2o27*( VeloY     ));
+      }
+
+      q = q_dirS[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_0P0])[kn] = f_N_in - (c6o1*c2o27*(-VeloY     ));
+         wallMomentumY -=  -(c6o1*c2o27*(-VeloY     ));
+      }
+
+      q = q_dirT[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_00M])[kb] = f_B_in - (c6o1*c2o27*( VeloZ     ));
+         wallMomentumZ += - (c6o1*c2o27*( VeloZ     ));
+      }
+
+      q = q_dirB[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_00P])[kt] = f_T_in - (c6o1*c2o27*(-VeloZ     ));
+         wallMomentumZ -= -(c6o1*c2o27*(-VeloZ     ));
+      }
+
+      q = q_dirNE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_MM0])[ksw] = f_SW_in - (c6o1*c1o54*(VeloX+VeloY));
+         wallMomentumX +=  -(c6o1*c1o54*(VeloX+VeloY));
+         wallMomentumY +=  -(c6o1*c1o54*(VeloX+VeloY));
+      }
+
+      q = q_dirSW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_PP0])[kne] = f_NE_in - (c6o1*c1o54*(-VeloX-VeloY));
+         wallMomentumX -= - (c6o1*c1o54*(-VeloX-VeloY));
+         wallMomentumY -= - (c6o1*c1o54*(-VeloX-VeloY));
+      }
+
+      q = q_dirSE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_MP0])[knw] = f_NW_in - (c6o1*c1o54*( VeloX-VeloY));
+         wallMomentumX += -(c6o1*c1o54*( VeloX-VeloY));
+         wallMomentumY -= -(c6o1*c1o54*( VeloX-VeloY));
+      }
+
+      q = q_dirNW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_PM0])[kse] = f_SE_in - (c6o1*c1o54*(-VeloX+VeloY));
+         wallMomentumX -= - (c6o1*c1o54*(-VeloX+VeloY));
+         wallMomentumY += - (c6o1*c1o54*(-VeloX+VeloY));
+      }
+
+      q = q_dirTE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_M0M])[kbw] = f_BW_in - (c6o1*c1o54*( VeloX+VeloZ));
+         wallMomentumX += - (c6o1*c1o54*( VeloX+VeloZ));
+         wallMomentumZ += - (c6o1*c1o54*( VeloX+VeloZ));
+      }
+
+      q = q_dirBW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_P0P])[kte] = f_TE_in - (c6o1*c1o54*(-VeloX-VeloZ));
+         wallMomentumX -= - (c6o1*c1o54*(-VeloX-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o54*(-VeloX-VeloZ));
+      }
+
+      q = q_dirBE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_M0P])[ktw] = f_TW_in - (c6o1*c1o54*( VeloX-VeloZ));
+         wallMomentumX += - (c6o1*c1o54*( VeloX-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o54*( VeloX-VeloZ));
+      }
+
+      q = q_dirTW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_P0M])[kbe] = f_BE_in - (c6o1*c1o54*(-VeloX+VeloZ));
+         wallMomentumX -= - (c6o1*c1o54*(-VeloX+VeloZ));
+         wallMomentumZ += - (c6o1*c1o54*(-VeloX+VeloZ));
+      }
+
+      q = q_dirTN[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_0MM])[kbs] = f_BS_in - (c6o1*c1o54*( VeloY+VeloZ));
+         wallMomentumY += - (c6o1*c1o54*( VeloY+VeloZ));
+         wallMomentumZ += - (c6o1*c1o54*( VeloY+VeloZ));
+      }
+
+      q = q_dirBS[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_0PP])[ktn] = f_TN_in - (c6o1*c1o54*( -VeloY-VeloZ));
+         wallMomentumY -= - (c6o1*c1o54*( -VeloY-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o54*( -VeloY-VeloZ));
+      }
+
+      q = q_dirBN[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_0MP])[kts] = f_TS_in - (c6o1*c1o54*( VeloY-VeloZ));
+         wallMomentumY += - (c6o1*c1o54*( VeloY-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o54*( VeloY-VeloZ));
+      }
+
+      q = q_dirTS[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_0PM])[kbn] = f_BN_in - (c6o1*c1o54*( -VeloY+VeloZ));
+         wallMomentumY -= - (c6o1*c1o54*( -VeloY+VeloZ));
+         wallMomentumZ += - (c6o1*c1o54*( -VeloY+VeloZ));
+      }
+
+      q = q_dirTNE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_MMM])[kbsw] = f_BSW_in - (c6o1*c1o216*( VeloX+VeloY+VeloZ));
+         wallMomentumX += - (c6o1*c1o216*( VeloX+VeloY+VeloZ));
+         wallMomentumY += - (c6o1*c1o216*( VeloX+VeloY+VeloZ));
+         wallMomentumZ += - (c6o1*c1o216*( VeloX+VeloY+VeloZ));
+      }
+
+      q = q_dirBSW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_PPP])[ktne] = f_TNE_in - (c6o1*c1o216*(-VeloX-VeloY-VeloZ));
+         wallMomentumX -= - (c6o1*c1o216*(-VeloX-VeloY-VeloZ));
+         wallMomentumY -= - (c6o1*c1o216*(-VeloX-VeloY-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o216*(-VeloX-VeloY-VeloZ));
+      }
+
+      q = q_dirBNE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_MMP])[ktsw] = f_TSW_in - (c6o1*c1o216*( VeloX+VeloY-VeloZ));
+         wallMomentumX += - (c6o1*c1o216*( VeloX+VeloY-VeloZ));
+         wallMomentumY += - (c6o1*c1o216*( VeloX+VeloY-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o216*( VeloX+VeloY-VeloZ));
+      }
+
+      q = q_dirTSW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_PPM])[kbne] = f_BNE_in - (c6o1*c1o216*(-VeloX-VeloY+VeloZ));
+         wallMomentumX -= - (c6o1*c1o216*(-VeloX-VeloY+VeloZ));
+         wallMomentumY -= - (c6o1*c1o216*(-VeloX-VeloY+VeloZ));
+         wallMomentumZ += - (c6o1*c1o216*(-VeloX-VeloY+VeloZ));
+      }
+
+      q = q_dirTSE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_MPM])[kbnw] = f_BNW_in - (c6o1*c1o216*( VeloX-VeloY+VeloZ));
+         wallMomentumX += - (c6o1*c1o216*( VeloX-VeloY+VeloZ));
+         wallMomentumY -= - (c6o1*c1o216*( VeloX-VeloY+VeloZ));
+         wallMomentumZ += - (c6o1*c1o216*( VeloX-VeloY+VeloZ));
+      }
+
+      q = q_dirBNW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_PMP])[ktse] = f_TSE_in - (c6o1*c1o216*(-VeloX+VeloY-VeloZ));
+         wallMomentumX -= - (c6o1*c1o216*(-VeloX+VeloY-VeloZ));
+         wallMomentumY += - (c6o1*c1o216*(-VeloX+VeloY-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o216*(-VeloX+VeloY-VeloZ));
+      }
+
+      q = q_dirBSE[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_MPP])[ktnw] = f_TNW_in - (c6o1*c1o216*( VeloX-VeloY-VeloZ));
+         wallMomentumX += - (c6o1*c1o216*( VeloX-VeloY-VeloZ));
+         wallMomentumY -= - (c6o1*c1o216*( VeloX-VeloY-VeloZ));
+         wallMomentumZ -= - (c6o1*c1o216*( VeloX-VeloY-VeloZ));
+      }
+
+      q = q_dirTNW[k];
+      if (q>=c0o1 && q<=c1o1)
+      {
+         (D.f[DIR_PMM])[kbse] = f_BSE_in - (c6o1*c1o216*(-VeloX+VeloY+VeloZ));
+         wallMomentumX -= - (c6o1*c1o216*(-VeloX+VeloY+VeloZ));
+         wallMomentumY += - (c6o1*c1o216*(-VeloX+VeloY+VeloZ));
+         wallMomentumZ += - (c6o1*c1o216*(-VeloX+VeloY+VeloZ));
+      }
+
+      if(hasWallModelMonitor)
+      {
+         Fx_monitor[k] = wallMomentumX;
+         Fy_monitor[k] = wallMomentumY;
+         Fz_monitor[k] = wallMomentumZ;
+      }
+
+   }
+}
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosity.h b/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosity.h
deleted file mode 100644
index c0f104f408469ebb65bca5ada4c53ba9a6b13829..0000000000000000000000000000000000000000
--- a/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosity.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef TURBULENT_VISCOSITY_H_
-#define TURBULENT_VISCOSITY_H_
-
-#include "Core/DataTypes.h"
-
-class Parameter;
-
-void calcTurbulentViscosityAMD(Parameter* para, int level);
-
-#endif //TURBULENT_VISCOSITY_H_
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityInlines.cuh b/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityInlines.cuh
new file mode 100644
index 0000000000000000000000000000000000000000..eb301515527a9e8a3056676b0d4dffe8197c7dbe
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityInlines.cuh
@@ -0,0 +1,61 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __         
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
+//      \    \  |    |   ________________________________________________________________    
+//       \    \ |    |  |  ______________________________________________________________|   
+//        \    \|    |  |  |         __          __     __     __     ______      _______    
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can 
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of 
+//  the License, or (at your option) any later version.
+//  
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT 
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+//  for more details.
+//  
+//  You should have received a copy of the GNU General Public License along
+//  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file TurbulentViscosity.h
+//! \ingroup GPU
+//! \author Henry Korb, Henrik Asmuth
+//======================================================================================
+
+#ifndef TURBULENT_VISCOSITY_INLINES_CUH_
+#define TURBULENT_VISCOSITY_INLINES_CUH_
+
+#include <cuda.h>
+#include <cuda_runtime.h>
+
+#include "LBM/LB.h" 
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
+
+__inline__ __device__ real calcTurbulentViscositySmagorinsky(real Cs, real dxux, real dyuy, real dzuz, real Dxy, real Dxz , real Dyz)
+{
+    return Cs*Cs * sqrt( c2o1 * ( dxux*dxux + dyuy*dyuy + dzuz*dzuz ) + Dxy*Dxy + Dxz*Dxz + Dyz*Dyz );
+}
+
+__inline__ __device__ real calcTurbulentViscosityQR(real C, real dxux, real dyuy, real dzuz, real Dxy, real Dxz , real Dyz)
+{
+        // ! Verstappen's QR model
+        //! Second invariant of the strain-rate tensor
+        real Q = c1o2*( dxux*dxux + dyuy*dyuy + dzuz*dzuz ) + c1o4*( Dxy*Dxy + Dxz*Dxz + Dyz*Dyz);
+        //! Third invariant of the strain-rate tensor (determinant)
+        real R = - dxux*dyuy*dzuz - c1o4*( Dxy*Dxz*Dyz + dxux*Dyz*Dyz + dyuy*Dxz*Dxz + dzuz*Dxy*Dxy );
+        
+        return C * max(R, c0o1) / Q;
+}
+
+#endif //TURBULENT_VISCOSITY_H_e
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosity.cu b/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityKernels.cu
similarity index 61%
rename from src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosity.cu
rename to src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityKernels.cu
index ed7a199e414709c6a3beff69374989fef2884dc2..3719ca3712e6f63a77f62bf314af7d19eea01f4c 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosity.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityKernels.cu
@@ -1,4 +1,37 @@
-#include "TurbulentViscosity.h"
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __         
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
+//      \    \  |    |   ________________________________________________________________    
+//       \    \ |    |  |  ______________________________________________________________|   
+//        \    \|    |  |  |         __          __     __     __     ______      _______    
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can 
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of 
+//  the License, or (at your option) any later version.
+//  
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT 
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+//  for more details.
+//  
+//  You should have received a copy of the GNU General Public License along
+//  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file TurbulentViscosityKernels.cu
+//! \ingroup GPU
+//! \author Henry Korb, Henrik Asmuth
+//======================================================================================
+
+#include "TurbulentViscosityKernels.h"
 #include "lbm/constants/NumericConstants.h"
 #include "Parameter/Parameter.h"
 #include "cuda/CudaGrid.h"
@@ -89,5 +122,4 @@ void calcTurbulentViscosityAMD(Parameter* para, int level)
         para->getSGSConstant()
     );
     getLastCudaError("calcAMD execution failed");
-}
-    
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityKernels.h b/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityKernels.h
new file mode 100644
index 0000000000000000000000000000000000000000..b227e680301cd4639d48a5cf3ce74f08eb7e1b9f
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/GPU/TurbulentViscosityKernels.h
@@ -0,0 +1,52 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __         
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
+//      \    \  |    |   ________________________________________________________________    
+//       \    \ |    |  |  ______________________________________________________________|   
+//        \    \|    |  |  |         __          __     __     __     ______      _______    
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can 
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of 
+//  the License, or (at your option) any later version.
+//  
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT 
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+//  for more details.
+//  
+//  You should have received a copy of the GNU General Public License along
+//  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file TurbulentViscosityKernels.h
+//! \ingroup GPU
+//! \author Henry Korb, Henrik Asmuth
+//======================================================================================
+
+#ifndef TURBULENT_VISCOSITY_KERNELS_H_
+#define TURBULENT_VISCOSITY_KERNELS_H_
+
+#include <cuda.h>
+#include <cuda_runtime.h>
+
+#include "LBM/LB.h" 
+#include "Core/DataTypes.h"
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
+
+class Parameter;
+
+void calcTurbulentViscosityAMD(Parameter* para, int level);
+
+
+
+#endif //TURBULENT_VISCOSITY_H_e
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.cu b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.cu
index c1be283f7fb0e5585c28bdaf5e4519f468c32c8f..a9d518d14a286ae3f6b565176969162994afa269 100644
--- a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.cu
+++ b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.cu
@@ -1,42 +1,46 @@
 #include "TurbulentViscosityCumulantK17CompChim.h"
 #include "cuda/CudaGrid.h"
+#include <logger/Logger.h>
 #include "Parameter/Parameter.h"
 #include "TurbulentViscosityCumulantK17CompChim_Device.cuh"
 
-std::shared_ptr<TurbulentViscosityCumulantK17CompChim> TurbulentViscosityCumulantK17CompChim::getNewInstance(std::shared_ptr<Parameter> para, int level)
+template<TurbulenceModel turbulenceModel> 
+std::shared_ptr< TurbulentViscosityCumulantK17CompChim<turbulenceModel> > TurbulentViscosityCumulantK17CompChim<turbulenceModel>::getNewInstance(std::shared_ptr<Parameter> para, int level)
 {
-	return std::shared_ptr<TurbulentViscosityCumulantK17CompChim>(new TurbulentViscosityCumulantK17CompChim(para,level));
+	return std::shared_ptr<TurbulentViscosityCumulantK17CompChim<turbulenceModel> >(new TurbulentViscosityCumulantK17CompChim<turbulenceModel>(para,level));
 }
 
-void TurbulentViscosityCumulantK17CompChim::run()
+template<TurbulenceModel turbulenceModel>
+void TurbulentViscosityCumulantK17CompChim<turbulenceModel>::run()
 {
 	vf::cuda::CudaGrid grid = vf::cuda::CudaGrid(para->getParH(level)->numberofthreads, para->getParH(level)->numberOfNodes);
 
-	LB_Kernel_TurbulentViscosityCumulantK17CompChim <<< grid.grid, grid.threads >>>(
-		para->getParD(level)->omega,
-		para->getParD(level)->typeOfGridNode,
-		para->getParD(level)->neighborX,
-		para->getParD(level)->neighborY,
-		para->getParD(level)->neighborZ,
-		para->getParD(level)->distributions.f[0],
-		para->getParD(level)->rho,
-		para->getParD(level)->velocityX,
-		para->getParD(level)->velocityY,
-		para->getParD(level)->velocityZ,
-		para->getParD(level)->turbViscosity,
-		(unsigned long)para->getParD(level)->numberOfNodes,
-		level,
-		para->getIsBodyForce(),
-		para->getForcesDev(),
-		para->getParD(level)->forceX_SP,
-		para->getParD(level)->forceY_SP,
-		para->getParD(level)->forceZ_SP,
-        para->getQuadricLimitersDev(),
-		para->getParD(level)->isEvenTimestep);
+	LB_Kernel_TurbulentViscosityCumulantK17CompChim < turbulenceModel  > <<< grid.grid, grid.threads >>>(   para->getParD(level)->omega, 	
+																											para->getParD(level)->typeOfGridNode, 										para->getParD(level)->neighborX,	
+																											para->getParD(level)->neighborY,	
+																											para->getParD(level)->neighborZ,	
+																											para->getParD(level)->distributions.f[0],	
+																											para->getParD(level)->rho,		
+																											para->getParD(level)->velocityX,		
+																											para->getParD(level)->velocityY,	
+																											para->getParD(level)->velocityZ,	
+																											para->getParD(level)->turbViscosity,
+																											para->getSGSConstant(),
+																											(unsigned long)para->getParD(level)->numberOfNodes,	
+																											level,				
+																											para->getIsBodyForce(),				
+																											para->getForcesDev(),				
+																											para->getParD(level)->forceX_SP,	
+																											para->getParD(level)->forceY_SP,
+																											para->getParD(level)->forceZ_SP,
+																											para->getQuadricLimitersDev(),			
+																											para->getParD(level)->isEvenTimestep);
+
 	getLastCudaError("LB_Kernel_TurbulentViscosityCumulantK17CompChim execution failed");
 }
 
-TurbulentViscosityCumulantK17CompChim::TurbulentViscosityCumulantK17CompChim(std::shared_ptr<Parameter> para, int level)
+template<TurbulenceModel turbulenceModel>
+TurbulentViscosityCumulantK17CompChim<turbulenceModel>::TurbulentViscosityCumulantK17CompChim(std::shared_ptr<Parameter> para, int level)
 {
 	this->para = para;
 	this->level = level;
@@ -44,4 +48,10 @@ TurbulentViscosityCumulantK17CompChim::TurbulentViscosityCumulantK17CompChim(std
 	myPreProcessorTypes.push_back(InitCompSP27);
 
 	myKernelGroup = BasicKernel;
-}
\ No newline at end of file
+
+	VF_LOG_INFO("Using turbulence model: {}", turbulenceModel);
+}
+
+template class TurbulentViscosityCumulantK17CompChim<TurbulenceModel::AMD>;
+template class TurbulentViscosityCumulantK17CompChim<TurbulenceModel::Smagorinsky>;
+template class TurbulentViscosityCumulantK17CompChim<TurbulenceModel::QR>;
diff --git a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.h b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.h
index d107700e59d657dc6da656037638a407ed0499a3..0d35b68c916e54c6ec6eeeacd7189fe4d9a33c10 100644
--- a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.h
+++ b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim.h
@@ -2,11 +2,13 @@
 #define TurbulentViscosityCUMULANT_K17_COMP_CHIM_H
 
 #include "Kernel/KernelImp.h"
+#include "Parameter/Parameter.h"
 
+template<TurbulenceModel turbulenceModel> 
 class TurbulentViscosityCumulantK17CompChim : public KernelImp
 {
 public:
-	static std::shared_ptr<TurbulentViscosityCumulantK17CompChim> getNewInstance(std::shared_ptr< Parameter> para, int level);
+	static std::shared_ptr< TurbulentViscosityCumulantK17CompChim<turbulenceModel> > getNewInstance(std::shared_ptr< Parameter> para, int level);
 	void run();
 
 private:
diff --git a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cu b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cu
index b7ff059192ef09623543fb009a2538a361577f35..afab2fba994738fdc7fb509a7611df52be722abf 100644
--- a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cu
+++ b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cu
@@ -42,6 +42,9 @@
 #include "LBM/LB.h" 
 #include "lbm/constants/D3Q27.h"
 #include <lbm/constants/NumericConstants.h>
+#include "Kernel/Utilities/DistributionHelper.cuh"
+
+#include "GPU/TurbulentViscosityInlines.cuh"
 
 using namespace vf::lbm::constant;
 using namespace vf::lbm::dir;
@@ -49,6 +52,7 @@ using namespace vf::lbm::dir;
 
 
 ////////////////////////////////////////////////////////////////////////////////
+template<TurbulenceModel turbulenceModel>
 __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
 	real omega_in,
 	uint* typeOfGridNode,
@@ -61,6 +65,7 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
     real* vy,
     real* vz,
     real* turbulentViscosity,
+    real SGSconstant,
 	unsigned long size_Mat,
 	int level,
     bool bodyForce,
@@ -82,144 +87,112 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
     ////////////////////////////////////////////////////////////////////////////////
     //! - Get node index coordinates from threadIdx, blockIdx, blockDim and gridDim.
     //!
-    const unsigned x = threadIdx.x;
-    const unsigned y = blockIdx.x;
-    const unsigned z = blockIdx.y;
-
-    const unsigned nx = blockDim.x;
-    const unsigned ny = gridDim.x;
-
-    const unsigned k = nx * (ny * z + y) + x;
+    const unsigned k_000 = vf::gpu::getNodeIndex();
 
     //////////////////////////////////////////////////////////////////////////
     // run for all indices in size_Mat and fluid nodes
-    if ((k < size_Mat) && (typeOfGridNode[k] == GEO_FLUID)) {
+    if ((k_000 < size_Mat) && (typeOfGridNode[k_000] == GEO_FLUID)) {
         //////////////////////////////////////////////////////////////////////////
         //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on
         //! timestep is based on the esoteric twist algorithm \ref <a
         //! href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
         //! DOI:10.3390/computation5020019 ]</b></a>
         //!
-        Distributions27 dist;
-        if (isEvenTimestep) {
-            dist.f[DIR_P00]    = &distributions[DIR_P00 * size_Mat];
-            dist.f[DIR_M00]    = &distributions[DIR_M00 * size_Mat];
-            dist.f[DIR_0P0]    = &distributions[DIR_0P0 * size_Mat];
-            dist.f[DIR_0M0]    = &distributions[DIR_0M0 * size_Mat];
-            dist.f[DIR_00P]    = &distributions[DIR_00P * size_Mat];
-            dist.f[DIR_00M]    = &distributions[DIR_00M * size_Mat];
-            dist.f[DIR_PP0]   = &distributions[DIR_PP0 * size_Mat];
-            dist.f[DIR_MM0]   = &distributions[DIR_MM0 * size_Mat];
-            dist.f[DIR_PM0]   = &distributions[DIR_PM0 * size_Mat];
-            dist.f[DIR_MP0]   = &distributions[DIR_MP0 * size_Mat];
-            dist.f[DIR_P0P]   = &distributions[DIR_P0P * size_Mat];
-            dist.f[DIR_M0M]   = &distributions[DIR_M0M * size_Mat];
-            dist.f[DIR_P0M]   = &distributions[DIR_P0M * size_Mat];
-            dist.f[DIR_M0P]   = &distributions[DIR_M0P * size_Mat];
-            dist.f[DIR_0PP]   = &distributions[DIR_0PP * size_Mat];
-            dist.f[DIR_0MM]   = &distributions[DIR_0MM * size_Mat];
-            dist.f[DIR_0PM]   = &distributions[DIR_0PM * size_Mat];
-            dist.f[DIR_0MP]   = &distributions[DIR_0MP * size_Mat];
-            dist.f[DIR_000] = &distributions[DIR_000 * size_Mat];
-            dist.f[DIR_PPP]  = &distributions[DIR_PPP * size_Mat];
-            dist.f[DIR_MMP]  = &distributions[DIR_MMP * size_Mat];
-            dist.f[DIR_PMP]  = &distributions[DIR_PMP * size_Mat];
-            dist.f[DIR_MPP]  = &distributions[DIR_MPP * size_Mat];
-            dist.f[DIR_PPM]  = &distributions[DIR_PPM * size_Mat];
-            dist.f[DIR_MMM]  = &distributions[DIR_MMM * size_Mat];
-            dist.f[DIR_PMM]  = &distributions[DIR_PMM * size_Mat];
-            dist.f[DIR_MPM]  = &distributions[DIR_MPM * size_Mat];
-        } else {
-            dist.f[DIR_M00]    = &distributions[DIR_P00 * size_Mat];
-            dist.f[DIR_P00]    = &distributions[DIR_M00 * size_Mat];
-            dist.f[DIR_0M0]    = &distributions[DIR_0P0 * size_Mat];
-            dist.f[DIR_0P0]    = &distributions[DIR_0M0 * size_Mat];
-            dist.f[DIR_00M]    = &distributions[DIR_00P * size_Mat];
-            dist.f[DIR_00P]    = &distributions[DIR_00M * size_Mat];
-            dist.f[DIR_MM0]   = &distributions[DIR_PP0 * size_Mat];
-            dist.f[DIR_PP0]   = &distributions[DIR_MM0 * size_Mat];
-            dist.f[DIR_MP0]   = &distributions[DIR_PM0 * size_Mat];
-            dist.f[DIR_PM0]   = &distributions[DIR_MP0 * size_Mat];
-            dist.f[DIR_M0M]   = &distributions[DIR_P0P * size_Mat];
-            dist.f[DIR_P0P]   = &distributions[DIR_M0M * size_Mat];
-            dist.f[DIR_M0P]   = &distributions[DIR_P0M * size_Mat];
-            dist.f[DIR_P0M]   = &distributions[DIR_M0P * size_Mat];
-            dist.f[DIR_0MM]   = &distributions[DIR_0PP * size_Mat];
-            dist.f[DIR_0PP]   = &distributions[DIR_0MM * size_Mat];
-            dist.f[DIR_0MP]   = &distributions[DIR_0PM * size_Mat];
-            dist.f[DIR_0PM]   = &distributions[DIR_0MP * size_Mat];
-            dist.f[DIR_000] = &distributions[DIR_000 * size_Mat];
-            dist.f[DIR_MMM]  = &distributions[DIR_PPP * size_Mat];
-            dist.f[DIR_PPM]  = &distributions[DIR_MMP * size_Mat];
-            dist.f[DIR_MPM]  = &distributions[DIR_PMP * size_Mat];
-            dist.f[DIR_PMM]  = &distributions[DIR_MPP * size_Mat];
-            dist.f[DIR_MMP]  = &distributions[DIR_PPM * size_Mat];
-            dist.f[DIR_PPP]  = &distributions[DIR_MMM * size_Mat];
-            dist.f[DIR_MPP]  = &distributions[DIR_PMM * size_Mat];
-            dist.f[DIR_PMP]  = &distributions[DIR_MPM * size_Mat];
-        }
+        Distributions27 dist = vf::gpu::getDistributionReferences27(distributions, size_Mat, isEvenTimestep);
+
         ////////////////////////////////////////////////////////////////////////////////
         //! - Set neighbor indices (necessary for indirect addressing)
-        uint kw   = neighborX[k];
-        uint ks   = neighborY[k];
-        uint kb   = neighborZ[k];
-        uint ksw  = neighborY[kw];
-        uint kbw  = neighborZ[kw];
-        uint kbs  = neighborZ[ks];
-        uint kbsw = neighborZ[ksw];
+        uint k_M00 = neighborX[k_000];
+        uint k_0M0 = neighborY[k_000];
+        uint k_00M = neighborZ[k_000];
+        uint k_MM0 = neighborY[k_M00];
+        uint k_M0M = neighborZ[k_M00];
+        uint k_0MM = neighborZ[k_0M0];
+        uint k_MMM = neighborZ[k_MM0];
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Set local distributions
         //!
-        real mfcbb = (dist.f[DIR_P00])[k];
-        real mfabb = (dist.f[DIR_M00])[kw];
-        real mfbcb = (dist.f[DIR_0P0])[k];
-        real mfbab = (dist.f[DIR_0M0])[ks];
-        real mfbbc = (dist.f[DIR_00P])[k];
-        real mfbba = (dist.f[DIR_00M])[kb];
-        real mfccb = (dist.f[DIR_PP0])[k];
-        real mfaab = (dist.f[DIR_MM0])[ksw];
-        real mfcab = (dist.f[DIR_PM0])[ks];
-        real mfacb = (dist.f[DIR_MP0])[kw];
-        real mfcbc = (dist.f[DIR_P0P])[k];
-        real mfaba = (dist.f[DIR_M0M])[kbw];
-        real mfcba = (dist.f[DIR_P0M])[kb];
-        real mfabc = (dist.f[DIR_M0P])[kw];
-        real mfbcc = (dist.f[DIR_0PP])[k];
-        real mfbaa = (dist.f[DIR_0MM])[kbs];
-        real mfbca = (dist.f[DIR_0PM])[kb];
-        real mfbac = (dist.f[DIR_0MP])[ks];
-        real mfbbb = (dist.f[DIR_000])[k];
-        real mfccc = (dist.f[DIR_PPP])[k];
-        real mfaac = (dist.f[DIR_MMP])[ksw];
-        real mfcac = (dist.f[DIR_PMP])[ks];
-        real mfacc = (dist.f[DIR_MPP])[kw];
-        real mfcca = (dist.f[DIR_PPM])[kb];
-        real mfaaa = (dist.f[DIR_MMM])[kbsw];
-        real mfcaa = (dist.f[DIR_PMM])[kbs];
-        real mfaca = (dist.f[DIR_MPM])[kbw];
+        real f_000 = (dist.f[DIR_000])[k_000];
+        real f_P00 = (dist.f[DIR_P00])[k_000];
+        real f_M00 = (dist.f[DIR_M00])[k_M00];
+        real f_0P0 = (dist.f[DIR_0P0])[k_000];
+        real f_0M0 = (dist.f[DIR_0M0])[k_0M0];
+        real f_00P = (dist.f[DIR_00P])[k_000];
+        real f_00M = (dist.f[DIR_00M])[k_00M];
+        real f_PP0 = (dist.f[DIR_PP0])[k_000];
+        real f_MM0 = (dist.f[DIR_MM0])[k_MM0];
+        real f_PM0 = (dist.f[DIR_PM0])[k_0M0];
+        real f_MP0 = (dist.f[DIR_MP0])[k_M00];
+        real f_P0P = (dist.f[DIR_P0P])[k_000];
+        real f_M0M = (dist.f[DIR_M0M])[k_M0M];
+        real f_P0M = (dist.f[DIR_P0M])[k_00M];
+        real f_M0P = (dist.f[DIR_M0P])[k_M00];
+        real f_0PP = (dist.f[DIR_0PP])[k_000];
+        real f_0MM = (dist.f[DIR_0MM])[k_0MM];
+        real f_0PM = (dist.f[DIR_0PM])[k_00M];
+        real f_0MP = (dist.f[DIR_0MP])[k_0M0];
+        real f_PPP = (dist.f[DIR_PPP])[k_000];
+        real f_MPP = (dist.f[DIR_MPP])[k_M00];
+        real f_PMP = (dist.f[DIR_PMP])[k_0M0];
+        real f_MMP = (dist.f[DIR_MMP])[k_MM0];
+        real f_PPM = (dist.f[DIR_PPM])[k_00M];
+        real f_MPM = (dist.f[DIR_MPM])[k_M0M];
+        real f_PMM = (dist.f[DIR_PMM])[k_0MM];
+        real f_MMM = (dist.f[DIR_MMM])[k_MMM];
+
+        ////////////////////////////////////////////////////////////////////////////////////
+        //! - Define aliases to use the same variable for the moments (m's):
+        //!
+        real& m_111 = f_000;
+        real& m_211 = f_P00;
+        real& m_011 = f_M00;
+        real& m_121 = f_0P0;
+        real& m_101 = f_0M0;
+        real& m_112 = f_00P;
+        real& m_110 = f_00M;
+        real& m_221 = f_PP0;
+        real& m_001 = f_MM0;
+        real& m_201 = f_PM0;
+        real& m_021 = f_MP0;
+        real& m_212 = f_P0P;
+        real& m_010 = f_M0M;
+        real& m_210 = f_P0M;
+        real& m_012 = f_M0P;
+        real& m_122 = f_0PP;
+        real& m_100 = f_0MM;
+        real& m_120 = f_0PM;
+        real& m_102 = f_0MP;
+        real& m_222 = f_PPP;
+        real& m_022 = f_MPP;
+        real& m_202 = f_PMP;
+        real& m_002 = f_MMP;
+        real& m_220 = f_PPM;
+        real& m_020 = f_MPM;
+        real& m_200 = f_PMM;
+        real& m_000 = f_MMM;
+
         //////////////////////////////////////////////////////(unsigned long)//////////////////////////////
         //! - Calculate density and velocity using pyramid summation for low round-off errors as in Eq. (J1)-(J3) \ref
         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
         //!
-        real drho = ((((mfccc + mfaaa) + (mfaca + mfcac)) + ((mfacc + mfcaa) + (mfaac + mfcca))) +
-                     (((mfbac + mfbca) + (mfbaa + mfbcc)) + ((mfabc + mfcba) + (mfaba + mfcbc)) +
-                      ((mfacb + mfcab) + (mfaab + mfccb))) +
-                     ((mfabb + mfcbb) + (mfbab + mfbcb) + (mfbba + mfbbc))) +
-                    mfbbb;
-
-        real rrho   = c1o1 + drho;
-        real OOrho = c1o1 / rrho;
-
-        real vvx = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) +
-                    (((mfcba - mfabc) + (mfcbc - mfaba)) + ((mfcab - mfacb) + (mfccb - mfaab))) + (mfcbb - mfabb)) *
-                   OOrho;
-        real vvy = ((((mfccc - mfaaa) + (mfaca - mfcac)) + ((mfacc - mfcaa) + (mfcca - mfaac))) +
-                    (((mfbca - mfbac) + (mfbcc - mfbaa)) + ((mfacb - mfcab) + (mfccb - mfaab))) + (mfbcb - mfbab)) *
-                   OOrho;
-        real vvz = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfacc - mfcaa) + (mfaac - mfcca))) +
-                    (((mfbac - mfbca) + (mfbcc - mfbaa)) + ((mfabc - mfcba) + (mfcbc - mfaba))) + (mfbbc - mfbba)) *
-                   OOrho;
+        real drho = ((((f_PPP + f_MMM) + (f_MPM + f_PMP)) + ((f_MPP + f_PMM) + (f_MMP + f_PPM))) +
+                    (((f_0MP + f_0PM) + (f_0MM + f_0PP)) + ((f_M0P + f_P0M) + (f_M0M + f_P0P)) +
+                    ((f_MP0 + f_PM0) + (f_MM0 + f_PP0))) +
+                    ((f_M00 + f_P00) + (f_0M0 + f_0P0) + (f_00M + f_00P))) +
+                        f_000;
+
+        real oneOverRho = c1o1 / (c1o1 + drho);
+
+        real vvx = ((((f_PPP - f_MMM) + (f_PMP - f_MPM)) + ((f_PMM - f_MPP) + (f_PPM - f_MMP))) +
+                    (((f_P0M - f_M0P) + (f_P0P - f_M0M)) + ((f_PM0 - f_MP0) + (f_PP0 - f_MM0))) + (f_P00 - f_M00)) *
+                oneOverRho;
+        real vvy = ((((f_PPP - f_MMM) + (f_MPM - f_PMP)) + ((f_MPP - f_PMM) + (f_PPM - f_MMP))) +
+                    (((f_0PM - f_0MP) + (f_0PP - f_0MM)) + ((f_MP0 - f_PM0) + (f_PP0 - f_MM0))) + (f_0P0 - f_0M0)) *
+                oneOverRho;
+        real vvz = ((((f_PPP - f_MMM) + (f_PMP - f_MPM)) + ((f_MPP - f_PMM) + (f_MMP - f_PPM))) +
+                    (((f_0MP - f_0PM) + (f_0PP - f_0MM)) + ((f_M0P - f_P0M) + (f_P0P - f_M0M))) + (f_00P - f_00M)) *
+                oneOverRho;
         
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Add half of the acceleration (body force) to the velocity as in Eq. (42) \ref
@@ -236,9 +209,9 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         real fz = forces[2];
 
         if( bodyForce ){
-            fx += bodyForceX[k]; 
-            fy += bodyForceY[k];
-            fz += bodyForceZ[k];
+            fx += bodyForceX[k_000]; 
+            fy += bodyForceY[k_000];
+            fz += bodyForceZ[k_000];
 
             real vx = vvx;
             real vy = vvy;
@@ -265,9 +238,9 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
             //!> differ by several orders of magnitude.
             //!> \note 16/05/2022: Testing, still ongoing! 
             //!
-            bodyForceX[k] = (acc_x-(vvx-vx))*factor*c2o1;
-            bodyForceY[k] = (acc_y-(vvy-vy))*factor*c2o1;
-            bodyForceZ[k] = (acc_z-(vvz-vz))*factor*c2o1;
+            bodyForceX[k_000] = (acc_x-(vvx-vx))*factor*c2o1;
+            bodyForceY[k_000] = (acc_y-(vvy-vy))*factor*c2o1;
+            bodyForceZ[k_000] = (acc_z-(vvz-vz))*factor*c2o1;
         }
         else{
             vvx += fx * c1o2 / factor;
@@ -286,10 +259,9 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //! section 6 in \ref <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
         //!
-        real wadjust;
-        real qudricLimitP = quadricLimiters[0];
-        real qudricLimitM = quadricLimiters[1];
-        real qudricLimitD = quadricLimiters[2];
+        real quadricLimitP = quadricLimiters[0];
+        real quadricLimitM = quadricLimiters[1];
+        real quadricLimitD = quadricLimiters[2];
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Chimera transform from well conditioned distributions to central moments as defined in Appendix J in \ref
         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
@@ -299,39 +271,39 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //!
         ////////////////////////////////////////////////////////////////////////////////////
         // Z - Dir
-        forwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36o1, c1o36);
-        forwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9o1, c1o9);
-        forwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36o1, c1o36);
-        forwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9o1, c1o9);
-        forwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9);
-        forwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9o1, c1o9);
-        forwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36o1, c1o36);
-        forwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9o1, c1o9);
-        forwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);
+        forwardInverseChimeraWithK(f_MMM, f_MM0, f_MMP, vvz, vz2, c36o1, c1o36);
+        forwardInverseChimeraWithK(f_M0M, f_M00, f_M0P, vvz, vz2, c9o1,  c1o9);
+        forwardInverseChimeraWithK(f_MPM, f_MP0, f_MPP, vvz, vz2, c36o1, c1o36);
+        forwardInverseChimeraWithK(f_0MM, f_0M0, f_0MP, vvz, vz2, c9o1,  c1o9);
+        forwardInverseChimeraWithK(f_00M, f_000, f_00P, vvz, vz2, c9o4,  c4o9);
+        forwardInverseChimeraWithK(f_0PM, f_0P0, f_0PP, vvz, vz2, c9o1,  c1o9);
+        forwardInverseChimeraWithK(f_PMM, f_PM0, f_PMP, vvz, vz2, c36o1, c1o36);
+        forwardInverseChimeraWithK(f_P0M, f_P00, f_P0P, vvz, vz2, c9o1,  c1o9);
+        forwardInverseChimeraWithK(f_PPM, f_PP0, f_PPP, vvz, vz2, c36o1, c1o36);
 
         ////////////////////////////////////////////////////////////////////////////////////
         // Y - Dir
-        forwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6o1, c1o6);
-        forwardChimera(mfaab, mfabb, mfacb, vvy, vy2);
-        forwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18o1, c1o18);
-        forwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3);
-        forwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2);
-        forwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9);
-        forwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6o1, c1o6);
-        forwardChimera(mfcab, mfcbb, mfccb, vvy, vy2);
-        forwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18o1, c1o18);
+        forwardInverseChimeraWithK(f_MMM, f_M0M, f_MPM, vvy, vy2, c6o1,  c1o6);
+        forwardChimera(            f_MM0, f_M00, f_MP0, vvy, vy2);
+        forwardInverseChimeraWithK(f_MMP, f_M0P, f_MPP, vvy, vy2, c18o1, c1o18);
+        forwardInverseChimeraWithK(f_0MM, f_00M, f_0PM, vvy, vy2, c3o2,  c2o3);
+        forwardChimera(            f_0M0, f_000, f_0P0, vvy, vy2);
+        forwardInverseChimeraWithK(f_0MP, f_00P, f_0PP, vvy, vy2, c9o2,  c2o9);
+        forwardInverseChimeraWithK(f_PMM, f_P0M, f_PPM, vvy, vy2, c6o1,  c1o6);
+        forwardChimera(            f_PM0, f_P00, f_PP0, vvy, vy2);
+        forwardInverseChimeraWithK(f_PMP, f_P0P, f_PPP, vvy, vy2, c18o1, c1o18);
 
         ////////////////////////////////////////////////////////////////////////////////////
         // X - Dir
-        forwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1o1, c1o1);
-        forwardChimera(mfaba, mfbba, mfcba, vvx, vx2);
-        forwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3o1, c1o3);
-        forwardChimera(mfaab, mfbab, mfcab, vvx, vx2);
-        forwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2);
-        forwardChimera(mfacb, mfbcb, mfccb, vvx, vx2);
-        forwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3o1, c1o3);
-        forwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2);
-        forwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c3o1, c1o9);
+        forwardInverseChimeraWithK(f_MMM, f_0MM, f_PMM, vvx, vx2, c1o1, c1o1);
+        forwardChimera(            f_M0M, f_00M, f_P0M, vvx, vx2);
+        forwardInverseChimeraWithK(f_MPM, f_0PM, f_PPM, vvx, vx2, c3o1, c1o3);
+        forwardChimera(            f_MM0, f_0M0, f_PM0, vvx, vx2);
+        forwardChimera(            f_M00, f_000, f_P00, vvx, vx2);
+        forwardChimera(            f_MP0, f_0P0, f_PP0, vvx, vx2);
+        forwardInverseChimeraWithK(f_MMP, f_0MP, f_PMP, vvx, vx2, c3o1, c1o3);
+        forwardChimera(            f_M0P, f_00P, f_P0P, vvx, vx2);
+        forwardInverseChimeraWithK(f_MPP, f_0PP, f_PPP, vvx, vx2, c3o1, c1o9);
 
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Setting relaxation rates for non-hydrodynamic cumulants (default values). Variable names and equations
@@ -354,7 +326,7 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Calculate modified omega with turbulent viscosity
         //!
-        real omega = omega_in / (c1o1 + c3o1*omega_in*turbulentViscosity[k]);
+        real omega = omega_in / (c1o1 + c3o1*omega_in*turbulentViscosity[k_000]);
         ////////////////////////////////////////////////////////////
         // 2.
         real OxxPyyPzz = c1o1;
@@ -391,63 +363,60 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //!
         ////////////////////////////////////////////////////////////
         // 4.
-        real CUMcbb = mfcbb - ((mfcaa + c1o3) * mfabb + c2o1 * mfbba * mfbab) * OOrho;
-        real CUMbcb = mfbcb - ((mfaca + c1o3) * mfbab + c2o1 * mfbba * mfabb) * OOrho;
-        real CUMbbc = mfbbc - ((mfaac + c1o3) * mfbba + c2o1 * mfbab * mfabb) * OOrho;
+        real c_211 = m_211 - ((m_200 + c1o3) * m_011 + c2o1 * m_110 * m_101) * oneOverRho;
+        real c_121 = m_121 - ((m_020 + c1o3) * m_101 + c2o1 * m_110 * m_011) * oneOverRho;
+        real c_112 = m_112 - ((m_002 + c1o3) * m_110 + c2o1 * m_101 * m_011) * oneOverRho;
 
-        real CUMcca =
-            mfcca - (((mfcaa * mfaca + c2o1 * mfbba * mfbba) + c1o3 * (mfcaa + mfaca)) * OOrho - c1o9 * (drho * OOrho));
-        real CUMcac =
-            mfcac - (((mfcaa * mfaac + c2o1 * mfbab * mfbab) + c1o3 * (mfcaa + mfaac)) * OOrho - c1o9 * (drho * OOrho));
-        real CUMacc =
-            mfacc - (((mfaac * mfaca + c2o1 * mfabb * mfabb) + c1o3 * (mfaac + mfaca)) * OOrho - c1o9 * (drho * OOrho));
+        real c_220 = m_220 - (((m_200 * m_020 + c2o1 * m_110 * m_110) + c1o3 * (m_200 + m_020)) * oneOverRho - c1o9 * (drho * oneOverRho));
+        real c_202 = m_202 - (((m_200 * m_002 + c2o1 * m_101 * m_101) + c1o3 * (m_200 + m_002)) * oneOverRho - c1o9 * (drho * oneOverRho));
+        real c_022 = m_022 - (((m_002 * m_020 + c2o1 * m_011 * m_011) + c1o3 * (m_002 + m_020)) * oneOverRho - c1o9 * (drho * oneOverRho));
         ////////////////////////////////////////////////////////////
         // 5.
-        real CUMbcc =
-            mfbcc - ((mfaac * mfbca + mfaca * mfbac + c4o1 * mfabb * mfbbb + c2o1 * (mfbab * mfacb + mfbba * mfabc)) +
-                     c1o3 * (mfbca + mfbac)) *
-                        OOrho;
-        real CUMcbc =
-            mfcbc - ((mfaac * mfcba + mfcaa * mfabc + c4o1 * mfbab * mfbbb + c2o1 * (mfabb * mfcab + mfbba * mfbac)) +
-                     c1o3 * (mfcba + mfabc)) *
-                        OOrho;
-        real CUMccb =
-            mfccb - ((mfcaa * mfacb + mfaca * mfcab + c4o1 * mfbba * mfbbb + c2o1 * (mfbab * mfbca + mfabb * mfcba)) +
-                     c1o3 * (mfacb + mfcab)) *
-                        OOrho;
+        real c_122 =
+            m_122 - ((m_002 * m_120 + m_020 * m_102 + c4o1 * m_011 * m_111 + c2o1 * (m_101 * m_021 + m_110 * m_012)) +
+                    c1o3 * (m_120 + m_102)) *
+                    oneOverRho;
+        real c_212 =
+            m_212 - ((m_002 * m_210 + m_200 * m_012 + c4o1 * m_101 * m_111 + c2o1 * (m_011 * m_201 + m_110 * m_102)) +
+                    c1o3 * (m_210 + m_012)) *
+                    oneOverRho;
+        real c_221 =
+            m_221 - ((m_200 * m_021 + m_020 * m_201 + c4o1 * m_110 * m_111 + c2o1 * (m_101 * m_120 + m_011 * m_210)) +
+                    c1o3 * (m_021 + m_201)) *
+                    oneOverRho;
         ////////////////////////////////////////////////////////////
         // 6.
-        real CUMccc = mfccc + ((-c4o1 * mfbbb * mfbbb - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) -
-                                c4o1 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) -
-                                c2o1 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) *
-                                   OOrho +
-                               (c4o1 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) +
-                                c2o1 * (mfcaa * mfaca * mfaac) + c16o1 * mfbba * mfbab * mfabb) *
-                                   OOrho * OOrho -
-                               c1o3 * (mfacc + mfcac + mfcca) * OOrho - c1o9 * (mfcaa + mfaca + mfaac) * OOrho +
-                               (c2o1 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) +
-                                (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) *
-                                   OOrho * OOrho * c2o3 +
-                               c1o27 * ((drho * drho - drho) * OOrho * OOrho));
+        real c_222 = m_222 + ((-c4o1 * m_111 * m_111 - (m_200 * m_022 + m_020 * m_202 + m_002 * m_220) -
+                                c4o1 * (m_011 * m_211 + m_101 * m_121 + m_110 * m_112) -
+                                c2o1 * (m_120 * m_102 + m_210 * m_012 + m_201 * m_021)) *
+                                oneOverRho +
+                            (c4o1 * (m_101 * m_101 * m_020 + m_011 * m_011 * m_200 + m_110 * m_110 * m_002) +
+                                c2o1 * (m_200 * m_020 * m_002) + c16o1 * m_110 * m_101 * m_011) *
+                                oneOverRho * oneOverRho -
+                                c1o3 * (m_022 + m_202 + m_220) * oneOverRho - c1o9 * (m_200 + m_020 + m_002) * oneOverRho +
+                            (c2o1 * (m_101 * m_101 + m_011 * m_011 + m_110 * m_110) +
+                                (m_002 * m_020 + m_002 * m_200 + m_020 * m_200) + c1o3 * (m_002 + m_020 + m_200)) *
+                                oneOverRho * oneOverRho * c2o3 +
+                                c1o27 * ((drho * drho - drho) * oneOverRho * oneOverRho));
 
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Compute linear combinations of second and third order cumulants
         //!
         ////////////////////////////////////////////////////////////
         // 2.
-        real mxxPyyPzz = mfcaa + mfaca + mfaac;
-        real mxxMyy    = mfcaa - mfaca;
-        real mxxMzz    = mfcaa - mfaac;
+        real mxxPyyPzz = m_200 + m_020 + m_002;
+        real mxxMyy    = m_200 - m_020;
+        real mxxMzz    = m_200 - m_002;
         ////////////////////////////////////////////////////////////
         // 3.
-        real mxxyPyzz = mfcba + mfabc;
-        real mxxyMyzz = mfcba - mfabc;
+        real mxxyPyzz = m_210 + m_012;
+        real mxxyMyzz = m_210 - m_012;
 
-        real mxxzPyyz = mfcab + mfacb;
-        real mxxzMyyz = mfcab - mfacb;
+        real mxxzPyyz = m_201 + m_021;
+        real mxxzMyyz = m_201 - m_021;
 
-        real mxyyPxzz = mfbca + mfbac;
-        real mxyyMxzz = mfbca - mfbac;
+        real mxyyPxzz = m_120 + m_102;
+        real mxyyMxzz = m_120 - m_102;
 
         ////////////////////////////////////////////////////////////////////////////////////
         // incl. correction
@@ -459,37 +428,33 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> Note that the division by rho is omitted here as we need rho times
         //! the gradients later.
         //!
-        real Dxy  = -c3o1 * omega * mfbba;
-        real Dxz  = -c3o1 * omega * mfbab;
-        real Dyz  = -c3o1 * omega * mfabb;
-        real dxux = c1o2 * (-omega) * (mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz * (mfaaa - mxxPyyPzz);
+        real Dxy  = -c3o1 * omega * m_110;
+        real Dxz  = -c3o1 * omega * m_101;
+        real Dyz  = -c3o1 * omega * m_011;
+        real dxux = c1o2 * (-omega) * (mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz * (m_000 - mxxPyyPzz);
         real dyuy = dxux + omega * c3o2 * mxxMyy;
         real dzuz = dxux + omega * c3o2 * mxxMzz;
 
-        //Smagorinsky for debugging
-        // if(true)
-        // {   
-            // if(false && k==99976)
-            // {
-            //     printf("dudz+dwdu: \t %1.14f \n", Dxz );
-            //     printf("dvdz+dudy: \t %1.14f \n", Dxy );  
-            //     printf("dwdy+dvdz: \t %1.14f \n", Dyz );  
-            //     printf("nu_t * dudz+dwdu: \t %1.14f \n", turbulentViscosity[k]*Dxz );
-            //     printf("nu_t * dvdz+dudy: \t %1.14f \n", turbulentViscosity[k]*Dxy );  
-            //     printf("nu_t * dwdy+dvdz: \t %1.14f \n", turbulentViscosity[k]*Dyz );      
-            // } 
-        //     real Sbar = sqrt(c2o1*(dxux*dxux+dyuy*dyuy+dzuz*dzuz)+Dxy*Dxy+Dxz*Dxz+Dyz*Dyz);
-        //     real Cs = 0.08f;
-        //     turbulentViscosity[k] = Cs*Cs*Sbar;
-        // }
-
+        ////////////////////////////////////////////////////////////////////////////////////
+        switch (turbulenceModel)
+        {
+        case TurbulenceModel::AMD:  //AMD is computed in separate kernel
+            break;
+        case TurbulenceModel::Smagorinsky:
+            turbulentViscosity[k_000] = calcTurbulentViscositySmagorinsky(SGSconstant, dxux, dyuy, dzuz, Dxy, Dxz , Dyz);
+            break;
+        case TurbulenceModel::QR:
+            turbulentViscosity[k_000] = calcTurbulentViscosityQR(SGSconstant, dxux, dyuy, dzuz, Dxy, Dxz , Dyz);
+            break;
+        default:
+            break;
+        }
         ////////////////////////////////////////////////////////////
         //! - Relaxation of second order cumulants with correction terms according to Eq. (33)-(35) in
         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
         //!
-        mxxPyyPzz +=
-            OxxPyyPzz * (mfaaa - mxxPyyPzz) - c3o1 * (c1o1 - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
+        mxxPyyPzz += OxxPyyPzz * (m_000 - mxxPyyPzz) - c3o1 * (c1o1 - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
         mxxMyy += omega * (-mxxMyy) - c3o1 * (c1o1 + c1o2 * (-omega)) * (vx2 * dxux - vy2 * dyuy);
         mxxMzz += omega * (-mxxMzz) - c3o1 * (c1o1 + c1o2 * (-omega)) * (vx2 * dxux - vz2 * dzuz);
 
@@ -499,9 +464,9 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         // mxxMyy += -(-omega) * (-mxxMyy);
         // mxxMzz += -(-omega) * (-mxxMzz);
         //////////////////////////////////////////////////////////////////////////
-        mfabb += omega * (-mfabb);
-        mfbab += omega * (-mfbab);
-        mfbba += omega * (-mfbba);
+        m_011 += omega * (-m_011);
+        m_101 += omega * (-m_101);
+        m_110 += omega * (-m_110);
 
         ////////////////////////////////////////////////////////////////////////////////////
         // relax
@@ -511,19 +476,19 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
         //!
-        wadjust = Oxyz + (c1o1 - Oxyz) * abs(mfbbb) / (abs(mfbbb) + qudricLimitD);
-        mfbbb += wadjust * (-mfbbb);
-        wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxxyPyzz) / (abs(mxxyPyzz) + qudricLimitP);
+        real wadjust = Oxyz + (c1o1 - Oxyz) * abs(m_111) / (abs(m_111) + quadricLimitD);
+        m_111 += wadjust * (-m_111);
+        wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxxyPyzz) / (abs(mxxyPyzz) + quadricLimitP);
         mxxyPyzz += wadjust * (-mxxyPyzz);
-        wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxxyMyzz) / (abs(mxxyMyzz) + qudricLimitM);
+        wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxxyMyzz) / (abs(mxxyMyzz) + quadricLimitM);
         mxxyMyzz += wadjust * (-mxxyMyzz);
-        wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxxzPyyz) / (abs(mxxzPyyz) + qudricLimitP);
+        wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxxzPyyz) / (abs(mxxzPyyz) + quadricLimitP);
         mxxzPyyz += wadjust * (-mxxzPyyz);
-        wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxxzMyyz) / (abs(mxxzMyyz) + qudricLimitM);
+        wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxxzMyyz) / (abs(mxxzMyyz) + quadricLimitM);
         mxxzMyyz += wadjust * (-mxxzMyyz);
-        wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxyyPxzz) / (abs(mxyyPxzz) + qudricLimitP);
+        wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxyyPxzz) / (abs(mxyyPxzz) + quadricLimitP);
         mxyyPxzz += wadjust * (-mxyyPxzz);
-        wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxyyMxzz) / (abs(mxyyMxzz) + qudricLimitM);
+        wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxyyMxzz) / (abs(mxyyMxzz) + quadricLimitM);
         mxyyMxzz += wadjust * (-mxyyMxzz);
         //////////////////////////////////////////////////////////////////////////
         // no limiter
@@ -538,16 +503,16 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Compute inverse linear combinations of second and third order cumulants
         //!
-        mfcaa = c1o3 * (mxxMyy + mxxMzz + mxxPyyPzz);
-        mfaca = c1o3 * (-c2o1 * mxxMyy + mxxMzz + mxxPyyPzz);
-        mfaac = c1o3 * (mxxMyy - c2o1 * mxxMzz + mxxPyyPzz);
-
-        mfcba = (mxxyMyzz + mxxyPyzz) * c1o2;
-        mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
-        mfcab = (mxxzMyyz + mxxzPyyz) * c1o2;
-        mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
-        mfbca = (mxyyMxzz + mxyyPxzz) * c1o2;
-        mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+        m_200 = c1o3 * (mxxMyy + mxxMzz + mxxPyyPzz);
+        m_020 = c1o3 * (-c2o1 * mxxMyy + mxxMzz + mxxPyyPzz);
+        m_002 = c1o3 * (mxxMyy - c2o1 * mxxMzz + mxxPyyPzz);
+
+        m_210 = ( mxxyMyzz + mxxyPyzz) * c1o2;
+        m_012 = (-mxxyMyzz + mxxyPyzz) * c1o2;
+        m_201 = ( mxxzMyyz + mxxzPyyz) * c1o2;
+        m_021 = (-mxxzMyyz + mxxzPyyz) * c1o2;
+        m_120 = ( mxyyMxzz + mxyyPxzz) * c1o2;
+        m_102 = (-mxyyMxzz + mxyyPxzz) * c1o2;
         //////////////////////////////////////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////
@@ -557,22 +522,23 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //! to Eq. (43)-(48) <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
         //!
-        CUMacc = -O4 * (c1o1 / omega - c1o2) * (dyuy + dzuz) * c2o3 * factorA + (c1o1 - O4) * (CUMacc);
-        CUMcac = -O4 * (c1o1 / omega - c1o2) * (dxux + dzuz) * c2o3 * factorA + (c1o1 - O4) * (CUMcac);
-        CUMcca = -O4 * (c1o1 / omega - c1o2) * (dyuy + dxux) * c2o3 * factorA + (c1o1 - O4) * (CUMcca);
-        CUMbbc = -O4 * (c1o1 / omega - c1o2) * Dxy * c1o3 * factorB + (c1o1 - O4) * (CUMbbc);
-        CUMbcb = -O4 * (c1o1 / omega - c1o2) * Dxz * c1o3 * factorB + (c1o1 - O4) * (CUMbcb);
-        CUMcbb = -O4 * (c1o1 / omega - c1o2) * Dyz * c1o3 * factorB + (c1o1 - O4) * (CUMcbb);
+        c_022 = -O4 * (c1o1 / omega - c1o2) * (dyuy + dzuz) * c2o3 * factorA + (c1o1 - O4) * (c_022);
+        c_202 = -O4 * (c1o1 / omega - c1o2) * (dxux + dzuz) * c2o3 * factorA + (c1o1 - O4) * (c_202);
+        c_220 = -O4 * (c1o1 / omega - c1o2) * (dyuy + dxux) * c2o3 * factorA + (c1o1 - O4) * (c_220);
+        c_112 = -O4 * (c1o1 / omega - c1o2) * Dxy           * c1o3 * factorB + (c1o1 - O4) * (c_112);
+        c_121 = -O4 * (c1o1 / omega - c1o2) * Dxz           * c1o3 * factorB + (c1o1 - O4) * (c_121);
+        c_211 = -O4 * (c1o1 / omega - c1o2) * Dyz           * c1o3 * factorB + (c1o1 - O4) * (c_211);
+
 
         //////////////////////////////////////////////////////////////////////////
         // 5.
-        CUMbcc += O5 * (-CUMbcc);
-        CUMcbc += O5 * (-CUMcbc);
-        CUMccb += O5 * (-CUMccb);
+        c_122 += O5 * (-c_122);
+        c_212 += O5 * (-c_212);
+        c_221 += O5 * (-c_221);
 
         //////////////////////////////////////////////////////////////////////////
         // 6.
-        CUMccc += O6 * (-CUMccc);
+        c_222 += O6 * (-c_222);
 
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Compute central moments from post collision cumulants according to Eq. (53)-(56) in
@@ -582,68 +548,58 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
 
         //////////////////////////////////////////////////////////////////////////
         // 4.
-        mfcbb = CUMcbb + c1o3 * ((c3o1 * mfcaa + c1o1) * mfabb + c6o1 * mfbba * mfbab) * OOrho;
-        mfbcb = CUMbcb + c1o3 * ((c3o1 * mfaca + c1o1) * mfbab + c6o1 * mfbba * mfabb) * OOrho;
-        mfbbc = CUMbbc + c1o3 * ((c3o1 * mfaac + c1o1) * mfbba + c6o1 * mfbab * mfabb) * OOrho;
+        m_211 = c_211 + c1o3 * ((c3o1 * m_200 + c1o1) * m_011 + c6o1 * m_110 * m_101) * oneOverRho;
+        m_121 = c_121 + c1o3 * ((c3o1 * m_020 + c1o1) * m_101 + c6o1 * m_110 * m_011) * oneOverRho;
+        m_112 = c_112 + c1o3 * ((c3o1 * m_002 + c1o1) * m_110 + c6o1 * m_101 * m_011) * oneOverRho;
 
-        mfcca =
-            CUMcca +
-            (((mfcaa * mfaca + c2o1 * mfbba * mfbba) * c9o1 + c3o1 * (mfcaa + mfaca)) * OOrho - (drho * OOrho)) * c1o9;
-        mfcac =
-            CUMcac +
-            (((mfcaa * mfaac + c2o1 * mfbab * mfbab) * c9o1 + c3o1 * (mfcaa + mfaac)) * OOrho - (drho * OOrho)) * c1o9;
-        mfacc =
-            CUMacc +
-            (((mfaac * mfaca + c2o1 * mfabb * mfabb) * c9o1 + c3o1 * (mfaac + mfaca)) * OOrho - (drho * OOrho)) * c1o9;
+        m_220 =
+            c_220 + (((m_200 * m_020 + c2o1 * m_110 * m_110) * c9o1 + c3o1 * (m_200 + m_020)) * oneOverRho - (drho * oneOverRho)) * c1o9;
+        m_202 =
+            c_202 + (((m_200 * m_002 + c2o1 * m_101 * m_101) * c9o1 + c3o1 * (m_200 + m_002)) * oneOverRho - (drho * oneOverRho)) * c1o9;
+        m_022 =
+            c_022 + (((m_002 * m_020 + c2o1 * m_011 * m_011) * c9o1 + c3o1 * (m_002 + m_020)) * oneOverRho - (drho * oneOverRho)) * c1o9;
 
         //////////////////////////////////////////////////////////////////////////
         // 5.
-        mfbcc = CUMbcc + c1o3 *
-                             (c3o1 * (mfaac * mfbca + mfaca * mfbac + c4o1 * mfabb * mfbbb +
-                                      c2o1 * (mfbab * mfacb + mfbba * mfabc)) +
-                              (mfbca + mfbac)) *
-                             OOrho;
-        mfcbc = CUMcbc + c1o3 *
-                             (c3o1 * (mfaac * mfcba + mfcaa * mfabc + c4o1 * mfbab * mfbbb +
-                                      c2o1 * (mfabb * mfcab + mfbba * mfbac)) +
-                              (mfcba + mfabc)) *
-                             OOrho;
-        mfccb = CUMccb + c1o3 *
-                             (c3o1 * (mfcaa * mfacb + mfaca * mfcab + c4o1 * mfbba * mfbbb +
-                                      c2o1 * (mfbab * mfbca + mfabb * mfcba)) +
-                              (mfacb + mfcab)) *
-                             OOrho;
+        m_122 = c_122 + c1o3 *
+                (c3o1 * (m_002 * m_120 + m_020 * m_102 + c4o1 * m_011 * m_111 + c2o1 * (m_101 * m_021 + m_110 * m_012)) +
+                (m_120 + m_102)) * oneOverRho;
+        m_212 = c_212 + c1o3 *
+                (c3o1 * (m_002 * m_210 + m_200 * m_012 + c4o1 * m_101 * m_111 + c2o1 * (m_011 * m_201 + m_110 * m_102)) +
+                (m_210 + m_012)) * oneOverRho;
+        m_221 = c_221 + c1o3 *
+                (c3o1 * (m_200 * m_021 + m_020 * m_201 + c4o1 * m_110 * m_111 + c2o1 * (m_101 * m_120 + m_011 * m_210)) +
+                (m_021 + m_201)) * oneOverRho;
 
         //////////////////////////////////////////////////////////////////////////
         // 6.
-        mfccc = CUMccc - ((-c4o1 * mfbbb * mfbbb - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) -
-                           c4o1 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) -
-                           c2o1 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) *
-                              OOrho +
-                          (c4o1 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) +
-                           c2o1 * (mfcaa * mfaca * mfaac) + c16o1 * mfbba * mfbab * mfabb) *
-                              OOrho * OOrho -
-                          c1o3 * (mfacc + mfcac + mfcca) * OOrho - c1o9 * (mfcaa + mfaca + mfaac) * OOrho +
-                          (c2o1 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) +
-                           (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) *
-                              OOrho * OOrho * c2o3 +
-                          c1o27 * ((drho * drho - drho) * OOrho * OOrho));
+        m_222 = c_222 - ((-c4o1 * m_111 * m_111 - (m_200 * m_022 + m_020 * m_202 + m_002 * m_220) -
+                        c4o1 * (m_011 * m_211 + m_101 * m_121 + m_110 * m_112) -
+                        c2o1 * (m_120 * m_102 + m_210 * m_012 + m_201 * m_021)) *
+                        oneOverRho +
+                        (c4o1 * (m_101 * m_101 * m_020 + m_011 * m_011 * m_200 + m_110 * m_110 * m_002) +
+                        c2o1 * (m_200 * m_020 * m_002) + c16o1 * m_110 * m_101 * m_011) *
+                        oneOverRho * oneOverRho -
+                        c1o3 * (m_022 + m_202 + m_220) * oneOverRho - c1o9 * (m_200 + m_020 + m_002) * oneOverRho +
+                        (c2o1 * (m_101 * m_101 + m_011 * m_011 + m_110 * m_110) +
+                        (m_002 * m_020 + m_002 * m_200 + m_020 * m_200) + c1o3 * (m_002 + m_020 + m_200)) *
+                        oneOverRho * oneOverRho * c2o3 +
+                        c1o27 * ((drho * drho - drho) * oneOverRho * oneOverRho));
 
         ////////////////////////////////////////////////////////////////////////////////////
         //! -  Add acceleration (body force) to first order cumulants according to Eq. (85)-(87) in
         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
         //!
-        mfbaa = -mfbaa;
-        mfaba = -mfaba;
-        mfaab = -mfaab;
-
+        m_100 = -m_100;
+        m_010 = -m_010;
+        m_001 = -m_001;
 
         //Write to array here to distribute read/write
-        rho[k] = drho;
-        vx[k] = vvx;
-        vy[k] = vvy;
-        vz[k] = vvz;
+        rho[k_000] = drho;
+        vx[k_000] = vvx;
+        vy[k_000] = vvy;
+        vz[k_000] = vvz;
 
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Chimera transform from central moments to well conditioned distributions as defined in Appendix J in
@@ -654,39 +610,39 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //!
         ////////////////////////////////////////////////////////////////////////////////////
         // X - Dir
-        backwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1o1, c1o1);
-        backwardChimera(mfaba, mfbba, mfcba, vvx, vx2);
-        backwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3o1, c1o3);
-        backwardChimera(mfaab, mfbab, mfcab, vvx, vx2);
-        backwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2);
-        backwardChimera(mfacb, mfbcb, mfccb, vvx, vx2);
-        backwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3o1, c1o3);
-        backwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2);
-        backwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c9o1, c1o9);
+        backwardInverseChimeraWithK(m_000, m_100, m_200, vvx, vx2, c1o1, c1o1);
+        backwardChimera(            m_010, m_110, m_210, vvx, vx2);
+        backwardInverseChimeraWithK(m_020, m_120, m_220, vvx, vx2, c3o1, c1o3);
+        backwardChimera(            m_001, m_101, m_201, vvx, vx2);
+        backwardChimera(            m_011, m_111, m_211, vvx, vx2);
+        backwardChimera(            m_021, m_121, m_221, vvx, vx2);
+        backwardInverseChimeraWithK(m_002, m_102, m_202, vvx, vx2, c3o1, c1o3);
+        backwardChimera(            m_012, m_112, m_212, vvx, vx2);
+        backwardInverseChimeraWithK(m_022, m_122, m_222, vvx, vx2, c9o1, c1o9);
 
         ////////////////////////////////////////////////////////////////////////////////////
         // Y - Dir
-        backwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6o1, c1o6);
-        backwardChimera(mfaab, mfabb, mfacb, vvy, vy2);
-        backwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18o1, c1o18);
-        backwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3);
-        backwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2);
-        backwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9);
-        backwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6o1, c1o6);
-        backwardChimera(mfcab, mfcbb, mfccb, vvy, vy2);
-        backwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18o1, c1o18);
+        backwardInverseChimeraWithK(m_000, m_010, m_020, vvy, vy2, c6o1, c1o6);
+        backwardChimera(            m_001, m_011, m_021, vvy, vy2);
+        backwardInverseChimeraWithK(m_002, m_012, m_022, vvy, vy2, c18o1, c1o18);
+        backwardInverseChimeraWithK(m_100, m_110, m_120, vvy, vy2, c3o2, c2o3);
+        backwardChimera(            m_101, m_111, m_121, vvy, vy2);
+        backwardInverseChimeraWithK(m_102, m_112, m_122, vvy, vy2, c9o2, c2o9);
+        backwardInverseChimeraWithK(m_200, m_210, m_220, vvy, vy2, c6o1, c1o6);
+        backwardChimera(            m_201, m_211, m_221, vvy, vy2);
+        backwardInverseChimeraWithK(m_202, m_212, m_222, vvy, vy2, c18o1, c1o18);
 
         ////////////////////////////////////////////////////////////////////////////////////
         // Z - Dir
-        backwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36o1, c1o36);
-        backwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9o1, c1o9);
-        backwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36o1, c1o36);
-        backwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9o1, c1o9);
-        backwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9);
-        backwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9o1, c1o9);
-        backwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36o1, c1o36);
-        backwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9o1, c1o9);
-        backwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);
+        backwardInverseChimeraWithK(m_000, m_001, m_002, vvz, vz2, c36o1, c1o36);
+        backwardInverseChimeraWithK(m_010, m_011, m_012, vvz, vz2, c9o1, c1o9);
+        backwardInverseChimeraWithK(m_020, m_021, m_022, vvz, vz2, c36o1, c1o36);
+        backwardInverseChimeraWithK(m_100, m_101, m_102, vvz, vz2, c9o1, c1o9);
+        backwardInverseChimeraWithK(m_110, m_111, m_112, vvz, vz2, c9o4, c4o9);
+        backwardInverseChimeraWithK(m_120, m_121, m_122, vvz, vz2, c9o1, c1o9);
+        backwardInverseChimeraWithK(m_200, m_201, m_202, vvz, vz2, c36o1, c1o36);
+        backwardInverseChimeraWithK(m_210, m_211, m_212, vvz, vz2, c9o1, c1o9);
+        backwardInverseChimeraWithK(m_220, m_221, m_222, vvz, vz2, c36o1, c1o36);
 
         ////////////////////////////////////////////////////////////////////////////////////
         //! - Write distributions: style of reading and writing the distributions from/to
@@ -694,905 +650,38 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
         //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
         //! DOI:10.3390/computation5020019 ]</b></a>
         //!
-        (dist.f[DIR_P00])[k]      = mfabb;
-        (dist.f[DIR_M00])[kw]     = mfcbb;
-        (dist.f[DIR_0P0])[k]      = mfbab;
-        (dist.f[DIR_0M0])[ks]     = mfbcb;
-        (dist.f[DIR_00P])[k]      = mfbba;
-        (dist.f[DIR_00M])[kb]     = mfbbc;
-        (dist.f[DIR_PP0])[k]     = mfaab;
-        (dist.f[DIR_MM0])[ksw]   = mfccb;
-        (dist.f[DIR_PM0])[ks]    = mfacb;
-        (dist.f[DIR_MP0])[kw]    = mfcab;
-        (dist.f[DIR_P0P])[k]     = mfaba;
-        (dist.f[DIR_M0M])[kbw]   = mfcbc;
-        (dist.f[DIR_P0M])[kb]    = mfabc;
-        (dist.f[DIR_M0P])[kw]    = mfcba;
-        (dist.f[DIR_0PP])[k]     = mfbaa;
-        (dist.f[DIR_0MM])[kbs]   = mfbcc;
-        (dist.f[DIR_0PM])[kb]    = mfbac;
-        (dist.f[DIR_0MP])[ks]    = mfbca;
-        (dist.f[DIR_000])[k]   = mfbbb;
-        (dist.f[DIR_PPP])[k]    = mfaaa;
-        (dist.f[DIR_PMP])[ks]   = mfaca;
-        (dist.f[DIR_PPM])[kb]   = mfaac;
-        (dist.f[DIR_PMM])[kbs]  = mfacc;
-        (dist.f[DIR_MPP])[kw]   = mfcaa;
-        (dist.f[DIR_MMP])[ksw]  = mfcca;
-        (dist.f[DIR_MPM])[kbw]  = mfcac;
-        (dist.f[DIR_MMM])[kbsw] = mfccc;
-
-
+        (dist.f[DIR_P00])[k_000]    = f_M00;
+        (dist.f[DIR_M00])[k_M00]    = f_P00;
+        (dist.f[DIR_0P0])[k_000]    = f_0M0;
+        (dist.f[DIR_0M0])[k_0M0]    = f_0P0;
+        (dist.f[DIR_00P])[k_000]    = f_00M;
+        (dist.f[DIR_00M])[k_00M]    = f_00P;
+        (dist.f[DIR_PP0])[k_000]   = f_MM0;
+        (dist.f[DIR_MM0])[k_MM0]   = f_PP0;
+        (dist.f[DIR_PM0])[k_0M0]   = f_MP0;
+        (dist.f[DIR_MP0])[k_M00]   = f_PM0;
+        (dist.f[DIR_P0P])[k_000]   = f_M0M;
+        (dist.f[DIR_M0M])[k_M0M]   = f_P0P;
+        (dist.f[DIR_P0M])[k_00M]   = f_M0P;
+        (dist.f[DIR_M0P])[k_M00]   = f_P0M;
+        (dist.f[DIR_0PP])[k_000]   = f_0MM;
+        (dist.f[DIR_0MM])[k_0MM]   = f_0PP;
+        (dist.f[DIR_0PM])[k_00M]   = f_0MP;
+        (dist.f[DIR_0MP])[k_0M0]   = f_0PM;
+        (dist.f[DIR_000])[k_000] = f_000;
+        (dist.f[DIR_PPP])[k_000]  = f_MMM;
+        (dist.f[DIR_PMP])[k_0M0]  = f_MPM;
+        (dist.f[DIR_PPM])[k_00M]  = f_MMP;
+        (dist.f[DIR_PMM])[k_0MM]  = f_MPP;
+        (dist.f[DIR_MPP])[k_M00]  = f_PMM;
+        (dist.f[DIR_MMP])[k_MM0]  = f_PPM;
+        (dist.f[DIR_MPM])[k_M0M]  = f_PMP;
+        (dist.f[DIR_MMM])[k_MMM]  = f_PPP;
     }
 }
 
+template __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim < TurbulenceModel::AMD > ( real omega_in, uint* typeOfGridNode, uint* neighborX, uint* neighborY, uint* neighborZ, real* distributions, real* rho, real* vx, real* vy, real* vz, real* turbulentViscosity, real SGSconstant, unsigned long size_Mat, int level, bool bodyForce, real* forces, real* bodyForceX, real* bodyForceY, real* bodyForceZ, real* quadricLimiters, bool isEvenTimestep);
 
+template __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim < TurbulenceModel::Smagorinsky > ( real omega_in, uint* typeOfGridNode, uint* neighborX, uint* neighborY, uint* neighborZ, real* distributions, real* rho, real* vx, real* vy, real* vz, real* turbulentViscosity, real SGSconstant, unsigned long size_Mat, int level, bool bodyForce, real* forces, real* bodyForceX, real* bodyForceY, real* bodyForceZ, real* quadricLimiters, bool isEvenTimestep);
 
-
-//WORK IN PROGRESS: Incorporating DistributionWrapper in kernel.....
-
-// //=======================================================================================
-// // ____          ____    __    ______     __________   __      __       __        __         
-// // \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
-// //  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
-// //   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
-// //    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
-// //     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
-// //      \    \  |    |   ________________________________________________________________    
-// //       \    \ |    |  |  ______________________________________________________________|   
-// //        \    \|    |  |  |         __          __     __     __     ______      _______    
-// //         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
-// //          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
-// //           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-// //            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
-// //
-// //  This file is part of VirtualFluids. VirtualFluids is free software: you can 
-// //  redistribute it and/or modify it under the terms of the GNU General Public
-// //  License as published by the Free Software Foundation, either version 3 of 
-// //  the License, or (at your option) any later version.
-// //  
-// //  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT 
-// //  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-// //  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
-// //  for more details.
-// //  
-// //  You should have received a copy of the GNU General Public License along
-// //  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
-// //
-// //! \file TurbulentViscosityCumulantK17CompChim_Device.cu
-// //! \author Henry Korb, Henrik Asmuth
-// //! \date 16/05/2022
-// //! \brief CumulantK17CompChim kernel by Martin Schönherr that inlcudes turbulent viscosity and other small mods.
-// //!
-// //! Additions to CumulantK17CompChim:
-// //!     - can incorporate local body force 
-// //!     - when applying a local body force, the total round of error of forcing+bodyforce is saved and added in next time step
-// //!     - uses turbulent viscosity that is computed in separate kernel (as of now AMD)
-// //!     - saves macroscopic values (needed for instance for probes, AMD, and actuator models)
-// //!
-// //=======================================================================================
-// /* Device code */
-// #include "LBM/LB.h" 
-// #include "lbm/constants/D3Q27.h"
-// #include <lbm/constants/NumericConstants.h>
-
-// using namespace vf::lbm::constant;
-// #include "Kernel/ChimeraTransformation.h"
-
-// #include "Kernel/Utilities/DistributionHelper.cuh"
-
-// #include "lbm/MacroscopicQuantities.h"
-
-// ////////////////////////////////////////////////////////////////////////////////
-// __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
-// 	real omega_in,
-// 	uint* typeOfGridNode,
-// 	uint* neighborX,
-// 	uint* neighborY,
-// 	uint* neighborZ,
-// 	real* distributions,
-//     real* rho,
-//     real* vx,
-//     real* vy,
-//     real* vz,
-//     real* turbulentViscosity,
-// 	unsigned long size_Mat,
-// 	int level,
-//     bool bodyForce,
-// 	real* forces,
-//     real* bodyForceX,
-//     real* bodyForceY,
-//     real* bodyForceZ,
-// 	real* quadricLimiters,
-// 	bool isEvenTimestep)
-// {
-//     //////////////////////////////////////////////////////////////////////////
-//     //! Cumulant K17 Kernel is based on \ref
-//     //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040
-//     //! ]</b></a> and \ref <a href="https://doi.org/10.1016/j.jcp.2017.07.004"><b>[ M. Geier et al. (2017),
-//     //! DOI:10.1016/j.jcp.2017.07.004 ]</b></a>
-//     //!
-//     //! The cumulant kernel is executed in the following steps
-//     //!
-//     ////////////////////////////////////////////////////////////////////////////////
-//     //! - Get node index coordinates from threadIdx, blockIdx, blockDim and gridDim.
-//     //!
-
-//     // const unsigned x = threadIdx.x;
-//     // const unsigned y = blockIdx.x;
-//     // const unsigned z = blockIdx.y;
-
-//     // const unsigned nx = blockDim.x;
-//     // const unsigned ny = gridDim.x;
-
-//     // const unsigned k = nx * (ny * z + y) + x;
-//     const unsigned k = vf::gpu::getNodeIndex();
-//     //////////////////////////////////////////////////////////////////////////
-//     // run for all indices in size_Mat and fluid nodes
-//     // if ((k < size_Mat) && (typeOfGridNode[k] == GEO_FLUID)) {
-//     if ((k < size_Mat) && vf::gpu::isValidFluidNode(typeOfGridNode[k])) {
-//         //////////////////////////////////////////////////////////////////////////
-//         //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on
-//         //! timestep is based on the esoteric twist algorithm \ref <a
-//         //! href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.3390/computation5020019 ]</b></a>
-//         //!
-
-//         vf::gpu::DistributionWrapper distr_wrapper( distributions, size_Mat, 
-//                                                     isEvenTimestep, k, 
-//                                                     neighborX, neighborY, neighborZ);
-
-//         Distributions27 dist;
-//         if (isEvenTimestep) {
-//             dist.f[DIR_P00]    = &distributions[DIR_P00 * size_Mat];
-//             dist.f[DIR_M00]    = &distributions[DIR_M00 * size_Mat];
-//             dist.f[DIR_0P0]    = &distributions[DIR_0P0 * size_Mat];
-//             dist.f[DIR_0M0]    = &distributions[DIR_0M0 * size_Mat];
-//             dist.f[DIR_00P]    = &distributions[DIR_00P * size_Mat];
-//             dist.f[DIR_00M]    = &distributions[DIR_00M * size_Mat];
-//             dist.f[DIR_PP0]   = &distributions[DIR_PP0 * size_Mat];
-//             dist.f[DIR_MM0]   = &distributions[DIR_MM0 * size_Mat];
-//             dist.f[DIR_PM0]   = &distributions[DIR_PM0 * size_Mat];
-//             dist.f[DIR_MP0]   = &distributions[DIR_MP0 * size_Mat];
-//             dist.f[DIR_P0P]   = &distributions[DIR_P0P * size_Mat];
-//             dist.f[DIR_M0M]   = &distributions[DIR_M0M * size_Mat];
-//             dist.f[DIR_P0M]   = &distributions[DIR_P0M * size_Mat];
-//             dist.f[DIR_M0P]   = &distributions[DIR_M0P * size_Mat];
-//             dist.f[DIR_0PP]   = &distributions[DIR_0PP * size_Mat];
-//             dist.f[DIR_0MM]   = &distributions[DIR_0MM * size_Mat];
-//             dist.f[DIR_0PM]   = &distributions[DIR_0PM * size_Mat];
-//             dist.f[DIR_0MP]   = &distributions[DIR_0MP * size_Mat];
-//             dist.f[DIR_000] = &distributions[DIR_000 * size_Mat];
-//             dist.f[DIR_PPP]  = &distributions[DIR_PPP * size_Mat];
-//             dist.f[DIR_MMP]  = &distributions[DIR_MMP * size_Mat];
-//             dist.f[DIR_PMP]  = &distributions[DIR_PMP * size_Mat];
-//             dist.f[DIR_MPP]  = &distributions[DIR_MPP * size_Mat];
-//             dist.f[DIR_PPM]  = &distributions[DIR_PPM * size_Mat];
-//             dist.f[DIR_MMM]  = &distributions[DIR_MMM * size_Mat];
-//             dist.f[DIR_PMM]  = &distributions[DIR_PMM * size_Mat];
-//             dist.f[DIR_MPM]  = &distributions[DIR_MPM * size_Mat];
-//         } else {
-//             dist.f[DIR_M00]    = &distributions[DIR_P00 * size_Mat];
-//             dist.f[DIR_P00]    = &distributions[DIR_M00 * size_Mat];
-//             dist.f[DIR_0M0]    = &distributions[DIR_0P0 * size_Mat];
-//             dist.f[DIR_0P0]    = &distributions[DIR_0M0 * size_Mat];
-//             dist.f[DIR_00M]    = &distributions[DIR_00P * size_Mat];
-//             dist.f[DIR_00P]    = &distributions[DIR_00M * size_Mat];
-//             dist.f[DIR_MM0]   = &distributions[DIR_PP0 * size_Mat];
-//             dist.f[DIR_PP0]   = &distributions[DIR_MM0 * size_Mat];
-//             dist.f[DIR_MP0]   = &distributions[DIR_PM0 * size_Mat];
-//             dist.f[DIR_PM0]   = &distributions[DIR_MP0 * size_Mat];
-//             dist.f[DIR_M0M]   = &distributions[DIR_P0P * size_Mat];
-//             dist.f[DIR_P0P]   = &distributions[DIR_M0M * size_Mat];
-//             dist.f[DIR_M0P]   = &distributions[DIR_P0M * size_Mat];
-//             dist.f[DIR_P0M]   = &distributions[DIR_M0P * size_Mat];
-//             dist.f[DIR_0MM]   = &distributions[DIR_0PP * size_Mat];
-//             dist.f[DIR_0PP]   = &distributions[DIR_0MM * size_Mat];
-//             dist.f[DIR_0MP]   = &distributions[DIR_0PM * size_Mat];
-//             dist.f[DIR_0PM]   = &distributions[DIR_0MP * size_Mat];
-//             dist.f[DIR_000] = &distributions[DIR_000 * size_Mat];
-//             dist.f[DIR_MMM]  = &distributions[DIR_PPP * size_Mat];
-//             dist.f[DIR_PPM]  = &distributions[DIR_MMP * size_Mat];
-//             dist.f[DIR_MPM]  = &distributions[DIR_PMP * size_Mat];
-//             dist.f[DIR_PMM]  = &distributions[DIR_MPP * size_Mat];
-//             dist.f[DIR_MMP]  = &distributions[DIR_PPM * size_Mat];
-//             dist.f[DIR_PPP]  = &distributions[DIR_MMM * size_Mat];
-//             dist.f[DIR_MPP]  = &distributions[DIR_PMM * size_Mat];
-//             dist.f[DIR_PMP]  = &distributions[DIR_MPM * size_Mat];
-//         }
-//         ////////////////////////////////////////////////////////////////////////////////
-//         //! - Set neighbor indices (necessary for indirect addressing)
-//         uint kw   = neighborX[k];
-//         uint ks   = neighborY[k];
-//         uint kb   = neighborZ[k];
-//         uint ksw  = neighborY[kw];
-//         uint kbw  = neighborZ[kw];
-//         uint kbs  = neighborZ[ks];
-//         uint kbsw = neighborZ[ksw];
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Set local distributions
-//         //!
-
-//         // real mfcbb = distr_wrapper.distribution.f[DIR_P00];
-//         // real mfabb = distr_wrapper.distribution.f[DIR_M00];
-//         // real mfbcb = distr_wrapper.distribution.f[DIR_0P0];
-//         // real mfbab = distr_wrapper.distribution.f[DIR_0M0];
-//         // real mfbbc = distr_wrapper.distribution.f[DIR_00P];
-//         // real mfbba = distr_wrapper.distribution.f[DIR_00M];
-//         // real mfccb = distr_wrapper.distribution.f[DIR_PP0];
-//         // real mfaab = distr_wrapper.distribution.f[DIR_MM0];
-//         // real mfcab = distr_wrapper.distribution.f[DIR_PM0];
-//         // real mfacb = distr_wrapper.distribution.f[DIR_MP0];
-//         // real mfcbc = distr_wrapper.distribution.f[DIR_P0P];
-//         // real mfaba = distr_wrapper.distribution.f[DIR_M0M];
-//         // real mfcba = distr_wrapper.distribution.f[DIR_P0M];
-//         // real mfabc = distr_wrapper.distribution.f[DIR_M0P];
-//         // real mfbcc = distr_wrapper.distribution.f[DIR_0PP];
-//         // real mfbaa = distr_wrapper.distribution.f[DIR_0MM];
-//         // real mfbca = distr_wrapper.distribution.f[DIR_0PM];
-//         // real mfbac = distr_wrapper.distribution.f[DIR_0MP];
-//         // real mfbbb = distr_wrapper.distribution.f[DIR_000];
-//         // real mfccc = distr_wrapper.distribution.f[DIR_PPP];
-//         // real mfaac = distr_wrapper.distribution.f[DIR_MMP];
-//         // real mfcac = distr_wrapper.distribution.f[DIR_PMP];
-//         // real mfacc = distr_wrapper.distribution.f[DIR_MPP];
-//         // real mfcca = distr_wrapper.distribution.f[DIR_PPM];
-//         // real mfaaa = distr_wrapper.distribution.f[DIR_MMM];
-//         // real mfcaa = distr_wrapper.distribution.f[DIR_PMM];
-//         // real mfaca = distr_wrapper.distribution.f[DIR_MPM];
-
-        
-//         real mfcbb = (dist.f[DIR_P00])[k];
-//         real mfabb = (dist.f[DIR_M00])[kw];
-//         real mfbcb = (dist.f[DIR_0P0])[k];
-//         real mfbab = (dist.f[DIR_0M0])[ks];
-//         real mfbbc = (dist.f[DIR_00P])[k];
-//         real mfbba = (dist.f[DIR_00M])[kb];
-//         real mfccb = (dist.f[DIR_PP0])[k];
-//         real mfaab = (dist.f[DIR_MM0])[ksw];
-//         real mfcab = (dist.f[DIR_PM0])[ks];
-//         real mfacb = (dist.f[DIR_MP0])[kw];
-//         real mfcbc = (dist.f[DIR_P0P])[k];
-//         real mfaba = (dist.f[DIR_M0M])[kbw];
-//         real mfcba = (dist.f[DIR_P0M])[kb];
-//         real mfabc = (dist.f[DIR_M0P])[kw];
-//         real mfbcc = (dist.f[DIR_0PP])[k];
-//         real mfbaa = (dist.f[DIR_0MM])[kbs];
-//         real mfbca = (dist.f[DIR_0PM])[kb];
-//         real mfbac = (dist.f[DIR_0MP])[ks];
-//         real mfbbb = (dist.f[DIR_000])[k];
-//         real mfccc = (dist.f[DIR_PPP])[k];
-//         real mfaac = (dist.f[DIR_MMP])[ksw];
-//         real mfcac = (dist.f[DIR_PMP])[ks];
-//         real mfacc = (dist.f[DIR_MPP])[kw];
-//         real mfcca = (dist.f[DIR_PPM])[kb];
-//         real mfaaa = (dist.f[DIR_MMM])[kbsw];
-//         real mfcaa = (dist.f[DIR_PMM])[kbs];
-//         real mfaca = (dist.f[DIR_MPM])[kbw];
-        
-//         //////////////////////////////////////////////////////(unsigned long)//////////////////////////////
-//         //! - Calculate density and velocity using pyramid summation for low round-off errors as in Eq. (J1)-(J3) \ref
-//         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-//         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
-//         //!
-//         // real drho = ((((mfccc + mfaaa) + (mfaca + mfcac)) + ((mfacc + mfcaa) + (mfaac + mfcca))) +
-//         //              (((mfbac + mfbca) + (mfbaa + mfbcc)) + ((mfabc + mfcba) + (mfaba + mfcbc)) +
-//         //               ((mfacb + mfcab) + (mfaab + mfccb))) +
-//         //              ((mfabb + mfcbb) + (mfbab + mfbcb) + (mfbba + mfbbc))) +
-//         //             mfbbb;
-//         real drho = vf::lbm::getDensity(distr_wrapper.distribution.f);
-
-//         real rrho   = c1o1 + drho;
-//         real OOrho = c1o1 / rrho;
-
-//         // real vvx = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) +
-//         //             (((mfcba - mfabc) + (mfcbc - mfaba)) + ((mfcab - mfacb) + (mfccb - mfaab))) + (mfcbb - mfabb)) *
-//         //            OOrho;
-//         real vvx = vf::lbm::getCompressibleVelocityX1(distr_wrapper.distribution.f, drho);
-//         // real vvy = ((((mfccc - mfaaa) + (mfaca - mfcac)) + ((mfacc - mfcaa) + (mfcca - mfaac))) +
-//         //             (((mfbca - mfbac) + (mfbcc - mfbaa)) + ((mfacb - mfcab) + (mfccb - mfaab))) + (mfbcb - mfbab)) *
-//         //            OOrho;
-//         real vvy = vf::lbm::getCompressibleVelocityX2(distr_wrapper.distribution.f, drho);
-//         // real vvz = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfacc - mfcaa) + (mfaac - mfcca))) +
-//         //             (((mfbac - mfbca) + (mfbcc - mfbaa)) + ((mfabc - mfcba) + (mfcbc - mfaba))) + (mfbbc - mfbba)) *
-//         //            OOrho;
-//         real vvz = vf::lbm::getCompressibleVelocityX3(distr_wrapper.distribution.f, drho);
-//         // if(k==100000){printf("%f \t %f \t%f \t%f \n\n", drho, vvx, vvz, vvy);}
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Add half of the acceleration (body force) to the velocity as in Eq. (42) \ref
-//         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-//         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
-//         //!
-//         real factor = c1o1;
-//         for (size_t i = 1; i <= level; i++) {
-//             factor *= c2o1;
-//         }
-        
-//         real fx = forces[0];
-//         real fy = forces[1];
-//         real fz = forces[2];
-
-//         if( bodyForce ){
-//             fx += bodyForceX[k]; 
-//             fy += bodyForceY[k];
-//             fz += bodyForceZ[k];
-
-//             real vx = vvx;
-//             real vy = vvy;
-//             real vz = vvz;
-//             real acc_x = fx * c1o2 / factor;
-//             real acc_y = fy * c1o2 / factor;
-//             real acc_z = fz * c1o2 / factor;
-
-//             vvx += acc_x;
-//             vvy += acc_y;
-//             vvz += acc_z;
-            
-//         //    // Reset body force. To be used when not using round-off correction.
-//         // bodyForceX[k] = 0.0f;
-//         // bodyForceY[k] = 0.0f;
-//         // bodyForceZ[k] = 0.0f;
-
-//             ////////////////////////////////////////////////////////////////////////////////////
-//             //!> Round-off correction
-//             //!
-//             //!> Similar to Kahan summation algorithm (https://en.wikipedia.org/wiki/Kahan_summation_algorithm)
-//             //!> Essentially computes the round-off error of the applied force and adds it in the next time step as a compensation.
-//             //!> Seems to be necesseary at very high Re boundary layers, where the forcing and velocity can  
-//             //!> differ by several orders of magnitude.
-//             //!> \note 16/05/2022: Testing, still ongoing! 
-//             //!
-//             bodyForceX[k] = (acc_x-(double)(vvx-vx))*factor*c2o1;
-//             bodyForceY[k] = (acc_y-(double)(vvy-vy))*factor*c2o1;
-//             bodyForceZ[k] = (acc_z-(double)(vvz-vz))*factor*c2o1;
-
-//         }
-//         else{
-//             vvx += fx * c1o2 / factor;
-//             vvy += fy * c1o2 / factor;
-//             vvz += fz * c1o2 / factor;
-//         }
-        
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // calculate the square of velocities for this lattice node
-//         real vx2 = vvx * vvx;
-//         real vy2 = vvy * vvy;
-//         real vz2 = vvz * vvz;
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Set relaxation limiters for third order cumulants to default value \f$ \lambda=0.001 \f$ according to
-//         //! section 6 in \ref <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
-//         //!
-//         real wadjust;
-//         real qudricLimitP = quadricLimiters[0];
-//         real qudricLimitM = quadricLimiters[1];
-//         real qudricLimitD = quadricLimiters[2];
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Chimera transform from well conditioned distributions to central moments as defined in Appendix J in \ref
-//         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-//         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (6)-(14) in \ref <a
-//         //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040
-//         //! ]</b></a>
-//         //!
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // Z - Dir
-//         forwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36o1, c1o36);
-//         forwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9o1, c1o9);
-//         forwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36o1, c1o36);
-//         forwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9o1, c1o9);
-//         forwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9);
-//         forwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9o1, c1o9);
-//         forwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36o1, c1o36);
-//         forwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9o1, c1o9);
-//         forwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // Y - Dir
-//         forwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6o1, c1o6);
-//         forwardChimera(mfaab, mfabb, mfacb, vvy, vy2);
-//         forwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18o1, c1o18);
-//         forwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3);
-//         forwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2);
-//         forwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9);
-//         forwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6o1, c1o6);
-//         forwardChimera(mfcab, mfcbb, mfccb, vvy, vy2);
-//         forwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18o1, c1o18);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // X - Dir
-//         forwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1o1, c1o1);
-//         forwardChimera(mfaba, mfbba, mfcba, vvx, vx2);
-//         forwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3o1, c1o3);
-//         forwardChimera(mfaab, mfbab, mfcab, vvx, vx2);
-//         forwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2);
-//         forwardChimera(mfacb, mfbcb, mfccb, vvx, vx2);
-//         forwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3o1, c1o3);
-//         forwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2);
-//         forwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c3o1, c1o9);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Setting relaxation rates for non-hydrodynamic cumulants (default values). Variable names and equations
-//         //! according to <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
-//         //!  => [NAME IN PAPER]=[NAME IN CODE]=[DEFAULT VALUE].
-//         //!  - Trace of second order cumulants \f$ C_{200}+C_{020}+C_{002} \f$ used to adjust bulk
-//         //!  viscosity:\f$\omega_2=OxxPyyPzz=1.0 \f$.
-//         //!  - Third order cumulants \f$ C_{120}+C_{102}, C_{210}+C_{012}, C_{201}+C_{021} \f$: \f$ \omega_3=OxyyPxzz
-//         //!  \f$ set according to Eq. (111) with simplifications assuming \f$ \omega_2=1.0\f$.
-//         //!  - Third order cumulants \f$ C_{120}-C_{102}, C_{210}-C_{012}, C_{201}-C_{021} \f$: \f$ \omega_4 = OxyyMxzz
-//         //!  \f$ set according to Eq. (112) with simplifications assuming \f$ \omega_2 = 1.0\f$.
-//         //!  - Third order cumulants \f$ C_{111} \f$: \f$ \omega_5 = Oxyz \f$ set according to Eq. (113) with
-//         //!  simplifications assuming \f$ \omega_2 = 1.0\f$  (modify for different bulk viscosity).
-//         //!  - Fourth order cumulants \f$ C_{220}, C_{202}, C_{022}, C_{211}, C_{121}, C_{112} \f$: for simplification
-//         //!  all set to the same default value \f$ \omega_6=\omega_7=\omega_8=O4=1.0 \f$.
-//         //!  - Fifth order cumulants \f$ C_{221}, C_{212}, C_{122}\f$: \f$\omega_9=O5=1.0\f$.
-//         //!  - Sixth order cumulant \f$ C_{222}\f$: \f$\omega_{10}=O6=1.0\f$.
-//         //!
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Calculate modified omega with turbulent viscosity
-//         //!
-//         real omega = omega_in / (c1o1 + c3o1*omega_in*turbulentViscosity[k]);
-//         ////////////////////////////////////////////////////////////
-//         // 2.
-//         real OxxPyyPzz = c1o1;
-//         ////////////////////////////////////////////////////////////
-//         // 3.
-//         real OxyyPxzz = c8o1 * (-c2o1 + omega) * (c1o1 + c2o1 * omega) / (-c8o1 - c14o1 * omega + c7o1 * omega * omega);
-//         real OxyyMxzz =
-//             c8o1 * (-c2o1 + omega) * (-c7o1 + c4o1 * omega) / (c56o1 - c50o1 * omega + c9o1 * omega * omega);
-//         real Oxyz = c24o1 * (-c2o1 + omega) * (-c2o1 - c7o1 * omega + c3o1 * omega * omega) /
-//                     (c48o1 + c152o1 * omega - c130o1 * omega * omega + c29o1 * omega * omega * omega);
-//         ////////////////////////////////////////////////////////////
-//         // 4.
-//         real O4 = c1o1;
-//         ////////////////////////////////////////////////////////////
-//         // 5.
-//         real O5 = c1o1;
-//         ////////////////////////////////////////////////////////////
-//         // 6.
-//         real O6 = c1o1;
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - A and DIR_00M: parameters for fourth order convergence of the diffusion term according to Eq. (115) and (116)
-//         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> with simplifications assuming \f$ \omega_2 = 1.0 \f$ (modify for
-//         //! different bulk viscosity).
-//         //!
-//         real A = (c4o1 + c2o1 * omega - c3o1 * omega * omega) / (c2o1 - c7o1 * omega + c5o1 * omega * omega);
-//         real DIR_00M = (c4o1 + c28o1 * omega - c14o1 * omega * omega) / (c6o1 - c21o1 * omega + c15o1 * omega * omega);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Compute cumulants from central moments according to Eq. (20)-(23) in
-//         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
-//         //!
-//         ////////////////////////////////////////////////////////////
-//         // 4.
-//         real CUMcbb = mfcbb - ((mfcaa + c1o3) * mfabb + c2o1 * mfbba * mfbab) * OOrho;
-//         real CUMbcb = mfbcb - ((mfaca + c1o3) * mfbab + c2o1 * mfbba * mfabb) * OOrho;
-//         real CUMbbc = mfbbc - ((mfaac + c1o3) * mfbba + c2o1 * mfbab * mfabb) * OOrho;
-
-//         real CUMcca =
-//             mfcca - (((mfcaa * mfaca + c2o1 * mfbba * mfbba) + c1o3 * (mfcaa + mfaca)) * OOrho - c1o9 * (drho * OOrho));
-//         real CUMcac =
-//             mfcac - (((mfcaa * mfaac + c2o1 * mfbab * mfbab) + c1o3 * (mfcaa + mfaac)) * OOrho - c1o9 * (drho * OOrho));
-//         real CUMacc =
-//             mfacc - (((mfaac * mfaca + c2o1 * mfabb * mfabb) + c1o3 * (mfaac + mfaca)) * OOrho - c1o9 * (drho * OOrho));
-//         ////////////////////////////////////////////////////////////
-//         // 5.
-//         real CUMbcc =
-//             mfbcc - ((mfaac * mfbca + mfaca * mfbac + c4o1 * mfabb * mfbbb + c2o1 * (mfbab * mfacb + mfbba * mfabc)) +
-//                      c1o3 * (mfbca + mfbac)) *
-//                         OOrho;
-//         real CUMcbc =
-//             mfcbc - ((mfaac * mfcba + mfcaa * mfabc + c4o1 * mfbab * mfbbb + c2o1 * (mfabb * mfcab + mfbba * mfbac)) +
-//                      c1o3 * (mfcba + mfabc)) *
-//                         OOrho;
-//         real CUMccb =
-//             mfccb - ((mfcaa * mfacb + mfaca * mfcab + c4o1 * mfbba * mfbbb + c2o1 * (mfbab * mfbca + mfabb * mfcba)) +
-//                      c1o3 * (mfacb + mfcab)) *
-//                         OOrho;
-//         ////////////////////////////////////////////////////////////
-//         // 6.
-//         real CUMccc = mfccc + ((-c4o1 * mfbbb * mfbbb - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) -
-//                                 c4o1 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) -
-//                                 c2o1 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) *
-//                                    OOrho +
-//                                (c4o1 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) +
-//                                 c2o1 * (mfcaa * mfaca * mfaac) + c16o1 * mfbba * mfbab * mfabb) *
-//                                    OOrho * OOrho -
-//                                c1o3 * (mfacc + mfcac + mfcca) * OOrho - c1o9 * (mfcaa + mfaca + mfaac) * OOrho +
-//                                (c2o1 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) +
-//                                 (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) *
-//                                    OOrho * OOrho * c2o3 +
-//                                c1o27 * ((drho * drho - drho) * OOrho * OOrho));
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Compute linear combinations of second and third order cumulants
-//         //!
-//         ////////////////////////////////////////////////////////////
-//         // 2.
-//         real mxxPyyPzz = mfcaa + mfaca + mfaac;
-//         real mxxMyy    = mfcaa - mfaca;
-//         real mxxMzz    = mfcaa - mfaac;
-//         ////////////////////////////////////////////////////////////
-//         // 3.
-//         real mxxyPyzz = mfcba + mfabc;
-//         real mxxyMyzz = mfcba - mfabc;
-
-//         real mxxzPyyz = mfcab + mfacb;
-//         real mxxzMyyz = mfcab - mfacb;
-
-//         real mxyyPxzz = mfbca + mfbac;
-//         real mxyyMxzz = mfbca - mfbac;
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // incl. correction
-//         ////////////////////////////////////////////////////////////
-//         //! - Compute velocity  gradients from second order cumulants according to Eq. (27)-(32)
-//         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> Further explanations of the correction in viscosity in Appendix H of
-//         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-//         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> Note that the division by rho is omitted here as we need rho times
-//         //! the gradients later.
-//         //!
-//         real Dxy  = -c3o1 * omega * mfbba;
-//         real Dxz  = -c3o1 * omega * mfbab;
-//         real Dyz  = -c3o1 * omega * mfabb;
-//         real dxux = c1o2 * (-omega) * (mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz * (mfaaa - mxxPyyPzz);
-//         real dyuy = dxux + omega * c3o2 * mxxMyy;
-//         real dzuz = dxux + omega * c3o2 * mxxMzz;
-
-//         //Smagorinsky for debugging
-//         // if(true)
-//         // {   
-//             // if(false && k==99976)
-//             // {
-//             //     printf("dudz+dwdu: \t %1.14f \n", Dxz );
-//             //     printf("dvdz+dudy: \t %1.14f \n", Dxy );  
-//             //     printf("dwdy+dvdz: \t %1.14f \n", Dyz );  
-//             //     printf("nu_t * dudz+dwdu: \t %1.14f \n", turbulentViscosity[k]*Dxz );
-//             //     printf("nu_t * dvdz+dudy: \t %1.14f \n", turbulentViscosity[k]*Dxy );  
-//             //     printf("nu_t * dwdy+dvdz: \t %1.14f \n", turbulentViscosity[k]*Dyz );      
-//             // } 
-//         //     real Sbar = sqrt(c2o1*(dxux*dxux+dyuy*dyuy+dzuz*dzuz)+Dxy*Dxy+Dxz*Dxz+Dyz*Dyz);
-//         //     real Cs = 0.08f;
-//         //     turbulentViscosity[k] = Cs*Cs*Sbar;
-//         // }
-
-//         ////////////////////////////////////////////////////////////
-//         //! - Relaxation of second order cumulants with correction terms according to Eq. (33)-(35) in
-//         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
-//         //!
-//         mxxPyyPzz +=
-//             OxxPyyPzz * (mfaaa - mxxPyyPzz) - c3o1 * (c1o1 - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz);
-//         mxxMyy += omega * (-mxxMyy) - c3o1 * (c1o1 + c1o2 * (-omega)) * (vx2 * dxux - vy2 * dyuy);
-//         mxxMzz += omega * (-mxxMzz) - c3o1 * (c1o1 + c1o2 * (-omega)) * (vx2 * dxux - vz2 * dzuz);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         ////no correction
-//         // mxxPyyPzz += OxxPyyPzz*(mfaaa - mxxPyyPzz);
-//         // mxxMyy += -(-omega) * (-mxxMyy);
-//         // mxxMzz += -(-omega) * (-mxxMzz);
-//         //////////////////////////////////////////////////////////////////////////
-//         mfabb += omega * (-mfabb);
-//         mfbab += omega * (-mfbab);
-//         mfbba += omega * (-mfbba);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // relax
-//         //////////////////////////////////////////////////////////////////////////
-//         // incl. limiter
-//         //! - Relaxation of third order cumulants including limiter according to Eq. (116)-(123)
-//         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
-//         //!
-//         wadjust = Oxyz + (c1o1 - Oxyz) * abs(mfbbb) / (abs(mfbbb) + qudricLimitD);
-//         mfbbb += wadjust * (-mfbbb);
-//         wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxxyPyzz) / (abs(mxxyPyzz) + qudricLimitP);
-//         mxxyPyzz += wadjust * (-mxxyPyzz);
-//         wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxxyMyzz) / (abs(mxxyMyzz) + qudricLimitM);
-//         mxxyMyzz += wadjust * (-mxxyMyzz);
-//         wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxxzPyyz) / (abs(mxxzPyyz) + qudricLimitP);
-//         mxxzPyyz += wadjust * (-mxxzPyyz);
-//         wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxxzMyyz) / (abs(mxxzMyyz) + qudricLimitM);
-//         mxxzMyyz += wadjust * (-mxxzMyyz);
-//         wadjust = OxyyPxzz + (c1o1 - OxyyPxzz) * abs(mxyyPxzz) / (abs(mxyyPxzz) + qudricLimitP);
-//         mxyyPxzz += wadjust * (-mxyyPxzz);
-//         wadjust = OxyyMxzz + (c1o1 - OxyyMxzz) * abs(mxyyMxzz) / (abs(mxyyMxzz) + qudricLimitM);
-//         mxyyMxzz += wadjust * (-mxyyMxzz);
-//         //////////////////////////////////////////////////////////////////////////
-//         // no limiter
-//         // mfbbb += OxyyMxzz * (-mfbbb);
-//         // mxxyPyzz += OxyyPxzz * (-mxxyPyzz);
-//         // mxxyMyzz += OxyyMxzz * (-mxxyMyzz);
-//         // mxxzPyyz += OxyyPxzz * (-mxxzPyyz);
-//         // mxxzMyyz += OxyyMxzz * (-mxxzMyyz);
-//         // mxyyPxzz += OxyyPxzz * (-mxyyPxzz);
-//         // mxyyMxzz += OxyyMxzz * (-mxyyMxzz);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Compute inverse linear combinations of second and third order cumulants
-//         //!
-//         mfcaa = c1o3 * (mxxMyy + mxxMzz + mxxPyyPzz);
-//         mfaca = c1o3 * (-c2o1 * mxxMyy + mxxMzz + mxxPyyPzz);
-//         mfaac = c1o3 * (mxxMyy - c2o1 * mxxMzz + mxxPyyPzz);
-
-//         mfcba = (mxxyMyzz + mxxyPyzz) * c1o2;
-//         mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
-//         mfcab = (mxxzMyyz + mxxzPyyz) * c1o2;
-//         mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
-//         mfbca = (mxyyMxzz + mxyyPxzz) * c1o2;
-//         mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
-//         //////////////////////////////////////////////////////////////////////////
-
-//         //////////////////////////////////////////////////////////////////////////
-//         // 4.
-//         // no limiter
-//         //! - Relax fourth order cumulants to modified equilibrium for fourth order convergence of diffusion according
-//         //! to Eq. (43)-(48) <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
-//         //!
-//         CUMacc = -O4 * (c1o1 / omega - c1o2) * (dyuy + dzuz) * c2o3 * A + (c1o1 - O4) * (CUMacc);
-//         CUMcac = -O4 * (c1o1 / omega - c1o2) * (dxux + dzuz) * c2o3 * A + (c1o1 - O4) * (CUMcac);
-//         CUMcca = -O4 * (c1o1 / omega - c1o2) * (dyuy + dxux) * c2o3 * A + (c1o1 - O4) * (CUMcca);
-//         CUMbbc = -O4 * (c1o1 / omega - c1o2) * Dxy * c1o3 * DIR_00M + (c1o1 - O4) * (CUMbbc);
-//         CUMbcb = -O4 * (c1o1 / omega - c1o2) * Dxz * c1o3 * DIR_00M + (c1o1 - O4) * (CUMbcb);
-//         CUMcbb = -O4 * (c1o1 / omega - c1o2) * Dyz * c1o3 * DIR_00M + (c1o1 - O4) * (CUMcbb);
-
-//         //////////////////////////////////////////////////////////////////////////
-//         // 5.
-//         CUMbcc += O5 * (-CUMbcc);
-//         CUMcbc += O5 * (-CUMcbc);
-//         CUMccb += O5 * (-CUMccb);
-
-//         //////////////////////////////////////////////////////////////////////////
-//         // 6.
-//         CUMccc += O6 * (-CUMccc);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Compute central moments from post collision cumulants according to Eq. (53)-(56) in
-//         //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
-//         //!
-
-//         //////////////////////////////////////////////////////////////////////////
-//         // 4.
-//         mfcbb = CUMcbb + c1o3 * ((c3o1 * mfcaa + c1o1) * mfabb + c6o1 * mfbba * mfbab) * OOrho;
-//         mfbcb = CUMbcb + c1o3 * ((c3o1 * mfaca + c1o1) * mfbab + c6o1 * mfbba * mfabb) * OOrho;
-//         mfbbc = CUMbbc + c1o3 * ((c3o1 * mfaac + c1o1) * mfbba + c6o1 * mfbab * mfabb) * OOrho;
-
-//         mfcca =
-//             CUMcca +
-//             (((mfcaa * mfaca + c2o1 * mfbba * mfbba) * c9o1 + c3o1 * (mfcaa + mfaca)) * OOrho - (drho * OOrho)) * c1o9;
-//         mfcac =
-//             CUMcac +
-//             (((mfcaa * mfaac + c2o1 * mfbab * mfbab) * c9o1 + c3o1 * (mfcaa + mfaac)) * OOrho - (drho * OOrho)) * c1o9;
-//         mfacc =
-//             CUMacc +
-//             (((mfaac * mfaca + c2o1 * mfabb * mfabb) * c9o1 + c3o1 * (mfaac + mfaca)) * OOrho - (drho * OOrho)) * c1o9;
-
-//         //////////////////////////////////////////////////////////////////////////
-//         // 5.
-//         mfbcc = CUMbcc + c1o3 *
-//                              (c3o1 * (mfaac * mfbca + mfaca * mfbac + c4o1 * mfabb * mfbbb +
-//                                       c2o1 * (mfbab * mfacb + mfbba * mfabc)) +
-//                               (mfbca + mfbac)) *
-//                              OOrho;
-//         mfcbc = CUMcbc + c1o3 *
-//                              (c3o1 * (mfaac * mfcba + mfcaa * mfabc + c4o1 * mfbab * mfbbb +
-//                                       c2o1 * (mfabb * mfcab + mfbba * mfbac)) +
-//                               (mfcba + mfabc)) *
-//                              OOrho;
-//         mfccb = CUMccb + c1o3 *
-//                              (c3o1 * (mfcaa * mfacb + mfaca * mfcab + c4o1 * mfbba * mfbbb +
-//                                       c2o1 * (mfbab * mfbca + mfabb * mfcba)) +
-//                               (mfacb + mfcab)) *
-//                              OOrho;
-
-//         //////////////////////////////////////////////////////////////////////////
-//         // 6.
-//         mfccc = CUMccc - ((-c4o1 * mfbbb * mfbbb - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) -
-//                            c4o1 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) -
-//                            c2o1 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) *
-//                               OOrho +
-//                           (c4o1 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) +
-//                            c2o1 * (mfcaa * mfaca * mfaac) + c16o1 * mfbba * mfbab * mfabb) *
-//                               OOrho * OOrho -
-//                           c1o3 * (mfacc + mfcac + mfcca) * OOrho - c1o9 * (mfcaa + mfaca + mfaac) * OOrho +
-//                           (c2o1 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) +
-//                            (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) *
-//                               OOrho * OOrho * c2o3 +
-//                           c1o27 * ((drho * drho - drho) * OOrho * OOrho));
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! -  Add acceleration (body force) to first order cumulants according to Eq. (85)-(87) in
-//         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-//         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
-//         //!
-//         mfbaa = -mfbaa;
-//         mfaba = -mfaba;
-//         mfaab = -mfaab;
-
-
-//         //Write to array here to distribute read/write
-//         rho[k] = drho;
-//         vx[k] = vvx;
-//         vy[k] = vvy;
-//         vz[k] = vvz;
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Chimera transform from central moments to well conditioned distributions as defined in Appendix J in
-//         //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-//         //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (88)-(96) in <a
-//         //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040
-//         //! ]</b></a>
-//         //!
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // X - Dir
-//         backwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1o1, c1o1);
-//         backwardChimera(mfaba, mfbba, mfcba, vvx, vx2);
-//         backwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3o1, c1o3);
-//         backwardChimera(mfaab, mfbab, mfcab, vvx, vx2);
-//         backwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2);
-//         backwardChimera(mfacb, mfbcb, mfccb, vvx, vx2);
-//         backwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3o1, c1o3);
-//         backwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2);
-//         backwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c9o1, c1o9);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // Y - Dir
-//         backwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6o1, c1o6);
-//         backwardChimera(mfaab, mfabb, mfacb, vvy, vy2);
-//         backwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18o1, c1o18);
-//         backwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3);
-//         backwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2);
-//         backwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9);
-//         backwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6o1, c1o6);
-//         backwardChimera(mfcab, mfcbb, mfccb, vvy, vy2);
-//         backwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18o1, c1o18);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         // Z - Dir
-//         backwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36o1, c1o36);
-//         backwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9o1, c1o9);
-//         backwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36o1, c1o36);
-//         backwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9o1, c1o9);
-//         backwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9);
-//         backwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9o1, c1o9);
-//         backwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36o1, c1o36);
-//         backwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9o1, c1o9);
-//         backwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);
-
-//         ////////////////////////////////////////////////////////////////////////////////////
-//         //! - Write distributions: style of reading and writing the distributions from/to
-//         //! stored arrays dependent on timestep is based on the esoteric twist algorithm
-//         //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
-//         //! DOI:10.3390/computation5020019 ]</b></a>
-//         //!
-
-
-//         distr_wrapper.distribution.f[DIR_P00]      = mfabb;
-//         distr_wrapper.distribution.f[DIR_M00]      = mfcbb;
-//         distr_wrapper.distribution.f[DIR_0P0]      = mfbab;
-//         distr_wrapper.distribution.f[DIR_0M0]      = mfbcb;
-//         distr_wrapper.distribution.f[DIR_00P]      = mfbba;
-//         distr_wrapper.distribution.f[DIR_00M]      = mfbbc;
-//         distr_wrapper.distribution.f[DIR_PP0]     = mfaab;
-//         distr_wrapper.distribution.f[DIR_MM0]     = mfccb;
-//         distr_wrapper.distribution.f[DIR_PM0]     = mfacb;
-//         distr_wrapper.distribution.f[DIR_MP0]     = mfcab;
-//         distr_wrapper.distribution.f[DIR_P0P]     = mfaba;
-//         distr_wrapper.distribution.f[DIR_M0M]     = mfcbc;
-//         distr_wrapper.distribution.f[DIR_P0M]     = mfabc;
-//         distr_wrapper.distribution.f[DIR_M0P]     = mfcba;
-//         distr_wrapper.distribution.f[DIR_0PP]     = mfbaa;
-//         distr_wrapper.distribution.f[DIR_0MM]     = mfbcc;
-//         distr_wrapper.distribution.f[DIR_0PM]     = mfbac;
-//         distr_wrapper.distribution.f[DIR_0MP]     = mfbca;
-//         distr_wrapper.distribution.f[DIR_000]   = mfbbb;
-//         distr_wrapper.distribution.f[DIR_PPP]    = mfaaa;
-//         distr_wrapper.distribution.f[DIR_MMP]    = mfaca;
-//         distr_wrapper.distribution.f[DIR_PMP]    = mfaac;
-//         distr_wrapper.distribution.f[DIR_MPP]    = mfacc;
-//         distr_wrapper.distribution.f[DIR_PPM]    = mfcaa;
-//         distr_wrapper.distribution.f[DIR_MMM]    = mfcca;
-//         distr_wrapper.distribution.f[DIR_PMM]    = mfcac;
-//         distr_wrapper.distribution.f[DIR_MPM]    = mfccc;
-
-//         distr_wrapper.write();
-//         if(k==100000)
-//         {
-//             printf("mfcbb \t %f \t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f \n\n", 
-//                                                 (dist.f[DIR_P00])[k]                  ,        
-//                                                 (dist.f[DIR_0P0])[k]       ,
-//                                                 (dist.f[DIR_0M0])[ks]      ,
-//                                                 (dist.f[DIR_00P])[k]       ,
-//                                                 (dist.f[DIR_00M])[kb]      ,
-//                                                 (dist.f[DIR_PP0])[k]      ,
-//                                                 (dist.f[DIR_MM0])[ksw]    ,
-//                                                 (dist.f[DIR_PM0])[ks]     ,
-//                                                 (dist.f[DIR_MP0])[kw]   ,
-//                                                 (dist.f[DIR_M00])[kw]    ,
-//                                                 (dist.f[DIR_P0P])[k]    ,
-//                                                 (dist.f[DIR_M0M])[kbw]  ,
-//                                                 (dist.f[DIR_P0M])[kb]   ,
-//                                                 (dist.f[DIR_M0P])[kw]   ,
-//                                                 (dist.f[DIR_0PP])[k]    ,
-//                                                 (dist.f[DIR_0MM])[kbs]  ,
-//                                                 (dist.f[DIR_0PM])[kb]   ,
-//                                                 (dist.f[DIR_0MP])[ks]   ,
-//                                                 (dist.f[DIR_000])[k]  ,
-//                                                 (dist.f[DIR_PPP])[k]   ,
-//                                                 (dist.f[DIR_PMP])[ks]  ,
-//                                                 (dist.f[DIR_PPM])[kb]  ,
-//                                                 (dist.f[DIR_PMM])[kbs] ,
-//                                                 (dist.f[DIR_MPP])[kw]  ,
-//                                                 (dist.f[DIR_MMP])[ksw] ,
-//                                                 (dist.f[DIR_MPM])[kbw] ,
-//                                                 (dist.f[DIR_MMM])[kbsw]);
-//         }
-
-//         (dist.f[DIR_P00])[k]      = mfabb;
-//         (dist.f[DIR_M00])[kw]     = mfcbb;
-//         (dist.f[DIR_0P0])[k]      = mfbab;
-//         (dist.f[DIR_0M0])[ks]     = mfbcb;
-//         (dist.f[DIR_00P])[k]      = mfbba;
-//         (dist.f[DIR_00M])[kb]     = mfbbc;
-//         (dist.f[DIR_PP0])[k]     = mfaab;
-//         (dist.f[DIR_MM0])[ksw]   = mfccb;
-//         (dist.f[DIR_PM0])[ks]    = mfacb;
-//         (dist.f[DIR_MP0])[kw]    = mfcab;
-//         (dist.f[DIR_P0P])[k]     = mfaba;
-//         (dist.f[DIR_M0M])[kbw]   = mfcbc;
-//         (dist.f[DIR_P0M])[kb]    = mfabc;
-//         (dist.f[DIR_M0P])[kw]    = mfcba;
-//         (dist.f[DIR_0PP])[k]     = mfbaa;
-//         (dist.f[DIR_0MM])[kbs]   = mfbcc;
-//         (dist.f[DIR_0PM])[kb]    = mfbac;
-//         (dist.f[DIR_0MP])[ks]    = mfbca;
-//         (dist.f[DIR_000])[k]   = mfbbb;
-//         (dist.f[DIR_PPP])[k]    = mfaaa;
-//         (dist.f[DIR_PMP])[ks]   = mfaca;
-//         (dist.f[DIR_PPM])[kb]   = mfaac;
-//         (dist.f[DIR_PMM])[kbs]  = mfacc;
-//         (dist.f[DIR_MPP])[kw]   = mfcaa;
-//         (dist.f[DIR_MMP])[ksw]  = mfcca;
-//         (dist.f[DIR_MPM])[kbw]  = mfcac;
-//         (dist.f[DIR_MMM])[kbsw] = mfccc;
-        
-//         if(k==100000)
-//         {
-//             printf("mfcbb \t %f \t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f \n\n\n", 
-//                                                 (dist.f[DIR_P00])[k]                  ,        
-//                                                 (dist.f[DIR_0P0])[k]       ,
-//                                                 (dist.f[DIR_0M0])[ks]      ,
-//                                                 (dist.f[DIR_00P])[k]       ,
-//                                                 (dist.f[DIR_00M])[kb]      ,
-//                                                 (dist.f[DIR_PP0])[k]      ,
-//                                                 (dist.f[DIR_MM0])[ksw]    ,
-//                                                 (dist.f[DIR_PM0])[ks]     ,
-//                                                 (dist.f[DIR_MP0])[kw]   ,
-//                                                 (dist.f[DIR_M00])[kw]   ,
-//                                                 (dist.f[DIR_P0P])[k]    ,
-//                                                 (dist.f[DIR_M0M])[kbw]  ,
-//                                                 (dist.f[DIR_P0M])[kb]   ,
-//                                                 (dist.f[DIR_M0P])[kw]   ,
-//                                                 (dist.f[DIR_0PP])[k]    ,
-//                                                 (dist.f[DIR_0MM])[kbs]  ,
-//                                                 (dist.f[DIR_0PM])[kb]   ,
-//                                                 (dist.f[DIR_0MP])[ks]   ,
-//                                                 (dist.f[DIR_000])[k]  ,
-//                                                 (dist.f[DIR_PPP])[k]   ,
-//                                                 (dist.f[DIR_PMP])[ks]  ,
-//                                                 (dist.f[DIR_PPM])[kb]  ,
-//                                                 (dist.f[DIR_PMM])[kbs] ,
-//                                                 (dist.f[DIR_MPP])[kw]  ,
-//                                                 (dist.f[DIR_MMP])[ksw] ,
-//                                                 (dist.f[DIR_MPM])[kbw] ,
-//                                                 (dist.f[DIR_MMM])[kbsw]);
-//         }
-//     }
-// }
\ No newline at end of file
+template __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim < TurbulenceModel::QR > ( real omega_in, uint* typeOfGridNode, uint* neighborX, uint* neighborY, uint* neighborZ, real* distributions, real* rho, real* vx, real* vy, real* vz, real* turbulentViscosity, real SGSconstant, unsigned long size_Mat, int level, bool bodyForce, real* forces, real* bodyForceX, real* bodyForceY, real* bodyForceZ, real* quadricLimiters, bool isEvenTimestep);
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cuh b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cuh
index 3633dfa4e18d057d60acf68faf348d3c5f5855d8..5ef37557399f263d25edf03b02b00f6a03c6e1cb 100644
--- a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cuh
+++ b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/TurbulentViscosityKernels/FluidFlow/Compressible/CumulantK17chim/TurbulentViscosityCumulantK17CompChim_Device.cuh
@@ -4,7 +4,7 @@
 #include <DataTypes.h>
 #include <curand.h>
 
-__global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
+template< TurbulenceModel turbulenceModel > __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
 	real omega_in,
 	uint* typeOfGridNode,
 	uint* neighborX,
@@ -16,6 +16,7 @@ __global__ void LB_Kernel_TurbulentViscosityCumulantK17CompChim(
     real* vy,
     real* vz,
 	real* turbulentViscosity,
+	real SGSconstant,
 	unsigned long size_Mat,
 	int level,
 	bool bodyForce,
diff --git a/src/gpu/VirtualFluids_GPU/Kernel/Utilities/KernelFactory/KernelFactoryImp.cpp b/src/gpu/VirtualFluids_GPU/Kernel/Utilities/KernelFactory/KernelFactoryImp.cpp
index 808bd005e8daa7850e10136f7b5d46147078857f..53ec240f096080097416e640fdd095c3812fb34c 100644
--- a/src/gpu/VirtualFluids_GPU/Kernel/Utilities/KernelFactory/KernelFactoryImp.cpp
+++ b/src/gpu/VirtualFluids_GPU/Kernel/Utilities/KernelFactory/KernelFactoryImp.cpp
@@ -195,11 +195,32 @@ std::shared_ptr<Kernel> KernelFactoryImp::makeKernel(std::shared_ptr<Parameter>
         checkStrategy = WaleFluidFlowCompStrategy::getInstance();
     } else if (kernel == "WaleBySoniMalavCumulantK15Comp") {                    //     /\      //
         newKernel     = WaleBySoniMalavCumulantK15Comp::getNewInstance(para, level);// ||
-        checkStrategy = WaleFluidFlowCompStrategy::getInstance();                    // wale model
-    }                                                                           //===============
-    else if (kernel == "TurbulentViscosityCumulantK17CompChim"){                               // AMD model
-        newKernel     = TurbulentViscosityCumulantK17CompChim::getNewInstance(para, level);    //      ||
-        checkStrategy = TurbulentViscosityFluidFlowCompStrategy::getInstance();                //      \/
+        checkStrategy = WaleFluidFlowCompStrategy::getInstance();               // wale model
+    }                                                                          //===============
+    else if (kernel == "TurbulentViscosityCumulantK17CompChim"){               // compressible with turbulent viscosity
+        switch(para->getTurbulenceModel())                                     //       ||          
+        {                                                                      //       \/      //
+            case TurbulenceModel::AMD:
+                newKernel = TurbulentViscosityCumulantK17CompChim<TurbulenceModel::AMD>::getNewInstance(para, level);   
+                break;
+            case TurbulenceModel::Smagorinsky:
+                newKernel = TurbulentViscosityCumulantK17CompChim<TurbulenceModel::Smagorinsky>::getNewInstance(para, level);  
+                break;
+            case TurbulenceModel::QR:
+                newKernel = TurbulentViscosityCumulantK17CompChim<TurbulenceModel::QR>::getNewInstance(para, level);  
+                break;
+            case TurbulenceModel::None:
+                throw std::runtime_error("TurbulentViscosityCumulantK17CompChim currently not implemented for TurbulenceModel::None!");
+                break;
+            default:
+                throw std::runtime_error("Unknown turbulence model!");
+            break;                                                              
+        }                                                                       
+        checkStrategy = TurbulentViscosityFluidFlowCompStrategy::getInstance(); 
+                                                                                //     /\      //
+                                                                                //     ||    
+                                                                                // compressible with turbulent viscosity  
+                                                                                //===============         
     }
     else {
         throw std::runtime_error("KernelFactory does not know the KernelType.");
diff --git a/src/gpu/VirtualFluids_GPU/LBM/LB.h b/src/gpu/VirtualFluids_GPU/LBM/LB.h
index 10bfa5977f7cccb421d05f94c876a185cd667fcb..eea4adfda3c1ef0862f39ef58fc6e065af7bab1b 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/LB.h
+++ b/src/gpu/VirtualFluids_GPU/LBM/LB.h
@@ -50,6 +50,19 @@
 #include <string>
 #include <vector>
 
+//! \brief An enumeration for selecting a turbulence model
+enum class TurbulenceModel {
+   //! - Smagorinsky
+    Smagorinsky,
+    //! - AMD (Anisotropic Minimum Dissipation) model, see e.g. Rozema et al., Phys. Fluids 27, 085107 (2015), https://doi.org/10.1063/1.4928700
+    AMD,
+    //! - QR model by Verstappen 
+    QR,
+    //! - TODO: move the WALE model here from the old kernels
+    //WALE
+    //! - No turbulence model
+    None
+};
 
 struct InitCondition
 {
@@ -122,8 +135,8 @@ struct InitCondition
    bool calcMedian {false};
    bool isConc {false};
    bool isWale {false};
+   TurbulenceModel turbulenceModel {TurbulenceModel::None};
    bool isTurbulentViscosity {false};
-   bool isAMD {false};
    real SGSConstant {0.0};
    bool isMeasurePoints {false};
    bool isInitNeq {false};
@@ -285,6 +298,8 @@ typedef struct PLP{
 	uint memSizeID, memSizeTimestep, memSizerealAll, memSizereal, memSizeBool, memSizeBoolBC;
 }PathLineParticles;
 
+
+
 //////////////////////////////////////////////////////////////////////////
 inline int vectorPosition(int i, int j, int k, int Lx, int Ly )
 {
diff --git a/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp b/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
index b2bf4853b3d822ad308131c69c1de38200d8ae5e..83ca85243ae4e8cc8ff1316e73ed8c5ae3816516 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
+++ b/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
@@ -56,7 +56,7 @@
 #include "PreProcessor/PreProcessorFactory/PreProcessorFactoryImp.h"
 #include "Kernel/Utilities/KernelFactory/KernelFactoryImp.h"
 #include "Kernel/Kernel.h"
-
+#include "TurbulenceModels/TurbulenceModelFactory.h"
 #include <cuda/DeviceInfo.h>
 
 #include <logger/Logger.h>
@@ -73,10 +73,19 @@ Simulation::Simulation(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemo
     : para(para), cudaMemoryManager(memoryManager), communicator(communicator), kernelFactory(std::make_unique<KernelFactoryImp>()),
       preProcessorFactory(std::make_shared<PreProcessorFactoryImp>()), dataWriter(std::make_unique<FileWriter>())
 {
-    init(gridProvider, bcFactory);
+	this->tmFactory = SPtr<TurbulenceModelFactory>( new TurbulenceModelFactory(para) );
+	init(gridProvider, bcFactory, tmFactory);
+}
+
+Simulation::Simulation(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> memoryManager,
+                       vf::gpu::Communicator &communicator, GridProvider &gridProvider, BoundaryConditionFactory* bcFactory, SPtr<TurbulenceModelFactory> tmFactory)
+    : para(para), cudaMemoryManager(memoryManager), communicator(communicator), kernelFactory(std::make_unique<KernelFactoryImp>()),
+      preProcessorFactory(std::make_shared<PreProcessorFactoryImp>()), dataWriter(std::make_unique<FileWriter>())
+{
+	init(gridProvider, bcFactory, tmFactory);
 }
 
-void Simulation::init(GridProvider &gridProvider, BoundaryConditionFactory *bcFactory)
+void Simulation::init(GridProvider &gridProvider, BoundaryConditionFactory *bcFactory, SPtr<TurbulenceModelFactory> tmFactory)
 {
     gridProvider.initalGridInformations();
 
@@ -117,8 +126,6 @@ void Simulation::init(GridProvider &gridProvider, BoundaryConditionFactory *bcFa
     VF_LOG_INFO("delta_rho:       {}", para->getDensityRatio());
     VF_LOG_INFO("QuadricLimiters: {}, \t{}, \t{}", para->getQuadricLimitersHost()[0],
                 para->getQuadricLimitersHost()[1], para->getQuadricLimitersHost()[2]);
-    if (para->getUseAMD())
-        VF_LOG_INFO("AMD SGS model:  {}", para->getSGSConstant());
     //////////////////////////////////////////////////////////////////////////
 
     /////////////////////////////////////////////////////////////////////////
@@ -348,7 +355,7 @@ void Simulation::init(GridProvider &gridProvider, BoundaryConditionFactory *bcFa
     //////////////////////////////////////////////////////////////////////////
     // Init UpdateGrid
     //////////////////////////////////////////////////////////////////////////
-    this->updateGrid27 = std::make_unique<UpdateGrid27>(para, communicator, cudaMemoryManager, pm, kernels, bcFactory);
+    this->updateGrid27 = std::make_unique<UpdateGrid27>(para, communicator, cudaMemoryManager, pm, kernels, bcFactory, tmFactory);
 
     //////////////////////////////////////////////////////////////////////////
     // Write Initialized Files
diff --git a/src/gpu/VirtualFluids_GPU/LBM/Simulation.h b/src/gpu/VirtualFluids_GPU/LBM/Simulation.h
index 3c3954fe909428a0e20f2755cb8befdbf64b1263..35a082a2387a87b28e2ba8ca8ff94279faad86f4 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/Simulation.h
+++ b/src/gpu/VirtualFluids_GPU/LBM/Simulation.h
@@ -29,12 +29,16 @@ class UpdateGrid27;
 class KineticEnergyAnalyzer;
 class EnstrophyAnalyzer;
 class BoundaryConditionFactory;
+class TurbulenceModelFactory;
 
 class Simulation
 {
 public:
     Simulation(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> memoryManager,
                vf::gpu::Communicator &communicator, GridProvider &gridProvider, BoundaryConditionFactory* bcFactory);
+	
+	Simulation(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> memoryManager,
+               vf::gpu::Communicator &communicator, GridProvider &gridProvider, BoundaryConditionFactory* bcFactory, SPtr<TurbulenceModelFactory> tmFactory);
 
     ~Simulation();
     void run();
@@ -46,7 +50,7 @@ public:
     void addEnstrophyAnalyzer(uint tAnalyse);
 
 private:
-	void init(GridProvider &gridProvider, BoundaryConditionFactory *bcFactory);
+	void init(GridProvider &gridProvider, BoundaryConditionFactory *bcFactory, SPtr<TurbulenceModelFactory> tmFactory);
     void allocNeighborsOffsetsScalesAndBoundaries(GridProvider& gridProvider);
     void porousMedia();
     void definePMarea(std::shared_ptr<PorousMedia>& pm);
@@ -72,6 +76,7 @@ private:
 	std::vector < SPtr< Kernel>> kernels;
 	std::vector < SPtr< ADKernel>> adKernels;
 	std::shared_ptr<PreProcessor> preProcessor;
+	SPtr<TurbulenceModelFactory> tmFactory;
 
     SPtr<RestartObject> restart_object;
 
diff --git a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
index 5dfb8cdf53c72b10e6441ad30a8418bfb47be7a3..c6e53ee3cbfb98f11e373ca014c7faf4e70a86f0 100644
--- a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
@@ -183,6 +183,20 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
     nodedatanames.push_back("vx2");
     nodedatanames.push_back("vx3");
     nodedatanames.push_back("geo");
+    
+    uint firstBodyForceNode = (uint) nodedatanames.size();
+    if(para->getIsBodyForce())
+    {
+        nodedatanames.push_back("Fx");
+        nodedatanames.push_back("Fy");
+        nodedatanames.push_back("Fz");
+    }
+
+    uint firstNutNode = (uint) nodedatanames.size();
+    if(para->getUseTurbulentViscosity())
+    {
+        nodedatanames.push_back("nut");
+    }
 
     uint firstTurbNode = (uint) nodedatanames.size();
     if (para->getCalcTurbulenceIntensity()) {
@@ -239,6 +253,18 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
                 nodedata[4][dn1] = (double)para->getParH(level)->velocityZ[pos] * (double)para->getVelocityRatio();
                 nodedata[5][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
 
+                if(para->getIsBodyForce())
+                {
+                    nodedata[firstBodyForceNode    ][dn1] = (double)para->getParH(level)->forceX_SP[pos] * (double)para->getScaledForceRatio(level);
+                    nodedata[firstBodyForceNode + 1][dn1] = (double)para->getParH(level)->forceY_SP[pos] * (double)para->getScaledForceRatio(level);
+                    nodedata[firstBodyForceNode + 2][dn1] = (double)para->getParH(level)->forceZ_SP[pos] * (double)para->getScaledForceRatio(level);
+                }
+
+                if(para->getUseTurbulentViscosity())
+                {
+                    nodedata[firstNutNode][dn1] = (double)para->getParH(level)->turbViscosity[pos] * (double)para->getScaledViscosityRatio(level);
+                }
+
                 if (para->getCalcTurbulenceIntensity()) {
                     nodedata[firstTurbNode    ][dn1] = (double)para->getParH(level)->vxx[pos];
                     nodedata[firstTurbNode + 1][dn1] = (double)para->getParH(level)->vyy[pos];
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
index 709fa092e70d9c3f0da80ab08c8ae68124cacf26..dc7d5cb07e573003bfebfa7ef327dddb1f9d4aa4 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
@@ -125,12 +125,6 @@ void Parameter::readConfigData(const vf::basics::ConfigurationFile &configData)
     if (configData.contains("UseWale"))
         this->setUseWale(configData.getValue<bool>("UseWale"));
     //////////////////////////////////////////////////////////////////////////
-    if (configData.contains("UseAMD"))
-        this->setUseAMD(configData.getValue<bool>("UseAMD"));
-    //////////////////////////////////////////////////////////////////////////
-    if (configData.contains("SGSconstant"))
-        this->setSGSConstant(configData.getValue<real>("SGSconstant"));
-    //////////////////////////////////////////////////////////////////////////
     if (configData.contains("UseInitNeq"))
         this->setUseInitNeq(configData.getValue<bool>("UseInitNeq"));
     //////////////////////////////////////////////////////////////////////////
@@ -809,17 +803,61 @@ void Parameter::setPressRatio(real PressRatio)
 {
     ic.delta_press = PressRatio;
 }
+real Parameter::getViscosityRatio()
+{
+    return ic.vis_ratio;
+}
+real Parameter::getVelocityRatio()
+{
+    return ic.u0_ratio;
+}
+real Parameter::getDensityRatio()
+{
+    return ic.delta_rho;
+}
+real Parameter::getPressureRatio()
+{
+    return ic.delta_press;
+}
 real Parameter::getTimeRatio()
 {
     return this->getViscosityRatio() * pow(this->getVelocityRatio(), -2);
 }
+real Parameter::getLengthRatio()
+{
+    return this->getViscosityRatio() / this->getVelocityRatio();
+}
 real Parameter::getForceRatio()
 {
-    return this->getDensityRatio() * pow(this->getViscosityRatio(), 2);
+    return this->getDensityRatio() * this->getVelocityRatio()/this->getTimeRatio();
 }
-real Parameter::getLengthRatio()
+real Parameter::getScaledViscosityRatio(int level)
 {
-    return this->getViscosityRatio() / this->getVelocityRatio();
+    return this->getViscosityRatio()/(level+1);
+}
+real Parameter::getScaledVelocityRatio(int level)
+{
+    return this->getVelocityRatio();
+}
+real Parameter::getScaledDensityRatio(int level)
+{
+    return this->getDensityRatio();
+}
+real Parameter::getScaledPressureRatio(int level)
+{
+    return this->getPressureRatio();
+}
+real Parameter::getScaledTimeRatio(int level)
+{
+    return this->getTimeRatio()/(level+1);
+}
+real Parameter::getScaledLengthRatio(int level)
+{
+    return this->getLengthRatio()/(level+1);
+}
+real Parameter::getScaledForceRatio(int level)
+{
+    return this->getForceRatio()*(level+1);
 }
 void Parameter::setRealX(real RealX)
 {
@@ -935,11 +973,9 @@ void Parameter::setUseWale(bool useWale)
     if (useWale)
         setUseTurbulentViscosity(true);
 }
-void Parameter::setUseAMD(bool useAMD)
+void Parameter::setTurbulenceModel(TurbulenceModel turbulenceModel)
 {
-    ic.isAMD = useAMD;
-    if (useAMD)
-        setUseTurbulentViscosity(true);
+    ic.turbulenceModel = turbulenceModel;
 }
 void Parameter::setSGSConstant(real SGSConstant)
 {
@@ -1712,7 +1748,7 @@ int Parameter::getNumberOfParticles()
 }
 bool Parameter::getEvenOrOdd(int level)
 {
-    return parH[level]->isEvenTimestep;
+	return parD[level]->isEvenTimestep;
 }
 bool Parameter::getDiffOn()
 {
@@ -1846,22 +1882,6 @@ real Parameter::getVelocity()
 {
     return ic.u0;
 }
-real Parameter::getViscosityRatio()
-{
-    return ic.vis_ratio;
-}
-real Parameter::getVelocityRatio()
-{
-    return ic.u0_ratio;
-}
-real Parameter::getDensityRatio()
-{
-    return ic.delta_rho;
-}
-real Parameter::getPressureRatio()
-{
-    return ic.delta_press;
-}
 real Parameter::getRealX()
 {
     return ic.RealX;
@@ -2262,6 +2282,26 @@ unsigned int Parameter::getTimeDoRestart()
 {
     return ic.tDoRestart;
 }
+
+//=======================================================================================
+//! \brief Get current (sub)time step of a given level.
+//! \param level 
+//! \param t current time step (of level 0)
+//! \param isPostCollision whether getTimeStep is called post- (before swap) or pre- (after swap) collision
+//!
+unsigned int Parameter::getTimeStep(int level, unsigned int t, bool isPostCollision)
+{
+    if(level>this->getMaxLevel()) throw std::runtime_error("Parameter::getTimeStep: level>this->getMaxLevel()!");
+	unsigned int tLevel = t;                                                                  
+    if(level>0)
+    {
+        for(int i=1; i<level; i++){ tLevel = 1 + 2*(tLevel-1) + !this->getEvenOrOdd(i); }     
+        bool addOne = isPostCollision? !this->getEvenOrOdd(level): this->getEvenOrOdd(level); 
+        tLevel = 1 + 2*(tLevel-1) + addOne;
+    }
+	return tLevel;
+}
+
 bool Parameter::getDoCheckPoint()
 {
     return ic.doCheckPoint;
@@ -2306,9 +2346,9 @@ bool Parameter::getUseWale()
 {
     return ic.isWale;
 }
-bool Parameter::getUseAMD()
+TurbulenceModel Parameter::getTurbulenceModel()
 {
-    return ic.isAMD;
+    return ic.turbulenceModel;
 }
 bool Parameter::getUseTurbulentViscosity()
 {
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
index 3ae501d12c89a9432fe44ad76a1ac329c324bf8a..813e6007737bbf402c9d54d5247597275637d096 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
@@ -42,6 +42,7 @@
 #include "lbm/constants/D3Q27.h"
 #include "LBM/LB.h"
 #include "PreCollisionInteractor/PreCollisionInteractor.h"
+#include "TurbulenceModels/TurbulenceModelFactory.h"
 
 #include "VirtualFluids_GPU_export.h"
 
@@ -520,6 +521,7 @@ public:
     void setStreetVelocityFile(bool streetVelocityFile);
     void setUseMeasurePoints(bool useMeasurePoints);
     void setUseWale(bool useWale);
+    void setTurbulenceModel(TurbulenceModel turbulenceModel);
     void setUseTurbulentViscosity(bool useTurbulentViscosity);
     void setUseAMD(bool useAMD);
     void setSGSConstant(real SGSConstant);
@@ -751,6 +753,20 @@ public:
     real getLengthRatio();
     //! \returns the force ratio in SI/LB units
     real getForceRatio();
+    //! \returns the viscosity ratio in SI/LB units scaled to the respective level
+    real getScaledViscosityRatio(int level);
+    //! \returns the velocity ratio in SI/LB units scaled to the respective level
+    real getScaledVelocityRatio(int level);
+    //! \returns the density ratio in SI/LB units scaled to the respective level
+    real getScaledDensityRatio(int level);
+    //! \returns the pressure ratio in SI/LB units scaled to the respective level
+    real getScaledPressureRatio(int level);
+    //! \returns the time ratio in SI/LB units scaled to the respective level
+    real getScaledTimeRatio(int level);
+    //! \returns the length ratio in SI/LB units scaled to the respective level
+    real getScaledLengthRatio(int level);
+    //! \returns the force ratio in SI/LB units scaled to the respective level
+    real getScaledForceRatio(int level);
     real getRealX();
     real getRealY();
     real getRe();
@@ -782,6 +798,7 @@ public:
     std::vector<SPtr<PreCollisionInteractor>> getProbes();
     unsigned int getTimeDoCheckPoint();
     unsigned int getTimeDoRestart();
+    unsigned int getTimeStep(int level, unsigned int t, bool isPostCollision);
     bool getDoCheckPoint();
     bool getDoRestart();
     bool overWritingRestart(unsigned int t);
@@ -799,8 +816,8 @@ public:
     bool isStreetVelocityFile();
     bool getUseMeasurePoints();
     bool getUseWale();
+    TurbulenceModel getTurbulenceModel();
     bool getUseTurbulentViscosity();
-    bool getUseAMD();
     real getSGSConstant();
     bool getHasWallModelMonitor();
     bool getUseInitNeq();
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu
index fda466354769d11910041a9ea351dd102f9c474d..f5b520acfad74f6787e9e657fce3ccdceed9d539 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu
@@ -142,55 +142,56 @@ std::vector<PostProcessingVariable> PlanarAverageProbe::getPostProcessingVariabl
     switch (statistic)
     {
     case Statistic::SpatialMeans:
-        postProcessingVariables.push_back( PostProcessingVariable("vx_spatMean",  velocityRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vx_spatMean",  this->velocityRatio) );
         postProcessingVariables.push_back( PostProcessingVariable("vy_spatMean",  this->velocityRatio) );
         postProcessingVariables.push_back( PostProcessingVariable("vz_spatMean",  this->velocityRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("nut_spatMean", this->viscosityRatio) );
         break;
     case Statistic::SpatioTemporalMeans:
         postProcessingVariables.push_back( PostProcessingVariable("vx_spatTmpMean",  this->velocityRatio) );
         postProcessingVariables.push_back( PostProcessingVariable("vy_spatTmpMean",  this->velocityRatio) );
         postProcessingVariables.push_back( PostProcessingVariable("vz_spatTmpMean",  this->velocityRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("nut_spatTmpMean", this->viscosityRatio) );
         break;
     case Statistic::SpatialCovariances:
-        postProcessingVariables.push_back( PostProcessingVariable("vxvx_spatMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vyvy_spatMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vzvz_spatMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vxvy_spatMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vxvz_spatMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vyvz_spatMean",  pow(this->velocityRatio, 2.0)) );
+        postProcessingVariables.push_back( PostProcessingVariable("vxvx_spatMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vyvy_spatMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vzvz_spatMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vxvy_spatMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vxvz_spatMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vyvz_spatMean",  this->stressRatio) );
         break;
     case Statistic::SpatioTemporalCovariances:
-        postProcessingVariables.push_back( PostProcessingVariable("vxvx_spatTmpMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vyvy_spatTmpMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vzvz_spatTmpMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vxvy_spatTmpMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vxvz_spatTmpMean",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vyvz_spatTmpMean",  pow(this->velocityRatio, 2.0)) );
+        postProcessingVariables.push_back( PostProcessingVariable("vxvx_spatTmpMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vyvy_spatTmpMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vzvz_spatTmpMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vxvy_spatTmpMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vxvz_spatTmpMean",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vyvz_spatTmpMean",  this->stressRatio) );
         break;
     case Statistic::SpatialSkewness:
-        postProcessingVariables.push_back( PostProcessingVariable("Sx_spatMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Sy_spatMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Sz_spatMean",  1.0) );
+        postProcessingVariables.push_back( PostProcessingVariable("Sx_spatMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Sy_spatMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Sz_spatMean",  this->nondimensional) );
         break;
     case Statistic::SpatioTemporalSkewness:
-        postProcessingVariables.push_back( PostProcessingVariable("Sx_spatTmpMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Sy_spatTmpMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Sz_spatTmpMean",  1.0) );
+        postProcessingVariables.push_back( PostProcessingVariable("Sx_spatTmpMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Sy_spatTmpMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Sz_spatTmpMean",  this->nondimensional) );
         break;
     case Statistic::SpatialFlatness:
-        postProcessingVariables.push_back( PostProcessingVariable("Fx_spatMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Fy_spatMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Fz_spatMean",  1.0) );
+        postProcessingVariables.push_back( PostProcessingVariable("Fx_spatMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Fy_spatMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Fz_spatMean",  this->nondimensional) );
         break;
     case Statistic::SpatioTemporalFlatness:
-        postProcessingVariables.push_back( PostProcessingVariable("Fx_spatTmpMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Fy_spatTmpMean",  1.0) );
-        postProcessingVariables.push_back( PostProcessingVariable("Fz_spatTmpMean",  1.0) );
+        postProcessingVariables.push_back( PostProcessingVariable("Fx_spatTmpMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Fy_spatTmpMean",  this->nondimensional) );
+        postProcessingVariables.push_back( PostProcessingVariable("Fz_spatTmpMean",  this->nondimensional) );
         break;
 
     default:
-        printf("Statistic unavailable in PlanarAverageProbe\n");
-        assert(false);
+        throw std::runtime_error("PlanarAverageProbe::getPostProcessingVariables: Statistic unavailable!");
         break;
     }
     return postProcessingVariables;
@@ -265,7 +266,7 @@ void PlanarAverageProbe::findPoints(Parameter* para, GridProvider* gridProvider,
 
 ///////////////////////////////////////////////////////////////////////////////////
 
-void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t, int level)
+void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t_level, int level)
 {   
     // Definition of normal and inplane directions for moveIndices kernels
     uint *neighborNormal, *neighborInplane1, *neighborInplane2;
@@ -288,13 +289,14 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
         neighborInplane2 = para->getParD(level)->neighborY;
     }
 
-    bool doTmpAveraging = (t>this->getTStartTmpAveraging());
+    bool doTmpAveraging = t_level>=(this->getTStartTmpAveraging()*pow(2,level));
 
     // Pointer casts to use device arrays in thrust reductions
     thrust::device_ptr<uint> indices_thrust = thrust::device_pointer_cast(probeStruct->pointIndicesD);
     thrust::device_ptr<real> vx_thrust = thrust::device_pointer_cast(para->getParD(level)->velocityX);
     thrust::device_ptr<real> vy_thrust = thrust::device_pointer_cast(para->getParD(level)->velocityY);
     thrust::device_ptr<real> vz_thrust = thrust::device_pointer_cast(para->getParD(level)->velocityZ);
+    thrust::device_ptr<real> nut_thrust = thrust::device_pointer_cast(para->getParD(level)->turbViscosity);
 
     real N = (real)probeStruct->nIndices;
     real n = (real)probeStruct->vals;
@@ -308,10 +310,12 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
     thrust::permutation_iterator<valIterator, indIterator> vy_iter_end  (vy_thrust, indices_thrust+probeStruct->nIndices);
     thrust::permutation_iterator<valIterator, indIterator> vz_iter_begin(vz_thrust, indices_thrust);
     thrust::permutation_iterator<valIterator, indIterator> vz_iter_end  (vz_thrust, indices_thrust+probeStruct->nIndices);
+    thrust::permutation_iterator<valIterator, indIterator> nut_iter_begin(nut_thrust, indices_thrust);
+    thrust::permutation_iterator<valIterator, indIterator> nut_iter_end  (nut_thrust, indices_thrust+probeStruct->nIndices);
 
     for( uint i=0; i<nPoints; i++ )
     {
-        uint node = this->isEvenTAvg? i : nPoints-1-i; // Note, loop moves in positive normal dir at even calls and in negative normal dir in odd calls
+        uint node = probeStruct->isEvenTAvg? i : nPoints-1-i; // Note, loop moves in positive normal dir at even calls and in negative normal dir in odd calls
 
         if(probeStruct->quantitiesH[int(Statistic::SpatialMeans)])
         {
@@ -320,10 +324,14 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
             real spatMean_vy = thrust::reduce(vy_iter_begin, vy_iter_end)/N;
             real spatMean_vz = thrust::reduce(vz_iter_begin, vz_iter_end)/N;
 
+            real spatMean_nut;
+            if(para->getUseTurbulentViscosity()) spatMean_nut = thrust::reduce(nut_iter_begin, nut_iter_end)/N;
+
             uint arrOff = probeStruct->arrayOffsetsH[int(Statistic::SpatialMeans)];
             probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] = spatMean_vx;
             probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] = spatMean_vy;
             probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] = spatMean_vz;
+            if(para->getUseTurbulentViscosity()) probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node] = spatMean_nut;
 
             if(probeStruct->quantitiesH[int(Statistic::SpatioTemporalMeans)] && doTmpAveraging)
             {
@@ -331,10 +339,14 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
             real spatTmpMean_vx_old = probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node];
             real spatTmpMean_vy_old = probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node];
             real spatTmpMean_vz_old = probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node];
+            real spatTmpMean_nut_old;
+            if(para->getUseTurbulentViscosity()) spatTmpMean_nut_old = probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node];;
 
             probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_vx-spatTmpMean_vx_old)/n;
             probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_vy-spatTmpMean_vy_old)/n;
             probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_vz-spatTmpMean_vz_old)/n;
+            if(para->getUseTurbulentViscosity()) probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node] += (spatMean_nut-spatTmpMean_nut_old)/n;
+
             }
         
             if(probeStruct->quantitiesH[int(Statistic::SpatialCovariances)])
@@ -445,13 +457,13 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
         if(i<probeStruct->nPoints-1)
         {
             vf::cuda::CudaGrid grid = vf::cuda::CudaGrid(para->getParH(level)->numberofthreads, probeStruct->nIndices);
-            if(this->isEvenTAvg) 
+            if(probeStruct->isEvenTAvg) 
                 moveIndicesInPosNormalDir<<<grid.grid, grid.threads>>>( probeStruct->pointIndicesD, probeStruct->nIndices, neighborNormal, para->getParD(level)->coordinateX, para->getParD(level)->coordinateY, para->getParD(level)->coordinateZ );
             else 
                 moveIndicesInNegNormalDir<<<grid.grid, grid.threads>>>( probeStruct->pointIndicesD, probeStruct->nIndices, para->getParD(level)->neighborInverse, neighborInplane1, neighborInplane2, para->getParD(level)->coordinateX, para->getParD(level)->coordinateY, para->getParD(level)->coordinateZ ); 
         } 
     }
-    this->isEvenTAvg=!this->isEvenTAvg;
+    probeStruct->isEvenTAvg=!(probeStruct->isEvenTAvg);
 
     getLastCudaError("PlanarAverageProbe::calculateQuantities execution failed");
 }
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h
index 7054f5fc7e02453418285281a0ea9cf9c32dc0c0..d11f8e76e4d13113b201af5494b7d0cfcfe18353 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h
@@ -40,6 +40,8 @@
 #ifndef PlanarAverageProbe_H
 #define PlanarAverageProbe_H
 
+#include <iostream>
+
 #include "Probe.h"
 
 __global__ void moveIndicesInNegNormalDir( uint* pointIndices, uint nPoints, uint* neighborWSB, uint* neighborInplane1, uint* neighborInplane2, real* coordsX, real* coordsY, real* coordsZ ); 
@@ -72,7 +74,8 @@ public:
         planeNormal(_planeNormal)
 
     {   
-        assert(_planeNormal == 'x' || _planeNormal == 'y' || _planeNormal == 'z');
+        if(!(_planeNormal == 'x' || _planeNormal == 'y' || _planeNormal == 'z')) 
+            throw std::runtime_error("PlanarAverageProbe: planeNormal must be 'x', 'y' or 'z'!");
     }
 
 
@@ -91,7 +94,6 @@ private:
     real posX, posY, posZ;
     real deltaX, deltaY, deltaZ;
     char planeNormal;
-    bool isEvenTAvg = true;
 };
 
 #endif
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu
index d2b101bc26bb5fd4e173ebaef20333225b4e7467..7d1c0205219737e4b28acbb1a893a0a6071ae9de 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu
@@ -57,15 +57,14 @@ std::vector<PostProcessingVariable> PlaneProbe::getPostProcessingVariables(Stati
         postProcessingVariables.push_back( PostProcessingVariable("rho_mean", this->densityRatio ) );
         break;
     case Statistic::Variances:
-        postProcessingVariables.push_back( PostProcessingVariable("vx_var",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vy_var",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vz_var",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("rho_var", pow(this->densityRatio,  2.0)) );
+        postProcessingVariables.push_back( PostProcessingVariable("vx_var",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vy_var",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vz_var",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("rho_var", this->densityRatio) );
         break;
 
     default:
-        printf("Statistic unavailable in PlaneProbe\n");
-        assert(false);
+        throw std::runtime_error("PlaneProbe::getPostProcessingVariables: Statistic unavailable!");
         break;
     }
     return postProcessingVariables;
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu
index 677710ec87ca091b45bdd665db3b58103874634d..e78a98f02ac2093fc46b4daa4a2485ed1395275b 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu
@@ -55,15 +55,14 @@ std::vector<PostProcessingVariable> PointProbe::getPostProcessingVariables(Stati
         postProcessingVariables.push_back( PostProcessingVariable("rho_mean", this->densityRatio ) );
         break;
     case Statistic::Variances:
-        postProcessingVariables.push_back( PostProcessingVariable("vx_var",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vy_var",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("vz_var",  pow(this->velocityRatio, 2.0)) );
-        postProcessingVariables.push_back( PostProcessingVariable("rho_var", pow(this->densityRatio,  2.0)) );
+        postProcessingVariables.push_back( PostProcessingVariable("vx_var",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vy_var",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("vz_var",  this->stressRatio) );
+        postProcessingVariables.push_back( PostProcessingVariable("rho_var", this->densityRatio) );
         break;
 
     default:
-        printf("Statistic unavailable in PointProbe\n");
-        assert(false);
+        throw std::runtime_error("PointProbe::getPostProcessingVariables: Statistic unavailable!");
         break;
     }
     return postProcessingVariables;
@@ -114,7 +113,7 @@ void PointProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* p
 void PointProbe::addProbePointsFromList(std::vector<real>& _pointCoordsX, std::vector<real>& _pointCoordsY, std::vector<real>& _pointCoordsZ)
 {
     bool isSameLength = ( (_pointCoordsX.size()==_pointCoordsY.size()) && (_pointCoordsY.size()==_pointCoordsZ.size()));
-    assert("Probe: point lists have different lengths" && isSameLength);
+    if (!isSameLength) throw std::runtime_error("Probe::addProbePointsFromList(): point lists have different lengths!");
     this->pointCoordsX.insert(this->pointCoordsX.end(), _pointCoordsX.begin(),  _pointCoordsX.end());
     this->pointCoordsY.insert(this->pointCoordsY.end(), _pointCoordsY.begin(),  _pointCoordsY.end());
     this->pointCoordsZ.insert(this->pointCoordsZ.end(), _pointCoordsZ.begin(),  _pointCoordsZ.end());
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu
index 8b2f7e004ba79b46dcb61a8f4e569887dfb882e9..cc027b07bded01455437e65e08ccdcd51bcf7dc0 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu
@@ -37,6 +37,7 @@
 #include <helper_cuda.h>
 
 #include "VirtualFluids_GPU/GPU/GeometryUtils.h"
+#include <lbm/constants/NumericConstants.h>
 #include "basics/writer/WbWriterVtkXmlBinary.h"
 #include <Core/StringUtilities/StringUtil.h>
 
@@ -44,6 +45,7 @@
 #include "DataStructureInitializer/GridProvider.h"
 #include "GPU/CudaMemoryManager.h"
 
+using namespace vf::lbm::constant;
 
 __device__ void calculatePointwiseQuantities(uint n, real* quantityArray, bool* quantities, uint* quantityArrayOffsets, uint nPoints, uint node, real vx, real vy, real vz, real rho)
 {
@@ -177,13 +179,17 @@ __global__ void interpAndCalcQuantitiesKernel(   uint* pointIndices,
 
 bool Probe::getHasDeviceQuantityArray(){ return this->hasDeviceQuantityArray; }
 
+real Probe::getNondimensionalConversionFactor(int level){ return c1o1; }
+
 void Probe::init(Parameter* para, GridProvider* gridProvider, CudaMemoryManager* cudaMemoryManager)
 {
-    this->velocityRatio      = para->getVelocityRatio();
-    this->densityRatio       = para->getDensityRatio();
-    this->forceRatio         = para->getForceRatio();
-    this->stressRatio        = para->getDensityRatio()*pow(para->getVelocityRatio(), 2.0);
-    this->accelerationRatio = para->getVelocityRatio()/para->getTimeRatio();
+    using std::placeholders::_1;
+    this->velocityRatio      = std::bind(&Parameter::getScaledVelocityRatio,        para, _1); 
+    this->densityRatio       = std::bind(&Parameter::getScaledDensityRatio,         para, _1);
+    this->forceRatio         = std::bind(&Parameter::getScaledForceRatio,           para, _1);
+    this->stressRatio        = std::bind(&Parameter::getScaledPressureRatio,        para, _1);
+    this->viscosityRatio     = std::bind(&Parameter::getScaledViscosityRatio,       para, _1);
+    this->nondimensional     = std::bind(&Probe::getNondimensionalConversionFactor, this, _1);
 
     probeParams.resize(para->getMaxLevel()+1);
 
@@ -196,7 +202,7 @@ void Probe::init(Parameter* para, GridProvider* gridProvider, CudaMemoryManager*
         std::vector<real> pointCoordsX_level;
         std::vector<real> pointCoordsY_level;
         std::vector<real> pointCoordsZ_level;
-
+        
         this->findPoints(para, gridProvider, probeIndices_level, distX_level, distY_level, distZ_level,      
                        pointCoordsX_level, pointCoordsY_level, pointCoordsZ_level,
                        level);
@@ -274,16 +280,23 @@ void Probe::addProbeStruct(CudaMemoryManager* cudaMemoryManager, std::vector<int
 
 void Probe::interact(Parameter* para, CudaMemoryManager* cudaMemoryManager, int level, uint t)
 {
-    if(max(int(t) - int(this->tStartAvg), -1) % this->tAvg==0)
+    uint t_level = para->getTimeStep(level, t, false);
+
+    //! if tAvg==1 the probe will be evaluated in every sub-timestep of each respective level
+    //! else, the probe will only be evaluated in each synchronous time step tAvg
+
+    uint tAvg_level = this->tAvg==1? this->tAvg: this->tAvg*pow(2,level);          
+
+    if(max(int(t_level) - int(this->tStartAvg*pow(2,level)), -1) % tAvg_level==0)
     {
         SPtr<ProbeStruct> probeStruct = this->getProbeStruct(level);
-
-        this->calculateQuantities(probeStruct, para, t, level);
-        if(t>=this->tStartTmpAveraging) probeStruct->vals++;
+        this->calculateQuantities(probeStruct, para, t_level, level);
+        if(t_level>=(this->tStartTmpAveraging*pow(2,level))) probeStruct->vals++;
     }
 
-    if(max(int(t) - int(this->tStartOut), -1) % this->tOut == 0)
-    {
+    //! output only in synchronous timesteps
+    if(max(int(t_level) - int(this->tStartOut*pow(2,level)), -1) % int(this->tOut*pow(2,level)) == 0)
+    {   
         if(this->hasDeviceQuantityArray)
             cudaMemoryManager->cudaCopyProbeQuantityArrayDtoH(this, level);
         this->write(para, level, t);
@@ -304,7 +317,7 @@ void Probe::free(Parameter* para, CudaMemoryManager* cudaMemoryManager)
 
 void Probe::addStatistic(Statistic variable)
 {
-    assert(this->isAvailableStatistic(variable));
+    if (!this->isAvailableStatistic(variable)) throw std::runtime_error("Probe::addStatistic(): Statistic not available for this probe type!");
 
     this->quantities[int(variable)] = true;
     switch(variable)
@@ -433,10 +446,10 @@ void Probe::writeGridFiles(Parameter* para, int level, std::vector<std::string>&
 
                 uint arrOff = probeStruct->arrayOffsetsH[var];
                 uint arrLen = probeStruct->nPoints;
-
+                
                 for(uint arr=0; arr<n_arrs; arr++)
                 {
-                    coeff = postProcessingVariables[arr].conversionFactor;
+                    coeff = postProcessingVariables[arr].conversionFactor(level);
                     
                     for (uint pos = startpos; pos < endpos; pos++)
                     {
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h
index 693252fec974eb45eb0eee6ae176c577de22cee4..9cb0bd43e27fb7a28cae9c363ce245fbd9cc5677 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h
@@ -43,6 +43,8 @@
 #ifndef Probe_H
 #define Probe_H
 
+#include <iostream>
+
 #include <cuda.h>
 
 #include "PreCollisionInteractor/PreCollisionInteractor.h"
@@ -90,9 +92,9 @@ enum class Statistic{
 
 typedef struct PostProcessingVariable{
     std::string name;
-    real conversionFactor;
+    std::function<real(int)> conversionFactor;
     PostProcessingVariable( std::string _name, 
-                            real        _conversionFactor): 
+                            std::function<real(int)>  _conversionFactor): 
     name(_name), conversionFactor(_conversionFactor){};
 } PostProcessingVariable;
 
@@ -105,6 +107,7 @@ struct ProbeStruct{
     real *quantitiesArrayH, *quantitiesArrayD;
     bool *quantitiesH, *quantitiesD;
     uint *arrayOffsetsH, *arrayOffsetsD;
+    bool isEvenTAvg = true;
 };
 
 __global__ void calcQuantitiesKernel(   uint* pointIndices,
@@ -149,7 +152,8 @@ public:
         outputTimeSeries(_outputTimeSeries),        
         PreCollisionInteractor()
     {
-        assert("Output starts before averaging!" && tStartOut>=tStartAvg);
+        if (_tStartOut<_tStartAvg)      throw std::runtime_error("Probe: tStartOut must be larger than tStartAvg!");
+        if (_tStartTmpAvg<_tStartAvg)   throw std::runtime_error("Probe: tStartTmpAvg must be larger than tStartAvg!");
     }
     
     void init(Parameter* para, GridProvider* gridProvider, CudaMemoryManager* cudaMemoryManager) override;
@@ -167,6 +171,8 @@ public:
     void setFileNameToNOut(){this->fileNameLU = false;}
     void setTStartTmpAveraging(uint _tStartTmpAveraging){this->tStartTmpAveraging = _tStartTmpAveraging;}
 
+    real getNondimensionalConversionFactor(int level);
+
 private:
     virtual bool isAvailableStatistic(Statistic _variable) = 0;
 
@@ -203,17 +209,19 @@ private:
 protected:
     uint tStartAvg;
     uint tStartTmpAveraging; //!> only non-zero in PlanarAverageProbe and WallModelProbe to switch on Spatio-temporal averaging (while only doing spatial averaging for t<tStartTmpAveraging) 
-    uint tAvg;
+    uint tAvg;  //! for tAvg==1 the probe will be evaluated in every sub-timestep of each respective level, else, the probe will only be evaluated in each synchronous time step 
     uint tStartOut;
     uint tOut;
 
     uint tProbe = 0; //!> counter for number of probe evaluations. Only used when outputting timeseries
 
-    real velocityRatio;
-    real densityRatio;
-    real forceRatio;
-    real stressRatio;
-    real accelerationRatio;
+
+    std::function<real(int)> velocityRatio;
+    std::function<real(int)> densityRatio;
+    std::function<real(int)> forceRatio;
+    std::function<real(int)> stressRatio;
+    std::function<real(int)> viscosityRatio;
+    std::function<real(int)> nondimensional;
 };
 
 #endif
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu
index ad79f582a45e75307801b5c494ae09ce8a2439c1..81da15595baae55aa562bc77e24442a9258d992f 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu
@@ -117,9 +117,9 @@ std::vector<PostProcessingVariable> WallModelProbe::getPostProcessingVariables(S
         postProcessingVariables.push_back( PostProcessingVariable("Fz_spatMean",     this->outputStress? this->stressRatio: this->forceRatio) );
         if(this->evaluatePressureGradient)
         {
-            postProcessingVariables.push_back( PostProcessingVariable("dpdx_spatMean",     this->accelerationRatio) ); 
-            postProcessingVariables.push_back( PostProcessingVariable("dpdy_spatMean",     this->accelerationRatio) );
-            postProcessingVariables.push_back( PostProcessingVariable("dpdz_spatMean",     this->accelerationRatio) );
+            postProcessingVariables.push_back( PostProcessingVariable("dpdx_spatMean",     this->forceRatio) ); 
+            postProcessingVariables.push_back( PostProcessingVariable("dpdy_spatMean",     this->forceRatio) );
+            postProcessingVariables.push_back( PostProcessingVariable("dpdz_spatMean",     this->forceRatio) );
         }
         break;
     case Statistic::SpatioTemporalMeans:
@@ -135,15 +135,14 @@ std::vector<PostProcessingVariable> WallModelProbe::getPostProcessingVariables(S
         postProcessingVariables.push_back( PostProcessingVariable("Fz_spatTmpMean",     this->outputStress? this->stressRatio: this->forceRatio) );
         if(this->evaluatePressureGradient)
         {
-            postProcessingVariables.push_back( PostProcessingVariable("dpdx_spatTmpMean",     this->accelerationRatio) ); 
-            postProcessingVariables.push_back( PostProcessingVariable("dpdy_spatTmpMean",     this->accelerationRatio) );
-            postProcessingVariables.push_back( PostProcessingVariable("dpdz_spatTmpMean",     this->accelerationRatio) );
+            postProcessingVariables.push_back( PostProcessingVariable("dpdx_spatTmpMean",     this->forceRatio) ); 
+            postProcessingVariables.push_back( PostProcessingVariable("dpdy_spatTmpMean",     this->forceRatio) );
+            postProcessingVariables.push_back( PostProcessingVariable("dpdz_spatTmpMean",     this->forceRatio) );
         }
         break;
 
     default:
-        printf("Statistic unavailable in WallModelProbe\n");
-        assert(false);
+        throw std::runtime_error("WallModelProbe::getPostProcessingVariables: Statistic unavailable!");
         break;
     }
     return postProcessingVariables;
@@ -156,7 +155,7 @@ void WallModelProbe::findPoints(Parameter* para, GridProvider* gridProvider, std
                             std::vector<real>& pointCoordsX_level, std::vector<real>& pointCoordsY_level, std::vector<real>& pointCoordsZ_level,
                             int level)
 {
-    assert( para->getParD(level)->stressBC.numberOfBCnodes > 0 && para->getHasWallModelMonitor() );
+    if ( !para->getHasWallModelMonitor())                    throw std::runtime_error("WallModelProbe::findPoints(): !para->getHasWallModelMonitor() !");
 
     real dt = para->getTimeRatio();
     uint nt = uint((para->getTimestepEnd()-this->tStartAvg)/this->tAvg);
@@ -170,7 +169,7 @@ void WallModelProbe::findPoints(Parameter* para, GridProvider* gridProvider, std
 
     if(this->evaluatePressureGradient)
     {
-        assert(para->getIsBodyForce());
+        if (!para->getIsBodyForce()) throw std::runtime_error("WallModelProbe::findPoints(): bodyforce not allocated!");
         // Find all fluid nodes
         for(uint j=1; j<para->getParH(level)->numberOfNodes; j++ )
         {
@@ -187,6 +186,10 @@ void WallModelProbe::findPoints(Parameter* para, GridProvider* gridProvider, std
 void WallModelProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t, int level)
 {   
     bool doTmpAveraging = (t>this->getTStartTmpAveraging());
+    real N = para->getParD(level)->stressBC.numberOfBCnodes;
+    if(N<1) return; //Skipping levels without StressBC
+    real n = (real)probeStruct->vals;
+    int nPoints = probeStruct->nPoints;
 
     // Pointer casts to use device arrays in thrust reductions
     thrust::device_ptr<real> u_el_thrust    = thrust::device_pointer_cast(para->getParD(level)->stressBC.Vx);
@@ -213,10 +216,6 @@ void WallModelProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Paramete
     thrust::permutation_iterator<valIterator, indIterator> dpdz_iter_begin(dpdz_thrust, indices_thrust);
     thrust::permutation_iterator<valIterator, indIterator> dpdz_iter_end  (dpdz_thrust, indices_thrust+probeStruct->nIndices);
 
-    real N = para->getParD(level)->stressBC.numberOfBCnodes;
-    real n = (real)probeStruct->vals;
-    int nPoints = probeStruct->nPoints;
-
     if(probeStruct->quantitiesH[int(Statistic::SpatialMeans)])
     {
         // Compute the instantaneous spatial means of the velocity moments 
@@ -293,6 +292,7 @@ void WallModelProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Paramete
             }
         }    
     }
+        
 
     this->tProbe += 1;
     getLastCudaError("WallModelProbe::calculateQuantities execution failed");
diff --git a/src/gpu/VirtualFluids_GPU/TurbulenceModels/TurbulenceModelFactory.cpp b/src/gpu/VirtualFluids_GPU/TurbulenceModels/TurbulenceModelFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..980a199b03710ac91310d26424c20c7371f1097d
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/TurbulenceModels/TurbulenceModelFactory.cpp
@@ -0,0 +1,88 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
+//
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file TurbulentViscosityFactory.cpp
+//! \ingroup TurbulentViscosity
+//! \author Henrik Asmuth
+//=======================================================================================
+#include "LBM/LB.h"
+#include "TurbulenceModelFactory.h"
+#include "GPU/TurbulentViscosityKernels.h"
+#include "Parameter/Parameter.h"
+#include <logger/Logger.h>
+
+#include <variant>
+
+void TurbulenceModelFactory::setTurbulenceModel(TurbulenceModel _turbulenceModel)
+{
+    this->turbulenceModel = _turbulenceModel;
+    para->setTurbulenceModel(_turbulenceModel);
+    if(this->turbulenceModel != TurbulenceModel::None) para->setUseTurbulentViscosity(true);
+
+    switch (this->turbulenceModel) {
+        case TurbulenceModel::AMD:
+            this->turbulenceModelKernel = calcTurbulentViscosityAMD;
+            break;
+        default:
+            this->turbulenceModelKernel = nullptr;
+    }
+}
+
+void TurbulenceModelFactory::setModelConstant(real modelConstant)
+{
+    para->setSGSConstant(modelConstant);
+}
+
+void TurbulenceModelFactory::readConfigFile(const vf::basics::ConfigurationFile &configData)
+{
+    if (configData.contains("TurbulenceModel"))
+    {
+        std::string config = configData.getValue<std::string>("TurbulenceModel");
+        
+        if      (config == "Smagorinsky") this->setTurbulenceModel( TurbulenceModel::Smagorinsky ); 
+        else if (config == "AMD")         this->setTurbulenceModel( TurbulenceModel::AMD );               
+        else if (config == "QR" )         this->setTurbulenceModel( TurbulenceModel::QR );             
+        else if (config == "None")        this->setTurbulenceModel( TurbulenceModel::None );           
+        else    std::runtime_error("TurbulenceModelFactory: Invalid turbulence model!");           
+
+        VF_LOG_INFO("Turbulence model: {}", config);
+        
+    }
+
+    if (configData.contains("SGSconstant"))
+    {
+        para->setSGSConstant(configData.getValue<real>("SGSconstant"));
+
+        VF_LOG_INFO("SGS constant: {}", para->getSGSConstant() );
+    }
+}
+
+void TurbulenceModelFactory::runTurbulenceModelKernel(const int level) const
+{
+    if(this->turbulenceModelKernel) this->turbulenceModelKernel(para.get(), level);
+}
diff --git a/src/gpu/VirtualFluids_GPU/TurbulenceModels/TurbulenceModelFactory.h b/src/gpu/VirtualFluids_GPU/TurbulenceModels/TurbulenceModelFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..e71c8ed5f7be016a4a800b83cfb3252ee6b8246e
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/TurbulenceModels/TurbulenceModelFactory.h
@@ -0,0 +1,71 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
+//
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file TurbulentViscosityFactory.h
+//! \ingroup TurbulentViscosity
+//! \author Henrik Asmuth
+//=======================================================================================
+#ifndef TurbulenceModelFactory_H
+#define TurbulenceModelFactory_H
+
+#include <functional>
+#include <map>
+#include <string>
+#include <variant>
+
+#include "LBM/LB.h"
+#include "Parameter/Parameter.h"
+
+#include <basics/config/ConfigurationFile.h>
+
+class Parameter;
+
+using TurbulenceModelKernel = std::function<void(Parameter *, int )>;
+
+class TurbulenceModelFactory
+{
+public:
+    
+    TurbulenceModelFactory(SPtr<Parameter> parameter): para(parameter) {}
+
+    void setTurbulenceModel(TurbulenceModel _turbulenceModel);
+
+    void setModelConstant(real modelConstant);
+
+    void readConfigFile(const vf::basics::ConfigurationFile &configData);
+
+    void runTurbulenceModelKernel(const int level) const;
+
+private:
+    TurbulenceModel turbulenceModel = TurbulenceModel::None;
+    TurbulenceModelKernel turbulenceModelKernel = nullptr;
+    SPtr<Parameter> para;
+
+};
+
+#endif