diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index d4fc6aca8444a1acdbd7ac7a044acf06ef347d49..64c0cfd85cae1b82b32b47de7ac95fbc42567578 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -7,8 +7,14 @@
     "ms-vscode.cpptools",
     "ms-vscode.cpptools-extension-pack",
     "xaver.clang-format",  
-    "notskm.clang-tidy"  
+    "notskm.clang-tidy",
+     "streetsidesoftware.code-spell-checker"
     ],  
     "runArgs": ["--gpus","all"],  
-    "image": "git.rz.tu-bs.de:4567/irmb/virtualfluids/ubuntu20_04:1.2"  
+    "image": "git.rz.tu-bs.de:4567/irmb/virtualfluids/ubuntu20_04:1.2",
+    "containerEnv": {"HOME": "/workspaces/"},
+    "mounts": [
+        "source=/mnt/d/output,target=/${containerWorkspaceFolder}/output,type=bind", 
+        "source=${localEnv:HOME}/STLs,target=${containerWorkspaceFolder}/stl,type=bind"    
+    ]
 }
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 56c05a6e981c2accd816b0c9e39631080c8d3540..a69595354473dac35d6cb4c49da4f01729281a44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,11 +16,14 @@ __pycache__/
 .sync/
 .idea/
 
-# Simulation results
+# simulation results
 output/
 
-# Scripts
+# scripts
 scripts/
 
+# stl files
+stl/
+
 # MacOS
 .DS_Store
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8ad5c98d9458e66f66a0e905dc045713d3d7521d..dedfc6898999f20f60a42ebc80b3cdf0522a8331 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -482,7 +482,9 @@ gcov_gcc_9:
       - coverage/
 
     reports:
-      cobertura: coverage/coverage.xml
+      coverage_report: 
+        coverage_format: cobertura
+        path: coverage/coverage.xml
 
   cache:
     key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/CMakeLists.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dba88229da2d2fb66dd893f058ece95005fa60e1
--- /dev/null
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/CMakeLists.txt
@@ -0,0 +1,10 @@
+PROJECT(DrivenCavityMultiGPU LANGUAGES CUDA CXX)
+
+vf_add_library(BUILDTYPE binary PRIVATE_LINK basics VirtualFluids_GPU GridGenerator MPI::MPI_CXX FILES DrivenCavityMultiGPU.cpp)
+
+set_source_files_properties(DrivenCavityMultiGPU.cpp PROPERTIES LANGUAGE CUDA)
+
+set_target_properties(DrivenCavityMultiGPU PROPERTIES 
+	CUDA_SEPARABLE_COMPILATION ON
+	VS_DEBUGGER_COMMAND "C:/Program Files/Microsoft MPI/Bin/mpiexec.exe"
+    VS_DEBUGGER_COMMAND_ARGUMENTS "-n 2 \"$<TARGET_FILE:DrivenCavityMultiGPU>\"")
\ No newline at end of file
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/DrivenCavityMultiGPU.cpp b/apps/gpu/LBM/DrivenCavityMultiGPU/DrivenCavityMultiGPU.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c8251915006613d50fabaaa52735b60c80e64a7e
--- /dev/null
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/DrivenCavityMultiGPU.cpp
@@ -0,0 +1,634 @@
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <stdexcept>
+#include <fstream>
+#include <exception>
+#include <memory>
+
+#include "mpi.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "basics/Core/DataTypes.h"
+#include "basics/PointerDefinitions.h"
+#include "basics/Core/VectorTypes.h"
+
+#include "basics/Core/LbmOrGks.h"
+#include "basics/Core/StringUtilities/StringUtil.h"
+#include "basics/config/ConfigurationFile.h"
+#include "basics/Core/Logger/Logger.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "GridGenerator/grid/GridBuilder/LevelGridBuilder.h"
+#include "GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
+#include "GridGenerator/grid/BoundaryConditions/Side.h"
+#include "GridGenerator/grid/GridFactory.h"
+
+#include "geometries/Cuboid/Cuboid.h"
+#include "geometries/TriangularMesh/TriangularMesh.h"
+
+#include "GridGenerator/io/SimulationFileWriter/SimulationFileWriter.h"
+#include "GridGenerator/io/GridVTKWriter/GridVTKWriter.h"
+#include "GridGenerator/io/STLReaderWriter/STLReader.h"
+#include "GridGenerator/io/STLReaderWriter/STLWriter.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "VirtualFluids_GPU/LBM/Simulation.h"
+#include "VirtualFluids_GPU/Communication/Communicator.h"
+#include "VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
+#include "VirtualFluids_GPU/DataStructureInitializer/GridProvider.h"
+#include "VirtualFluids_GPU/DataStructureInitializer/GridReaderFiles/GridReader.h"
+#include "VirtualFluids_GPU/Parameter/Parameter.h"
+#include "VirtualFluids_GPU/Output/FileWriter.h"
+
+#include "VirtualFluids_GPU/Kernel/Utilities/KernelFactory/KernelFactoryImp.h"
+#include "VirtualFluids_GPU/PreProcessor/PreProcessorFactory/PreProcessorFactoryImp.h"
+
+#include "VirtualFluids_GPU/GPU/CudaMemoryManager.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "utilities/communication.h"
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+//          U s e r    s e t t i n g s
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//  Tesla 03
+// std::string outPath("E:/temp/DrivenCavityMultiGPUResults/");
+// std::string gridPath = "D:/STLs/DrivenCavity";
+// std::string simulationName("DrivenCavityMultiGPU");
+
+// Phoenix
+// std::string outPath("/work/y0078217/Results/DrivenCavityMultiGPUResults/");
+// std::string gridPath = "/work/y0078217/Grids/GridDrivenCavityMultiGPU/";
+// std::string simulationName("DrivenCavityMultiGPU");
+
+//  Aragorn
+std::string outPath("/workspaces/VirtualFluids_dev/output/DrivenCavity_Results/");
+std::string gridPath = "/workspaces/VirtualFluids_dev/output/DrivenCavity_Results/grid/";
+std::string simulationName("DrivenCavity");
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void multipleLevel(const std::string& configPath)
+{
+    logging::Logger::addStream(&std::cout);
+    logging::Logger::setDebugLevel(logging::Logger::Level::INFO_LOW);
+    logging::Logger::timeStamp(logging::Logger::ENABLE);
+    logging::Logger::enablePrintedRankNumbers(logging::Logger::ENABLE);
+
+    auto gridFactory = GridFactory::make();
+    gridFactory->setGridStrategy(Device::CPU);
+    gridFactory->setTriangularMeshDiscretizationMethod(TriangularMeshDiscretizationMethod::POINT_IN_OBJECT);
+
+    auto gridBuilder = MultipleGridBuilder::makeShared(gridFactory);
+    
+	vf::gpu::Communicator* comm = vf::gpu::Communicator::getInstanz();
+    vf::basics::ConfigurationFile config;
+    std::cout << configPath << std::endl;
+    config.load(configPath);
+    SPtr<Parameter> para = std::make_shared<Parameter>(config, comm->getNummberOfProcess(), comm->getPID());
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    bool useGridGenerator = true;
+    bool useLevels        = true;
+    // para->setUseStreams(useStreams);                  // set in config
+    // para->useReducedCommunicationAfterFtoC = true;    // set in config
+    para->setCalcTurbulenceIntensity(false);
+
+    if (para->getNumprocs() == 1) {
+       para->useReducedCommunicationAfterFtoC = false;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    const real L  = 1.0;
+    const real Re = 1000.0; //1000
+    const real velocity  = 1.0;
+    const real dt = (real)1.0e-3; //0.5e-3;
+    const uint nx = 64;
+    std::string simulationName("DrivenCavityChimMultiGPU");
+
+    // para->setTOut(10000);   // set in config
+    // para->setTEnd(10000);   // set in config
+
+
+    const real dxGrid = L / real(nx);
+    const real velocityLB = velocity * dt / dxGrid; // LB units
+	const real vxLB = velocityLB / (real)sqrt(2.0); // LB units
+	const real vyLB = velocityLB / (real)sqrt(2.0); // LB units
+    const real viscosityLB = nx * velocityLB / Re; // LB units
+
+    *logging::out << logging::Logger::INFO_HIGH << "velocity  [dx/dt] = " << velocityLB << " \n";
+    *logging::out << logging::Logger::INFO_HIGH << "viscosity [dx^2/dt] = " << viscosityLB << "\n";
+
+    para->setVelocity(velocityLB);
+    para->setViscosity(viscosityLB);
+    para->setVelocityRatio(velocity/ velocityLB);
+    para->setDensityRatio((real) 1.0); // correct value?
+
+	para->setInitialCondition([&](real coordX, real coordY, real coordZ, real &rho, real &vx, real &vy, real &vz) {
+           rho = (real) 1.0;
+           vx  = (real) (coordX * velocityLB);
+           vy  = (real) (coordY * velocityLB);
+           vz  = (real) (coordZ * velocityLB);
+    });
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    para->setCalcDragLift(false);
+    para->setUseWale(false);
+
+    if (para->getOutputPath().size() == 0) {
+        para->setOutputPath(outPath);
+    }
+    para->setOutputPrefix(simulationName);
+    para->setFName(para->getOutputPath() + para->getOutputPrefix());
+    para->setPrintFiles(true);
+    std::cout << "Write result files to " << para->getFName() << std::endl;
+
+
+    if (useLevels)
+        para->setMaxLevel(2);
+    else
+        para->setMaxLevel(1);
+
+
+    // para->setMainKernel("CumulantK17CompChim");
+    para->setMainKernel("CumulantK17CompChimStream");
+    *logging::out << logging::Logger::INFO_HIGH << "Kernel: " << para->getMainKernel() << "\n";
+
+    // if (para->getNumprocs() > 1) {
+    //     para->setDevices(std::vector<uint>{ (uint)0, (uint)1 });
+    //     para->setMaxDev(2);
+    // } else 
+    //     para->setDevices(std::vector<uint>{ (uint)0 });
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    if (useGridGenerator) {
+        const real xGridMin  = -0.5 * L;
+        const real xGridMax  = 0.5 * L;
+        const real yGridMin  = -0.5 * L;
+        const real yGridMax  = 0.5 * L;
+        const real zGridMin  = -0.5 * L;     
+        const real zGridMax  = 0.5 * L;
+
+        Cuboid *level1 = nullptr;
+        if (useLevels)
+            level1 = new Cuboid(-0.25 * L,-0.25 * L, -0.25 * L, 0.25 * L, 0.25 * L, 0.25 * L);  
+
+
+        if (para->getNumprocs() > 1) {
+
+            const uint generatePart = vf::gpu::Communicator::getInstanz()->getPID();
+            real overlap = (real)8.0 * dxGrid;
+            gridBuilder->setNumberOfLayers(10, 8);
+
+            const real xSplit = 0.0;
+            const real ySplit = 0.0;
+            const real zSplit = 0.0;
+
+            if (comm->getNummberOfProcess() == 2) {
+
+                if (generatePart == 0) {
+                    gridBuilder->addCoarseGrid( xGridMin,   yGridMin,     zGridMin, 
+                                                xGridMax,   yGridMax,     zSplit+overlap,   dxGrid);
+                }
+                if (generatePart == 1) {
+                    gridBuilder->addCoarseGrid( xGridMin,    yGridMin,     zSplit-overlap, 
+                                                xGridMax,    yGridMax,     zGridMax,        dxGrid);
+                }
+
+
+                if (useLevels) {
+                    gridBuilder->addGrid(level1, 1);
+                }
+
+                if (generatePart == 0){
+                    gridBuilder->setSubDomainBox(std::make_shared<BoundingBox>(xGridMin,    xGridMax,
+                                                                               yGridMin,    yGridMax, 
+                                                                               zGridMin,    zSplit));
+                }
+                if (generatePart == 1){
+                    gridBuilder->setSubDomainBox(std::make_shared<BoundingBox>(xGridMin,    xGridMax, 
+                                                                               yGridMin,    yGridMax, 
+                                                                               zSplit,      zGridMax));            
+                }
+
+                gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
+
+                if (generatePart == 0) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PZ, 1);
+                }
+
+                if (generatePart == 1) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MZ, 0);
+                }
+                
+                gridBuilder->setPeriodicBoundaryCondition(false, false, false);
+                ////////////////////////////////////////////////////////////////////////// 
+                if (generatePart == 0)
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
+                if (generatePart == 1)
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+                gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+                gridBuilder->setVelocityBoundaryCondition(SideType::MY, 0.0, 0.0, 0.0);
+                gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+                gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);
+                //////////////////////////////////////////////////////////////////////////           
+            } else if (comm->getNummberOfProcess() == 4) {
+
+                if (generatePart == 0) {
+                    gridBuilder->addCoarseGrid(xGridMin, yGridMin, zGridMin, xSplit + overlap, yGridMax,
+                                               zSplit + overlap, dxGrid);
+                }
+                if (generatePart == 1) {
+                    gridBuilder->addCoarseGrid(xSplit - overlap, yGridMin, zGridMin, xGridMax, yGridMax,
+                                               zSplit+overlap, dxGrid);
+                }
+                if (generatePart == 2) {
+                    gridBuilder->addCoarseGrid(xGridMin, yGridMin, zSplit-overlap, xSplit + overlap, yGridMax,
+                                               zGridMax, dxGrid);
+                }
+                if (generatePart == 3) {
+                    gridBuilder->addCoarseGrid(xSplit - overlap, yGridMin, zSplit-overlap, xGridMax, yGridMax,
+                                               zGridMax, dxGrid);
+                }
+
+                if (useLevels) {
+                    gridBuilder->addGrid(level1, 1);
+                }
+
+                if (generatePart == 0)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xGridMin, xSplit, yGridMin, yGridMax, zGridMin, zSplit));
+                if (generatePart == 1)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xSplit, xGridMax, yGridMin, yGridMax, zGridMin, zSplit));
+                if (generatePart == 2)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xGridMin, xSplit, yGridMin, yGridMax, zSplit, zGridMax));
+                if (generatePart == 3)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xSplit, xGridMax, yGridMin, yGridMax, zSplit, zGridMax));
+
+                gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
+
+                if (generatePart == 0) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PX, 1);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PZ, 2);
+                }
+                if (generatePart == 1) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MX, 0);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PZ, 3);
+                }
+                if (generatePart == 2) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PX, 3);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MZ, 0);
+                }
+                if (generatePart == 3) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MX, 2);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MZ, 1);
+                }
+
+                gridBuilder->setPeriodicBoundaryCondition(false, false, false);
+                //////////////////////////////////////////////////////////////////////////
+                if (generatePart == 0) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+                }
+                if (generatePart == 2) {                    
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+                }
+                gridBuilder->setVelocityBoundaryCondition(SideType::MY, 0.0, 0.0, 0.0);
+                gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);                
+                if (generatePart == 3) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+                }
+                if (generatePart == 1) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);                    
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+                }
+                //////////////////////////////////////////////////////////////////////////
+            } else if (comm->getNummberOfProcess() == 8) {
+
+                if (generatePart == 0) {
+                    gridBuilder->addCoarseGrid(xGridMin, yGridMin, zGridMin, xSplit + overlap, ySplit + overlap,
+                                               zSplit + overlap, dxGrid);
+                }
+                if (generatePart == 1) {
+                    gridBuilder->addCoarseGrid(xGridMin, ySplit - overlap, zGridMin, xSplit + overlap, yGridMax,
+                                               zSplit + overlap, dxGrid);
+                }
+                if (generatePart == 2) {
+                    gridBuilder->addCoarseGrid(xSplit - overlap, yGridMin, zGridMin, xGridMax, ySplit + overlap,
+                                               zSplit + overlap, dxGrid);
+                }
+                if (generatePart == 3) {
+                    gridBuilder->addCoarseGrid(xSplit - overlap, ySplit - overlap, zGridMin, xGridMax, yGridMax,
+                                               zSplit + overlap, dxGrid);
+                }
+                if (generatePart == 4) {
+                    gridBuilder->addCoarseGrid(xGridMin, yGridMin, zSplit - overlap, xSplit + overlap, ySplit + overlap,
+                                               zGridMax, dxGrid);
+                }
+                if (generatePart == 5) {
+                    gridBuilder->addCoarseGrid(xGridMin, ySplit - overlap, zSplit - overlap, xSplit + overlap, yGridMax,
+                                               zGridMax, dxGrid);
+                }
+                if (generatePart == 6) {
+                    gridBuilder->addCoarseGrid(xSplit - overlap, yGridMin, zSplit - overlap, xGridMax, ySplit + overlap,
+                                               zGridMax, dxGrid);
+                }
+                if (generatePart == 7) {
+                    gridBuilder->addCoarseGrid(xSplit - overlap, ySplit - overlap, zSplit - overlap, xGridMax, yGridMax,
+                                               zGridMax, dxGrid);
+                }
+
+                if (useLevels) {
+                    gridBuilder->addGrid(level1, 1);
+                }
+                
+                if (generatePart == 0)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xGridMin, xSplit, yGridMin, ySplit, zGridMin, zSplit));
+                if (generatePart == 1)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xGridMin, xSplit, ySplit, yGridMax, zGridMin, zSplit));
+                if (generatePart == 2)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xSplit, xGridMax, yGridMin, ySplit, zGridMin, zSplit));
+                if (generatePart == 3)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xSplit, xGridMax, ySplit, yGridMax, zGridMin, zSplit));
+                if (generatePart == 4)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xGridMin, xSplit, yGridMin, ySplit, zSplit, zGridMax));
+                if (generatePart == 5)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xGridMin, xSplit, ySplit, yGridMax, zSplit, zGridMax));
+                if (generatePart == 6)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xSplit, xGridMax, yGridMin, ySplit, zSplit, zGridMax));
+                if (generatePart == 7)
+                    gridBuilder->setSubDomainBox(
+                        std::make_shared<BoundingBox>(xSplit, xGridMax, ySplit, yGridMax, zSplit, zGridMax));
+
+                gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
+                gridBuilder->setPeriodicBoundaryCondition(false, false, false);
+
+                if (generatePart == 0) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PY, 1);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PX, 2);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PZ, 4);
+                }
+                if (generatePart == 1) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MY, 0);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PX, 3);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PZ, 5);
+                }
+                if (generatePart == 2) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PY, 3);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MX, 0);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PZ, 6);
+                }
+                if (generatePart == 3) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MY, 2);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MX, 1);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PZ, 7);
+                }
+                if (generatePart == 4) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PY, 5);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PX, 6);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MZ, 0);
+                }
+                if (generatePart == 5) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MY, 4);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PX, 7);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MZ, 1);
+                }
+                if (generatePart == 6) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::PY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::PY, 7);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MX, 4);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MZ, 2);
+                }
+                if (generatePart == 7) {
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MY, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MY, 6);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MX, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MX, 5);
+                    gridBuilder->findCommunicationIndices(CommunicationDirections::MZ, LBM);
+                    gridBuilder->setCommunicationProcess(CommunicationDirections::MZ, 3);
+                }
+
+                //////////////////////////////////////////////////////////////////////////
+                if (generatePart == 0) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MY,  0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
+                }
+                if (generatePart == 1) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
+                }
+                if (generatePart == 2) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MY,  0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+                }
+                if (generatePart == 3) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+                }
+                if (generatePart == 4) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MY,  0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+                }
+                if (generatePart == 5) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+                }
+                if (generatePart == 6) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::MY,  0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+                }
+                if (generatePart == 7) {
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+                    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+                }
+                //////////////////////////////////////////////////////////////////////////                
+            }
+            if (para->getKernelNeedsFluidNodeIndicesToRun())
+                gridBuilder->findFluidNodes(para->getUseStreams());
+
+            // gridBuilder->writeGridsToVtk(outPath +  "/grid/part" + std::to_string(generatePart) + "_"); 
+            // gridBuilder->writeGridsToVtk(outPath + "/" + std::to_string(generatePart) + "/grid/"); 
+            // gridBuilder->writeArrows(outPath + "/" + std::to_string(generatePart) + " /arrow");
+
+            SimulationFileWriter::write(gridPath + std::to_string(generatePart) + "/", gridBuilder,
+                                        FILEFORMAT::BINARY);
+        } else {
+
+            gridBuilder->addCoarseGrid(xGridMin, yGridMin, zGridMin, xGridMax, yGridMax, zGridMax, dxGrid);
+
+            if (useLevels) {
+                gridBuilder->setNumberOfLayers(10, 8);
+                gridBuilder->addGrid(level1, 1);
+            }
+
+            gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
+            gridBuilder->setPeriodicBoundaryCondition(false, false, false);
+            //////////////////////////////////////////////////////////////////////////
+            gridBuilder->setVelocityBoundaryCondition(SideType::MX, 0.0, 0.0, 0.0);
+            gridBuilder->setVelocityBoundaryCondition(SideType::PX, 0.0, 0.0, 0.0);
+            gridBuilder->setVelocityBoundaryCondition(SideType::MY, 0.0, 0.0, 0.0);
+            gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);
+            gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
+            gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vxLB, 0.0, 0.0);
+
+            //////////////////////////////////////////////////////////////////////////
+            if (para->getKernelNeedsFluidNodeIndicesToRun())
+                gridBuilder->findFluidNodes(para->getUseStreams());
+
+            gridBuilder->writeGridsToVtk(outPath +  "/grid/");
+            // gridBuilder->writeArrows(outPath + "/arrow");
+
+            SimulationFileWriter::write(gridPath, gridBuilder, FILEFORMAT::BINARY);
+        }
+    }
+        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    SPtr<CudaMemoryManager> cudaMemoryManager = CudaMemoryManager::make(para);
+
+    SPtr<GridProvider> gridGenerator;
+    if (useGridGenerator)
+        gridGenerator = GridProvider::makeGridGenerator(gridBuilder, para, cudaMemoryManager);
+    else {
+        gridGenerator = GridProvider::makeGridReader(FILEFORMAT::BINARY, para, cudaMemoryManager);
+    }
+           
+    Simulation sim;
+    SPtr<FileWriter> fileWriter = SPtr<FileWriter>(new FileWriter());
+    SPtr<KernelFactoryImp> kernelFactory = KernelFactoryImp::getInstance();
+    SPtr<PreProcessorFactoryImp> preProcessorFactory = PreProcessorFactoryImp::getInstance();
+    sim.setFactories(kernelFactory, preProcessorFactory);
+    sim.init(para, gridGenerator, fileWriter, cudaMemoryManager);
+    sim.run();
+    sim.free();
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
+
+int main( int argc, char* argv[])
+{
+    MPI_Init(&argc, &argv);
+    std::string str, str2, configFile;
+
+    if ( argv != NULL )
+    {
+        //str = static_cast<std::string>(argv[0]);
+        
+        try {
+            //////////////////////////////////////////////////////////////////////////
+
+            std::string targetPath;
+
+            targetPath = __FILE__;
+
+            if (argc == 2) {
+                configFile = argv[1];
+                std::cout << "Using configFile command line argument: " << configFile << std::endl;
+            }
+
+#ifdef _WIN32
+            targetPath = targetPath.substr(0, targetPath.find_last_of('\\') + 1);
+#else
+            targetPath = targetPath.substr(0, targetPath.find_last_of('/') + 1);
+#endif
+
+            std::cout << targetPath << std::endl;
+
+            if (configFile.size() == 0) {
+                configFile = targetPath + "configDrivenCavityMultiGPU.txt";
+            }
+
+            multipleLevel(configFile);
+
+            //////////////////////////////////////////////////////////////////////////
+        }
+        catch (const std::bad_alloc& e)
+        { 
+            *logging::out << logging::Logger::LOGGER_ERROR << "Bad Alloc:" << e.what() << "\n";
+        }
+        catch (const std::exception& e)
+        {   
+            *logging::out << logging::Logger::LOGGER_ERROR << e.what() << "\n";
+        }
+        catch (...)
+        {
+            *logging::out << logging::Logger::LOGGER_ERROR << "Unknown exception!\n";
+        }
+    }
+
+   MPI_Finalize();
+   return 0;
+}
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/configDrivenCavityMultiGPU.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/configDrivenCavityMultiGPU.txt
new file mode 100644
index 0000000000000000000000000000000000000000..97f5b5d8079e6b937863cca09e6076e0a753af23
--- /dev/null
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/configDrivenCavityMultiGPU.txt
@@ -0,0 +1,36 @@
+##################################################
+#GPU Mapping
+##################################################
+Devices="0"
+NumberOfDevices=1
+
+##################################################
+#informations for Writing
+##################################################
+Path=/workspaces/VirtualFluids_dev/output/DrivenCavity_Results/  # Aragorn
+#Prefix="DrivenCavity"
+#WriteGrid=true
+##################################################
+#informations for reading
+##################################################
+GridPath=/workspaces/VirtualFluids_dev/output/DrivenCavity_Results/grid/  # Aragorn
+#GridPath="C:"
+
+##################################################
+#number of grid levels
+##################################################
+#NOGL=1
+
+##################################################
+#LBM Version
+##################################################
+
+#D3Qxx=27
+#MainKernelName=CumulantK17CompChim
+
+##################################################
+#simulation parameter
+##################################################
+TimeEnd=1000
+TimeOut=100
+#TimeStartOut=0
\ No newline at end of file
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix1GPU.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix1GPU.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e63db13b533d24ef44b2e4d472ffba481d79f828
--- /dev/null
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix1GPU.txt
@@ -0,0 +1,35 @@
+##################################################
+#GPU Mapping
+##################################################
+Devices="0"
+NumberOfDevices=1
+
+##################################################
+#informations for Writing
+##################################################
+Path=/work/y0078217/Results/DrivenCavityMultiGPUResults/1GPU/
+#Prefix="DrivenCavityMultiGPU" 
+#WriteGrid=true
+##################################################
+#informations for reading
+##################################################
+GridPath=/work/y0078217/Grids/GridDrivenCavityMultiGPU/1GPU/
+#GridPath="C:"
+
+##################################################
+#number of grid levels
+##################################################
+#NOGL=1
+
+##################################################
+#LBM Version
+##################################################
+#D3Qxx=27
+#MainKernelName=CumulantK17CompChim
+
+##################################################
+#simulation parameter
+##################################################
+TimeEnd=1000
+TimeOut=1000
+#TimeStartOut=0
\ No newline at end of file
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix2GPU.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix2GPU.txt
new file mode 100644
index 0000000000000000000000000000000000000000..30b1882df34dcae63674b42ce6d65a47942ff87e
--- /dev/null
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix2GPU.txt
@@ -0,0 +1,41 @@
+##################################################
+#GPU Mapping
+##################################################
+Devices="0 1"
+NumberOfDevices=2
+
+##################################################
+#informations for Writing
+##################################################
+Path=/work/y0078217/Results/DrivenCavityMultiGPUResults/2GPU/
+#Prefix="DrivenCavityMultiGPU" 
+#WriteGrid=true
+##################################################
+#informations for reading
+##################################################
+GridPath=/work/y0078217/Grids/GridDrivenCavityMultiGPU/2GPU/
+#GridPath="C:"
+
+##################################################
+#number of grid levels
+##################################################
+#NOGL=1
+
+##################################################
+#LBM Version
+##################################################
+#D3Qxx=27
+#MainKernelName=CumulantK17CompChim
+
+##################################################
+#simulation parameter
+##################################################
+TimeEnd=1
+TimeOut=1
+#TimeStartOut=0
+
+##################################################
+# CUDA Streams and optimized communication (only used for multiple GPUs)
+##################################################
+useStreams = true
+useReducedCommunicationInInterpolation = true
\ No newline at end of file
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix4GPU.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix4GPU.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c710922b9fc82ac7680f5f7daade4faa235bc957
--- /dev/null
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix4GPU.txt
@@ -0,0 +1,41 @@
+##################################################
+#GPU Mapping
+##################################################
+Devices="0 1 2 3"
+NumberOfDevices=4
+
+##################################################
+#informations for Writing
+##################################################
+Path=/work/y0078217/Results/DrivenCavityMultiGPUResults/4GPU/
+#Prefix="DrivenCavityMultiGPU" 
+#WriteGrid=true
+##################################################
+#informations for reading
+##################################################
+GridPath=/work/y0078217/Grids/GridDrivenCavityMultiGPU/4GPU/
+#GridPath="C:"
+
+##################################################
+#number of grid levels
+##################################################
+#NOGL=1
+
+##################################################
+#LBM Version
+##################################################
+#D3Qxx=27
+#MainKernelName=CumulantK17CompChim
+
+##################################################
+#simulation parameter
+##################################################
+TimeEnd=1
+TimeOut=1
+#TimeStartOut=0
+
+##################################################
+# CUDA Streams and optimized communication (only used for multiple GPUs)
+##################################################
+useStreams = true
+useReducedCommunicationInInterpolation = true
\ No newline at end of file
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix8GPU.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix8GPU.txt
new file mode 100644
index 0000000000000000000000000000000000000000..85684e7589dad91e53356c16bc2eae44081d7e96
--- /dev/null
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix8GPU.txt
@@ -0,0 +1,41 @@
+##################################################
+#GPU Mapping
+##################################################
+Devices="0 1 2 3"
+NumberOfDevices=4
+
+##################################################
+#informations for Writing
+##################################################
+Path=/work/y0078217/Results/DrivenCavityMultiGPUResults/8GPU/
+#Prefix="DrivenCavityMultiGPU" 
+#WriteGrid=true
+##################################################
+#informations for reading
+##################################################
+GridPath=/work/y0078217/Grids/GridDrivenCavityMultiGPU/8GPU/
+#GridPath="C:"
+
+##################################################
+#number of grid levels
+##################################################
+#NOGL=1
+
+##################################################
+#LBM Version
+##################################################
+#D3Qxx=27
+#MainKernelName=CumulantK17CompChim
+
+##################################################
+#simulation parameter
+##################################################
+TimeEnd=1000
+TimeOut=1000
+#TimeStartOut=0
+
+##################################################
+# CUDA Streams and optimized communication (only used for multiple GPUs)
+##################################################
+useStreams = true
+useReducedCommunicationInInterpolation = true
\ No newline at end of file
diff --git a/apps/gpu/LBM/MusselOyster/MusselOyster.cpp b/apps/gpu/LBM/MusselOyster/MusselOyster.cpp
index f5c40013bf8931440b95b85d65ab07849d80183d..2c9290a062244f5437f3915d9da0c322370b0097 100644
--- a/apps/gpu/LBM/MusselOyster/MusselOyster.cpp
+++ b/apps/gpu/LBM/MusselOyster/MusselOyster.cpp
@@ -1,4 +1,3 @@
-
 #define _USE_MATH_DEFINES
 #include <math.h>
 #include <string>
@@ -67,12 +66,18 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-//  Tesla 03
+// Tesla 03
 // std::string outPath("E:/temp/MusselOysterResults/");
 // std::string gridPathParent = "E:/temp/GridMussel/";
 // std::string stlPath("C:/Users/Master/Documents/MasterAnna/STL/");
 // std::string simulationName("MusselOyster");
 
+// Aragorn
+// std::string outPath("/workspaces/VirtualFluids_dev/output/MusselOysterResults/");
+// std::string gridPathParent = "/workspaces/VirtualFluids_dev/output/MusselOysterResults/grid/";
+// std::string stlPath("/workspaces/VirtualFluids_dev/stl/MusselOyster/");
+// std::string simulationName("MusselOyster");
+
 // Phoenix
 std::string outPath("/work/y0078217/Results/MusselOysterResults/");
 std::string gridPathParent = "/work/y0078217/Grids/GridMusselOyster/";
@@ -123,7 +128,6 @@ void multipleLevel(const std::string& configPath)
     para->setCalcTurbulenceIntensity(true);
 
     if (para->getNumprocs() == 1) {
-       useStreams       = false;
        para->useReducedCommunicationAfterFtoC = false;
     }
 
@@ -138,16 +142,8 @@ void multipleLevel(const std::string& configPath)
         dxGrid = 0.5;  
     real vxLB = (real)0.051; // LB units
     real Re = (real)300.0;
-
-    // real heightBivalve;
-    // if (bivalveType == "MUSSEL")
-    //     heightBivalve = (real)35.0; 
-    // else if (bivalveType == "OYSTER")
-    //     heightBivalve = (real)72.0;
-    // else
-    //     std::cerr << "Error: unknown bivalveType" << std::endl;
-    real length = 1.0 / dxGrid; // heightBivalve / dxGrid
-    real viscosityLB = (vxLB * length) / Re;
+    real referenceLength = 1.0 / dxGrid; // heightBivalve / dxGrid
+    real viscosityLB = (vxLB * referenceLength) / Re;
 
     para->setVelocity(vxLB);
     para->setViscosity(viscosityLB);
@@ -165,7 +161,6 @@ void multipleLevel(const std::string& configPath)
     *logging::out << logging::Logger::INFO_HIGH << "useStreams = " << useStreams << "\n";
     *logging::out << logging::Logger::INFO_HIGH << "number of processes = " << para->getNumprocs() << "\n";
 
-    
     // para->setTOut(1000);
     // para->setTEnd(10000);
 
@@ -187,46 +182,16 @@ void multipleLevel(const std::string& configPath)
         para->setMaxLevel(1);
 
 
-    if (useStreams)
-        para->setUseStreams();
+
+    para->setUseStreams(useStreams);
     // para->setMainKernel("CumulantK17CompChim");
     para->setMainKernel("CumulantK17CompChimStream");
     *logging::out << logging::Logger::INFO_HIGH << "Kernel: " << para->getMainKernel() << "\n";
 
-    // if (para->getNumprocs() > 1) {
-    //     para->setDevices(std::vector<uint>{ (uint)0, (uint)1 });
-    //     para->setMaxDev(2);
-    // } else 
-    //     para->setDevices(std::vector<uint>{ (uint)0 });
-
-
-
     //////////////////////////////////////////////////////////////////////////
 
 
     if (useGridGenerator) {
-        // real bbzm;
-        // real bbzp;
-        // if (bivalveType == "MUSSEL")
-        //     bbzp = 9.0;
-        // if (bivalveType == "OYSTER")
-        //     bbzp = 13.0;
-        // bbzm = -bbzp;
-        // bounding box mussel:
-        // const real bbxm = 0.0;
-        // const real bbxp = 76.0;
-        // const real bbym = 0.0;
-        // const real bbyp = 35.0;
-        // const real bbzm = -9.15;
-        // const real bbzp = 9.15;
-        // bounding box oyster:
-        // const real bbxm = 0.0;
-        // const real bbxp = 102.0;
-        // const real bbym = 0.0;
-        // const real bbyp = 72.0;
-        // const real bbzm = -13.0;
-        // const real bbzp = 13.0;
-
         const real xGridMin  = -100.0;     // -100.0;
         const real xGridMax  = 470.0;      // alt 540.0 // neu 440 // mit groesserem Level 1 470
         const real yGridMin  = 1.0;        // 1.0;
@@ -234,6 +199,9 @@ void multipleLevel(const std::string& configPath)
         const real zGridMin  = -85;        // -85;
         const real zGridMax  = 85.0;       // 85;
 
+        // height MUSSEL = 35.0
+        // height Oyster = 72.0
+
         TriangularMesh *bivalveSTL       = TriangularMesh::make(stlPath + bivalveType + ".stl");
         TriangularMesh *bivalveRef_1_STL = nullptr;
         if (useLevels)
@@ -541,12 +509,12 @@ void multipleLevel(const std::string& configPath)
                 if (generatePart == 2) {
                     gridBuilder->setVelocityBoundaryCondition(SideType::MY,  0.0, 0.0, 0.0);
                     gridBuilder->setVelocityBoundaryCondition(SideType::MZ, vxLB, 0.0, 0.0);
-                    gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);
+                    gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);   // set pressure BC after velocity BCs
                 }
                 if (generatePart == 3) {
                     gridBuilder->setVelocityBoundaryCondition(SideType::PY, vxLB, 0.0, 0.0);
                     gridBuilder->setVelocityBoundaryCondition(SideType::MZ, vxLB, 0.0, 0.0);
-                    gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);
+                    gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);   // set pressure BC after velocity BCs
                 }
                 if (generatePart == 4) {
                     gridBuilder->setVelocityBoundaryCondition(SideType::MX, vxLB, 0.0, 0.0);
@@ -574,12 +542,12 @@ void multipleLevel(const std::string& configPath)
             if (para->getKernelNeedsFluidNodeIndicesToRun())
                 gridBuilder->findFluidNodes(useStreams);
 
-            // gridBuilder->writeGridsToVtk(outPath +  bivalveType + "/grid/part" + std::to_string(generatePart) + "_"); 
-            // gridBuilder->writeGridsToVtk(outPath + bivalveType + "/" + std::to_string(generatePart) + "/grid/"); 
+            // std::cout << "Writing grids to vtk" << outPath <<  bivalveType << "/grid/part" << std::to_string(generatePart) + "...";
+            // gridBuilder->writeGridsToVtk(outPath +  bivalveType + "/grid/part" + std::to_string(generatePart) + "_");
+            // std::cout << "... done" << std::endl;
             // gridBuilder->writeArrows(outPath + bivalveType + "/" + std::to_string(generatePart) + " /arrow");
-
-            SimulationFileWriter::write(gridPath + std::to_string(generatePart) + "/", gridBuilder,
-                                        FILEFORMAT::BINARY);
+            // SimulationFileWriter::write(gridPath + std::to_string(generatePart) + "/", gridBuilder,
+            //                             FILEFORMAT::BINARY);
         } else {
 
             gridBuilder->addCoarseGrid(xGridMin, yGridMin, zGridMin, xGridMax, yGridMax, zGridMax, dxGrid);
@@ -612,41 +580,6 @@ void multipleLevel(const std::string& configPath)
 
             SimulationFileWriter::write(gridPath, gridBuilder, FILEFORMAT::BINARY);
         }
-        
-        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-        // const real velocityLB = velocity * dt / dx; // LB units
-
-        // const real vx = velocityLB / (real)sqrt(2.0); // LB units
-        // const real vy = velocityLB / (real)sqrt(2.0); // LB units
-
-        // const real viscosityLB = nx * velocityLB / Re; // LB units
-
-        //*logging::out << logging::Logger::INFO_HIGH << "velocity  [dx/dt] = " << velocityLB << " \n";
-        //*logging::out << logging::Logger::INFO_HIGH << "viscosity [dx^2/dt] = " << viscosityLB << "\n";
-
-        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-        // para->setVelocity(velocityLB);
-        // para->setViscosity(viscosityLB);
-
-        // para->setVelocityRatio(velocity/ velocityLB);
-
-        // para->setMainKernel("CumulantK17CompChim");
-
-        // para->setInitialCondition([&](real coordX, real coordY, real coordZ, real &rho, real &vx, real &vy, real &vz)
-        // {
-        //          rho = (real)0.0;
-        //          vx  = (real)0.0; //(6 * velocityLB * coordZ * (L - coordZ) / (L * L));
-        //          vy  = (real)0.0;
-        //          vz  = (real)0.0;
-        //      });
-
-
-
-       //return;
     }
         ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
diff --git a/apps/gpu/LBM/MusselOyster/configMusselOyster.txt b/apps/gpu/LBM/MusselOyster/configMusselOyster.txt
index 3c6ac8b5fdff8b5c3befbf2975938416066a61f1..0978e65f0500371a54af99e319ae6c53572d93c0 100644
--- a/apps/gpu/LBM/MusselOyster/configMusselOyster.txt
+++ b/apps/gpu/LBM/MusselOyster/configMusselOyster.txt
@@ -8,6 +8,9 @@
 # Phoenix openmpi
 # mpirun -np 4 nvprof -f -o MusselOyster.%q{OMPI_COMM_WORLD_RANK}.nvprof "./VirtualFluids_dev/build/bin/MusselOyster" "./VirtualFluids_dev/apps/gpu/LBM/SphereScaling/configPhoenix4GPU.txt"
 
+# Aragorn
+ ./bin/MusselOyster "../apps/gpu/LBM/MusselOyster/configMusselOyster.txt"
+
 ##################################################
 #GPU Mapping
 ##################################################
@@ -17,16 +20,15 @@ NumberOfDevices=2
 ##################################################
 #informations for Writing
 ##################################################
-Path=/work/y0078217/Results/MusselOysterResults/
-#Path=E:/temp/MusselOysterResults/
-#Path="F:/Work/Computations/out/MusselOyster/"
+#Path=/work/y0078217/Results/MusselOysterResults/
+Path=/workspaces/VirtualFluids_dev/output/MusselOysterResults/
 #Prefix="MusselOyster" 
 #WriteGrid=true
 ##################################################
 #informations for reading
 ##################################################
-GridPath=E/work/y0078217/Grids/GridMusselOyster/
-#GridPath=E:/temp/GridMussel/MUSSEL/
+#GridPath=E:/work/y0078217/Grids/GridMusselOyster/
+GridPath=/workspaces/VirtualFluids_dev/output/MusselOysterResults/grid/
 #GridPath="C:"
 
 ##################################################
@@ -44,5 +46,5 @@ GridPath=E/work/y0078217/Grids/GridMusselOyster/
 #simulation parameter
 ##################################################
 TimeEnd=10000
-TimeOut=1000 
+TimeOut=10000 
 #TimeStartOut=0
\ No newline at end of file
diff --git a/apps/gpu/LBM/MusselOyster/configPhoenix1GPU.txt b/apps/gpu/LBM/MusselOyster/configPhoenix1GPU.txt
index 4e3863eae9a0f2d52413e7c68b8aa4032b193ae3..369d68be327f72ef3762a2ddaf31ff89b84e06c7 100644
--- a/apps/gpu/LBM/MusselOyster/configPhoenix1GPU.txt
+++ b/apps/gpu/LBM/MusselOyster/configPhoenix1GPU.txt
@@ -31,6 +31,6 @@ GridPath=/work/y0078217/Grids/GridMusselOyster/Mussel1GPU/
 ##################################################
 #simulation parameter
 ##################################################
-TimeEnd=400000 #400000 / 200000
-TimeOut=200000 #200000 / 100000
+TimeEnd=10000 #400000 / 200000
+TimeOut=5000 #200000 / 100000
 #TimeStartOut=0
\ No newline at end of file
diff --git a/apps/gpu/LBM/MusselOyster/configPhoenix8GPU.txt b/apps/gpu/LBM/MusselOyster/configPhoenix8GPU.txt
index a7ef59a69ac43327fff2648dcaae36ec91f70282..4e2b0c91482b6a650ff28a210673cac097cb8c2d 100644
--- a/apps/gpu/LBM/MusselOyster/configPhoenix8GPU.txt
+++ b/apps/gpu/LBM/MusselOyster/configPhoenix8GPU.txt
@@ -7,14 +7,14 @@ NumberOfDevices=4
 ##################################################
 #informations for Writing
 ##################################################
-Path=/work/y0078217/Results/MusselOysterResults/8GPUMussel05/
-#Path="F:/Work/Computations/out/SphereScaling/"
-#Prefix="SphereScaling" 
+Path=/work/y0078217/Results/MusselOysterResults/8GPUOyster05/
+#Path="F:/Work/Computations/out/MusselOyster/"
+#Prefix="MusselOyster" 
 #WriteGrid=true
 ##################################################
 #informations for reading
 ##################################################
-GridPath=/work/y0078217/Grids/GridMusselOyster/Mussel8GPU/
+GridPath=/work/y0078217/Grids/GridMusselOyster/Oyster8GPU/
 #GridPath="C:"
 
 ##################################################
@@ -31,12 +31,12 @@ GridPath=/work/y0078217/Grids/GridMusselOyster/Mussel8GPU/
 ##################################################
 #simulation parameter
 ##################################################
-TimeEnd=1000 # 800000
-TimeOut=1000 # 400000
+TimeEnd=400000 # 800000
+TimeOut=100000 # 400000
 #TimeStartOut=0
 
 ##################################################
 # CUDA Streams and optimized communication (only used for multiple GPUs)
 ##################################################
-useStreams = false
+useStreams = true
 useReducedCommunicationInInterpolation = true
\ No newline at end of file
diff --git a/apps/gpu/LBM/SphereScaling/SphereScaling.cpp b/apps/gpu/LBM/SphereScaling/SphereScaling.cpp
index fbde84da226c4076990cde7b1dfeb76f7b66a645..569a5da6cb0fd62abd24095f7bce27e00b119944 100644
--- a/apps/gpu/LBM/SphereScaling/SphereScaling.cpp
+++ b/apps/gpu/LBM/SphereScaling/SphereScaling.cpp
@@ -119,14 +119,12 @@ void multipleLevel(const std::string& configPath)
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
     bool useGridGenerator                  = true;
-    bool useLevels                         = false;
-    std::string scalingType                = "strong"; // "strong" // "weak"
-    // bool useStreams                        = true;
-    // para->useReducedCommunicationAfterFtoC = true;
-    bool useStreams = para->getUseStreams();
+    bool useLevels                         = true;
+    std::string scalingType                = "strong";   // "strong" // "weak"
+    // para->setUseStreams(true);                        // set in config
+    // para->useReducedCommunicationAfterFtoC = true;    // set in config
 
     if (para->getNumprocs() == 1) {
-       useStreams       = false;
        para->useReducedCommunicationAfterFtoC = false;
     }
     if (scalingType != "weak" && scalingType != "strong")
@@ -150,7 +148,7 @@ void multipleLevel(const std::string& configPath)
     *logging::out << logging::Logger::INFO_HIGH << "viscosity real [m^2/s] = " << viscosityLB * para->getViscosityRatio() << "\n";
     *logging::out << logging::Logger::INFO_HIGH << "dxGrid = " << dxGrid << "\n";
     *logging::out << logging::Logger::INFO_HIGH << "useGridGenerator = " << useGridGenerator << "\n";
-    *logging::out << logging::Logger::INFO_HIGH << "useStreams = " << useStreams << "\n";
+    *logging::out << logging::Logger::INFO_HIGH << "useStreams = " << para->getUseStreams() << "\n";
     *logging::out << logging::Logger::INFO_HIGH << "number of processes = " << para->getNumprocs() << "\n";
     *logging::out << logging::Logger::INFO_HIGH << "para->useReducedCommunicationAfterFtoC = " <<  para->useReducedCommunicationAfterFtoC << "\n";
     *logging::out << logging::Logger::INFO_HIGH << "scalingType = " <<  scalingType << "\n";
@@ -175,8 +173,6 @@ void multipleLevel(const std::string& configPath)
         para->setMaxLevel(1);
 
 
-    if (useStreams)
-        para->setUseStreams();
     //para->setMainKernel("CumulantK17CompChim");
     para->setMainKernel("CumulantK17CompChimStream");
     *logging::out << logging::Logger::INFO_HIGH << "Kernel: " << para->getMainKernel() << "\n";
@@ -607,7 +603,7 @@ void multipleLevel(const std::string& configPath)
                 //////////////////////////////////////////////////////////////////////////                
             }
             if (para->getKernelNeedsFluidNodeIndicesToRun())
-                gridBuilder->findFluidNodes(useStreams);
+                gridBuilder->findFluidNodes(para->getUseStreams());
 
             // gridBuilder->writeGridsToVtk(outPath + "grid/part" +
             // std::to_string(generatePart) + "_"); gridBuilder->writeGridsToVtk(outPath +
@@ -654,7 +650,7 @@ void multipleLevel(const std::string& configPath)
             // gridBuilder->setVelocityBoundaryCondition(SideType::GEOMETRY, 0.0, 0.0, 0.0);
             //////////////////////////////////////////////////////////////////////////
             if (para->getKernelNeedsFluidNodeIndicesToRun())
-                gridBuilder->findFluidNodes(useStreams);
+                gridBuilder->findFluidNodes(para->getUseStreams());
 
             // gridBuilder->writeGridsToVtk("E:/temp/MusselOyster/" + "/grid/");
             // gridBuilder->writeArrows ("E:/temp/MusselOyster/" + "/arrow");
diff --git a/apps/gpu/LBM/SphereScaling/configPhoenix8GPU_2LevStrongStream.txt b/apps/gpu/LBM/SphereScaling/configPhoenix8GPU_2LevStrongStream.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a6d54810d8d4f0ded262a61c5535764c2f6f91b3
--- /dev/null
+++ b/apps/gpu/LBM/SphereScaling/configPhoenix8GPU_2LevStrongStream.txt
@@ -0,0 +1,42 @@
+##################################################
+#GPU Mapping
+##################################################
+Devices="0 1 2 3"
+NumberOfDevices=4
+
+##################################################
+#informations for Writing
+##################################################
+Path=/work/y0078217/Results/SphereScalingResults/8GPU/2LevStrongStream/
+#Path="F:/Work/Computations/out/SphereScaling/"
+#Prefix="SphereScaling" 
+#WriteGrid=true
+##################################################
+#informations for reading
+##################################################
+GridPath=/work/y0078217/Grids/GridSphereScaling/SphereScaling8GPU/
+#GridPath="C:"
+
+##################################################
+#number of grid levels
+##################################################
+#NOGL=1
+
+##################################################
+#LBM Version
+##################################################
+#D3Qxx=27
+#MainKernelName=CumulantK17CompChim
+
+##################################################
+#simulation parameter
+##################################################
+TimeEnd=10000
+TimeOut=10000
+#TimeStartOut=0
+
+##################################################
+# CUDA Streams and optimized communication (only used for multiple GPUs)
+##################################################
+useStreams = true
+useReducedCommunicationInInterpolation = true
\ No newline at end of file
diff --git a/gpu.cmake b/gpu.cmake
index bd27b92e37a61ede1dabcde00026920e34b5ac35..26eafd6ac44dda71480554d6995ba7cbfa342a06 100644
--- a/gpu.cmake
+++ b/gpu.cmake
@@ -44,8 +44,10 @@ IF (BUILD_VF_GPU)
     #add_subdirectory(apps/gpu/LBM/gridGeneratorTest)
     #add_subdirectory(apps/gpu/LBM/TGV_3D)
     #add_subdirectory(apps/gpu/LBM/TGV_3D_MultiGPU)
-	add_subdirectory(apps/gpu/LBM/SphereScaling)
+	#add_subdirectory(apps/gpu/LBM/SphereScaling)
+    #add_subdirectory(apps/gpu/LBM/DrivenCavityMultiGPU)
 	add_subdirectory(apps/gpu/LBM/MusselOyster)
+    # add_subdirectory(apps/gpu/LBM/Poiseuille)
 ELSE()
     MESSAGE( STATUS "exclude Virtual Fluids GPU." )
 ENDIF()
diff --git a/src/gpu/GridGenerator/io/STLReaderWriter/STLReader.cpp b/src/gpu/GridGenerator/io/STLReaderWriter/STLReader.cpp
index a1d0fbbd484d705f6f4f1d28a95e9c0e5ff42442..9c874456ff0956429fafb34cec9fff026a11cafb 100644
--- a/src/gpu/GridGenerator/io/STLReaderWriter/STLReader.cpp
+++ b/src/gpu/GridGenerator/io/STLReaderWriter/STLReader.cpp
@@ -86,7 +86,7 @@ std::vector<Triangle> STLReader::readASCIISTLWithPatches(const std::string& name
     std::ifstream file;
     file.open(name.c_str(), std::ifstream::in);
 
-    if( !file.is_open() ) throw std::runtime_error(name + "cannot be opened!");
+    if( !file.is_open() ) throw std::runtime_error(name + " cannot be opened!");
 
     uint currentPatchIndex = 0;
 
diff --git a/src/gpu/VirtualFluids_GPU/CMakeLists.txt b/src/gpu/VirtualFluids_GPU/CMakeLists.txt
index 194200b5f46093007a35787c61f4183cf197685e..14bf4f6641f9b874788d3674b11fa6ca135f7564 100644
--- a/src/gpu/VirtualFluids_GPU/CMakeLists.txt
+++ b/src/gpu/VirtualFluids_GPU/CMakeLists.txt
@@ -21,4 +21,6 @@ if(BUILD_VF_UNIT_TESTS)
     set_target_properties(VirtualFluids_GPUTests PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
     set_source_files_properties(Kernel/Utilities/DistributionHelperTests.cpp PROPERTIES LANGUAGE CUDA)
 	set_source_files_properties(DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp PROPERTIES LANGUAGE CUDA)
+    set_source_files_properties(Communication/ExchangeData27Test.cpp PROPERTIES LANGUAGE CUDA)
+    target_include_directories(VirtualFluids_GPUTests PRIVATE "${VF_THIRD_DIR}/cuda_samples/")
 endif()
diff --git a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp
index c47c14521efc7833058fc7816e298aeb4d333d7f..cd53553174ee74de2b3ff32b1ff0356ec79cc436 100644
--- a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp
+++ b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.cpp
@@ -48,7 +48,7 @@ void UpdateGrid27::updateGrid(int level, unsigned int t)
 
 void UpdateGrid27::refinementAndExchange_noRefinementAndExchange(int level) {}
 
-void UpdateGrid27::refinementAndExchange_streams(int level)
+void UpdateGrid27::refinementAndExchange_streams_onlyExchangeInterface(int level)
 {
     int borderStreamIndex = para->getStreamManager()->getBorderStreamIndex();
     int bulkStreamIndex   = para->getStreamManager()->getBulkStreamIndex();
@@ -82,6 +82,40 @@ void UpdateGrid27::refinementAndExchange_streams(int level)
     cudaDeviceSynchronize(); 
 }
 
+void UpdateGrid27::refinementAndExchange_streams_completeExchange(int level)
+{
+    int borderStreamIndex = para->getStreamManager()->getBorderStreamIndex();
+    int bulkStreamIndex   = para->getStreamManager()->getBulkStreamIndex();
+
+    // fine to coarse border
+    fineToCoarseWithStream(para.get(), level, para->getParD(level)->intFCBorder.ICellFCC,
+                           para->getParD(level)->intFCBorder.ICellFCF, para->getParD(level)->intFCBorder.kFC,
+                           borderStreamIndex);
+
+    // prepare exchange and trigger bulk kernel when finished
+    prepareExchangeMultiGPU(para.get(), level, borderStreamIndex);
+    if (para->getUseStreams())
+        para->getStreamManager()->triggerStartBulkKernel(borderStreamIndex);
+
+    // launch bulk kernels (f to c and c to f)
+    para->getStreamManager()->waitOnStartBulkKernelEvent(bulkStreamIndex);
+    fineToCoarseWithStream(para.get(), level, para->getParD(level)->intFCBulk.ICellFCC,
+                           para->getParD(level)->intFCBulk.ICellFCF, para->getParD(level)->intFCBulk.kFC,
+                           bulkStreamIndex);
+    coarseToFineWithStream(para.get(), level, para->getParD(level)->intCFBulk.ICellCFC,
+                           para->getParD(level)->intCFBulk.ICellCFF, para->getParD(level)->intCFBulk.kCF, para->getParD(level)->offCFBulk,
+                           bulkStreamIndex);
+
+    // exchange
+    exchangeMultiGPU(para.get(), comm, cudaManager.get(), level, borderStreamIndex);
+
+    // coarse to fine border
+    coarseToFineWithStream(para.get(), level, para->getParD(level)->intCFBorder.ICellCFC,
+                           para->getParD(level)->intCFBorder.ICellCFF, para->getParD(level)->intCFBorder.kCF, para->getParD(level)->offCF,
+                           borderStreamIndex);
+    cudaDeviceSynchronize(); 
+}
+
 void UpdateGrid27::refinementAndExchange_noStreams_onlyExchangeInterface(int level)
 {
     fineToCoarse(para.get(), level);
@@ -1533,14 +1567,18 @@ void UpdateGrid27::chooseFunctionForRefinementAndExchange()
         this->refinementAndExchange = &UpdateGrid27::refinementAndExchange_noExchange;
         std::cout << "refinementAndExchange_noExchange()" << std::endl;
     
-    } else if (para->getUseStreams() && para->getNumprocs() > 1 && para->useReducedCommunicationAfterFtoC) {
-        this->refinementAndExchange = &UpdateGrid27::refinementAndExchange_streams;
-        std::cout << "refinementAndExchange_streams()" << std::endl;
+    } else if (para->getNumprocs() > 1 && para->getUseStreams() && para->useReducedCommunicationAfterFtoC) {
+        this->refinementAndExchange = &UpdateGrid27::refinementAndExchange_streams_onlyExchangeInterface;
+        std::cout << "refinementAndExchange_streams_onlyExchangeInterface()" << std::endl;
+    
+    } else if(para->getNumprocs() > 1 && para->getUseStreams() && !para->useReducedCommunicationAfterFtoC){
+        this->refinementAndExchange = &UpdateGrid27::refinementAndExchange_streams_completeExchange; 
+        std::cout << "refinementAndExchange_streams_completeExchange()" << std::endl;
     
-    } else if (para->getNumprocs() > 1 && para->useReducedCommunicationAfterFtoC) {
+    } else if (para->getNumprocs() > 1 && !para->getUseStreams() && para->useReducedCommunicationAfterFtoC) {
         this->refinementAndExchange = &UpdateGrid27::refinementAndExchange_noStreams_onlyExchangeInterface;
         std::cout << "refinementAndExchange_noStreams_onlyExchangeInterface()" << std::endl;
-    
+
     } else {
         this->refinementAndExchange = &UpdateGrid27::refinementAndExchange_noStreams_completeExchange;
         std::cout << "refinementAndExchange_noStreams_completeExchange()" << std::endl;
diff --git a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h
index d55e4ee7283c1cf0436f5f418804912c426be151..086b39fcb2745cbd66467d1316c25482dd2ab323 100644
--- a/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h
+++ b/src/gpu/VirtualFluids_GPU/Calculation/UpdateGrid27.h
@@ -32,10 +32,11 @@ private:
     void collisionAndExchange_streams(int level, unsigned int t);
 
     // functions for refinement and exchange
-    void refinementAndExchange_noRefinementAndExchange(int level);
-    void refinementAndExchange_streams(int level);
+    void refinementAndExchange_streams_onlyExchangeInterface(int level);
+    void refinementAndExchange_streams_completeExchange(int level);
     void refinementAndExchange_noStreams_onlyExchangeInterface(int level);
     void refinementAndExchange_noStreams_completeExchange(int level);
+    void refinementAndExchange_noRefinementAndExchange(int level);
     void refinementAndExchange_noExchange(int level);
 
 
diff --git a/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.cpp b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.cpp
index 30d9e7a3d69e16e938d2e8e884c163aca0ef2329..2f2e57bf4f97600012d1dad835956e89c5722b91 100644
--- a/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.cpp
+++ b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.cpp
@@ -69,6 +69,35 @@ void startNonBlockingMpiReceive(unsigned int numberOfSendProcessNeighbors, vf::g
     }
 }
 
+
+void copyEdgeNodes(std::vector<LBMSimulationParameter::EdgeNodePositions> &edgeNodes,
+                   std::vector<ProcessNeighbor27> &recvProcessNeighborHost, std::vector<ProcessNeighbor27> &sendProcessNeighborHost)
+{
+    
+    int indexInSubdomainRecv = 0;
+    int indexInSubdomainSend = 0;
+    int numNodesInBufferRecv = 0;
+    int numNodesInBufferSend = 0;
+    
+#pragma omp parallel for
+    for (uint i = 0; i < edgeNodes.size(); i++) {
+        indexInSubdomainRecv = edgeNodes[i].indexOfProcessNeighborRecv;
+        indexInSubdomainSend = edgeNodes[i].indexOfProcessNeighborSend;
+        numNodesInBufferRecv = recvProcessNeighborHost[indexInSubdomainRecv].numberOfNodes;
+        numNodesInBufferSend = sendProcessNeighborHost[indexInSubdomainSend].numberOfNodes;
+        if(edgeNodes[i].indexInSendBuffer >= numNodesInBufferSend){
+            // for reduced communication after fine to coarse: only copy send nodes which are not part of the reduced comm
+            continue;
+        }
+
+        for (int direction = 0; direction <= (int) dirEND; direction++) {
+            (sendProcessNeighborHost[indexInSubdomainSend].f[0] + (direction * numNodesInBufferSend))[edgeNodes[i].indexInSendBuffer] =
+                (recvProcessNeighborHost[indexInSubdomainRecv].f[0] + (direction * numNodesInBufferRecv))[edgeNodes[i].indexInRecvBuffer];
+        }
+    }
+}
+
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // X
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -220,23 +249,13 @@ void exchangeCollDataYGPU27(Parameter *para, vf::gpu::Communicator *comm, CudaMe
     if (para->getUseStreams()) cudaStreamSynchronize(stream);
     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // edge nodes: copy received node values from x
-    if (para->getUseStreams()  && para->getNumberOfProcessNeighborsX(level, "recv") > 0) {
-        uint indexInSubdomainX = 0;
-        uint indexInSubdomainY = 0;
-        uint numNodesInBufferX = 0;
-        uint numNodesInBufferY = 0;  
-#pragma omp parallel for
-        for (uint i = 0; i < para->getParH(level)->edgeNodesXtoY.size(); i++) {
-            indexInSubdomainX = para->getParH(level)->edgeNodesXtoY[i].indexOfProcessNeighborRecv;
-            indexInSubdomainY = para->getParH(level)->edgeNodesXtoY[i].indexOfProcessNeighborSend;
-            numNodesInBufferX = para->getParH(level)->recvProcessNeighborX[indexInSubdomainX].numberOfNodes;
-            numNodesInBufferY = para->getParH(level)->sendProcessNeighborY[indexInSubdomainY].numberOfNodes;
-
-            for (uint direction = 0; direction <= dirEND; direction++) {
-                (para->getParH(level)->sendProcessNeighborY[indexInSubdomainY].f[0]+(direction * numNodesInBufferY))[para->getParH(level)->edgeNodesXtoY[i].indexInSendBuffer] =  
-                (para->getParH(level)->recvProcessNeighborX[indexInSubdomainX].f[0]+(direction * numNodesInBufferX))[para->getParH(level)->edgeNodesXtoY[i].indexInRecvBuffer];
-            }
-        }    
+    if (para->getUseStreams() && para->getNumberOfProcessNeighborsX(level, "recv") > 0 && para->getParH(level)->sendProcessNeighborY.size() != 0) {
+        if(  para->getParH(level)->sendProcessNeighborY[0].numberOfNodes == (*sendProcessNeighborHost)[0].numberOfNodes){
+            // check if in communication of all nodes (as opposed to reduced communication after fine to coarse)
+            copyEdgeNodes(para->getParH(level)->edgeNodesXtoY, para->getParH(level)->recvProcessNeighborX, *sendProcessNeighborHost);
+        } else{
+            copyEdgeNodes(para->getParH(level)->edgeNodesXtoY, para->getParH(level)->recvProcessNeighborsAfterFtoCX, *sendProcessNeighborHost);
+        }
     }
     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     startBlockingMpiSend((unsigned int)(*sendProcessNeighborHost).size(), comm, sendProcessNeighborHost);
@@ -323,42 +342,22 @@ void exchangeCollDataZGPU27(Parameter *para, vf::gpu::Communicator *comm, CudaMe
     if (para->getUseStreams()) cudaStreamSynchronize(stream);
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // edge nodes: copy received node values from x
-    if (para->getUseStreams() && para->getNumberOfProcessNeighborsX(level, "recv") > 0) {
-        uint indexInSubdomainX = 0;
-        uint indexInSubdomainZ = 0;
-        uint numNodesInBufferX = 0;
-        uint numNodesInBufferZ = 0;
-#pragma omp parallel for
-        for (uint i = 0; i < para->getParH(level)->edgeNodesXtoZ.size(); i++) {
-            indexInSubdomainX = para->getParH(level)->edgeNodesXtoZ[i].indexOfProcessNeighborRecv;
-            indexInSubdomainZ = para->getParH(level)->edgeNodesXtoZ[i].indexOfProcessNeighborSend;
-            numNodesInBufferX = para->getParH(level)->recvProcessNeighborX[indexInSubdomainX].numberOfNodes;
-            numNodesInBufferZ = para->getParH(level)->sendProcessNeighborZ[indexInSubdomainZ].numberOfNodes;
-
-            for (uint direction = 0; direction <= dirEND; direction++) {
-                (para->getParH(level)->sendProcessNeighborZ[indexInSubdomainZ].f[0] + (direction * numNodesInBufferZ))[para->getParH(level)->edgeNodesXtoZ[i].indexInSendBuffer] =
-                    (para->getParH(level)->recvProcessNeighborX[indexInSubdomainX].f[0] + (direction * numNodesInBufferX))[para->getParH(level)->edgeNodesXtoZ[i].indexInRecvBuffer];
-            }
+    if (para->getUseStreams() && para->getNumberOfProcessNeighborsX(level, "recv") > 0 && para->getParH(level)->sendProcessNeighborZ.size() != 0) {
+        if( para->getParH(level)->sendProcessNeighborZ[0].numberOfNodes == (*sendProcessNeighborHost)[0].numberOfNodes){
+             // check if in communication of all nodes (as opposed to reduced communication after fine to coarse)
+            copyEdgeNodes(para->getParH(level)->edgeNodesXtoZ, para->getParH(level)->recvProcessNeighborX, *sendProcessNeighborHost);
+        } else{
+            copyEdgeNodes(para->getParH(level)->edgeNodesXtoZ, para->getParH(level)->recvProcessNeighborsAfterFtoCX, *sendProcessNeighborHost);
         }
     }
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // edge nodes: copy received node values from y
-    if (para->getUseStreams() && para->getNumberOfProcessNeighborsY(level, "recv") > 0) {
-        uint indexInSubdomainY = 0;
-        uint indexInSubdomainZ = 0;
-        uint numNodesInBufferY = 0;
-        uint numNodesInBufferZ = 0;
-#pragma omp parallel for
-        for (uint i = 0; i < para->getParH(level)->edgeNodesYtoZ.size(); i++) {
-            indexInSubdomainY = para->getParH(level)->edgeNodesYtoZ[i].indexOfProcessNeighborRecv;
-            indexInSubdomainZ = para->getParH(level)->edgeNodesYtoZ[i].indexOfProcessNeighborSend;
-            numNodesInBufferY = para->getParH(level)->recvProcessNeighborY[indexInSubdomainY].numberOfNodes;
-            numNodesInBufferZ = para->getParH(level)->sendProcessNeighborZ[indexInSubdomainZ].numberOfNodes;
-
-            for (uint direction = 0; direction <= dirEND; direction++) {
-                (para->getParH(level)->sendProcessNeighborZ[indexInSubdomainZ].f[0] + (direction * numNodesInBufferZ))[para->getParH(level)->edgeNodesYtoZ[i].indexInSendBuffer] =
-                    (para->getParH(level)->recvProcessNeighborY[indexInSubdomainY].f[0] + (direction * numNodesInBufferY))[para->getParH(level)->edgeNodesYtoZ[i].indexInRecvBuffer];
-            }
+    if (para->getUseStreams() && para->getNumberOfProcessNeighborsY(level, "recv") > 0  && para->getParH(level)->sendProcessNeighborZ.size() != 0) {
+        if( para->getParH(level)->sendProcessNeighborZ[0].numberOfNodes == (*sendProcessNeighborHost)[0].numberOfNodes){ 
+            // check if in communication of all nodes (as opposed to reduced communication after fine to coarse)
+            copyEdgeNodes(para->getParH(level)->edgeNodesYtoZ, para->getParH(level)->recvProcessNeighborY, *sendProcessNeighborHost);
+        } else{
+            copyEdgeNodes(para->getParH(level)->edgeNodesYtoZ, para->getParH(level)->recvProcessNeighborsAfterFtoCY, *sendProcessNeighborHost);
         }
     }
     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.h b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.h
index 0f17d307a5e620be201f4da15f6ca29ca3ccf948..d57a9dad95d74a77b8e387811ab9d0262072add8 100644
--- a/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.h
+++ b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27.h
@@ -21,6 +21,9 @@ extern "C" void collectNodesInSendBufferGPU(Parameter *para, int level, int stre
 extern "C" void scatterNodesFromRecvBufferGPU(Parameter *para, int level, int streamIndex,
                                               std::vector<ProcessNeighbor27> *recvProcessNeighborDev,
                                               unsigned int numberOfRecvProcessNeighbors);
+extern "C" void copyEdgeNodes(std::vector<LBMSimulationParameter::EdgeNodePositions> &edgeNodes, 
+                              std::vector<ProcessNeighbor27> &recvProcessNeighborHost,
+                              std::vector<ProcessNeighbor27> &sendProcessNeighborHost);
 
 // x
 extern "C" void prepareExchangeCollDataXGPU27AllNodes(Parameter *para, int level, int streamIndex);
diff --git a/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27Test.cfg b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27Test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..e414d4f3173e555b8944fa9637ebbd2023ce393c
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27Test.cfg
@@ -0,0 +1,3 @@
+# these two parameters need to be defined in each config file
+Path = /output/path
+GridPath = /path/to/grid
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27Test.cpp b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27Test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ed4470e79e913502bf219e649b4cc08ad6734113
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/Communication/ExchangeData27Test.cpp
@@ -0,0 +1,146 @@
+#include <gmock/gmock.h>
+
+#include <filesystem>
+
+#include "ExchangeData27.h"
+#include "gpu/VirtualFluids_GPU/LBM/LB.h"
+
+#include <basics/config/ConfigurationFile.h>
+
+SPtr<Parameter> initParameterClass()
+{
+    std::filesystem::path filePath = __FILE__; //  assuming that the config file is stored parallel to this file.
+    filePath.replace_filename("ExchangeData27Test.cfg");
+    vf::basics::ConfigurationFile config;
+    config.load(filePath.string());
+    return std::make_shared<Parameter>(config, 1, 0);
+}
+
+void setUpFsByCopyingF0(std::vector<real> &distributionVector, int numberOfNodes)
+{
+    for (uint direction = 0; direction < dirEND; direction++) {
+        distributionVector.insert(distributionVector.end(), distributionVector.begin(),
+                                  distributionVector.begin() + numberOfNodes);
+    }
+}
+
+class ExchangeData27Test_CopyEdgeNodesXZTest : public testing::Test
+{
+protected:
+    SPtr<Parameter> para;
+    int level    = 0;
+    int numNodes = 10;
+    std::vector<real> recvFs;
+    std::vector<real> sendFs;    
+    std::vector<ProcessNeighbor27> sendProcessNeighborHost;
+    std::vector<ProcessNeighbor27> recvProcessNeighborHost;
+
+    void SetUp() override
+    {
+        para = initParameterClass();
+        para->setMaxLevel(level + 1);       // setMaxLevel resizes parH
+        para->initLBMSimulationParameter(); // init parH
+
+        para->getParH(level)->edgeNodesXtoZ.emplace_back(0, 1, 0, 1);
+        para->getParH(level)->edgeNodesXtoZ.emplace_back(0, 6, 0, 6);
+        para->getParH(level)->edgeNodesXtoZ.emplace_back(0, 2, 0, 3);
+        para->getParH(level)->edgeNodesXtoZ.emplace_back(0, 7, 0, 8);
+        para->getParH(level)->edgeNodesXtoZ.emplace_back(0, 7, 0, 8);
+        para->getParH(level)->edgeNodesXtoZ.emplace_back(0, 7, 0, 8);
+
+    }
+
+   void setUpRecvProcessNeighbors(int numberOfNodesInRecv)
+    {
+        recvFs.resize(numberOfNodesInRecv);
+        std::fill(recvFs.begin(), recvFs.end(), 0.5); // 0.5s should not be copied
+        for (LBMSimulationParameter::EdgeNodePositions edgeNode : para->getParH(level)->edgeNodesXtoZ) {
+            if(edgeNode.indexInRecvBuffer>numberOfNodesInRecv){
+                continue;
+            }
+            recvFs[edgeNode.indexInRecvBuffer] = 0.1; // 0.1s should be copied
+        }
+        setUpFsByCopyingF0(recvFs, numberOfNodesInRecv);
+
+        recvProcessNeighborHost.resize(1);
+        recvProcessNeighborHost[0].f[0]          = recvFs.data();
+        recvProcessNeighborHost[0].numberOfNodes = numberOfNodesInRecv;
+    }
+
+    void setUpSendProcessNeighbors(int numberOfNodesInSend)
+    {
+        sendFs.resize(27 * numberOfNodesInSend);
+        std::fill(sendFs.begin(), sendFs.end(), 0.0);
+
+        sendProcessNeighborHost.resize(1);
+        sendProcessNeighborHost[0].f[0]          = sendFs.data();
+        sendProcessNeighborHost[0].numberOfNodes = numberOfNodesInSend;
+    }
+};
+
+TEST_F(ExchangeData27Test_CopyEdgeNodesXZTest, copyEdgeNodes_XZ_CommunicationAfterFtoC_recvVectorFullSize)
+{
+    int numNodesAfterFtoC = 5; // indexInSend < 5 --> mode is in AfterFToC
+    setUpRecvProcessNeighbors(numNodes);
+    setUpSendProcessNeighbors(numNodesAfterFtoC);
+
+    // expected
+    std::vector<real> expectedFs(numNodesAfterFtoC, 0.0);
+    expectedFs[1] = 0.1;
+    expectedFs[3] = 0.1;
+    setUpFsByCopyingF0(expectedFs, numNodesAfterFtoC);
+
+    // act
+    copyEdgeNodes(para->getParH(level)->edgeNodesXtoZ, recvProcessNeighborHost, sendProcessNeighborHost);
+
+    // convert result to std::vector
+    std::vector<real> result;
+    result.assign(sendProcessNeighborHost[0].f[0], sendProcessNeighborHost[0].f[0] + 27 * numNodesAfterFtoC);
+
+    EXPECT_THAT(result, testing::Eq(expectedFs));
+}
+
+TEST_F(ExchangeData27Test_CopyEdgeNodesXZTest, copyEdgeNodes_XZ_CommunicationAfterFtoC_recvVectorShort)
+{
+    int numNodesAfterFtoC = 5; // indexInSend < 5 --> mode is in AfterFToC
+    setUpRecvProcessNeighbors(numNodesAfterFtoC);
+    setUpSendProcessNeighbors(numNodesAfterFtoC);
+
+    // expected
+    std::vector<real> expectedFs(numNodesAfterFtoC, 0.0);
+    expectedFs[1] = 0.1;
+    expectedFs[3] = 0.1;
+    setUpFsByCopyingF0(expectedFs, numNodesAfterFtoC);
+
+    // act
+    copyEdgeNodes(para->getParH(level)->edgeNodesXtoZ, recvProcessNeighborHost, sendProcessNeighborHost);
+
+    // convert result to std::vector
+    std::vector<real> result;
+    result.assign(sendProcessNeighborHost[0].f[0], sendProcessNeighborHost[0].f[0] + 27 * numNodesAfterFtoC);
+
+    EXPECT_THAT(result, testing::Eq(expectedFs));
+}
+
+TEST_F(ExchangeData27Test_CopyEdgeNodesXZTest, copyEdgeNodes_XZ_CommunicateAll)
+{
+    setUpRecvProcessNeighbors(numNodes);
+    setUpSendProcessNeighbors(numNodes);
+
+    // expected
+    std::vector<real> expectedFs(numNodes, 0.0);
+    expectedFs[1] = 0.1;
+    expectedFs[3] = 0.1;
+    expectedFs[6] = 0.1;
+    expectedFs[8] = 0.1;
+    setUpFsByCopyingF0(expectedFs, numNodes);
+
+    // act
+    copyEdgeNodes(para->getParH(level)->edgeNodesXtoZ, recvProcessNeighborHost, sendProcessNeighborHost);
+
+    // convert result to std::vector
+    std::vector<real> result;
+    result.assign(sendProcessNeighborHost[0].f[0], sendProcessNeighborHost[0].f[0] + 27 * numNodes);
+
+    EXPECT_THAT(result, testing::Eq(expectedFs));
+}
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp
index bcf4b83cd66fa3179e71515f1ead07cc30b3cf21..1bdf32f281dc4f2d22cf6bf3b3ff43ca62cd592c 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.cpp
@@ -233,9 +233,9 @@ void IndexRearrangementForStreams::reorderSendIndicesForCommAfterFtoCX(
     int direction, int level, int indexOfProcessNeighbor, std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
     int *sendIndices = para->getParH(level)->sendProcessNeighborX[indexOfProcessNeighbor].index;
-    int &numberOfSendNeighborsAfterFtoC =
+    int &numberOfSendNodesAfterFtoC =
         para->getParH(level)->sendProcessNeighborsAfterFtoCX[indexOfProcessNeighbor].numberOfNodes;
-    reorderSendIndicesForCommAfterFtoC(sendIndices, numberOfSendNeighborsAfterFtoC, direction, level,
+    reorderSendIndicesForCommAfterFtoC(sendIndices, numberOfSendNodesAfterFtoC, direction, level,
                                        sendIndicesForCommAfterFtoCPositions);
 }
 
@@ -243,9 +243,9 @@ void IndexRearrangementForStreams::reorderSendIndicesForCommAfterFtoCY(
     int direction, int level, int indexOfProcessNeighbor, std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
     int *sendIndices = para->getParH(level)->sendProcessNeighborY[indexOfProcessNeighbor].index;
-    int &numberOfSendNeighborsAfterFtoC =
+    int &numberOfSendNodesAfterFtoC =
         para->getParH(level)->sendProcessNeighborsAfterFtoCY[indexOfProcessNeighbor].numberOfNodes;
-    reorderSendIndicesForCommAfterFtoC(sendIndices, numberOfSendNeighborsAfterFtoC, direction, level,
+    reorderSendIndicesForCommAfterFtoC(sendIndices, numberOfSendNodesAfterFtoC, direction, level,
                                        sendIndicesForCommAfterFtoCPositions);
 }
 
@@ -253,14 +253,14 @@ void IndexRearrangementForStreams::reorderSendIndicesForCommAfterFtoCZ(
     int direction, int level, int indexOfProcessNeighbor, std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
     int *sendIndices = para->getParH(level)->sendProcessNeighborZ[indexOfProcessNeighbor].index;
-    int &numberOfSendNeighborsAfterFtoC =
+    int &numberOfSendNodesAfterFtoC =
         para->getParH(level)->sendProcessNeighborsAfterFtoCZ[indexOfProcessNeighbor].numberOfNodes;
-    reorderSendIndicesForCommAfterFtoC(sendIndices, numberOfSendNeighborsAfterFtoC, direction, level,
+    reorderSendIndicesForCommAfterFtoC(sendIndices, numberOfSendNodesAfterFtoC, direction, level,
                                        sendIndicesForCommAfterFtoCPositions);
 }
 
 void IndexRearrangementForStreams::reorderSendIndicesForCommAfterFtoC(
-    int *sendIndices, int &numberOfSendNeighborsAfterFtoC, int direction, int level,
+    int *sendIndices, int &numberOfSendNodesAfterFtoC, int direction, int level,
     std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
     *logging::out << logging::Logger::INFO_INTERMEDIATE
@@ -268,23 +268,22 @@ void IndexRearrangementForStreams::reorderSendIndicesForCommAfterFtoC(
                   << " direction: " << direction;
     if (para->getParH(level)->intCF.kCF == 0 || para->getParH(level)->intFC.kFC == 0)
         *logging::out << logging::Logger::LOGGER_ERROR
-                      << "reorderSendIndicesForCommAfterFtoC(): iCellFCC needs to be inititalized before calling "
+                      << "reorderSendIndicesForCommAfterFtoC(): para->getParH(level)->intCF needs to be inititalized before calling "
                          "this function "
                       << "\n";
 
     int sparseIndexSend;
     std::vector<int> sendIndicesAfterFtoC;
     std::vector<int> sendIndicesOther;
-    std::array<int, 7> neighbors;
     uint numberOfSendIndices = builder->getNumberOfSendIndices(direction, level);
 
     // iCellFCC
     for (uint posInSendIndices = 0; posInSendIndices < numberOfSendIndices; posInSendIndices++) {
-        neighbors.fill(-1);
         sparseIndexSend = sendIndices[posInSendIndices];
-        if (isSparseIndexInICellFCC(para->getParH(level)->intFC.kFC, sparseIndexSend, level))
+        if (isSparseIndexInICellFCC(para->getParH(level)->intFC.kFC, sparseIndexSend, level)) {
             addUniqueIndexToCommunicationVectors(sendIndicesAfterFtoC, sparseIndexSend,
                                                  sendIndicesForCommAfterFtoCPositions, posInSendIndices);
+        }
     }
 
     // iCellCFC
@@ -294,25 +293,25 @@ void IndexRearrangementForStreams::reorderSendIndicesForCommAfterFtoC(
         findIfSparseIndexIsInSendIndicesAndAddToCommVectors(sparseIndex, sendIndices, numberOfSendIndices,
                                                             sendIndicesAfterFtoC, sendIndicesForCommAfterFtoCPositions);
 
-    numberOfSendNeighborsAfterFtoC = (int)sendIndicesAfterFtoC.size();
+    numberOfSendNodesAfterFtoC = (int)sendIndicesAfterFtoC.size();
 
     findIndicesNotInCommAfterFtoC(numberOfSendIndices, sendIndices, sendIndicesAfterFtoC, sendIndicesOther);
 
     // copy new vectors back to sendIndices array
-    for (int i = 0; i < numberOfSendNeighborsAfterFtoC; i++)
+    for (int i = 0; i < numberOfSendNodesAfterFtoC; i++)
         sendIndices[i] = sendIndicesAfterFtoC[i];
     for (uint i = 0; i < (uint)sendIndicesOther.size(); i++)
-        sendIndices[i + numberOfSendNeighborsAfterFtoC] = sendIndicesOther[i];
+        sendIndices[i + numberOfSendNodesAfterFtoC] = sendIndicesOther[i];
 
     *logging::out << logging::Logger::INFO_INTERMEDIATE << "... Process "
                   << " " << vf::gpu::Communicator::getInstanz()->getPID()
-                  << " numberOfSendNeighborsAfterFtoC: " << numberOfSendNeighborsAfterFtoC << "\n ";
+                  << " numberOfSendNodesAfterFtoC: " << numberOfSendNodesAfterFtoC << "\n ";
 
-    if (numberOfSendNeighborsAfterFtoC + sendIndicesOther.size() != numberOfSendIndices) {
+    if (numberOfSendNodesAfterFtoC + sendIndicesOther.size() != numberOfSendIndices) {
         *logging::out << logging::Logger::LOGGER_ERROR
                       << "reorderSendIndicesForCommAfterFtoC(): incorrect number of nodes"
                       << "\n";
-        std::cout << "numberOfSendNeighborsAfterFtoC = " << numberOfSendNeighborsAfterFtoC
+        std::cout << "numberOfSendNodesAfterFtoC = " << numberOfSendNodesAfterFtoC
                   << ", sendOrIndicesOther.size() = " << sendIndicesOther.size()
                   << ", numberOfSendOrRecvIndices = " << numberOfSendIndices << std::endl;
     }
@@ -359,7 +358,7 @@ void IndexRearrangementForStreams::addUniqueIndexToCommunicationVectors(
     std::vector<int> &sendIndicesAfterFtoC, int &sparseIndexSend,
     std::vector<unsigned int> &sendIndicesForCommAfterFtoCPositions, uint &posInSendIndices) const
 {
-    // add index to corresponding vectors but omit indices which are already in sendIndicesAfterFtoC
+    // add index to corresponding vectors, but omit indices which are already in sendIndicesAfterFtoC
     if (std::find(sendIndicesAfterFtoC.begin(), sendIndicesAfterFtoC.end(), sparseIndexSend) ==
         sendIndicesAfterFtoC.end()) {
         sendIndicesAfterFtoC.push_back(sparseIndexSend);
@@ -400,8 +399,8 @@ void IndexRearrangementForStreams::reorderRecvIndicesForCommAfterFtoCX(
     int direction, int level, int indexOfProcessNeighbor, std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
     int *recvIndices                    = para->getParH(level)->recvProcessNeighborX[indexOfProcessNeighbor].index;
-    int &numberOfRecvNeighborsAfterFtoC = para->getParH(level)->recvProcessNeighborsAfterFtoCX[indexOfProcessNeighbor].numberOfNodes;
-    reorderRecvIndicesForCommAfterFtoC(recvIndices, numberOfRecvNeighborsAfterFtoC, direction, level,
+    int &numberOfRecvNodesAfterFtoC = para->getParH(level)->recvProcessNeighborsAfterFtoCX[indexOfProcessNeighbor].numberOfNodes;
+    reorderRecvIndicesForCommAfterFtoC(recvIndices, numberOfRecvNodesAfterFtoC, direction, level,
                                        sendIndicesForCommAfterFtoCPositions);
 }
 
@@ -409,22 +408,23 @@ void IndexRearrangementForStreams::reorderRecvIndicesForCommAfterFtoCY(
     int direction, int level, int indexOfProcessNeighbor, std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
     int *recvIndices                    = para->getParH(level)->recvProcessNeighborY[indexOfProcessNeighbor].index;
-    int &numberOfRecvNeighborsAfterFtoC = para->getParH(level)->recvProcessNeighborsAfterFtoCY[indexOfProcessNeighbor].numberOfNodes;
-    reorderRecvIndicesForCommAfterFtoC(recvIndices, numberOfRecvNeighborsAfterFtoC, direction, level,
+    int &numberOfRecvNodesAfterFtoC = para->getParH(level)->recvProcessNeighborsAfterFtoCY[indexOfProcessNeighbor].numberOfNodes;
+    reorderRecvIndicesForCommAfterFtoC(recvIndices, numberOfRecvNodesAfterFtoC, direction, level,
                                        sendIndicesForCommAfterFtoCPositions);
 }
 
 void IndexRearrangementForStreams::reorderRecvIndicesForCommAfterFtoCZ(
     int direction, int level, int indexOfProcessNeighbor, std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
-    int *recvIndices                    = para->getParH(level)->recvProcessNeighborZ[indexOfProcessNeighbor].index;
-    int &numberOfRecvNeighborsAfterFtoC = para->getParH(level)->recvProcessNeighborsAfterFtoCZ[indexOfProcessNeighbor].numberOfNodes;
-    reorderRecvIndicesForCommAfterFtoC(recvIndices, numberOfRecvNeighborsAfterFtoC, direction, level,
+    int *recvIndices = para->getParH(level)->recvProcessNeighborZ[indexOfProcessNeighbor].index;
+    int &numberOfRecvNodesAfterFtoC =
+        para->getParH(level)->recvProcessNeighborsAfterFtoCZ[indexOfProcessNeighbor].numberOfNodes;
+    reorderRecvIndicesForCommAfterFtoC(recvIndices, numberOfRecvNodesAfterFtoC, direction, level,
                                        sendIndicesForCommAfterFtoCPositions);
 }
 
 void IndexRearrangementForStreams::reorderRecvIndicesForCommAfterFtoC(
-    int *recvIndices, int &numberOfRecvNeighborsAfterFtoC, int direction, int level,
+    int *recvIndices, int &numberOfRecvNodesAfterFtoC, int direction, int level,
     std::vector<uint> &sendIndicesForCommAfterFtoCPositions)
 {
     *logging::out << logging::Logger::INFO_INTERMEDIATE
@@ -445,23 +445,23 @@ void IndexRearrangementForStreams::reorderRecvIndicesForCommAfterFtoC(
 
     findIndicesNotInCommAfterFtoC(numberOfRecvIndices, recvIndices, recvIndicesAfterFtoC, recvIndicesOther);
 
-    numberOfRecvNeighborsAfterFtoC = (int)recvIndicesAfterFtoC.size();
+    numberOfRecvNodesAfterFtoC = (int)recvIndicesAfterFtoC.size();
 
     // copy new vectors back to sendIndices array
-    for (int i = 0; i < numberOfRecvNeighborsAfterFtoC; i++)
+    for (int i = 0; i < numberOfRecvNodesAfterFtoC; i++)
         recvIndices[i] = recvIndicesAfterFtoC[i];
     for (uint i = 0; i < (uint)recvIndicesOther.size(); i++)
-        recvIndices[i + numberOfRecvNeighborsAfterFtoC] = recvIndicesOther[i];
+        recvIndices[i + numberOfRecvNodesAfterFtoC] = recvIndicesOther[i];
 
     *logging::out << logging::Logger::INFO_INTERMEDIATE << "... Process "
                   << " " << vf::gpu::Communicator::getInstanz()->getPID()
-                  << " numberOfRecvNeighborsAfterFtoC: " << numberOfRecvNeighborsAfterFtoC << "\n ";
+                  << " numberOfRecvNodesAfterFtoC: " << numberOfRecvNodesAfterFtoC << "\n ";
 
-    if (numberOfRecvNeighborsAfterFtoC + recvIndicesOther.size() != numberOfRecvIndices) {
+    if (numberOfRecvNodesAfterFtoC + recvIndicesOther.size() != numberOfRecvIndices) {
         *logging::out << logging::Logger::LOGGER_ERROR
                       << "reorderRecvIndicesForCommAfterFtoC(): incorrect number of nodes"
                       << "\n";
-        std::cout << "numberOfRecvNeighborsAfterFtoC = " << numberOfRecvNeighborsAfterFtoC
+        std::cout << "numberOfRecvNodesAfterFtoC = " << numberOfRecvNodesAfterFtoC
                   << ", recvIndicesOther.size() = " << recvIndicesOther.size()
                   << ", numberOfRecvIndices = " << numberOfRecvIndices << std::endl;
     }
@@ -469,11 +469,6 @@ void IndexRearrangementForStreams::reorderRecvIndicesForCommAfterFtoC(
 
 void IndexRearrangementForStreams::splitFineToCoarseIntoBorderAndBulk(const uint &level)
 {
-    // For communication hiding, the interpolation cells from the fine to the coarse grid need to be split into two
-    // groups:
-    // - cells which are at the border between two gpus --> "border"
-    // - the other cells which are not directly related to the communication betweeen the two gpus --> "bulk"
-
     this->getGridInterfaceIndicesBorderBulkFC(level);
 
     para->getParD(level)->intFCBorder.kFC      = para->getParH(level)->intFCBorder.kFC;
@@ -488,10 +483,6 @@ void IndexRearrangementForStreams::splitFineToCoarseIntoBorderAndBulk(const uint
 
 void IndexRearrangementForStreams::getGridInterfaceIndicesBorderBulkFC(int level)
 {
-    // This function reorders the arrays of FCC/FCF indices and return pointers and sizes of the new subarrays:
-    // The coarse cells for interpolation from fine to coarse (iCellFCC) are divided into two subgroups: border and
-    // bulk. The fine cells (iCellFCF) are reordered accordingly.
-
     // create some local variables for better readability
     uint *iCellFccAll = para->getParH(level)->intFC.ICellFCC;
     uint *iCellFcfAll = para->getParH(level)->intFC.ICellFCF;
@@ -521,6 +512,7 @@ void IndexRearrangementForStreams::getGridInterfaceIndicesBorderBulkFC(int level
     para->getParH(level)->intFCBulk.ICellFCF   = iCellFcfAll + para->getParH(level)->intFCBorder.kFC;
 
     // copy the created vectors to the memory addresses of the old arrays
+    // this is inefficient :(
     for (uint i = 0; i < (uint)iCellFccBorderVector.size(); i++) {
         iCellFccAll[i] = iCellFccBorderVector[i];
         iCellFcfAll[i] = iCellFcfBorderVector[i];
@@ -533,11 +525,6 @@ void IndexRearrangementForStreams::getGridInterfaceIndicesBorderBulkFC(int level
 
 void IndexRearrangementForStreams::splitCoarseToFineIntoBorderAndBulk(const uint &level)
 {
-    // For communication hiding, the interpolation cells from the coarse to the fine grid need to be split into two
-    // groups:
-    // - cells which are at the border between two gpus --> "border"
-    // - the other cells which are not directly related to the communication betweeen the two gpus --> "bulk"
-
     this->getGridInterfaceIndicesBorderBulkCF(level);
 
     para->getParD(level)->intCFBorder.kCF      = para->getParH(level)->intCFBorder.kCF;
@@ -555,11 +542,6 @@ void IndexRearrangementForStreams::splitCoarseToFineIntoBorderAndBulk(const uint
 
 void IndexRearrangementForStreams::getGridInterfaceIndicesBorderBulkCF(int level)
 {
-    // This function reorders the arrays of CFC/CFF indices and sets the pointers and sizes of the new subarrays:
-    // The coarse cells for interpolation from coarse to fine (iCellCFC) are divided into two subgroups: border and
-    // bulk. The fine cells (iCellCFF) are reordered accordingly. The offset cells (xOffCF, yOffCF, zOffCF) must be
-    // reordered in the same way.
-
     // create some local variables for better readability
     uint *iCellCfcAll  = para->getParH(level)->intCF.ICellCFC;
     uint *iCellCffAll  = para->getParH(level)->intCF.ICellCFF;
@@ -622,6 +604,7 @@ void IndexRearrangementForStreams::getGridInterfaceIndicesBorderBulkCF(int level
     para->getParH(level)->offCFBulk.zOffCF = para->getParH(level)->offCF.zOffCF + para->getParH(level)->intCFBorder.kCF;
 
     // copy the created vectors to the memory addresses of the old arrays
+    // this is inefficient :(
     for (uint i = 0; i < (uint)iCellCfcBorderVector.size(); i++) {
         para->getParH(level)->intCFBorder.ICellCFC[i] = iCellCfcBorderVector[i];
         para->getParH(level)->intCFBorder.ICellCFF[i] = iCellCffBorderVector[i];
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h
index c1430232b2e4c9380886a47c819f75abde9e4757..65ee08666247308c3cdf1e533106189b441a325e 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h
@@ -1,11 +1,16 @@
+//! \file IndexRearrangementForStreams.h
+//! \ingroup GPU
+//! \author Anna Wellmann
+//! \ref master thesis of Anna Wellmann
+
 #ifndef IndexRearrangementForStreams_H
 #define IndexRearrangementForStreams_H
 
 #include <gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.h>
 
-#include <vector>
-#include <string>
 #include <memory>
+#include <string>
+#include <vector>
 
 #include "LBM/LB.h"
 
@@ -13,33 +18,74 @@ class Parameter;
 class GridBuilder;
 namespace vf
 {
-	namespace gpu
-	{
-		class Communicator;
-	}
+namespace gpu
+{
+class Communicator;
 }
+} // namespace vf
 
 class IndexRearrangementForStreams
 {
 private:
-	std::shared_ptr<GridBuilder> builder;
+    std::shared_ptr<GridBuilder> builder;
     std::shared_ptr<Parameter> para;
 
 public:
+    //! \brief construct IndexRearrangementForStreams object
     IndexRearrangementForStreams(std::shared_ptr<Parameter> para, std::shared_ptr<GridBuilder> builder);
-    
+
+    //////////////////////////////////////////////////////////////////////////
     // communication after coarse to fine
+    //////////////////////////////////////////////////////////////////////////
+
+    //! \brief initialize the arrays for the communication after the interpolation from fine to coarse in x direction
+    //! \details Only the nodes involved in the interpolation need to be exchanged. Therefore in this method all nodes,
+    //! which are part of the interpolation as well as the communication, are identified.
+    //!
+    //! \ref see master thesis of Anna
+    //! Wellmann (p. 59-62: "Reduzieren der auszutauschenden Knoten")
     void initCommunicationArraysForCommAfterFinetoCoarseX(const uint &level, int j, int direction);
+    //! \brief initialize the arrays for the communication after the interpolation from fine to coarse in y direction
+    //! \details --> see x direction
     void initCommunicationArraysForCommAfterFinetoCoarseY(const uint &level, int j, int direction);
+    //! \brief initialize the arrays for the communication after the interpolation from fine to coarse in z direction
+    //! \details --> see x direction
     void initCommunicationArraysForCommAfterFinetoCoarseZ(const uint &level, int j, int direction);
 
+public:
+    //////////////////////////////////////////////////////////////////////////
     // split interpolation cells
+    //////////////////////////////////////////////////////////////////////////
+
+    //! \brief split the interpolation cells from coarse to fine into border an bulk
+    //! \details For communication hiding, the interpolation cells from the coarse to the fine grid need to be split
+    //! into two groups:
+    //!
+    //! - cells which are at the border between two gpus --> "border"
+    //!
+    //! - the other cells which are not directly related to the communication between the two gpus --> "bulk"
+    //!
+    //! \ref see master thesis of Anna Wellmann (p. 62-68: "Ãœberdeckung der reduzierten Kommunikation")
     void splitCoarseToFineIntoBorderAndBulk(const uint &level);
-    void splitFineToCoarseIntoBorderAndBulk(const uint &level);
 
+    //! \brief split the interpolation cells from fine to coarse into border an bulk
+    //! \details For communication hiding, the interpolation cells from the fine to the coarse grid need to be split
+    //! into two groups:
+    //!
+    //! - cells which are at the border between two gpus --> "border"
+    //!
+    //! - the other cells which are not directly related to the communication between the two gpus --> "bulk"
+    //!
+    //! \ref see master thesis of Anna Wellmann (p. 62-68: "Ãœberdeckung der reduzierten Kommunikation")
+    void splitFineToCoarseIntoBorderAndBulk(const uint &level);
 
 private:
+    //////////////////////////////////////////////////////////////////////////
     // communication after coarse to fine
+    //////////////////////////////////////////////////////////////////////////
+
+    //! \brief inits pointers for reduced communication after interpolation fine to coarse by copying them from "normal"
+    //! communication
     void copyProcessNeighborToCommAfterFtoCX(const uint &level, int indexOfProcessNeighbor);
     void copyProcessNeighborToCommAfterFtoCY(const uint &level, int indexOfProcessNeighbor);
     void copyProcessNeighborToCommAfterFtoCZ(const uint &level, int indexOfProcessNeighbor);
@@ -50,17 +96,32 @@ private:
                                              std::vector<uint> &sendIndicesForCommAfterFtoCPositions);
     void reorderSendIndicesForCommAfterFtoCZ(int direction, int level, int indexOfProcessNeighbor,
                                              std::vector<uint> &sendIndicesForCommAfterFtoCPositions);
-    void reorderSendIndicesForCommAfterFtoC(int *sendIndices, int &numberOfSendNeighborsAfterFtoC, int direction,
-                                            int level, std::vector<uint> &sendIndicesForCommAfterFtoCPositions);
 
+    //! \brief the send indices are reordered for the communication after the interpolation from fine to coarse
+    //! \details The indices of nodes which are part of the interpolation are moved to the front of vector with the send
+    //! indices. 
+    //! \pre para->getParH(level)->intCF needs to be inititalized 
+    //! \param sendIndices is the pointer to the vector with the send indices, which will be reordered in this function
+    //! \param numberOfSendNodesAfterFtoC will be set in this method 
+    //! \param sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering
+    void reorderSendIndicesForCommAfterFtoC(int *sendIndices, int &numberOfSendNodesAfterFtoC, int direction,
+                                            int level, std::vector<uint> &sendIndicesForCommAfterFtoCPositions);
+    //! \brief check if a sparse index occurs in the ICellFCC
     bool isSparseIndexInICellFCC(uint sizeOfICellFCC, int sparseIndexSend, int level);
+    //! \brief aggregate all nodes in the coarse cells for the interpolation in coarse to fine
+    //! \details For the coarse cells in the interpolation from coarse to fine only one node is stored. This methods
+    //! looks for the other nodes of each cell and puts them into vector. Duplicate nodes are only stored once.
     void aggregateNodesInICellCFC(int level, std::vector<uint> &nodesCFC);
+    //! \brief add index to sendIndicesAfterFtoC and sendIndicesForCommAfterFtoCPositions, but omit indices which are already in sendIndicesAfterFtoC
     void addUniqueIndexToCommunicationVectors(std::vector<int> &sendIndicesAfterFtoC, int &sparseIndexSend,
                                               std::vector<unsigned int> &sendIndicesForCommAfterFtoCPositions,
                                               uint &posInSendIndices) const;
-    void findIfSparseIndexIsInSendIndicesAndAddToCommVectors(int sparseIndex, int *sendIndices, uint numberOfSendIndices,
-                                                             std::vector<int> &sendIndicesAfterFtoC,
-                                                             std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
+    //! \brief find if a sparse index is a send index. If true, call addUniqueIndexToCommunicationVectors()
+    void
+    findIfSparseIndexIsInSendIndicesAndAddToCommVectors(int sparseIndex, int *sendIndices, uint numberOfSendIndices,
+                                                        std::vector<int> &sendIndicesAfterFtoC,
+                                                        std::vector<uint> &sendIndicesForCommAfterFtoCPositions) const;
+    //! \brief find all indices which are not part of the communication after the interpolation from fine to coarse
     void findIndicesNotInCommAfterFtoC(const uint &numberOfSendOrRecvIndices, int *sendOrReceiveIndices,
                                        std::vector<int> &sendOrReceiveIndicesAfterFtoC,
                                        std::vector<int> &sendOrIndicesOther);
@@ -71,14 +132,31 @@ private:
                                              std::vector<uint> &sendIndicesForCommAfterFtoCPositions);
     void reorderRecvIndicesForCommAfterFtoCZ(int direction, int level, int indexOfProcessNeighbor,
                                              std::vector<uint> &sendIndicesForCommAfterFtoCPositions);
-    void reorderRecvIndicesForCommAfterFtoC(int *recvIndices, int &numberOfRecvNeighborsAfterFtoC, int direction,
+                                             
+    //! \brief reorder the receive indices in the same way that the send indices were reordered.
+    //! \details When the send indices are reordered, the receive indices need to be reordered accordingly.
+    //! \pre sendIndicesForCommAfterFtoCPositions should not be empty
+    //! \param recvIndices is the pointer to the vector with the receive indices, which will be reordered in this function
+    //! \param numberOfRecvNodesAfterFtoC will be set in this function
+    //! \param sendIndicesForCommAfterFtoCPositions stores each sendIndex's positions before reordering and is used to reorder the receive indices in the same way
+    void reorderRecvIndicesForCommAfterFtoC(int *recvIndices, int &numberOfRecvNodesAfterFtoC, int direction,
                                             int level, std::vector<uint> &sendIndicesForCommAfterFtoCPositions);
-    
+
+private:
+    //////////////////////////////////////////////////////////////////////////
     // split interpolation cells
+    //////////////////////////////////////////////////////////////////////////
+
+    //! \brief This function reorders the arrays of CFC/CFF indices and sets the pointers and sizes of the new
+    //! subarrays: \details The coarse cells for interpolation from coarse to fine (iCellCFC) are divided into two
+    //! subgroups: border and bulk. The fine cells (iCellCFF) are reordered accordingly. The offset cells (xOffCF,
+    //! yOffCF, zOffCF) must be reordered in the same way.
     void getGridInterfaceIndicesBorderBulkCF(int level);
-    void getGridInterfaceIndicesBorderBulkFC(int level);
 
-    friend class IndexRearrangementForStreamsTest;
+    //! \brief This function reorders the arrays of FCC/FCF indices and return pointers and sizes of the new subarrays:
+    //! \details The coarse cells for interpolation from fine to coarse (iCellFCC) are divided into two subgroups:
+    //! border and bulk. The fine cells (iCellFCF) are reordered accordingly.
+    void getGridInterfaceIndicesBorderBulkFC(int level);
 };
 
 #endif
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp
index 7dceee2ee4cc354567da6d01ac0ef559f35276ea..88f69afe84bb53fea734dda6b58e4cfbbc2d721d 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp
@@ -1,44 +1,42 @@
 #include <gmock/gmock.h>
 
-#include <iostream>
 #include <algorithm>
 #include <filesystem>
+#include <iostream>
 
-#include <basics/config/ConfigurationFile.h>
 #include <Parameter/Parameter.h>
+#include <basics/config/ConfigurationFile.h>
 
 #include <DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreams.h>
 #include <gpu/GridGenerator/grid/GridBuilder/LevelGridBuilder.h>
 #include <gpu/GridGenerator/grid/GridImp.h>
 #include <gpu/GridGenerator/utilities/communication.h>
 
+template <typename T>
+bool vectorsAreEqual(T *vector1, std::vector<T> vectorExpected)
+{
+    for (uint i = 0; i < vectorExpected.size(); i++) {
+        if (vector1[i] != vectorExpected[i])
+            return false;
+    }
+    return true;
+}
 
-auto RealEq = [](auto value) { 
-#ifdef VF_DOUBLE_ACCURACY
-    return testing::DoubleEq(value); 
-#else 
-    return testing::FloatEq(value);
-#endif
-};
-
-
-class GridBuilderDouble : public LevelGridBuilder
+class LevelGridBuilderDouble : public LevelGridBuilder
 {
 private:
     SPtr<Grid> grid;
-    GridBuilderDouble()=default;
+    LevelGridBuilderDouble() = default;
 
     uint numberOfSendIndices;
 public:
-    GridBuilderDouble(SPtr<Grid> grid) : LevelGridBuilder(Device(), ""), grid(grid){};
-    SPtr<Grid> getGrid(uint level) override{ return grid; };
-    std::shared_ptr<Grid> getGrid(int level, int box) override {return grid; };
-
+    LevelGridBuilderDouble(SPtr<Grid> grid) : LevelGridBuilder(Device(), ""), grid(grid){};
+    SPtr<Grid> getGrid(uint level) override { return grid; };
+    std::shared_ptr<Grid> getGrid(int level, int box) override { return grid; };
     void setNumberOfSendIndices(uint numberOfSendIndices){this->numberOfSendIndices=numberOfSendIndices;};
     uint getNumberOfSendIndices(int direction, uint level) override {return numberOfSendIndices;};
 };
 
-
 class GridImpDouble : public GridImp
 {
 private:
@@ -46,13 +44,13 @@ private:
 
 public:
     GridImpDouble(Object *object, real startX, real startY, real startZ, real endX, real endY, real endZ, real delta,
-                   SPtr<GridStrategy> gridStrategy, Distribution d, uint level)
+                  SPtr<GridStrategy> gridStrategy, Distribution d, uint level)
         : GridImp(object, startX, startY, startZ, endX, endY, endZ, delta, gridStrategy, d, level)
     {
     }
 
     static SPtr<GridImpDouble> makeShared(Object *object, real startX, real startY, real startZ, real endX, real endY,
-                                           real endZ, real delta, SPtr<GridStrategy> gridStrategy, Distribution d,
+                                          real endZ, real delta, SPtr<GridStrategy> gridStrategy, Distribution d,
                                           uint level)
     {
         SPtr<GridImpDouble> grid(
@@ -65,8 +63,10 @@ public:
         this->fluidNodeIndicesBorder = fluidNodeIndicesBorder;
     }
 
-    bool isSparseIndexInFluidNodeIndicesBorder(uint& sparseIndex) const override { 
-        return std::find(this->fluidNodeIndicesBorder.begin(), this->fluidNodeIndicesBorder.end(), sparseIndex)!=this->fluidNodeIndicesBorder.end();
+    bool isSparseIndexInFluidNodeIndicesBorder(uint &sparseIndex) const override
+    {
+        return std::find(this->fluidNodeIndicesBorder.begin(), this->fluidNodeIndicesBorder.end(), sparseIndex) !=
+               this->fluidNodeIndicesBorder.end();
     }
 };
 
@@ -75,7 +75,7 @@ struct CFBorderBulk {
     std::vector<uint> fluidNodeIndicesBorder = { 10, 11, 12, 13, 14, 15, 16 };
     std::vector<uint> iCellCFC               = { 1, 11, 3, 13, 5, 15, 7 };
     std::vector<uint> iCellCFF               = { 2, 12, 4, 14, 6, 16, 8 };
-    uint sizeOfICellCf                       = (uint) iCellCFC.size();
+    uint sizeOfICellCf                       = (uint)iCellCFC.size();
     uint neighborX_SP[17]                    = { 0u };
     uint neighborY_SP[17]                    = { 0u };
     uint neighborZ_SP[17]                    = { 0u };
@@ -85,18 +85,34 @@ struct CFBorderBulk {
     std::vector<real> offsetCFz              = { 1001, 1011, 1003, 1013, 1005, 1015, 1007 };
 
     // expected data
-    std::vector<uint> iCellCfcBorder_expected = { 11, 13, 15 };
-    std::vector<uint> iCellCfcBulk_expected   = { 1, 3, 5, 7 };
-    std::vector<uint> iCellCffBorder_expected = { 12, 14, 16 };
-    std::vector<uint> iCellCffBulk_expected   = { 2, 4, 6, 8 };
-    std::vector<uint> offsetCFx_Border_expected = { 11, 13, 15 };
-    std::vector<uint> offsetCFx_Bulk_expected   = { 1, 3, 5, 7 };
-    std::vector<uint> offsetCFy_Border_expected = { 111, 113, 115 };
-    std::vector<uint> offsetCFy_Bulk_expected   = { 101, 103, 105, 107 };
-    std::vector<uint> offsetCFz_Border_expected = { 1011, 1013, 1015 };
-    std::vector<uint> offsetCFz_Bulk_expected   = { 1001, 1003, 1005, 1007 };
+    std::vector<uint> iCellCfcBorder_expected   = { 11, 13, 15 };
+    std::vector<uint> iCellCfcBulk_expected     = { 1, 3, 5, 7 };
+    std::vector<uint> iCellCffBorder_expected   = { 12, 14, 16 };
+    std::vector<uint> iCellCffBulk_expected     = { 2, 4, 6, 8 };
+    std::vector<real> offsetCFx_Border_expected = { 11, 13, 15 };
+    std::vector<real> offsetCFx_Bulk_expected   = { 1, 3, 5, 7 };
+    std::vector<real> offsetCFy_Border_expected = { 111, 113, 115 };
+    std::vector<real> offsetCFy_Bulk_expected   = { 101, 103, 105, 107 };
+    std::vector<real> offsetCFz_Border_expected = { 1011, 1013, 1015 };
+    std::vector<real> offsetCFz_Bulk_expected   = { 1001, 1003, 1005, 1007 };
 };
 
+struct FCBorderBulk {
+    // data to work on
+    std::vector<uint> fluidNodeIndicesBorder = { 110, 111, 112, 113, 114, 115, 116 };
+    std::vector<uint> iCellFCC               = { 11, 111, 13, 113, 15, 115, 17 };
+    std::vector<uint> iCellFCF               = { 12, 112, 14, 114, 16, 116, 18 };
+    uint sizeOfICellFC                       = (uint)iCellFCC.size();
+    int level                                = 1;
+
+    // expected data
+    std::vector<uint> iCellFccBorder_expected = { 111, 113, 115 };
+    std::vector<uint> iCellFccBulk_expected   = { 11, 13, 15, 17 };
+    std::vector<uint> iCellFcfBorder_expected = { 112, 114, 116 };
+    std::vector<uint> iCellFcfBulk_expected   = { 12, 14, 16, 18 };
+};
+
+
 struct SendIndicesForCommAfterFtoCX {
     // data to work on
     std::vector<int> sendIndices = { 10, 11, 12, 13, 14, 15, 16 };
@@ -108,25 +124,35 @@ struct SendIndicesForCommAfterFtoCX {
     std::vector<uint> sendIndicesForCommAfterFtoCPositions;
     int numberOfSendNeighborsAfterFtoC;
 
-    // expected data
-  
+    // expected data  
 };
 
 
+static SPtr<Parameter> initParameterClass()
+{
+    std::filesystem::path filePath = __FILE__; //  assuming that the config file is stored parallel to this file.
+    filePath.replace_filename("IndexRearrangementForStreamsTest.cfg");
+    vf::basics::ConfigurationFile config;
+    config.load(filePath.string());
+    return std::make_shared<Parameter>(config, 1, 0);
+}
 
-static void initParameterClass(std::shared_ptr<Parameter> &para);
-
-class IndexRearrangementForStreamsTest
+class IndexRearrangementForStreamsTest_IndicesCFBorderBulkTest : public testing::Test
 {
 public:
-    static void setUpAndRun_splitCoarseToFineIntoBorderAndBulk(CFBorderBulk &cf, std::shared_ptr<Parameter> para)
+    CFBorderBulk cf;
+    SPtr<Parameter> para;
+
+private:
+    static std::unique_ptr<IndexRearrangementForStreams> createTestSubjectCFBorderBulk(CFBorderBulk &cf,
+                                                                                       std::shared_ptr<Parameter> para)
     {
         SPtr<GridImpDouble> grid =
             GridImpDouble::makeShared(nullptr, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, nullptr, Distribution(), 1);
         grid->setFluidNodeIndicesBorder(cf.fluidNodeIndicesBorder);
-        std::shared_ptr<GridBuilderDouble> builder = std::make_shared<GridBuilderDouble>(grid);
+        std::shared_ptr<LevelGridBuilderDouble> builder = std::make_shared<LevelGridBuilderDouble>(grid);
 
-        para->setMaxLevel(cf.level + 1);
+        para->setMaxLevel(cf.level + 1); // setMaxLevel resizes parH and parD
         para->parH[cf.level]                    = std::make_shared<LBMSimulationParameter>();
         para->parD[cf.level]                    = std::make_shared<LBMSimulationParameter>();
         para->getParH(cf.level)->intCF.ICellCFC = &(cf.iCellCFC.front());
@@ -139,164 +165,130 @@ public:
         para->getParH(cf.level)->offCF.yOffCF   = &(cf.offsetCFy.front());
         para->getParH(cf.level)->offCF.zOffCF   = &(cf.offsetCFz.front());
 
-        IndexRearrangementForStreams testSubject = IndexRearrangementForStreams(para, builder);
-
-        testSubject.splitCoarseToFineIntoBorderAndBulk(cf.level);
+        return std::make_unique<IndexRearrangementForStreams>(para, builder);
     };
 
-    static void setUpAndRun_reorderSendIndicesForCommAfterFtoCX(SendIndicesForCommAfterFtoCX &si, std::shared_ptr<Parameter> para)
+    void SetUp() override
     {
-        SPtr<GridImpDouble> grid =
-            GridImpDouble::makeShared(nullptr, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, nullptr, Distribution(), 1);
-        std::shared_ptr<GridBuilderDouble> builder = std::make_shared<GridBuilderDouble>(grid);
-
-        builder->setNumberOfSendIndices((uint) si.sendIndices.size());
-
-
-        IndexRearrangementForStreams testSubject = IndexRearrangementForStreams(para, builder);
-        para->getParH(si.level)->sendProcessNeighborX[si.indexOfProcessNeighbor].index=si.sendIndices.data();
-        para->getParH(si.level)->sendProcessNeighborsAfterFtoCX[si.indexOfProcessNeighbor].numberOfNodes=0;
-
-        testSubject.reorderSendIndicesForCommAfterFtoCX(si.direction, si.level, si.indexOfProcessNeighbor, si.sendIndicesForCommAfterFtoCPositions);
-    };
-};
-
-void initParameterClass(std::shared_ptr<Parameter> &para)
-{
-    std::filesystem::path filePath = __FILE__; //  assuming that the config file is stored parallel to this file.
-    filePath.replace_filename("IndexRearrangementForStreamsTest.cfg");
-    vf::basics::ConfigurationFile config;
-    config.load(filePath.string());
-    para = std::make_shared<Parameter>(config, 1, 0);
-}
-
-bool vectorsAreEqual(std::vector<uint> vector1, std::vector<uint> vectorExpected)
-{
-    return vector1 == vectorExpected;
-}
-
-bool vectorsAreEqual(uint *vector1, std::vector<uint> vectorExpected)
-{
-    for (uint i = 0; i < vectorExpected.size(); i++) {
-        if (vector1[i] != vectorExpected[i])
-            return false;
+        para             = initParameterClass();
+        auto testSubject = createTestSubjectCFBorderBulk(cf, para);
+        testSubject->splitCoarseToFineIntoBorderAndBulk(cf.level);
     }
-    return true;
-}
+};
 
-bool vectorsAreEqual(real *vector1, std::vector<uint> vectorExpected)
+TEST_F(IndexRearrangementForStreamsTest_IndicesCFBorderBulkTest, splitCoarseToFineIntoBorderAndBulk)
 {
-    for (uint i = 0; i < vectorExpected.size(); i++) {
-        if (vector1[i] != vectorExpected[i])
-            return false;
-    }
-    return true;
+    EXPECT_THAT(para->getParH(cf.level)->intCFBorder.kCF + para->getParH(cf.level)->intCFBulk.kCF,
+                testing::Eq(cf.sizeOfICellCf))
+        << "The number of interpolation cells from coarse to fine changed during reordering.";
+
+    // check coarse to fine border (coarse nodes)
+    EXPECT_THAT(para->getParH(cf.level)->intCFBorder.kCF, testing::Eq((uint)cf.iCellCfcBorder_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBorder.ICellCFC, cf.iCellCfcBorder_expected))
+        << "intCFBorder.ICellCFC does not match the expected border vector";
+    // check coarse to fine border (fine nodes)
+    EXPECT_THAT(para->getParH(cf.level)->intCFBorder.kCF, testing::Eq((uint)cf.iCellCffBorder_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBorder.ICellCFF, cf.iCellCffBorder_expected))
+        << "intCFBorder.ICellCFF does not match the expected border vector";
+
+    // check coarse to fine bulk (coarse nodes)
+    EXPECT_THAT(para->getParH(cf.level)->intCFBulk.kCF, testing::Eq((uint)cf.iCellCfcBulk_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBulk.ICellCFC, cf.iCellCfcBulk_expected))
+        << "intCFBulk.ICellCFC does not match the expected bulk vector";
+    // check coarse to fine bulk (fine nodes)
+    EXPECT_THAT(para->getParH(cf.level)->intCFBulk.kCF, testing::Eq((uint)cf.iCellCffBulk_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBulk.ICellCFF, cf.iCellCffBulk_expected))
+        << "intCFBulk.ICellCFF does not match the expected bulk vector";
+
+    // check offset cells
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCF.xOffCF, cf.offsetCFx_Border_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCFBulk.xOffCF, cf.offsetCFx_Bulk_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCF.yOffCF, cf.offsetCFy_Border_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCFBulk.yOffCF, cf.offsetCFy_Bulk_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCF.zOffCF, cf.offsetCFz_Border_expected));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCFBulk.zOffCF, cf.offsetCFz_Bulk_expected));
 }
 
-
-TEST(IndexRearrangementForStreamsTest_reorderSendIndicesForCommAfterFtoCX, wip)
+class IndexRearrangementForStreamsTest_IndicesFCBorderBulkTest : public testing::Test
 {
-    SendIndicesForCommAfterFtoCX si;
+public:
+    FCBorderBulk fc;
     SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_reorderSendIndicesForCommAfterFtoCX(si, para);
-    EXPECT_TRUE(false);
-}
 
+private:
+    static std::unique_ptr<IndexRearrangementForStreams> createTestSubjectFCBorderBulk(FCBorderBulk &fc,
+                                                                                       std::shared_ptr<Parameter> para)
+    {
+        SPtr<GridImpDouble> grid =
+            GridImpDouble::makeShared(nullptr, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, nullptr, Distribution(), 1);
+        grid->setFluidNodeIndicesBorder(fc.fluidNodeIndicesBorder);
+        std::shared_ptr<LevelGridBuilderDouble> builder = std::make_shared<LevelGridBuilderDouble>(grid);
 
+        para->setMaxLevel(fc.level + 1); // setMaxLevel resizes parH and parD
+        para->parH[fc.level]                    = std::make_shared<LBMSimulationParameter>();
+        para->parD[fc.level]                    = std::make_shared<LBMSimulationParameter>();
+        para->getParH(fc.level)->intFC.ICellFCC = &(fc.iCellFCC.front());
+        para->getParH(fc.level)->intFC.ICellFCF = &(fc.iCellFCF.front());
+        para->getParH(fc.level)->intFC.kFC      = fc.sizeOfICellFC;
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, sizeIsConstant)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_TRUE(para->getParH(cf.level)->intCFBorder.kCF + para->getParH(cf.level)->intCFBulk.kCF == cf.sizeOfICellCf);
-}
+        return std::make_unique<IndexRearrangementForStreams>(para, builder);
+    };
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, borderSizeCFC)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_EQ(para->getParH(cf.level)->intCFBorder.kCF, (uint)cf.iCellCfcBorder_expected.size());
-}
+    void SetUp() override
+    {
+        para             = initParameterClass();
+        auto testSubject = createTestSubjectFCBorderBulk(fc, para);
+        testSubject->splitFineToCoarseIntoBorderAndBulk(fc.level);
+    }
+};
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, borderVectorCFC)
+TEST_F(IndexRearrangementForStreamsTest_IndicesFCBorderBulkTest, splitFineToCoarseIntoBorderAndBulk)
 {
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBorder.ICellCFC, cf.iCellCfcBorder_expected));
+    EXPECT_THAT(para->getParH(fc.level)->intFCBorder.kFC + para->getParH(fc.level)->intFCBulk.kFC,
+                testing::Eq(fc.sizeOfICellFC))
+        << "The number of interpolation cells from coarse to fine changed during reordering.";
+
+    // check coarse to fine border (coarse nodes)
+    EXPECT_THAT(para->getParH(fc.level)->intFCBorder.kFC, testing::Eq((uint)fc.iCellFccBorder_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(fc.level)->intFCBorder.ICellFCC, fc.iCellFccBorder_expected))
+        << "intFCBorder.ICellFCC does not match the expected border vector";
+    // check coarse to fine border (fine nodes)
+    EXPECT_THAT(para->getParH(fc.level)->intFCBorder.kFC, testing::Eq((uint)fc.iCellFcfBorder_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(fc.level)->intFCBorder.ICellFCF, fc.iCellFcfBorder_expected))
+        << "intFCBorder.ICellFCF does not match the expected border vector";
+
+    // check coarse to fine bulk (coarse nodes)
+    EXPECT_THAT(para->getParH(fc.level)->intFCBulk.kFC, testing::Eq((uint)fc.iCellFccBulk_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(fc.level)->intFCBulk.ICellFCC, fc.iCellFccBulk_expected))
+        << "intFCBulk.ICellFCC does not match the expected bulk vector";
+    // check coarse to fine bulk (fine nodes)
+    EXPECT_THAT(para->getParH(fc.level)->intFCBulk.kFC, testing::Eq((uint)fc.iCellFcfBulk_expected.size()));
+    EXPECT_TRUE(vectorsAreEqual(para->getParH(fc.level)->intFCBulk.ICellFCF, fc.iCellFcfBulk_expected))
+        << "intFCBulk.ICellFCF does not match the expected bulk vector";
 }
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, bulkSizeCFC)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_EQ(para->getParH(cf.level)->intCFBulk.kCF, (uint)cf.iCellCfcBulk_expected.size());
-}
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, bulkVectorCFC)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBulk.ICellCFC, cf.iCellCfcBulk_expected));
-}
+static void setUpAndRun_reorderSendIndicesForCommAfterFtoCX(SendIndicesForCommAfterFtoCX &si, std::shared_ptr<Parameter> para)
+    {
+        SPtr<GridImpDouble> grid =
+            GridImpDouble::makeShared(nullptr, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, nullptr, Distribution(), 1);
+        std::shared_ptr<LevelGridBuilderDouble> builder = std::make_shared<LevelGridBuilderDouble>(grid);
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, borderSizeCFF)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_EQ(para->getParH(cf.level)->intCFBorder.kCF, (uint)cf.iCellCffBorder_expected.size());
-}
+        builder->setNumberOfSendIndices((uint) si.sendIndices.size());
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, borderVectorCFF)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBorder.ICellCFF, cf.iCellCffBorder_expected));
-}
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, bulkSizeCFF)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_EQ(para->getParH(cf.level)->intCFBulk.kCF, (uint)cf.iCellCffBulk_expected.size());
-}
+        IndexRearrangementForStreams testSubject = IndexRearrangementForStreams(para, builder);
+        para->getParH(si.level)->sendProcessNeighborX[si.indexOfProcessNeighbor].index=si.sendIndices.data();
+        para->getParH(si.level)->sendProcessNeighborsAfterFtoCX[si.indexOfProcessNeighbor].numberOfNodes=0;
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, bulkVectorCFF)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->intCFBulk.ICellCFF, cf.iCellCffBulk_expected));
-}
+        // testSubject.reorderSendIndicesForCommAfterFtoCX(si.direction, si.level, si.indexOfProcessNeighbor, si.sendIndicesForCommAfterFtoCPositions);
+    };
 
-TEST(IndexRearrangementForStreamsTest_IndicesCFBorderBulk, offsetsVectorsCFC)
-{
-    CFBorderBulk cf;
-    SPtr<Parameter> para;
-    initParameterClass(para);
-    IndexRearrangementForStreamsTest::setUpAndRun_splitCoarseToFineIntoBorderAndBulk(cf, para);
 
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCF.xOffCF, cf.offsetCFx_Border_expected));
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCFBulk.xOffCF, cf.offsetCFx_Bulk_expected));
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCF.yOffCF, cf.offsetCFy_Border_expected));
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCFBulk.yOffCF, cf.offsetCFy_Bulk_expected));
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCF.zOffCF, cf.offsetCFz_Border_expected));
-    EXPECT_TRUE(vectorsAreEqual(para->getParH(cf.level)->offCFBulk.zOffCF, cf.offsetCFz_Bulk_expected));
+TEST(IndexRearrangementForStreamsTest_reorderSendIndicesForCommAfterFtoCX, wip)
+{
+    SendIndicesForCommAfterFtoCX si;
+    SPtr<Parameter> para = initParameterClass();
+    // IndexRearrangementForStreamsTest::setUpAndRun_reorderSendIndicesForCommAfterFtoCX(si, para);
+    EXPECT_TRUE(false);
 }
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/BasicKernels/FluidFlow/Compressible/CumulantK17chimStream/CumulantK17CompChimStreamDevice.cu b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/BasicKernels/FluidFlow/Compressible/CumulantK17chimStream/CumulantK17CompChimStreamDevice.cu
index da37bb1e2fee675cb07410d483dac21dc84215dc..f57fd9dd9bc2a372c7790bf8f3837e69d1d52beb 100644
--- a/src/gpu/VirtualFluids_GPU/Kernel/Kernels/BasicKernels/FluidFlow/Compressible/CumulantK17chimStream/CumulantK17CompChimStreamDevice.cu
+++ b/src/gpu/VirtualFluids_GPU/Kernel/Kernels/BasicKernels/FluidFlow/Compressible/CumulantK17chimStream/CumulantK17CompChimStreamDevice.cu
@@ -26,9 +26,9 @@
 //  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 Cumulant27chim.cu
+//! \file Cumulant27chimStream.cu
 //! \ingroup GPU
-//! \author Martin Schoenherr
+//! \author Martin Schoenherr, Anna Wellmann
 //=======================================================================================
 /* Device code */
 #include "LBM/LB.h" 
diff --git a/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp b/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
index 92096a76abc023c478921cd2543aec7c48bb6a32..baf268b25e02e86522df749d4820a4e36ee0b99b 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
+++ b/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
@@ -17,6 +17,7 @@
 #include "Output/MeasurePointWriter.hpp"
 #include "Output/AnalysisData.hpp"
 #include "Output/InterfaceDebugWriter.hpp"
+#include "Output/EdgeNodeDebugWriter.hpp"
 #include "Output/VeloASCIIWriter.hpp"
 //////////////////////////////////////////////////////////////////////////
 #include "Utilities/Buffer2D.hpp"
@@ -383,11 +384,21 @@ void Simulation::init(SPtr<Parameter> para, SPtr<GridProvider> gridProvider, std
 
    //////////////////////////////////////////////////////////////////////////
    output << "used Device Memory: " << cudaManager->getMemsizeGPU() / 1000000.0 << " MB\n";
-   std::cout << "Process " << comm->getPID() <<": used device memory" << cudaManager->getMemsizeGPU() / 1000000.0 << " MB\n" << std::endl;
+   // std::cout << "Process " << comm->getPID() <<": used device memory" << cudaManager->getMemsizeGPU() / 1000000.0 << " MB\n" << std::endl;
    //////////////////////////////////////////////////////////////////////////
 
    //InterfaceDebugWriter::writeInterfaceLinesDebugCF(para.get());
    //InterfaceDebugWriter::writeInterfaceLinesDebugFC(para.get());
+
+   // writers for version with communication hiding
+   //    if(para->getNumprocs() > 1 && para->getUseStreams()){
+   //        InterfaceDebugWriter::writeInterfaceFCC_Send(para.get());
+   //        InterfaceDebugWriter::writeInterfaceCFC_Recv(para.get());
+   //        InterfaceDebugWriter::writeSendNodesStream(para.get());
+   //        InterfaceDebugWriter::writeRecvNodesStream(para.get());
+   //        EdgeNodeDebugWriter::writeEdgeNodesXZ_Send(para);
+   //        EdgeNodeDebugWriter::writeEdgeNodesXZ_Recv(para);
+   //    }
 }
 
 void Simulation::allocNeighborsOffsetsScalesAndBoundaries(SPtr<GridProvider> &gridProvider)
diff --git a/src/gpu/VirtualFluids_GPU/Output/EdgeNodeDebugWriter.hpp b/src/gpu/VirtualFluids_GPU/Output/EdgeNodeDebugWriter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b2d2f275bd127f0065f135acb94b738260c4668
--- /dev/null
+++ b/src/gpu/VirtualFluids_GPU/Output/EdgeNodeDebugWriter.hpp
@@ -0,0 +1,101 @@
+#ifndef EDGENODEDEBUG_HPP
+#define EDGENODEDEBUG_HPP
+
+#include <fstream>
+#include <sstream>
+#include <stdio.h>
+// #include <math.h>
+#include "Core/StringUtilities/StringUtil.h"
+#include "LBM/D3Q27.h"
+#include "LBM/LB.h"
+#include "Parameter/Parameter.h"
+#include "basics/utilities/UbSystem.h"
+#include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <cmath>
+
+#include "VirtualFluids_GPU/Communication/Communicator.h"
+
+namespace EdgeNodeDebugWriter
+{
+
+void addCoordinatesToNodeVector(SPtr<LBMSimulationParameter> parH, std::vector<UbTupleFloat3> &nodesVec, int indexInNodesVector, int sparseIndexOfNode){
+            double x1           = parH->coordX_SP[sparseIndexOfNode];
+            double x2           = parH->coordY_SP[sparseIndexOfNode];
+            double x3           = parH->coordZ_SP[sparseIndexOfNode];
+            nodesVec[indexInNodesVector] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+}
+
+void writeEdgeNodesXZ_Send(SPtr<Parameter> para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<std::string> datanames = { "SparseIndex", "ProcessNeighbor", "IndexInSendVector", "AfterFtoC" };
+    std::vector<std::vector<double>> nodedata;
+
+    int numberOfNodes = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++){
+        numberOfNodes += (int) para->getParH(level)->edgeNodesXtoZ.size();
+    }
+    nodesVec.resize(numberOfNodes);
+    nodedata.resize(datanames.size(), std::vector<double>(numberOfNodes));
+
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (int u = 0; u < numberOfNodes; u++) {
+            int indexOfProcessNeighborSend = para->getParH(level)->edgeNodesXtoZ[u].indexOfProcessNeighborSend;
+            int indexInSendBuffer = para->getParH(level)->edgeNodesXtoZ[u].indexInSendBuffer;
+            int sparseIndex = para->getParH(level)->sendProcessNeighborZ[indexOfProcessNeighborSend].index[indexInSendBuffer];
+            nodedata[0][nodeCount] = sparseIndex;
+            nodedata[1][nodeCount] = indexOfProcessNeighborSend;
+            nodedata[2][nodeCount] = indexInSendBuffer;
+            nodedata[3][nodeCount] = indexInSendBuffer < para->getParH(level)->sendProcessNeighborsAfterFtoCZ[indexOfProcessNeighborSend].numberOfNodes;
+
+            addCoordinatesToNodeVector(para->getParH(level), nodesVec, nodeCount, sparseIndex);
+
+            nodeCount++;
+        }
+        std::string filenameVec = para->getFName() + "_writeEdgeNodesXZ_Send_PID_" +
+                                  std::to_string(vf::gpu::Communicator::getInstanz()->getPID()) + "_" +
+                                  StringUtil::toString<int>(level);
+
+        WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(filenameVec, nodesVec, datanames, nodedata);
+    }
+}
+
+void writeEdgeNodesXZ_Recv(SPtr<Parameter> para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<std::string> datanames = { "SparseIndex", "ProcessNeighbor", "IndexInRecvVector", "AfterFtoC" };
+    std::vector<std::vector<double>> nodedata;
+
+    int numberOfNodes = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++){
+        numberOfNodes += (int) para->getParH(level)->edgeNodesXtoZ.size();
+    }
+    nodesVec.resize(numberOfNodes);
+    nodedata.resize(datanames.size(), std::vector<double>(numberOfNodes));
+
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (int u = 0; u < numberOfNodes; u++) {
+            int indexOfProcessNeighborRecv = para->getParH(level)->edgeNodesXtoZ[u].indexOfProcessNeighborRecv;
+            int indexInRecvBuffer = para->getParH(level)->edgeNodesXtoZ[u].indexInRecvBuffer;
+            int sparseIndex = para->getParH(level)->recvProcessNeighborX[indexOfProcessNeighborRecv].index[indexInRecvBuffer];
+            nodedata[0][nodeCount] = sparseIndex;
+            nodedata[1][nodeCount] = indexOfProcessNeighborRecv;
+            nodedata[2][nodeCount] = indexInRecvBuffer;
+            nodedata[3][nodeCount] = indexInRecvBuffer < para->getParH(level)->recvProcessNeighborX[indexOfProcessNeighborRecv].numberOfNodes;
+
+            addCoordinatesToNodeVector(para->getParH(level), nodesVec, nodeCount, sparseIndex);
+
+            nodeCount++;
+        }
+        std::string filenameVec = para->getFName() + "_writeEdgeNodesXZ_Recv_PID_" +
+                                  std::to_string(vf::gpu::Communicator::getInstanz()->getPID()) + "_" +
+                                  StringUtil::toString<int>(level);
+
+        WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(filenameVec, nodesVec, datanames, nodedata);
+    }
+}
+} // namespace EdgeNodeDebugWriter
+
+#endif
diff --git a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
index 5c293118e7583b38ab700fffa317febabdeb64a1..a86afac9982091eb1c12363568817c43f3d54116 100644
--- a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
@@ -25,10 +25,10 @@
 void FileWriter::writeInit(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> cudaManager)
 {
     unsigned int timestep = para->getTInit();
-	for (int level = para->getCoarse(); level <= para->getFine(); level++) {
-		cudaManager->cudaCopyPrint(level);
-		writeTimestep(para, timestep, level);
-	}
+    for (int level = para->getCoarse(); level <= para->getFine(); level++) {
+        cudaManager->cudaCopyPrint(level);
+        writeTimestep(para, timestep, level);
+    }
 
     this->writeCollectionFile(para, timestep);
 
@@ -51,35 +51,35 @@ void FileWriter::writeTimestep(std::shared_ptr<Parameter> para, unsigned int tim
 {
     const unsigned int numberOfParts = para->getParH(level)->size_Mat_SP / para->getlimitOfNodesForVTK() + 1;
     std::vector<std::string> fname;
-	std::vector<std::string> fnameMed;
-	for (unsigned int i = 1; i <= numberOfParts; i++)
-	{
-		fname.push_back(para->getFName() + "_bin_lev_" + StringUtil::toString<int>(level) + "_ID_" + StringUtil::toString<int>(para->getMyID()) + "_Part_" + StringUtil::toString<int>(i) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk");
-		fnameMed.push_back(para->getFName() + "_bin_median_lev_" + StringUtil::toString<int>(level) + "_ID_" + StringUtil::toString<int>(para->getMyID()) + "_Part_" + StringUtil::toString<int>(i) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk");
+    std::vector<std::string> fnameMed;
+    for (unsigned int i = 1; i <= numberOfParts; i++)
+    {
+        fname.push_back(para->getFName() + "_bin_lev_" + StringUtil::toString<int>(level) + "_ID_" + StringUtil::toString<int>(para->getMyID()) + "_Part_" + StringUtil::toString<int>(i) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk");
+        fnameMed.push_back(para->getFName() + "_bin_median_lev_" + StringUtil::toString<int>(level) + "_ID_" + StringUtil::toString<int>(para->getMyID()) + "_Part_" + StringUtil::toString<int>(i) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk");
 
         this->fileNamesForCollectionFile.push_back( fname.back() );
         this->fileNamesForCollectionFileMedian.push_back( fnameMed.back() );
-	}
-
-	if (para->getDiffOn() == true)
-		writeUnstrucuredGridLTConc(para, level, fname);
-	else
-		writeUnstrucuredGridLT(para, level, fname);
-
-	if (para->getCalcMedian())
-	{
-		if (para->getDiffOn() == true)
-			writeUnstrucuredGridMedianLTConc(para, level, fnameMed);
-		else
-			writeUnstrucuredGridMedianLT(para, level, fnameMed);
-	}
+    }
+
+    if (para->getDiffOn() == true)
+        writeUnstrucuredGridLTConc(para, level, fname);
+    else
+        writeUnstrucuredGridLT(para, level, fname);
+
+    if (para->getCalcMedian())
+    {
+        if (para->getDiffOn() == true)
+            writeUnstrucuredGridMedianLTConc(para, level, fnameMed);
+        else
+            writeUnstrucuredGridMedianLT(para, level, fnameMed);
+    }
 }
 
 bool FileWriter::isPeriodicCell(std::shared_ptr<Parameter> para, int level, unsigned int number2, unsigned int number1, unsigned int number3, unsigned int number5)
 {
-	return (para->getParH(level)->coordX_SP[number2] < para->getParH(level)->coordX_SP[number1]) ||
-		   (para->getParH(level)->coordY_SP[number3] < para->getParH(level)->coordY_SP[number1]) ||
-		   (para->getParH(level)->coordZ_SP[number5] < para->getParH(level)->coordZ_SP[number1]);
+    return (para->getParH(level)->coordX_SP[number2] < para->getParH(level)->coordX_SP[number1]) ||
+           (para->getParH(level)->coordY_SP[number3] < para->getParH(level)->coordY_SP[number1]) ||
+           (para->getParH(level)->coordZ_SP[number5] < para->getParH(level)->coordZ_SP[number1]);
 }
 
 void VIRTUALFLUIDS_GPU_EXPORT FileWriter::writeCollectionFile(std::shared_ptr<Parameter> para, unsigned int timestep)
@@ -92,18 +92,18 @@ void VIRTUALFLUIDS_GPU_EXPORT FileWriter::writeCollectionFile(std::shared_ptr<Pa
     file.open( filename + ".pvtu" );
 
     //////////////////////////////////////////////////////////////////////////
-    
-    file << "<VTKFile type=\"PUnstructuredGrid\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">" << std::endl;
+    file << "<?xml version=\"1.0\"?>" << std::endl;
+    file << "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << std::endl;
     file << "  <PUnstructuredGrid GhostLevel=\"1\">" << std::endl;
 
     file << "    <PPointData>" << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"press\" /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"rho\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"vx1\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"vx2\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"vx3\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"geo\"   /> " << std::endl;
-    if( para->getDiffOn() ) file << "       <DataArray type=\"Float32\" Name=\"conc\"  /> " << std::endl;
+    file << "       <PDataArray type=\"Float64\" Name=\"press\" /> " << std::endl;
+    file << "       <PDataArray type=\"Float64\" Name=\"rho\"   /> " << std::endl;
+    file << "       <PDataArray type=\"Float64\" Name=\"vx1\"   /> " << std::endl;
+    file << "       <PDataArray type=\"Float64\" Name=\"vx2\"   /> " << std::endl;
+    file << "       <PDataArray type=\"Float64\" Name=\"vx3\"   /> " << std::endl;
+    file << "       <PDataArray type=\"Float64\" Name=\"geo\"   /> " << std::endl;
+    if( para->getDiffOn() ) file << "       <PDataArray type=\"Float64\" Name=\"conc\"  /> " << std::endl;
     file << "    </PPointData>" << std::endl;
 
     file << "    <PPoints>" << std::endl;
@@ -181,8 +181,6 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
     nodedatanames.push_back("vx2");
     nodedatanames.push_back("vx3");
     nodedatanames.push_back("geo");
-    //nodedatanames.push_back("sendNodes");
-    //nodedatanames.push_back("sparseIndex");
 
     uint firstTurbNode = (uint) nodedatanames.size();
     if (para->getCalcTurbulenceIntensity()) {
@@ -192,7 +190,7 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
         nodedatanames.push_back("vxy");
         nodedatanames.push_back("vxz");
         nodedatanames.push_back("vyz");
-	}
+    }
     unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
     uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
     bool neighborsAreFluid;
@@ -215,7 +213,7 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
         cells.clear();
         nodes.resize(sizeOfNodes);
         for (uint i = 0; i < (uint)nodedatanames.size(); i++)
-			nodedata[i].resize(sizeOfNodes);
+            nodedata[i].resize(sizeOfNodes);
 
         //////////////////////////////////////////////////////////////////////////
         for (unsigned int pos = startpos; pos < endpos; pos++)
@@ -239,12 +237,6 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
                 nodedata[4][dn1] = (double)para->getParH(level)->vz_SP[pos] * (double)para->getVelocityRatio();
                 nodedata[5][dn1] = (double)para->getParH(level)->geoSP[pos];
 
-                //nodedata[6][dn1] = (double) pos;
-
-				//int sendNode = 0; // 0 - not a sendNode; 1 - sendNode; 2 - sendNode in communication after fine to coarse
-    //            testForSendNodeZ(para, level, pos, sendNode); // slow and should not be done multiple times --> use for debugging only!
-				//nodedata[6][dn1] = (double) sendNode;
-
                 if (para->getCalcTurbulenceIntensity()) {
                     nodedata[firstTurbNode    ][dn1] = (double)para->getParH(level)->vxx[pos];
                     nodedata[firstTurbNode + 1][dn1] = (double)para->getParH(level)->vyy[pos];
@@ -286,10 +278,10 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
                 dn6 = number6 - startpos;
                 dn7 = number7 - startpos;
                 dn8 = number8 - startpos;
-				//////////////////////////////////////////////////////////////////////////
-				if (isPeriodicCell(para, level, number2, number1, number3, number5))
-					continue;
-				//////////////////////////////////////////////////////////////////////////
+                //////////////////////////////////////////////////////////////////////////
+                if (isPeriodicCell(para, level, number2, number1, number3, number5))
+                    continue;
+                //////////////////////////////////////////////////////////////////////////
                 if (neighborsAreFluid)
                     cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
             }
@@ -298,360 +290,329 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
     }
 }
 
-void FileWriter::testForSendNodeY(std::shared_ptr<Parameter> &para, int level, unsigned int pos, int &sendNode)
+void FileWriter::writeUnstrucuredGridLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
 {
-    testForCommunicationNode(para, level, pos, sendNode, &para->getParH(level)->sendProcessNeighborY,
-                        &para->getParH(level)->sendProcessNeighborsAfterFtoCY);
-}
+    std::vector< UbTupleFloat3 > nodes;
+    std::vector< UbTupleUInt8 > cells;
+    std::vector< std::string > nodedatanames;
+    nodedatanames.push_back("press");
+    nodedatanames.push_back("rho");
+    nodedatanames.push_back("vx1");
+    nodedatanames.push_back("vx2");
+    nodedatanames.push_back("vx3");
+    nodedatanames.push_back("geo");
+    nodedatanames.push_back("conc");
+    unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
+    uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
+    bool neighborsAreFluid;
+    unsigned int startpos = 0;
+    unsigned int endpos = 0;
+    unsigned int sizeOfNodes = 0;
+    std::vector< std::vector< double > > nodedata(nodedatanames.size());
 
-void FileWriter::testForSendNodeZ(std::shared_ptr<Parameter> &para, int level, unsigned int pos, int &sendNode)
-{
-    testForCommunicationNode(para, level, pos, sendNode, &para->getParH(level)->sendProcessNeighborZ,
-                             &para->getParH(level)->sendProcessNeighborsAfterFtoCZ);
-}
+    for (unsigned int part = 0; part < fname.size(); part++)
+    {
+        if (((part + 1)*para->getlimitOfNodesForVTK()) > para->getParH(level)->size_Mat_SP)
+            sizeOfNodes = para->getParH(level)->size_Mat_SP - (part * para->getlimitOfNodesForVTK());
+        else
+            sizeOfNodes = para->getlimitOfNodesForVTK();
 
-void FileWriter::testForCommunicationNode(std::shared_ptr<Parameter> &para, int level, unsigned int pos, int &sendNode,
-                                     std::vector<PN27> *sendOrRecvProcessNeighbor,
-                                     std::vector<PN27> *sendOrRecvProcessNeighborAfterFtoC)
-{
-    for (uint direction = 0; direction < (uint)sendOrRecvProcessNeighbor->size(); direction++) {
-        for (int i = 0; i < (*sendOrRecvProcessNeighbor)[direction].numberOfNodes; i++) {
-            if (pos == (uint)(*sendOrRecvProcessNeighbor)[direction].index[i]) {
-                sendNode = 1;
-				//std::cout << "send/recv Node found: " << pos << std::endl;
-                if (level < para->getMaxLevel() && i < (*sendOrRecvProcessNeighborAfterFtoC)[direction].numberOfNodes) {
-                    //std::cout << "Communication send/recv Node found: " << pos << std::endl;
-					sendNode = 2;
-                }
-                return;
+        //////////////////////////////////////////////////////////////////////////
+        startpos = part * para->getlimitOfNodesForVTK();
+        endpos = startpos + sizeOfNodes;
+        //////////////////////////////////////////////////////////////////////////
+        cells.clear();
+        nodes.resize(sizeOfNodes);
+        nodedata[0].resize(sizeOfNodes);
+        nodedata[1].resize(sizeOfNodes);
+        nodedata[2].resize(sizeOfNodes);
+        nodedata[3].resize(sizeOfNodes);
+        nodedata[4].resize(sizeOfNodes);
+        nodedata[5].resize(sizeOfNodes);
+        nodedata[6].resize(sizeOfNodes);
+        //////////////////////////////////////////////////////////////////////////
+        for (unsigned int pos = startpos; pos < endpos; pos++)
+        {
+            if (para->getParH(level)->geoSP[pos] == GEO_FLUID)
+            {
+                //////////////////////////////////////////////////////////////////////////
+                double x1 = para->getParH(level)->coordX_SP[pos];
+                double x2 = para->getParH(level)->coordY_SP[pos];
+                double x3 = para->getParH(level)->coordZ_SP[pos];
+                //////////////////////////////////////////////////////////////////////////
+                number1 = pos;
+                dn1 = pos - startpos;
+                neighborsAreFluid = true;
+                //////////////////////////////////////////////////////////////////////////
+                nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+                nodedata[0][dn1] = (double)para->getParH(level)->press_SP[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
+                nodedata[1][dn1] = (double)para->getParH(level)->rho_SP[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
+                nodedata[2][dn1] = (double)para->getParH(level)->vx_SP[pos] * (double)para->getVelocityRatio();
+                nodedata[3][dn1] = (double)para->getParH(level)->vy_SP[pos] * (double)para->getVelocityRatio();
+                nodedata[4][dn1] = (double)para->getParH(level)->vz_SP[pos] * (double)para->getVelocityRatio();
+                nodedata[5][dn1] = (double)para->getParH(level)->geoSP[pos];
+                nodedata[6][dn1] = (double)para->getParH(level)->Conc[pos];
+                //////////////////////////////////////////////////////////////////////////
+                number2 = para->getParH(level)->neighborX_SP[number1];
+                number3 = para->getParH(level)->neighborY_SP[number2];
+                number4 = para->getParH(level)->neighborY_SP[number1];
+                number5 = para->getParH(level)->neighborZ_SP[number1];
+                number6 = para->getParH(level)->neighborZ_SP[number2];
+                number7 = para->getParH(level)->neighborZ_SP[number3];
+                number8 = para->getParH(level)->neighborZ_SP[number4];
+                //////////////////////////////////////////////////////////////////////////
+                if (para->getParH(level)->geoSP[number2] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number3] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number4] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number5] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number6] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number7] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number8] != GEO_FLUID)  neighborsAreFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                if (number2 > endpos ||
+                    number3 > endpos ||
+                    number4 > endpos ||
+                    number5 > endpos ||
+                    number6 > endpos ||
+                    number7 > endpos ||
+                    number8 > endpos)  neighborsAreFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                dn2 = number2 - startpos;
+                dn3 = number3 - startpos;
+                dn4 = number4 - startpos;
+                dn5 = number5 - startpos;
+                dn6 = number6 - startpos;
+                dn7 = number7 - startpos;
+                dn8 = number8 - startpos;
+                //////////////////////////////////////////////////////////////////////////
+                if (isPeriodicCell(para, level, number2, number1, number3, number5))
+                    continue;
+                //////////////////////////////////////////////////////////////////////////
+                if (neighborsAreFluid)
+                    cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
             }
         }
+        WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
     }
 }
 
-void FileWriter::writeUnstrucuredGridLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
-{
-	std::vector< UbTupleFloat3 > nodes;
-	std::vector< UbTupleUInt8 > cells;
-	std::vector< std::string > nodedatanames;
-	nodedatanames.push_back("press");
-	nodedatanames.push_back("rho");
-	nodedatanames.push_back("vx1");
-	nodedatanames.push_back("vx2");
-	nodedatanames.push_back("vx3");
-	nodedatanames.push_back("geo");
-	nodedatanames.push_back("conc");
-	unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
-	uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
-	bool neighborsAreFluid;
-	unsigned int startpos = 0;
-	unsigned int endpos = 0;
-	unsigned int sizeOfNodes = 0;
-	std::vector< std::vector< double > > nodedata(nodedatanames.size());
-
-	for (unsigned int part = 0; part < fname.size(); part++)
-	{
-		if (((part + 1)*para->getlimitOfNodesForVTK()) > para->getParH(level)->size_Mat_SP)
-			sizeOfNodes = para->getParH(level)->size_Mat_SP - (part * para->getlimitOfNodesForVTK());
-		else
-			sizeOfNodes = para->getlimitOfNodesForVTK();
-
-		//////////////////////////////////////////////////////////////////////////
-		startpos = part * para->getlimitOfNodesForVTK();
-		endpos = startpos + sizeOfNodes;
-		//////////////////////////////////////////////////////////////////////////
-		cells.clear();
-		nodes.resize(sizeOfNodes);
-		nodedata[0].resize(sizeOfNodes);
-		nodedata[1].resize(sizeOfNodes);
-		nodedata[2].resize(sizeOfNodes);
-		nodedata[3].resize(sizeOfNodes);
-		nodedata[4].resize(sizeOfNodes);
-		nodedata[5].resize(sizeOfNodes);
-		nodedata[6].resize(sizeOfNodes);
-		//////////////////////////////////////////////////////////////////////////
-		for (unsigned int pos = startpos; pos < endpos; pos++)
-		{
-			if (para->getParH(level)->geoSP[pos] == GEO_FLUID)
-			{
-				//////////////////////////////////////////////////////////////////////////
-				double x1 = para->getParH(level)->coordX_SP[pos];
-				double x2 = para->getParH(level)->coordY_SP[pos];
-				double x3 = para->getParH(level)->coordZ_SP[pos];
-				//////////////////////////////////////////////////////////////////////////
-				number1 = pos;
-				dn1 = pos - startpos;
-				neighborsAreFluid = true;
-				//////////////////////////////////////////////////////////////////////////
-				nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
-				nodedata[0][dn1] = (double)para->getParH(level)->press_SP[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
-				nodedata[1][dn1] = (double)para->getParH(level)->rho_SP[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
-				nodedata[2][dn1] = (double)para->getParH(level)->vx_SP[pos] * (double)para->getVelocityRatio();
-				nodedata[3][dn1] = (double)para->getParH(level)->vy_SP[pos] * (double)para->getVelocityRatio();
-				nodedata[4][dn1] = (double)para->getParH(level)->vz_SP[pos] * (double)para->getVelocityRatio();
-				nodedata[5][dn1] = (double)para->getParH(level)->geoSP[pos];
-				nodedata[6][dn1] = (double)para->getParH(level)->Conc[pos];
-				//////////////////////////////////////////////////////////////////////////
-				number2 = para->getParH(level)->neighborX_SP[number1];
-				number3 = para->getParH(level)->neighborY_SP[number2];
-				number4 = para->getParH(level)->neighborY_SP[number1];
-				number5 = para->getParH(level)->neighborZ_SP[number1];
-				number6 = para->getParH(level)->neighborZ_SP[number2];
-				number7 = para->getParH(level)->neighborZ_SP[number3];
-				number8 = para->getParH(level)->neighborZ_SP[number4];
-				//////////////////////////////////////////////////////////////////////////
-				if (para->getParH(level)->geoSP[number2] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number3] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number4] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number5] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number6] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number7] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number8] != GEO_FLUID)  neighborsAreFluid = false;
-				//////////////////////////////////////////////////////////////////////////
-				if (number2 > endpos ||
-					number3 > endpos ||
-					number4 > endpos ||
-					number5 > endpos ||
-					number6 > endpos ||
-					number7 > endpos ||
-					number8 > endpos)  neighborsAreFluid = false;
-				//////////////////////////////////////////////////////////////////////////
-				dn2 = number2 - startpos;
-				dn3 = number3 - startpos;
-				dn4 = number4 - startpos;
-				dn5 = number5 - startpos;
-				dn6 = number6 - startpos;
-				dn7 = number7 - startpos;
-				dn8 = number8 - startpos;
-				//////////////////////////////////////////////////////////////////////////
-				if (isPeriodicCell(para, level, number2, number1, number3, number5))
-					continue;
-				//////////////////////////////////////////////////////////////////////////
-				if (neighborsAreFluid)
-					cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
-			}
-		}
-		WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
-	}
-}
-
 void FileWriter::writeUnstrucuredGridMedianLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
 {
-	std::vector< UbTupleFloat3 > nodes;
-	std::vector< UbTupleUInt8 > cells;
-	//std::vector< UbTupleUInt8 > cells2;
-	std::vector< std::string > nodedatanames;
-	nodedatanames.push_back("pressMed");
-	nodedatanames.push_back("rhoMed");
-	nodedatanames.push_back("vx1Med");
-	nodedatanames.push_back("vx2Med");
-	nodedatanames.push_back("vx3Med");
-	nodedatanames.push_back("geo");
-	unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
-	unsigned int dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
-	bool neighborsFluid;
-	unsigned int startpos = 0;
-	unsigned int endpos = 0;
-	unsigned int sizeOfNodes = 0;
-	std::vector< std::vector< double > > nodedata(nodedatanames.size());
-
-	//printf("\n test for if... \n");
-	for (unsigned int part = 0; part < fname.size(); part++)
-	{
-		//printf("\n test in if I... \n");
-		//////////////////////////////////////////////////////////////////////////
-		if (((part + 1)*para->getlimitOfNodesForVTK()) > para->getParH(level)->size_Mat_SP)
-		{
-			sizeOfNodes = para->getParH(level)->size_Mat_SP - (part * para->getlimitOfNodesForVTK());
-		}
-		else
-		{
-			sizeOfNodes = para->getlimitOfNodesForVTK();
-		}
-		//////////////////////////////////////////////////////////////////////////
-		startpos = part * para->getlimitOfNodesForVTK();
-		endpos = startpos + sizeOfNodes;
-		//////////////////////////////////////////////////////////////////////////
-		cells.clear();
-		nodes.resize(sizeOfNodes);
-		nodedata[0].resize(sizeOfNodes);
-		nodedata[1].resize(sizeOfNodes);
-		nodedata[2].resize(sizeOfNodes);
-		nodedata[3].resize(sizeOfNodes);
-		nodedata[4].resize(sizeOfNodes);
-		nodedata[5].resize(sizeOfNodes);
-		//////////////////////////////////////////////////////////////////////////
-		//printf("\n test in if II... \n");
-		for (unsigned int pos = startpos; pos < endpos; pos++)
-		{
-			if (para->getParH(level)->geoSP[pos] == GEO_FLUID)
-			{
-				//////////////////////////////////////////////////////////////////////////
-				double x1 = para->getParH(level)->coordX_SP[pos];
-				double x2 = para->getParH(level)->coordY_SP[pos];
-				double x3 = para->getParH(level)->coordZ_SP[pos];
-				//////////////////////////////////////////////////////////////////////////
-				number1 = pos;
-				dn1 = pos - startpos;
-				neighborsFluid = true;
-				//////////////////////////////////////////////////////////////////////////
-				nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
-				nodedata[0][dn1] = para->getParH(level)->press_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-				nodedata[1][dn1] = para->getParH(level)->rho_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-				nodedata[2][dn1] = para->getParH(level)->vx_SP_Med_Out[pos] * para->getVelocityRatio();
-				nodedata[3][dn1] = para->getParH(level)->vy_SP_Med_Out[pos] * para->getVelocityRatio();
-				nodedata[4][dn1] = para->getParH(level)->vz_SP_Med_Out[pos] * para->getVelocityRatio();
-				nodedata[5][dn1] = (double)para->getParH(level)->geoSP[pos];
-				//////////////////////////////////////////////////////////////////////////
-				number2 = para->getParH(level)->neighborX_SP[number1];
-				number3 = para->getParH(level)->neighborY_SP[number2];
-				number4 = para->getParH(level)->neighborY_SP[number1];
-				number5 = para->getParH(level)->neighborZ_SP[number1];
-				number6 = para->getParH(level)->neighborZ_SP[number2];
-				number7 = para->getParH(level)->neighborZ_SP[number3];
-				number8 = para->getParH(level)->neighborZ_SP[number4];
-				//////////////////////////////////////////////////////////////////////////
-				if (para->getParH(level)->geoSP[number2] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number3] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number4] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number5] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number6] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number7] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number8] != GEO_FLUID)  neighborsFluid = false;
-				//////////////////////////////////////////////////////////////////////////
-				if (number2 > endpos ||
-					number3 > endpos ||
-					number4 > endpos ||
-					number5 > endpos ||
-					number6 > endpos ||
-					number7 > endpos ||
-					number8 > endpos)  neighborsFluid = false;
-				//////////////////////////////////////////////////////////////////////////
-				dn2 = number2 - startpos;
-				dn3 = number3 - startpos;
-				dn4 = number4 - startpos;
-				dn5 = number5 - startpos;
-				dn6 = number6 - startpos;
-				dn7 = number7 - startpos;
-				dn8 = number8 - startpos;
-				//////////////////////////////////////////////////////////////////////////
-				if (isPeriodicCell(para, level, number2, number1, number3, number5))
-					continue;
-				//////////////////////////////////////////////////////////////////////////
-				if (neighborsFluid == true) cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
-				//////////////////////////////////////////////////////////////////////////
-			}
-		}
-		WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
-		//////////////////////////////////////////////////////////////////////////
-	}
+    std::vector< UbTupleFloat3 > nodes;
+    std::vector< UbTupleUInt8 > cells;
+    //std::vector< UbTupleUInt8 > cells2;
+    std::vector< std::string > nodedatanames;
+    nodedatanames.push_back("pressMed");
+    nodedatanames.push_back("rhoMed");
+    nodedatanames.push_back("vx1Med");
+    nodedatanames.push_back("vx2Med");
+    nodedatanames.push_back("vx3Med");
+    nodedatanames.push_back("geo");
+    unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
+    unsigned int dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
+    bool neighborsFluid;
+    unsigned int startpos = 0;
+    unsigned int endpos = 0;
+    unsigned int sizeOfNodes = 0;
+    std::vector< std::vector< double > > nodedata(nodedatanames.size());
+
+    //printf("\n test for if... \n");
+    for (unsigned int part = 0; part < fname.size(); part++)
+    {
+        //printf("\n test in if I... \n");
+        //////////////////////////////////////////////////////////////////////////
+        if (((part + 1)*para->getlimitOfNodesForVTK()) > para->getParH(level)->size_Mat_SP)
+        {
+            sizeOfNodes = para->getParH(level)->size_Mat_SP - (part * para->getlimitOfNodesForVTK());
+        }
+        else
+        {
+            sizeOfNodes = para->getlimitOfNodesForVTK();
+        }
+        //////////////////////////////////////////////////////////////////////////
+        startpos = part * para->getlimitOfNodesForVTK();
+        endpos = startpos + sizeOfNodes;
+        //////////////////////////////////////////////////////////////////////////
+        cells.clear();
+        nodes.resize(sizeOfNodes);
+        nodedata[0].resize(sizeOfNodes);
+        nodedata[1].resize(sizeOfNodes);
+        nodedata[2].resize(sizeOfNodes);
+        nodedata[3].resize(sizeOfNodes);
+        nodedata[4].resize(sizeOfNodes);
+        nodedata[5].resize(sizeOfNodes);
+        //////////////////////////////////////////////////////////////////////////
+        //printf("\n test in if II... \n");
+        for (unsigned int pos = startpos; pos < endpos; pos++)
+        {
+            if (para->getParH(level)->geoSP[pos] == GEO_FLUID)
+            {
+                //////////////////////////////////////////////////////////////////////////
+                double x1 = para->getParH(level)->coordX_SP[pos];
+                double x2 = para->getParH(level)->coordY_SP[pos];
+                double x3 = para->getParH(level)->coordZ_SP[pos];
+                //////////////////////////////////////////////////////////////////////////
+                number1 = pos;
+                dn1 = pos - startpos;
+                neighborsFluid = true;
+                //////////////////////////////////////////////////////////////////////////
+                nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+                nodedata[0][dn1] = para->getParH(level)->press_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
+                nodedata[1][dn1] = para->getParH(level)->rho_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
+                nodedata[2][dn1] = para->getParH(level)->vx_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodedata[3][dn1] = para->getParH(level)->vy_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodedata[4][dn1] = para->getParH(level)->vz_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodedata[5][dn1] = (double)para->getParH(level)->geoSP[pos];
+                //////////////////////////////////////////////////////////////////////////
+                number2 = para->getParH(level)->neighborX_SP[number1];
+                number3 = para->getParH(level)->neighborY_SP[number2];
+                number4 = para->getParH(level)->neighborY_SP[number1];
+                number5 = para->getParH(level)->neighborZ_SP[number1];
+                number6 = para->getParH(level)->neighborZ_SP[number2];
+                number7 = para->getParH(level)->neighborZ_SP[number3];
+                number8 = para->getParH(level)->neighborZ_SP[number4];
+                //////////////////////////////////////////////////////////////////////////
+                if (para->getParH(level)->geoSP[number2] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number3] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number4] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number5] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number6] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number7] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number8] != GEO_FLUID)  neighborsFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                if (number2 > endpos ||
+                    number3 > endpos ||
+                    number4 > endpos ||
+                    number5 > endpos ||
+                    number6 > endpos ||
+                    number7 > endpos ||
+                    number8 > endpos)  neighborsFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                dn2 = number2 - startpos;
+                dn3 = number3 - startpos;
+                dn4 = number4 - startpos;
+                dn5 = number5 - startpos;
+                dn6 = number6 - startpos;
+                dn7 = number7 - startpos;
+                dn8 = number8 - startpos;
+                //////////////////////////////////////////////////////////////////////////
+                if (isPeriodicCell(para, level, number2, number1, number3, number5))
+                    continue;
+                //////////////////////////////////////////////////////////////////////////
+                if (neighborsFluid == true) cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
+                //////////////////////////////////////////////////////////////////////////
+            }
+        }
+        WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
+        //////////////////////////////////////////////////////////////////////////
+    }
 }
 
 void FileWriter::writeUnstrucuredGridMedianLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
 {
-	std::vector< UbTupleFloat3 > nodes;
-	std::vector< UbTupleUInt8 > cells;
-	std::vector< std::string > nodedatanames;
-	nodedatanames.push_back("concMed");
-	nodedatanames.push_back("pressMed");
-	nodedatanames.push_back("rhoMed");
-	nodedatanames.push_back("vx1Med");
-	nodedatanames.push_back("vx2Med");
-	nodedatanames.push_back("vx3Med");
-	nodedatanames.push_back("geo");
-	uint number1, number2, number3, number4, number5, number6, number7, number8;
-	uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
-	bool neighborsFluid;
-	uint startpos = 0;
-	uint endpos = 0;
-	uint sizeOfNodes = 0;
-	std::vector< std::vector< double > > nodedata(nodedatanames.size());
-
-	for (unsigned int part = 0; part < fname.size(); part++)
-	{
-		if (((part + 1)*para->getlimitOfNodesForVTK()) > para->getParH(level)->size_Mat_SP)
-			sizeOfNodes = para->getParH(level)->size_Mat_SP - (part * para->getlimitOfNodesForVTK());
-		else
-			sizeOfNodes = para->getlimitOfNodesForVTK();
-		//////////////////////////////////////////////////////////////////////////
-		startpos = part * para->getlimitOfNodesForVTK();
-		endpos = startpos + sizeOfNodes;
-		//////////////////////////////////////////////////////////////////////////
-		cells.clear();
-		nodes.resize(sizeOfNodes);
-		nodedata[0].resize(sizeOfNodes);
-		nodedata[1].resize(sizeOfNodes);
-		nodedata[2].resize(sizeOfNodes);
-		nodedata[3].resize(sizeOfNodes);
-		nodedata[4].resize(sizeOfNodes);
-		nodedata[5].resize(sizeOfNodes);
-		nodedata[6].resize(sizeOfNodes);
-		//////////////////////////////////////////////////////////////////////////
-		for (unsigned int pos = startpos; pos < endpos; pos++)
-		{
-			if (para->getParH(level)->geoSP[pos] == GEO_FLUID)
-			{
-				//////////////////////////////////////////////////////////////////////////
-				double x1 = para->getParH(level)->coordX_SP[pos];
-				double x2 = para->getParH(level)->coordY_SP[pos];
-				double x3 = para->getParH(level)->coordZ_SP[pos];
-				//////////////////////////////////////////////////////////////////////////
-				number1 = pos;
-				dn1 = pos - startpos;
-				neighborsFluid = true;
-				//////////////////////////////////////////////////////////////////////////
-				nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
-				nodedata[0][dn1] = (double)para->getParH(level)->Conc_Med_Out[pos];
-				nodedata[1][dn1] = (double)para->getParH(level)->press_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-				nodedata[2][dn1] = (double)para->getParH(level)->rho_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-				nodedata[3][dn1] = (double)para->getParH(level)->vx_SP_Med_Out[pos] * para->getVelocityRatio();
-				nodedata[4][dn1] = (double)para->getParH(level)->vy_SP_Med_Out[pos] * para->getVelocityRatio();
-				nodedata[5][dn1] = (double)para->getParH(level)->vz_SP_Med_Out[pos] * para->getVelocityRatio();
-				nodedata[6][dn1] = (double)para->getParH(level)->geoSP[pos];
-				//////////////////////////////////////////////////////////////////////////
-				number2 = para->getParH(level)->neighborX_SP[number1];
-				number3 = para->getParH(level)->neighborY_SP[number2];
-				number4 = para->getParH(level)->neighborY_SP[number1];
-				number5 = para->getParH(level)->neighborZ_SP[number1];
-				number6 = para->getParH(level)->neighborZ_SP[number2];
-				number7 = para->getParH(level)->neighborZ_SP[number3];
-				number8 = para->getParH(level)->neighborZ_SP[number4];
-				//////////////////////////////////////////////////////////////////////////
-				if (para->getParH(level)->geoSP[number2] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number3] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number4] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number5] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number6] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number7] != GEO_FLUID ||
-					para->getParH(level)->geoSP[number8] != GEO_FLUID)  neighborsFluid = false;
-				//////////////////////////////////////////////////////////////////////////
-				if (number2 > endpos ||
-					number3 > endpos ||
-					number4 > endpos ||
-					number5 > endpos ||
-					number6 > endpos ||
-					number7 > endpos ||
-					number8 > endpos)  neighborsFluid = false;
-				//////////////////////////////////////////////////////////////////////////
-				dn2 = number2 - startpos;
-				dn3 = number3 - startpos;
-				dn4 = number4 - startpos;
-				dn5 = number5 - startpos;
-				dn6 = number6 - startpos;
-				dn7 = number7 - startpos;
-				dn8 = number8 - startpos;
-				//////////////////////////////////////////////////////////////////////////
-				if (isPeriodicCell(para, level, number2, number1, number3, number5))
-					continue;
-				//////////////////////////////////////////////////////////////////////////
-				if (neighborsFluid) 
-					cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
-				//////////////////////////////////////////////////////////////////////////
-			}
-		}
-		WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
-		//////////////////////////////////////////////////////////////////////////
-	}
+    std::vector< UbTupleFloat3 > nodes;
+    std::vector< UbTupleUInt8 > cells;
+    std::vector< std::string > nodedatanames;
+    nodedatanames.push_back("concMed");
+    nodedatanames.push_back("pressMed");
+    nodedatanames.push_back("rhoMed");
+    nodedatanames.push_back("vx1Med");
+    nodedatanames.push_back("vx2Med");
+    nodedatanames.push_back("vx3Med");
+    nodedatanames.push_back("geo");
+    uint number1, number2, number3, number4, number5, number6, number7, number8;
+    uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
+    bool neighborsFluid;
+    uint startpos = 0;
+    uint endpos = 0;
+    uint sizeOfNodes = 0;
+    std::vector< std::vector< double > > nodedata(nodedatanames.size());
+
+    for (unsigned int part = 0; part < fname.size(); part++)
+    {
+        if (((part + 1)*para->getlimitOfNodesForVTK()) > para->getParH(level)->size_Mat_SP)
+            sizeOfNodes = para->getParH(level)->size_Mat_SP - (part * para->getlimitOfNodesForVTK());
+        else
+            sizeOfNodes = para->getlimitOfNodesForVTK();
+        //////////////////////////////////////////////////////////////////////////
+        startpos = part * para->getlimitOfNodesForVTK();
+        endpos = startpos + sizeOfNodes;
+        //////////////////////////////////////////////////////////////////////////
+        cells.clear();
+        nodes.resize(sizeOfNodes);
+        nodedata[0].resize(sizeOfNodes);
+        nodedata[1].resize(sizeOfNodes);
+        nodedata[2].resize(sizeOfNodes);
+        nodedata[3].resize(sizeOfNodes);
+        nodedata[4].resize(sizeOfNodes);
+        nodedata[5].resize(sizeOfNodes);
+        nodedata[6].resize(sizeOfNodes);
+        //////////////////////////////////////////////////////////////////////////
+        for (unsigned int pos = startpos; pos < endpos; pos++)
+        {
+            if (para->getParH(level)->geoSP[pos] == GEO_FLUID)
+            {
+                //////////////////////////////////////////////////////////////////////////
+                double x1 = para->getParH(level)->coordX_SP[pos];
+                double x2 = para->getParH(level)->coordY_SP[pos];
+                double x3 = para->getParH(level)->coordZ_SP[pos];
+                //////////////////////////////////////////////////////////////////////////
+                number1 = pos;
+                dn1 = pos - startpos;
+                neighborsFluid = true;
+                //////////////////////////////////////////////////////////////////////////
+                nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+                nodedata[0][dn1] = (double)para->getParH(level)->Conc_Med_Out[pos];
+                nodedata[1][dn1] = (double)para->getParH(level)->press_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
+                nodedata[2][dn1] = (double)para->getParH(level)->rho_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
+                nodedata[3][dn1] = (double)para->getParH(level)->vx_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodedata[4][dn1] = (double)para->getParH(level)->vy_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodedata[5][dn1] = (double)para->getParH(level)->vz_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodedata[6][dn1] = (double)para->getParH(level)->geoSP[pos];
+                //////////////////////////////////////////////////////////////////////////
+                number2 = para->getParH(level)->neighborX_SP[number1];
+                number3 = para->getParH(level)->neighborY_SP[number2];
+                number4 = para->getParH(level)->neighborY_SP[number1];
+                number5 = para->getParH(level)->neighborZ_SP[number1];
+                number6 = para->getParH(level)->neighborZ_SP[number2];
+                number7 = para->getParH(level)->neighborZ_SP[number3];
+                number8 = para->getParH(level)->neighborZ_SP[number4];
+                //////////////////////////////////////////////////////////////////////////
+                if (para->getParH(level)->geoSP[number2] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number3] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number4] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number5] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number6] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number7] != GEO_FLUID ||
+                    para->getParH(level)->geoSP[number8] != GEO_FLUID)  neighborsFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                if (number2 > endpos ||
+                    number3 > endpos ||
+                    number4 > endpos ||
+                    number5 > endpos ||
+                    number6 > endpos ||
+                    number7 > endpos ||
+                    number8 > endpos)  neighborsFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                dn2 = number2 - startpos;
+                dn3 = number3 - startpos;
+                dn4 = number4 - startpos;
+                dn5 = number5 - startpos;
+                dn6 = number6 - startpos;
+                dn7 = number7 - startpos;
+                dn8 = number8 - startpos;
+                //////////////////////////////////////////////////////////////////////////
+                if (isPeriodicCell(para, level, number2, number1, number3, number5))
+                    continue;
+                //////////////////////////////////////////////////////////////////////////
+                if (neighborsFluid) 
+                    cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
+                //////////////////////////////////////////////////////////////////////////
+            }
+        }
+        WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
+        //////////////////////////////////////////////////////////////////////////
+    }
 }
 //////////////////////////////////////////////////////////////////////////
 
diff --git a/src/gpu/VirtualFluids_GPU/Output/FileWriter.h b/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
index 99c82cbd70aeda67fb92bf0de7ff37e346ccaf11..f0983b8987d85a21668d801e4b8c7260e118adf1 100644
--- a/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
+++ b/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
@@ -26,11 +26,6 @@ private:
 	//void VIRTUALFLUIDS_GPU_EXPORT writeParticle(Parameter* para, unsigned int t);
     void VIRTUALFLUIDS_GPU_EXPORT writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int level,
                                                          std::vector<std::string> &fname);
-    void testForSendNodeY(std::shared_ptr<Parameter> &para, int level, unsigned int pos, int &sendNode);
-    void testForSendNodeZ(std::shared_ptr<Parameter> &para, int level, unsigned int pos, int &sendNode);
-    void testForCommunicationNode(std::shared_ptr<Parameter> &para, int level, unsigned int pos, int &sendNode,
-                                  std::vector<PN27> *sendOrRecvProcessNeighbor,
-                                  std::vector<PN27> *sendOrRecvProcessNeighborAfterFtoC);
 	void VIRTUALFLUIDS_GPU_EXPORT writeUnstrucuredGridLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname);
 	void VIRTUALFLUIDS_GPU_EXPORT writeUnstrucuredGridMedianLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname);
 	void VIRTUALFLUIDS_GPU_EXPORT writeUnstrucuredGridMedianLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname);
diff --git a/src/gpu/VirtualFluids_GPU/Output/InterfaceDebugWriter.hpp b/src/gpu/VirtualFluids_GPU/Output/InterfaceDebugWriter.hpp
index 8d1337be8088f3daa55f03fc5fcf1e405c8d0b3d..26fc6851842ba20b73feb8efae29768fa1a47e9e 100644
--- a/src/gpu/VirtualFluids_GPU/Output/InterfaceDebugWriter.hpp
+++ b/src/gpu/VirtualFluids_GPU/Output/InterfaceDebugWriter.hpp
@@ -1,604 +1,911 @@
 #ifndef INTERFACEDEBUG_HPP
 #define INTERFACEDEBUG_HPP
 
-#include <stdio.h>
 #include <fstream>
 #include <sstream>
+#include <stdio.h>
 // #include <math.h>
-#include <cmath>
-#include "LBM/LB.h"
+#include "Core/StringUtilities/StringUtil.h"
 #include "LBM/D3Q27.h"
+#include "LBM/LB.h"
 #include "Parameter/Parameter.h"
 #include "basics/utilities/UbSystem.h"
-#include "Core/StringUtilities/StringUtil.h"
 #include <basics/writer/WbWriterVtkXmlBinary.h>
+#include <cmath>
 
-
-//using namespace std;
+#include "VirtualFluids_GPU/Communication/Communicator.h"
 
 namespace InterfaceDebugWriter
 {
 
-    void writeGridInterfaceLines(Parameter* para, int level, const uint* coarse, const uint* fine, uint numberOfNodes, const std::string& name)
+void writeGridInterfaceLines(Parameter *para, int level, const uint *coarse, const uint *fine, uint numberOfNodes,
+                             const std::string &name)
+{
+    std::vector<UbTupleFloat3> nodes(numberOfNodes * 2);
+    std::vector<UbTupleInt2> cells(numberOfNodes);
+
+    int actualNodeNumber = 0;
+    for (uint u = 0; u < numberOfNodes; u++) {
+        const int posCoarse   = coarse[u];
+        const double x1Coarse = para->getParH(level)->coordX_SP[posCoarse];
+        const double x2Coarse = para->getParH(level)->coordY_SP[posCoarse];
+        const double x3Coarse = para->getParH(level)->coordZ_SP[posCoarse];
+
+        const int posFine   = fine[u];
+        const double x1Fine = para->getParH(level + 1)->coordX_SP[posFine];
+        const double x2Fine = para->getParH(level + 1)->coordY_SP[posFine];
+        const double x3Fine = para->getParH(level + 1)->coordZ_SP[posFine];
+
+        nodes[actualNodeNumber++] = makeUbTuple(float(x1Coarse), float(x2Coarse), float(x3Coarse));
+        nodes[actualNodeNumber++] = makeUbTuple(float(x1Fine), float(x2Fine), float(x3Fine));
+
+        cells[u] = makeUbTuple(actualNodeNumber - 2, actualNodeNumber - 1);
+    }
+    WbWriterVtkXmlBinary::getInstance()->writeLines(name, nodes, cells);
+}
+
+void writeInterfaceLinesDebugCF(Parameter *para)
+{
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        const std::string fileName = para->getFName() + "_" + StringUtil::toString<int>(level) + "_OffDebugCF.vtk";
+        writeGridInterfaceLines(para, level, para->getParH(level)->intCF.ICellCFC, para->getParH(level)->intCF.ICellCFF,
+                                para->getParH(level)->K_CF, fileName);
+    }
+}
+
+void writeInterfaceLinesDebugFC(Parameter *para)
+{
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        const std::string fileName = para->getFName() + "_" + StringUtil::toString<int>(level) + "_OffDebugFC.vtk";
+        writeGridInterfaceLines(para, level, para->getParH(level)->intFC.ICellFCC, para->getParH(level)->intFC.ICellFCF,
+                                para->getParH(level)->K_FC, fileName);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void writeGridInterfaceLinesNeighbors(Parameter *para, int level, const uint *interfaceIndices, uint numberOfNodes,
+                                      const std::string &name)
+{
+    std::vector<UbTupleFloat3> nodes(numberOfNodes * 2);
+    std::vector<UbTupleInt2> cells(numberOfNodes);
+
+    int actualNodeNumber = 0;
+    for (uint u = 0; u < numberOfNodes; u++) {
+        const int pos   = interfaceIndices[u];
+        const double x1 = para->getParH(level)->coordX_SP[pos];
+        const double x2 = para->getParH(level)->coordY_SP[pos];
+        const double x3 = para->getParH(level)->coordZ_SP[pos];
+
+        const double x1Neighbor = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[pos]];
+        const double x2Neighbor = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[pos]];
+        const double x3Neighbor = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[pos]];
+
+        nodes[actualNodeNumber++] = (makeUbTuple(float(x1), float(x2), float(x3)));
+        nodes[actualNodeNumber++] = (makeUbTuple(float(x1Neighbor), float(x2Neighbor), float(x3Neighbor)));
+
+        cells[u] = makeUbTuple(actualNodeNumber - 2, actualNodeNumber - 1);
+    }
+    WbWriterVtkXmlBinary::getInstance()->writeLines(name, nodes, cells);
+}
+
+void writeInterfaceLinesDebugCFCneighbor(Parameter *para)
+{
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_CFCneighbor.vtk";
+        writeGridInterfaceLinesNeighbors(para, level, para->getParH(level)->intCF.ICellCFC, para->getParH(level)->K_CF,
+                                         filename);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void writeInterfaceLinesDebugCFFneighbor(Parameter *para)
+{
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_CFFneighbor.vtk";
+        writeGridInterfaceLinesNeighbors(para, level + 1, para->getParH(level)->intCF.ICellCFF,
+                                         para->getParH(level)->K_CF, filename);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void writeInterfaceLinesDebugFCCneighbor(Parameter *para)
+{
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_FCCneighbor.vtk";
+        writeGridInterfaceLinesNeighbors(para, level, para->getParH(level)->intFC.ICellFCC, para->getParH(level)->K_FC,
+                                         filename);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void writeInterfaceLinesDebugFCFneighbor(Parameter *para)
+{
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_FCFneighbor.vtk";
+        writeGridInterfaceLinesNeighbors(para, level + 1, para->getParH(level)->intFC.ICellFCF,
+                                         para->getParH(level)->K_FC, filename);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void writeInterfaceLinesDebugOff(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<UbTupleInt2> cellsVec;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level < para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-        std::vector<UbTupleFloat3> nodes(numberOfNodes * 2);
-        std::vector<UbTupleInt2> cells(numberOfNodes);
-
-        int actualNodeNumber = 0;
-        for (uint u = 0; u < numberOfNodes; u++)
-        {
-            const int posCoarse = coarse[u];
-            const double x1Coarse = para->getParH(level)->coordX_SP[posCoarse];
-            const double x2Coarse = para->getParH(level)->coordY_SP[posCoarse];
-            const double x3Coarse = para->getParH(level)->coordZ_SP[posCoarse];
-
-            const int posFine = fine[u];
-            const double x1Fine = para->getParH(level + 1)->coordX_SP[posFine];
-            const double x2Fine = para->getParH(level + 1)->coordY_SP[posFine];
-            const double x3Fine = para->getParH(level + 1)->coordZ_SP[posFine];
-
-            nodes[actualNodeNumber++] = makeUbTuple(float(x1Coarse), float(x2Coarse), float(x3Coarse));
-            nodes[actualNodeNumber++] = makeUbTuple(float(x1Fine), float(x2Fine), float(x3Fine));
-
-            cells[u] = makeUbTuple(actualNodeNumber - 2, actualNodeNumber - 1);
+        nodeNumberVec += (int)para->getParH(level)->K_CF;
+    }
+    nodesVec.resize(nodeNumberVec * 8);
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->K_CF; u++) {
+            double xoff = para->getParH(level)->offCF.xOffCF[u];
+            double yoff = para->getParH(level)->offCF.yOffCF[u];
+            double zoff = para->getParH(level)->offCF.zOffCF[u];
+
+            int posFine = para->getParH(level)->intCF.ICellCFF[u];
+
+            double x1Fine = para->getParH(level + 1)->coordX_SP[posFine];
+            double x2Fine = para->getParH(level + 1)->coordY_SP[posFine];
+            double x3Fine = para->getParH(level + 1)->coordZ_SP[posFine];
+
+            double x1 = x1Fine + xoff;
+            double x2 = x2Fine + yoff;
+            double x3 = x3Fine + zoff;
+
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1Fine), (float)(x2Fine), (float)(x3Fine)));
+
+            cellsVec.push_back(makeUbTuple(nodeCount - 2, nodeCount - 1));
+        }
+        std::string filenameVec = para->getFName() + "_" + StringUtil::toString<int>(level) + "_OffDebugCF_Offs.vtk";
+        WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec, nodesVec, cellsVec);
+        cellsVec.clear();
+        nodesVec.clear();
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void writeInterfacePointsDebugCFC(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec2;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level < para->getMaxLevel(); level++) // evtl. Maxlevel + 1
+    {
+        nodeNumberVec += (int)para->getParH(level)->K_CF;
+    }
+    nodesVec2.resize(nodeNumberVec * 8);
+    int nodeCount2 = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->K_CF; u++) {
+            int pos = para->getParH(level)->intCF.ICellCFC[u];
+
+            double x1 = para->getParH(level)->coordX_SP[pos];
+            double x2 = para->getParH(level)->coordY_SP[pos];
+            double x3 = para->getParH(level)->coordZ_SP[pos];
+
+            nodesVec2[nodeCount2++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
         }
-        WbWriterVtkXmlBinary::getInstance()->writeLines(name, nodes, cells);
+        std::string filenameVec2 = para->getFName() + "_" + StringUtil::toString<int>(level) + "_OffDebugPointsCF.vtk";
+        WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec2, nodesVec2);
     }
+}
 
+//////////////////////////////////////////////////////////////////////////
 
-    void writeInterfaceLinesDebugCF(Parameter* para)
+void writeBcPointsDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec2;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level <= para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-            const std::string fileName = para->getFName() + "_" + StringUtil::toString<int>(level) + "_OffDebugCF.vtk";
-            writeGridInterfaceLines(para, level, para->getParH(level)->intCF.ICellCFC, para->getParH(level)->intCF.ICellCFF, para->getParH(level)->K_CF, fileName);
-		}
-	}
+        nodeNumberVec += (int)para->getParH(level)->QWall.kQ;
+    }
+    nodesVec2.resize(nodeNumberVec * 8);
+    int nodeCount2 = 0;
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        for (int u = 0; u < para->getParH(level)->QWall.kQ; u++) {
+            int pos = para->getParH(level)->QWall.k[u];
+
+            double x1 = para->getParH(level)->coordX_SP[pos];
+            double x2 = para->getParH(level)->coordY_SP[pos];
+            double x3 = para->getParH(level)->coordZ_SP[pos];
 
+            nodesVec2[nodeCount2++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+        }
+        std::string filenameVec2 = para->getFName() + "_PointsBc_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec2, nodesVec2);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void writePressPointsDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    int nodeNumberVec = 0;
 
-	void writeInterfaceLinesDebugFC(Parameter* para)
+    for (int level = 0; level <= para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-        for (int level = 0; level < para->getMaxLevel(); level++)
-        {
-            const std::string fileName = para->getFName() + "_" + StringUtil::toString<int>(level) + "_OffDebugFC.vtk";
-            writeGridInterfaceLines(para, level, para->getParH(level)->intFC.ICellFCC, para->getParH(level)->intFC.ICellFCF, para->getParH(level)->K_FC, fileName);
+        nodeNumberVec += (int)para->getParH(level)->QPress.kQ;
+    }
+    nodesVec.resize(nodeNumberVec);
+    int nodeCount2 = 0;
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        for (int u = 0; u < para->getParH(level)->QPress.kQ; u++) {
+            int pos = para->getParH(level)->QPress.k[u];
+
+            double x1 = para->getParH(level)->coordX_SP[pos];
+            double x2 = para->getParH(level)->coordY_SP[pos];
+            double x3 = para->getParH(level)->coordZ_SP[pos];
+
+            nodesVec[nodeCount2++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+        }
+        std::string filenameVec = para->getFName() + "_PointsPress_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec, nodesVec);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void writePressNeighborPointsDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        nodeNumberVec += (int)para->getParH(level)->QPress.kQ;
+    }
+    nodesVec.resize(nodeNumberVec);
+    int nodeCount2 = 0;
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        for (int u = 0; u < para->getParH(level)->QPress.kQ; u++) {
+            int pos = para->getParH(level)->QPress.kN[u];
+
+            real x1 = para->getParH(level)->coordX_SP[pos];
+            real x2 = para->getParH(level)->coordY_SP[pos];
+            real x3 = para->getParH(level)->coordZ_SP[pos];
+
+            nodesVec[nodeCount2++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
         }
-	}
+        std::string filenameVec = para->getFName() + "_PointsPressNeighbor_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec, nodesVec);
+    }
+}
 
+//////////////////////////////////////////////////////////////////////////
+
+void writeNeighborXPointsDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    int nodeNumberVec = 0;
 
-	//////////////////////////////////////////////////////////////////////////
-    void writeGridInterfaceLinesNeighbors(Parameter* para, int level, const uint* interfaceIndices, uint numberOfNodes, const std::string& name)
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
+    }
+    nodesVec.resize(nodeNumberVec);
+    int nodeCount2 = 0;
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->size_Mat_SP; u++) {
+            real x1 = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[u]];
+            real x2 = para->getParH(level)->coordY_SP[para->getParH(level)->neighborX_SP[u]];
+            real x3 = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborX_SP[u]];
+
+            nodesVec[nodeCount2++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+        }
+        std::string filenameVec = para->getFName() + "_PointsNeighborX_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec, nodesVec);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void writeNeighborXLinesDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<UbTupleInt2> cellsVec;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level < para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-        std::vector<UbTupleFloat3> nodes(numberOfNodes * 2);
-        std::vector<UbTupleInt2> cells(numberOfNodes);
-
-        int actualNodeNumber = 0;
-        for (uint u = 0; u < numberOfNodes; u++)
-        {
-            const int pos = interfaceIndices[u];
-            const double x1 = para->getParH(level)->coordX_SP[pos];
-            const double x2 = para->getParH(level)->coordY_SP[pos];
-            const double x3 = para->getParH(level)->coordZ_SP[pos];
-	
-            const double x1Neighbor = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[pos]];
-            const double x2Neighbor = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[pos]];
-            const double x3Neighbor = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[pos]];
-
-            nodes[actualNodeNumber++] = (makeUbTuple(float(x1), float(x2), float(x3)));
-            nodes[actualNodeNumber++] = (makeUbTuple(float(x1Neighbor), float(x2Neighbor), float(x3Neighbor)));
-
-            cells[u] = makeUbTuple(actualNodeNumber - 2, actualNodeNumber - 1);
+        nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
+    }
+    nodesVec.resize(nodeNumberVec * 2);
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->size_Mat_SP; u++) {
+            real x1  = para->getParH(level)->coordX_SP[u];
+            real x2  = para->getParH(level)->coordY_SP[u];
+            real x3  = para->getParH(level)->coordZ_SP[u];
+            real x1N = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[u]];
+            real x2N = para->getParH(level)->coordY_SP[para->getParH(level)->neighborX_SP[u]];
+            real x3N = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborX_SP[u]];
+
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1N), (float)(x2N), (float)(x3N)));
+
+            if (para->getParH(level)->geoSP[u] == GEO_FLUID) {
+                cellsVec.push_back(makeUbTuple(nodeCount - 2, nodeCount - 1));
+            }
         }
-        WbWriterVtkXmlBinary::getInstance()->writeLines(name, nodes, cells);
+        std::string filenameVec = para->getFName() + "_" + StringUtil::toString<int>(level) + "_NeighborX_Lines.vtk";
+        WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec, nodesVec, cellsVec);
     }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void writeNeighborYPointsDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
+    }
+    nodesVec.resize(nodeNumberVec);
+    int nodeCount2 = 0;
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->size_Mat_SP; u++) {
+            real x1 = para->getParH(level)->coordX_SP[para->getParH(level)->neighborY_SP[u]];
+            real x2 = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[u]];
+            real x3 = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborY_SP[u]];
+
+            nodesVec[nodeCount2++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+        }
+        std::string filenameVec = para->getFName() + "_PointsNeighborY_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec, nodesVec);
+    }
+}
 
-	void writeInterfaceLinesDebugCFCneighbor(Parameter* para)
+//////////////////////////////////////////////////////////////////////////
+
+void writeNeighborYLinesDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<UbTupleInt2> cellsVec;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level < para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-            std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_CFCneighbor.vtk";
-            writeGridInterfaceLinesNeighbors(para, level, para->getParH(level)->intCF.ICellCFC, para->getParH(level)->K_CF, filename);
-		}
-	}
+        nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
+    }
+    nodesVec.resize(nodeNumberVec * 2);
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->size_Mat_SP; u++) {
+            real x1  = para->getParH(level)->coordX_SP[u];
+            real x2  = para->getParH(level)->coordY_SP[u];
+            real x3  = para->getParH(level)->coordZ_SP[u];
+            real x1N = para->getParH(level)->coordX_SP[para->getParH(level)->neighborY_SP[u]];
+            real x2N = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[u]];
+            real x3N = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborY_SP[u]];
+
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1N), (float)(x2N), (float)(x3N)));
+
+            if (para->getParH(level)->geoSP[u] == GEO_FLUID) {
+                cellsVec.push_back(makeUbTuple(nodeCount - 2, nodeCount - 1));
+            }
+        }
+        std::string filenameVec = para->getFName() + "_" + StringUtil::toString<int>(level) + "_NeighborY_Lines.vtk";
+        WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec, nodesVec, cellsVec);
+    }
+}
 
+//////////////////////////////////////////////////////////////////////////
+
+void writeNeighborZPointsDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    int nodeNumberVec = 0;
 
-	//////////////////////////////////////////////////////////////////////////
-	void writeInterfaceLinesDebugCFFneighbor(Parameter* para)
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
+    }
+    nodesVec.resize(nodeNumberVec);
+    int nodeCount2 = 0;
+    for (int level = 0; level <= para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->size_Mat_SP; u++) {
+            real x1 = para->getParH(level)->coordX_SP[para->getParH(level)->neighborZ_SP[u]];
+            real x2 = para->getParH(level)->coordY_SP[para->getParH(level)->neighborZ_SP[u]];
+            real x3 = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[u]];
+
+            nodesVec[nodeCount2++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+        }
+        std::string filenameVec = para->getFName() + "_PointsNeighborZ_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec, nodesVec);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void writeNeighborZLinesDebug(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<UbTupleInt2> cellsVec;
+    int nodeNumberVec = 0;
+
+    for (int level = 0; level < para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-        for (int level = 0; level < para->getMaxLevel(); level++)
-        {
-            std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_CFFneighbor.vtk";
-            writeGridInterfaceLinesNeighbors(para, level + 1, para->getParH(level)->intCF.ICellCFF, para->getParH(level)->K_CF, filename);
+        nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
+    }
+    nodesVec.resize(nodeNumberVec * 2);
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->size_Mat_SP; u++) {
+            real x1  = para->getParH(level)->coordX_SP[u];
+            real x2  = para->getParH(level)->coordY_SP[u];
+            real x3  = para->getParH(level)->coordZ_SP[u];
+            real x1N = para->getParH(level)->coordX_SP[para->getParH(level)->neighborZ_SP[u]];
+            real x2N = para->getParH(level)->coordY_SP[para->getParH(level)->neighborZ_SP[u]];
+            real x3N = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[u]];
+
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1N), (float)(x2N), (float)(x3N)));
+
+            if (para->getParH(level)->geoSP[u] == GEO_FLUID) {
+                cellsVec.push_back(makeUbTuple(nodeCount - 2, nodeCount - 1));
+            }
         }
-	}
+        std::string filenameVec = para->getFName() + "_" + StringUtil::toString<int>(level) + "_NeighborZ_Lines.vtk";
+        WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec, nodesVec, cellsVec);
+    }
+}
 
+//////////////////////////////////////////////////////////////////////////
+
+void writeInterfaceCellsDebugCFC(Parameter *para)
+{
 
-	//////////////////////////////////////////////////////////////////////////
-	void writeInterfaceLinesDebugFCCneighbor(Parameter* para)
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<UbTupleInt8> cellsVec;
+    int nodeNumberVec = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-        for (int level = 0; level < para->getMaxLevel(); level++)
-        {
-            std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_FCCneighbor.vtk";
-            writeGridInterfaceLinesNeighbors(para, level, para->getParH(level)->intFC.ICellFCC, para->getParH(level)->K_FC, filename);
+        nodeNumberVec += (int)para->getParH(level)->K_CF;
+    }
+    nodesVec.resize(nodeNumberVec * 8);
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->K_CF; u++) {
+            int pos = para->getParH(level)->intCF.ICellCFC[u];
+
+            double x1             = para->getParH(level)->coordX_SP[pos];
+            double x2             = para->getParH(level)->coordY_SP[pos];
+            double x3             = para->getParH(level)->coordZ_SP[pos];
+            double x1P            = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[pos]];
+            double x2P            = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[pos]];
+            double x3P            = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[pos]];
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2P), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2P), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3P)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2), (float)(x3P)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2P), (float)(x3P)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2P), (float)(x3P)));
+
+            cellsVec.push_back(makeUbTuple(nodeCount - 8, nodeCount - 7, nodeCount - 6, nodeCount - 5, nodeCount - 4,
+                                           nodeCount - 3, nodeCount - 2, nodeCount - 1));
         }
-	}
+        std::string filenameVec = para->getFName() + "_CellsCFC_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeOcts(filenameVec, nodesVec, cellsVec);
+    }
+}
 
+//////////////////////////////////////////////////////////////////////////
 
-	//////////////////////////////////////////////////////////////////////////
-	void writeInterfaceLinesDebugFCFneighbor(Parameter* para)
+void writeInterfaceCellsDebugCFF(Parameter *para)
+{
+
+    std::vector<UbTupleFloat3> nodesVec;
+    std::vector<UbTupleInt8> cellsVec;
+    int nodeNumberVec = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) // evtl. Maxlevel + 1
     {
-        for (int level = 0; level < para->getMaxLevel(); level++)
-        {
-            std::string filename = para->getFName() + "_" + StringUtil::toString<int>(level) + "_FCFneighbor.vtk";
-            writeGridInterfaceLinesNeighbors(para, level + 1, para->getParH(level)->intFC.ICellFCF, para->getParH(level)->K_FC, filename);
+        nodeNumberVec += (int)para->getParH(level)->K_CF;
+    }
+    nodesVec.resize(nodeNumberVec * 8);
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->K_CF; u++) {
+            int pos = para->getParH(level)->intCF.ICellCFF[u];
+
+            double x1             = para->getParH(level + 1)->coordX_SP[pos];
+            double x2             = para->getParH(level + 1)->coordY_SP[pos];
+            double x3             = para->getParH(level + 1)->coordZ_SP[pos];
+            double x1P            = para->getParH(level + 1)->coordX_SP[para->getParH(level + 1)->neighborX_SP[pos]];
+            double x2P            = para->getParH(level + 1)->coordY_SP[para->getParH(level + 1)->neighborY_SP[pos]];
+            double x3P            = para->getParH(level + 1)->coordZ_SP[para->getParH(level + 1)->neighborZ_SP[pos]];
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2P), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2P), (float)(x3)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3P)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2), (float)(x3P)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1P), (float)(x2P), (float)(x3P)));
+            nodesVec[nodeCount++] = (makeUbTuple((float)(x1), (float)(x2P), (float)(x3P)));
+
+            cellsVec.push_back(makeUbTuple(nodeCount - 8, nodeCount - 7, nodeCount - 6, nodeCount - 5, nodeCount - 4,
+                                           nodeCount - 3, nodeCount - 2, nodeCount - 1));
         }
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-	void writeInterfaceLinesDebugOff(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		std::vector< UbTupleInt2 > cellsVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level < para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->K_CF;
-		}
-		nodesVec.resize(nodeNumberVec*8);
-		int nodeCount = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->K_CF;u++)
-			{
-				double xoff = para->getParH(level)->offCF.xOffCF[u];
-				double yoff = para->getParH(level)->offCF.yOffCF[u];
-				double zoff = para->getParH(level)->offCF.zOffCF[u];
+        std::string filenameVec = para->getFName() + "_CellsCFF_" + StringUtil::toString<int>(level);
+        WbWriterVtkXmlBinary::getInstance()->writeOcts(filenameVec, nodesVec, cellsVec);
+    }
+}
+
 
-				int posFine = para->getParH(level)->intCF.ICellCFF[u];
-
-				double x1Fine = para->getParH(level+1)->coordX_SP[posFine];
-				double x2Fine = para->getParH(level+1)->coordY_SP[posFine];
-				double x3Fine = para->getParH(level+1)->coordZ_SP[posFine];
-
-				double x1 = x1Fine + xoff;
-				double x2 = x2Fine + yoff;
-				double x3 = x3Fine + zoff;
-
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1Fine),(float)(x2Fine),(float)(x3Fine) ) );
-
-				cellsVec.push_back( makeUbTuple(nodeCount-2,nodeCount-1) );
-
-			}
-			std::string filenameVec = para->getFName()+"_"+StringUtil::toString<int>(level)+"_OffDebugCF_Offs.vtk";
-			WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec,nodesVec,cellsVec);
-            cellsVec.clear();
-            nodesVec.clear();
-		}
-	}
 
 
-	//////////////////////////////////////////////////////////////////////////
 
 
-	void writeInterfacePointsDebugCFC(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec2;
-		int nodeNumberVec = 0;
 
-		for (int level = 0; level < para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->K_CF;
-		}
-		nodesVec2.resize(nodeNumberVec*8); 
-		int nodeCount2 = 0; 
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->K_CF;u++)
-			{
-				int pos = para->getParH(level)->intCF.ICellCFC[u];
-
-				double x1 = para->getParH(level)->coordX_SP[pos];
-				double x2 = para->getParH(level)->coordY_SP[pos];
-				double x3 = para->getParH(level)->coordZ_SP[pos];
-
-				nodesVec2[nodeCount2++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-
-			}
-			std::string filenameVec2 = para->getFName()+"_"+StringUtil::toString<int>(level)+"_OffDebugPointsCF.vtk";
-			WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec2,nodesVec2);
-		}
-	}
 
 
-	//////////////////////////////////////////////////////////////////////////
 
 
-	void writeBcPointsDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec2;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level <= para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->QWall.kQ;
-		}
-		nodesVec2.resize(nodeNumberVec*8); 
-		int nodeCount2 = 0; 
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			for(int u=0;u<para->getParH(level)->QWall.kQ;u++)
-			{
-				int pos = para->getParH(level)->QWall.k[u];
-
-				double x1 = para->getParH(level)->coordX_SP[pos];
-				double x2 = para->getParH(level)->coordY_SP[pos];
-				double x3 = para->getParH(level)->coordZ_SP[pos];
-
-				nodesVec2[nodeCount2++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-
-			}
-			std::string filenameVec2 = para->getFName()+"_PointsBc_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec2,nodesVec2);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writePressPointsDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level <= para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->QPress.kQ;
-		}
-		nodesVec.resize(nodeNumberVec); 
-		int nodeCount2 = 0; 
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			for(int u=0;u<para->getParH(level)->QPress.kQ;u++)
-			{
-				int pos = para->getParH(level)->QPress.k[u];
-
-				double x1 = para->getParH(level)->coordX_SP[pos];
-				double x2 = para->getParH(level)->coordY_SP[pos];
-				double x3 = para->getParH(level)->coordZ_SP[pos];
-
-				nodesVec[nodeCount2++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-
-			}
-			std::string filenameVec = para->getFName()+"_PointsPress_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec,nodesVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writePressNeighborPointsDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			nodeNumberVec += (int)para->getParH(level)->QPress.kQ;
-		}
-		nodesVec.resize(nodeNumberVec); 
-		int nodeCount2 = 0; 
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			for(int u=0;u<para->getParH(level)->QPress.kQ;u++)
-			{
-				int pos = para->getParH(level)->QPress.kN[u];
-
-				real x1 = para->getParH(level)->coordX_SP[pos];
-				real x2 = para->getParH(level)->coordY_SP[pos];
-				real x3 = para->getParH(level)->coordZ_SP[pos];
-
-				nodesVec[nodeCount2++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-			}
-			std::string filenameVec = para->getFName()+"_PointsPressNeighbor_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec,nodesVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeNeighborXPointsDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
-		}
-		nodesVec.resize(nodeNumberVec); 
-		int nodeCount2 = 0;
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->size_Mat_SP;u++)
-			{
-				real x1 = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[u]];
-				real x2 = para->getParH(level)->coordY_SP[para->getParH(level)->neighborX_SP[u]];
-				real x3 = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborX_SP[u]];
-
-				nodesVec[nodeCount2++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-			}
-			std::string filenameVec = para->getFName()+"_PointsNeighborX_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec,nodesVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeNeighborXLinesDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		std::vector< UbTupleInt2 > cellsVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level < para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
-		}
-		nodesVec.resize(nodeNumberVec*2);
-		int nodeCount = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->size_Mat_SP;u++)
-			{
-				real x1 = para->getParH(level)->coordX_SP[u];
-				real x2 = para->getParH(level)->coordY_SP[u];
-				real x3 = para->getParH(level)->coordZ_SP[u];
-				real x1N = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[u]];
-				real x2N = para->getParH(level)->coordY_SP[para->getParH(level)->neighborX_SP[u]];
-				real x3N = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborX_SP[u]];
-
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1N),(float)(x2N),(float)(x3N) ) );
-
-				if (para->getParH(level)->geoSP[u]==GEO_FLUID)
-				{
-					cellsVec.push_back( makeUbTuple(nodeCount-2,nodeCount-1) );
-				}
-
-			}
-			std::string filenameVec = para->getFName()+"_"+StringUtil::toString<int>(level)+"_NeighborX_Lines.vtk";
-			WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec,nodesVec,cellsVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeNeighborYPointsDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
-		}
-		nodesVec.resize(nodeNumberVec); 
-		int nodeCount2 = 0;
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->size_Mat_SP;u++)
-			{
-				real x1 = para->getParH(level)->coordX_SP[para->getParH(level)->neighborY_SP[u]];
-				real x2 = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[u]];
-				real x3 = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborY_SP[u]];
-
-				nodesVec[nodeCount2++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-			}
-			std::string filenameVec = para->getFName()+"_PointsNeighborY_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec,nodesVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeNeighborYLinesDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		std::vector< UbTupleInt2 > cellsVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level < para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
-		}
-		nodesVec.resize(nodeNumberVec*2);
-		int nodeCount = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->size_Mat_SP;u++)
-			{
-				real x1 = para->getParH(level)->coordX_SP[u];
-				real x2 = para->getParH(level)->coordY_SP[u];
-				real x3 = para->getParH(level)->coordZ_SP[u];
-				real x1N = para->getParH(level)->coordX_SP[para->getParH(level)->neighborY_SP[u]];
-				real x2N = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[u]];
-				real x3N = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborY_SP[u]];
-
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1N),(float)(x2N),(float)(x3N) ) );
-
-				if (para->getParH(level)->geoSP[u]==GEO_FLUID)
-				{
-					cellsVec.push_back( makeUbTuple(nodeCount-2,nodeCount-1) );
-				}
-
-			}
-			std::string filenameVec = para->getFName()+"_"+StringUtil::toString<int>(level)+"_NeighborY_Lines.vtk";
-			WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec,nodesVec,cellsVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeNeighborZPointsDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
-		}
-		nodesVec.resize(nodeNumberVec); 
-		int nodeCount2 = 0;
-		for (int level = 0; level <= para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->size_Mat_SP;u++)
-			{
-				real x1 = para->getParH(level)->coordX_SP[para->getParH(level)->neighborZ_SP[u]];
-				real x2 = para->getParH(level)->coordY_SP[para->getParH(level)->neighborZ_SP[u]];
-				real x3 = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[u]];
-
-				nodesVec[nodeCount2++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-			}
-			std::string filenameVec = para->getFName()+"_PointsNeighborZ_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeNodes(filenameVec,nodesVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeNeighborZLinesDebug(Parameter* para){
-		std::vector< UbTupleFloat3 > nodesVec;
-		std::vector< UbTupleInt2 > cellsVec;
-		int nodeNumberVec = 0;
-
-		for (int level = 0; level < para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->size_Mat_SP;
-		}
-		nodesVec.resize(nodeNumberVec*2);
-		int nodeCount = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->size_Mat_SP;u++)
-			{
-				real x1 = para->getParH(level)->coordX_SP[u];
-				real x2 = para->getParH(level)->coordY_SP[u];
-				real x3 = para->getParH(level)->coordZ_SP[u];
-				real x1N = para->getParH(level)->coordX_SP[para->getParH(level)->neighborZ_SP[u]];
-				real x2N = para->getParH(level)->coordY_SP[para->getParH(level)->neighborZ_SP[u]];
-				real x3N = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[u]];
-
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1),(float)(x2),(float)(x3) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1N),(float)(x2N),(float)(x3N) ) );
-
-				if (para->getParH(level)->geoSP[u]==GEO_FLUID)
-				{
-					cellsVec.push_back( makeUbTuple(nodeCount-2,nodeCount-1) );
-				}
-
-			}
-			std::string filenameVec = para->getFName()+"_"+StringUtil::toString<int>(level)+"_NeighborZ_Lines.vtk";
-			WbWriterVtkXmlBinary::getInstance()->writeLines(filenameVec,nodesVec,cellsVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeInterfaceCellsDebugCFC(Parameter* para){
-
-		std::vector< UbTupleFloat3 > nodesVec;
-		std::vector< UbTupleInt8 > cellsVec;
-		int nodeNumberVec = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->K_CF;
-		}
-		nodesVec.resize(nodeNumberVec*8);
-		int nodeCount = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->K_CF;u++)
-			{
-				int pos  = para->getParH(level)->intCF.ICellCFC[u];
-
-				double x1  = para->getParH(level)->coordX_SP[pos];
-				double x2  = para->getParH(level)->coordY_SP[pos];
-				double x3  = para->getParH(level)->coordZ_SP[pos];
-				double x1P = para->getParH(level)->coordX_SP[para->getParH(level)->neighborX_SP[pos]];
-				double x2P = para->getParH(level)->coordY_SP[para->getParH(level)->neighborY_SP[pos]];
-				double x3P = para->getParH(level)->coordZ_SP[para->getParH(level)->neighborZ_SP[pos]];
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2 ),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2 ),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2P),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2P),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2 ),(float)(x3P) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2 ),(float)(x3P) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2P),(float)(x3P) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2P),(float)(x3P) ) );
-
-				cellsVec.push_back( makeUbTuple(nodeCount-8,nodeCount-7,nodeCount-6,nodeCount-5,nodeCount-4,nodeCount-3,nodeCount-2,nodeCount-1) );
-
-			}
-			std::string filenameVec = para->getFName()+"_CellsCFC_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeOcts(filenameVec,nodesVec,cellsVec);
-		}
-	}
-
-
-	//////////////////////////////////////////////////////////////////////////
-
-
-	void writeInterfaceCellsDebugCFF(Parameter* para){
-
-		std::vector< UbTupleFloat3 > nodesVec;
-		std::vector< UbTupleInt8 > cellsVec;
-		int nodeNumberVec = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++) //evtl. Maxlevel + 1
-		{
-			nodeNumberVec += (int)para->getParH(level)->K_CF;
-		}
-		nodesVec.resize(nodeNumberVec*8);
-		int nodeCount = 0;
-		for (int level = 0; level < para->getMaxLevel(); level++)
-		{
-			for(unsigned int u=0;u<para->getParH(level)->K_CF;u++)
-			{
-				int pos  = para->getParH(level  )->intCF.ICellCFF[u];
-
-				double x1  = para->getParH(level+1)->coordX_SP[pos];
-				double x2  = para->getParH(level+1)->coordY_SP[pos];
-				double x3  = para->getParH(level+1)->coordZ_SP[pos];
-				double x1P = para->getParH(level+1)->coordX_SP[para->getParH(level+1)->neighborX_SP[pos]];
-				double x2P = para->getParH(level+1)->coordY_SP[para->getParH(level+1)->neighborY_SP[pos]];
-				double x3P = para->getParH(level+1)->coordZ_SP[para->getParH(level+1)->neighborZ_SP[pos]];
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2 ),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2 ),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2P),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2P),(float)(x3 ) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2 ),(float)(x3P) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2 ),(float)(x3P) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1P),(float)(x2P),(float)(x3P) ) );
-				nodesVec[nodeCount++]=( makeUbTuple( (float)(x1 ),(float)(x2P),(float)(x3P) ) );
-
-				cellsVec.push_back( makeUbTuple(nodeCount-8,nodeCount-7,nodeCount-6,nodeCount-5,nodeCount-4,nodeCount-3,nodeCount-2,nodeCount-1) );
-
-			}
-			std::string filenameVec = para->getFName()+"_CellsCFF_"+StringUtil::toString<int>(level);
-			WbWriterVtkXmlBinary::getInstance()->writeOcts(filenameVec,nodesVec,cellsVec);
-		}
-	}
+
+//////////////////////////////////////////////////////////////////////////
+// Functions for version with streams
+//////////////////////////////////////////////////////////////////////////
+void checkForSendOrRecvNode(int pos, int &commDir, int &commDirectionInCommAfterFtoC, int& indexInCommVector,
+                            std::vector<ProcessNeighbor27> &sendRecvProcessNeighbor,
+                            std::vector<ProcessNeighbor27> &sendRecvProcessNeighborsAfterFtoC, double indicator)
+{
+    for (uint pn = 0; pn < (uint)sendRecvProcessNeighbor.size(); pn++) {
+        for (int j = 0; j < sendRecvProcessNeighbor[pn].numberOfNodes; j++) {
+            if (pos == sendRecvProcessNeighbor[pn].index[j]) {
+                commDir = indicator;
+                indexInCommVector = j;
+                if (j < sendRecvProcessNeighborsAfterFtoC[pn].numberOfNodes) {
+                    commDirectionInCommAfterFtoC = indicator;
+                }
+                return;
+            }
+        }
+    }
+}
+
+void checkForRecvNodeX(int pos, int &recvDir, int &recvDirectionInCommAfterFtoC, int& recvIndex, Parameter *para, int level)
+{
+    checkForSendOrRecvNode(pos, recvDir, recvDirectionInCommAfterFtoC, recvIndex, para->getParH(level)->recvProcessNeighborX,
+                           para->getParH(level)->recvProcessNeighborsAfterFtoCX, 2.0);
+}
+
+void checkForRecvNodeY(int pos, int &recvDir, int &recvDirectionInCommAfterFtoC, int& recvIndex, Parameter *para, int level)
+{
+    checkForSendOrRecvNode(pos, recvDir, recvDirectionInCommAfterFtoC, recvIndex, para->getParH(level)->recvProcessNeighborY,
+                           para->getParH(level)->recvProcessNeighborsAfterFtoCY, 4.0);
+}
+
+void checkForRecvNodeZ(int pos, int &recvDir, int &recvDirectionInCommAfterFtoC, int& recvIndex, Parameter *para, int level)
+{
+    checkForSendOrRecvNode(pos, recvDir, recvDirectionInCommAfterFtoC, recvIndex, para->getParH(level)->recvProcessNeighborZ,
+                           para->getParH(level)->recvProcessNeighborsAfterFtoCZ, 8.0);
+}
+
+void checkForSendNodeX(int pos, int &sendDir, int &sendDirectionInCommAfterFtoC, int& sendIndex, Parameter *para, int level)
+{
+    checkForSendOrRecvNode(pos, sendDir, sendDirectionInCommAfterFtoC, sendIndex, para->getParH(level)->sendProcessNeighborX,
+                           para->getParH(level)->sendProcessNeighborsAfterFtoCX, 2.0);
+}
+
+void checkForSendNodeY(int pos, int &sendDir, int &sendDirectionInCommAfterFtoC, int& sendIndex, Parameter *para, int level)
+{
+    checkForSendOrRecvNode(pos, sendDir, sendDirectionInCommAfterFtoC, sendIndex, para->getParH(level)->sendProcessNeighborY,
+                           para->getParH(level)->sendProcessNeighborsAfterFtoCY, 4.0);
+}
+
+void checkForSendNodeZ(int pos, int &sendDir, int &sendDirectionInCommAfterFtoC, int& sendIndex, Parameter *para, int level)
+{
+    checkForSendOrRecvNode(pos, sendDir, sendDirectionInCommAfterFtoC, sendIndex, para->getParH(level)->sendProcessNeighborZ,
+                           para->getParH(level)->sendProcessNeighborsAfterFtoCZ, 8.0);
+}
+
+void writeInterfaceFCC_Send(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    int nodeNumberVec = 0;
+
+    // nodedata
+    std::vector<std::string> datanames = { "sparse index", "borderBulk", "sendDirection",
+                                           "sendDirectionInCommAfterFtoC", "sendIndex" };
+    // sendDirection: x = 2, y = 4, z = 8
+    // borderBulk: border = 1, bulk = 0
+    std::vector<std::vector<double>> nodedata;
+
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        nodeNumberVec += (int)para->getParH(level)->intFC.kFC;
+    }
+
+    nodesVec.resize(nodeNumberVec);
+    nodedata.resize(datanames.size(), std::vector<double>(nodeNumberVec));
+
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->intFC.kFC; u++) {
+            int pos                = para->getParH(level)->intFC.ICellFCC[u];
+            nodedata[0][nodeCount] = pos;
+
+            // coordinate section
+            double x1           = para->getParH(level)->coordX_SP[pos];
+            double x2           = para->getParH(level)->coordY_SP[pos];
+            double x3           = para->getParH(level)->coordZ_SP[pos];
+            nodesVec[nodeCount] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+
+            // nodedata section
+            nodedata[1][nodeCount]           = u < para->getParH(level)->intFCBorder.kFC;
+            int sendDir                      = 0.0;
+            int sendDirectionInCommAfterFtoC = 0.0;
+            int sendIndex                    = 0.0;
+
+            checkForSendNodeX(pos, sendDir, sendIndex, sendDirectionInCommAfterFtoC, para, level);
+            checkForSendNodeY(pos, sendDir, sendIndex, sendDirectionInCommAfterFtoC, para, level);
+            checkForSendNodeZ(pos, sendDir, sendIndex, sendDirectionInCommAfterFtoC, para, level);
+            nodedata[2][nodeCount] = sendDir;
+            nodedata[3][nodeCount] = sendDirectionInCommAfterFtoC;
+            nodedata[4][nodeCount] = sendIndex;
+
+            nodeCount++;
+        }
+        std::string filenameVec = para->getFName() + "_writeInterfaceFCC_Send_PID_" +
+                                  std::to_string(vf::gpu::Communicator::getInstanz()->getPID()) + "_" +
+                                  StringUtil::toString<int>(level);
+
+        WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(filenameVec, nodesVec, datanames, nodedata);
+    }
+}
+
+void writeInterfaceCFC_Recv(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+    int nodeNumberVec = 0;
+
+    // nodedata
+    std::vector<std::string> datanames = { "sparse index", "borderBulk", "recvDirection",
+                                           "recvDirectionInCommAfterFtoC", "recvIndex"};
+    // recvDirection: x = 2, y = 4, z = 8
+    // borderBulk: border = 1, bulk = 0
+    std::vector<std::vector<double>> nodedata;
+
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        nodeNumberVec += (int)para->getParH(level)->intCF.kCF;
+    }
+
+    nodesVec.resize(nodeNumberVec);
+    nodedata.resize(datanames.size(), std::vector<double>(nodeNumberVec));
+
+    int nodeCount = 0;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        for (unsigned int u = 0; u < para->getParH(level)->intCF.kCF; u++) {
+            int pos                = para->getParH(level)->intCF.ICellCFC[u];
+            nodedata[0][nodeCount] = pos;
+
+            // coordinate section
+            double x1           = para->getParH(level)->coordX_SP[pos];
+            double x2           = para->getParH(level)->coordY_SP[pos];
+            double x3           = para->getParH(level)->coordZ_SP[pos];
+            nodesVec[nodeCount] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+
+            // nodedata section
+            nodedata[1][nodeCount]           = u < para->getParH(level)->intCFBorder.kCF;
+            int recvDir                      = 0.0;
+            int recvDirectionInCommAfterFtoC = 0.0;
+            int recvIndex                    = 0.0;
+
+            checkForRecvNodeX(pos, recvDir, recvIndex, recvDirectionInCommAfterFtoC, para, level);
+            checkForRecvNodeY(pos, recvDir, recvIndex, recvDirectionInCommAfterFtoC, para, level);
+            checkForRecvNodeZ(pos, recvDir, recvIndex, recvDirectionInCommAfterFtoC, para, level);
+            nodedata[2][nodeCount] = recvDir;
+            nodedata[3][nodeCount] = recvDirectionInCommAfterFtoC;
+            nodedata[4][nodeCount] = recvIndex;
+            nodeCount++;
+        }
+        std::string filenameVec = para->getFName() + "_writeInterfaceCFC_Recv_PID_" +
+                                  std::to_string(vf::gpu::Communicator::getInstanz()->getPID()) + "_" +
+                                  StringUtil::toString<int>(level);
+
+        WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(filenameVec, nodesVec, datanames, nodedata);
+    }
+}
+
+void addToNodesVector(const int level, const int pos, std::vector<UbTupleFloat3> &nodesVec, Parameter *para)
+{
+    double x1 = para->getParH(level)->coordX_SP[pos];
+    double x2 = para->getParH(level)->coordY_SP[pos];
+    double x3 = para->getParH(level)->coordZ_SP[pos];
+    nodesVec.push_back(makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
+}
+
+void writeSendNodesStream(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+
+    // nodedata
+    std::vector<std::string> datanames = { "sparse index", "sendDirection", "sendDirectionInCommAfterFtoC", "sendIndex",
+                                           "inICcellFCC" };
+    // sendDirection: x = 2, y = 4, z = 8
+    std::vector<std::vector<double>> nodedata;
+    nodedata.resize(datanames.size());
+
+    int pos;
+    int sendDirectionInCommAfterFtoC;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        // X
+        for (int pn = 0; pn < (int)para->getParH(level)->sendProcessNeighborX.size(); pn++) {
+            for (int i = 0; i < para->getParH(level)->sendProcessNeighborX[pn].numberOfNodes; i++) {
+                pos = para->getParH(level)->sendProcessNeighborX[pn].index[i];
+                nodedata[0].push_back(pos);
+                addToNodesVector(level, pos, nodesVec, para);
+
+                nodedata[1].push_back(2.0);
+                sendDirectionInCommAfterFtoC =
+                    (i < para->getParH(level)->sendProcessNeighborsAfterFtoCX[pn].numberOfNodes) ? 2.0 : 0.0;
+                nodedata[2].push_back(sendDirectionInCommAfterFtoC);
+                nodedata[3].push_back((double)i);
+            }
+        }
+
+        // Y
+        for (int pn = 0; pn < (int)para->getParH(level)->sendProcessNeighborY.size(); pn++) {
+            for (int i = 0; i < para->getParH(level)->sendProcessNeighborY[pn].numberOfNodes; i++) {
+                pos = para->getParH(level)->sendProcessNeighborY[pn].index[i];
+
+                sendDirectionInCommAfterFtoC =
+                    (i < para->getParH(level)->sendProcessNeighborsAfterFtoCY[pn].numberOfNodes) ? 4.0 : 0.0;
+
+                auto it = std::find(nodedata[0].begin(), nodedata[0].end(), pos);
+                if (it == nodedata[0].end()) {
+                    nodedata[0].push_back(pos);
+                    addToNodesVector(level, pos, nodesVec, para);
+                    nodedata[1].push_back(4.0);
+                    nodedata[2].push_back(sendDirectionInCommAfterFtoC);
+                    nodedata[3].push_back((double) i);
+                } else {
+                    int posInVectors = it - nodedata[0].begin();
+                    nodedata[1][posInVectors] += 4.0;
+                    nodedata[2][posInVectors] += sendDirectionInCommAfterFtoC;
+                    nodedata[3][posInVectors] = (double)i;
+                }
+            }
+        }
+
+        // Z
+        for (int pn = 0; pn < (int)para->getParH(level)->sendProcessNeighborZ.size(); pn++) {
+            for (int i = 0; i < para->getParH(level)->sendProcessNeighborZ[pn].numberOfNodes; i++) {
+                pos = para->getParH(level)->sendProcessNeighborZ[pn].index[i];
+
+                sendDirectionInCommAfterFtoC =
+                    (i < para->getParH(level)->sendProcessNeighborsAfterFtoCZ[pn].numberOfNodes) ? 8.0 : 0.0;
+
+                auto it = std::find(nodedata[0].begin(), nodedata[0].end(), pos);
+                if (it == nodedata[0].end()) {
+                    nodedata[0].push_back(pos);
+                    addToNodesVector(level, pos, nodesVec, para);
+                    nodedata[1].push_back(8.0);
+                    nodedata[2].push_back(sendDirectionInCommAfterFtoC);
+                    nodedata[3].push_back((double) i);
+                } else {
+                    int posInVectors = it - nodedata[0].begin();
+                    nodedata[1][posInVectors] += 8.0;
+                    nodedata[2][posInVectors] += sendDirectionInCommAfterFtoC;
+                    nodedata[3][posInVectors] = (double)i;
+                }
+            }
+        }
+
+        // check if node is in iCellFCC
+        nodedata[4].resize(nodedata[0].size());
+        for (int i = 0; i < (int)nodedata[0].size(); i++) {
+            pos = nodedata[0][i];
+            for (unsigned int u = 0; u < para->getParH(level)->intFC.kFC; u++) {
+                if (para->getParH(level)->intFC.ICellFCC[u] == (uint)pos) {
+                    nodedata[4][i] = 1.0;
+                    break;
+                }
+                nodedata[4][i] = 0.0;
+            }
+        }
+        std::string filenameVec = para->getFName() + "_writeSendNodesStreams_PID_" +
+                                  std::to_string(vf::gpu::Communicator::getInstanz()->getPID()) + "_" +
+                                  StringUtil::toString<int>(level);
+
+        WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(filenameVec, nodesVec, datanames, nodedata);
+    }
+}
+
+void writeRecvNodesStream(Parameter *para)
+{
+    std::vector<UbTupleFloat3> nodesVec;
+
+    // nodedata
+    std::vector<std::string> datanames = { "sparse index", "recvDirection", "recvDirectionInCommAfterFtoC", "recvIndex" };
+    // sendDirection: x = 2, y = 4, z = 8
+    std::vector<std::vector<double>> nodedata;
+    nodedata.resize(datanames.size());
+
+    int pos;
+    int recvDirectionInCommAfterFtoC;
+    for (int level = 0; level < para->getMaxLevel(); level++) {
+        // X
+        for (int pn = 0; pn < (int)para->getParH(level)->recvProcessNeighborX.size(); pn++) {
+            for (int i = 0; i < para->getParH(level)->recvProcessNeighborX[pn].numberOfNodes; i++) {
+                pos = para->getParH(level)->recvProcessNeighborX[pn].index[i];
+                nodedata[0].push_back(pos);
+                addToNodesVector(level, pos, nodesVec, para);
+
+                nodedata[1].push_back(2.0);
+                recvDirectionInCommAfterFtoC =
+                    (i < para->getParH(level)->recvProcessNeighborsAfterFtoCX[pn].numberOfNodes) ? 2.0 : 0.0;
+                nodedata[2].push_back(recvDirectionInCommAfterFtoC);
+                nodedata[3].push_back(i);
+            }
+        }
+
+        // Y
+        for (int pn = 0; pn < (int)para->getParH(level)->recvProcessNeighborY.size(); pn++) {
+            for (int i = 0; i < para->getParH(level)->recvProcessNeighborY[pn].numberOfNodes; i++) {
+                pos = para->getParH(level)->recvProcessNeighborY[pn].index[i];
+
+                recvDirectionInCommAfterFtoC =
+                    (i < para->getParH(level)->recvProcessNeighborsAfterFtoCY[pn].numberOfNodes) ? 4.0 : 0.0;
+
+                auto it = std::find(nodedata[0].begin(), nodedata[0].end(), pos);
+                if (it == nodedata[0].end()) {
+                    nodedata[0].push_back(pos);
+                    addToNodesVector(level, pos, nodesVec, para);
+                    nodedata[1].push_back(4.0);
+                    nodedata[2].push_back(recvDirectionInCommAfterFtoC);
+                    nodedata[3].push_back(i);
+                } else {
+                    int posInVectors = it - nodedata[0].begin();
+                    nodedata[1][posInVectors] += 4.0;
+                    nodedata[2][posInVectors] += recvDirectionInCommAfterFtoC;
+                    nodedata[3][posInVectors] += i;
+                }
+            }
+        }
+
+        // Z
+        for (int pn = 0; pn < (int)para->getParH(level)->recvProcessNeighborZ.size(); pn++) {
+            for (int i = 0; i < para->getParH(level)->recvProcessNeighborZ[pn].numberOfNodes; i++) {
+                pos = para->getParH(level)->recvProcessNeighborZ[pn].index[i];
+
+                recvDirectionInCommAfterFtoC =
+                    (i < para->getParH(level)->recvProcessNeighborsAfterFtoCZ[pn].numberOfNodes) ? 8.0 : 0.0;
+
+                auto it = std::find(nodedata[0].begin(), nodedata[0].end(), pos);
+                if (it == nodedata[0].end()) {
+                    nodedata[0].push_back(pos);
+                    addToNodesVector(level, pos, nodesVec, para);
+                    nodedata[1].push_back(8.0);
+                    nodedata[2].push_back(recvDirectionInCommAfterFtoC);
+                    nodedata[3].push_back(i);
+                } else {
+                    int posInVectors = it - nodedata[0].begin();
+                    nodedata[1][posInVectors] += 8.0;
+                    nodedata[2][posInVectors] += recvDirectionInCommAfterFtoC;
+                    nodedata[3][posInVectors] += i;
+                }
+            }
+        }
+
+        // Recv are nodes ghost nodes and therefore they can't be iCellCFCs
+
+        std::string filenameVec = para->getFName() + "_writeRecvNodesStreams_PID_" +
+                                  std::to_string(vf::gpu::Communicator::getInstanz()->getPID()) + "_" +
+                                  StringUtil::toString<int>(level);
+
+        WbWriterVtkXmlBinary::getInstance()->writeNodesWithNodeData(filenameVec, nodesVec, datanames, nodedata);
+    }
 }
+} // namespace InterfaceDebugWriter
 
 #endif
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
index c7c01026d07b81811a815aeb9f0656c3a2cf2412..bf31cc6d8c95453d1dd05d355a793d49e6864c4f 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
@@ -1,28 +1,28 @@
 //=======================================================================================
-// ____          ____    __    ______     __________   __      __       __        __         
-// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
-//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
-//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
-//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
-//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
-//      \    \  |    |   ________________________________________________________________    
-//       \    \ |    |  |  ______________________________________________________________|   
-//        \    \|    |  |  |         __          __     __     __     ______      _______    
-//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
-//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
 //           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
 //
-//  This file is part of VirtualFluids. VirtualFluids is free software: you can 
+//  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 
+//  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 
+//
+//  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/>.
 //
@@ -32,9 +32,9 @@
 //=======================================================================================
 #include "Parameter.h"
 
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <math.h>
 
 #include <curand_kernel.h>
 
@@ -44,15 +44,13 @@
 
 #include "Parameter/CudaStreamManager.h"
 
-
-
 Parameter::Parameter(const vf::basics::ConfigurationFile &configData, int numberOfProcesses, int myId)
 {
     ic.numprocs = numberOfProcesses;
-    ic.myid = myId;
+    ic.myid     = myId;
 
     readConfigData(configData);
-    //initLBMSimulationParameter();
+    // initLBMSimulationParameter();
 }
 
 Parameter::~Parameter() = default;
@@ -154,7 +152,7 @@ void Parameter::readConfigData(const vf::basics::ConfigurationFile &configData)
         this->setPressOutZ(configData.getValue<int>("PressOutZ"));
 
     //////////////////////////////////////////////////////////////////////////
-    //second component
+    // second component
     if (configData.contains("DiffOn"))
         this->setDiffOn(configData.getValue<bool>("DiffOn"));
     //////////////////////////////////////////////////////////////////////////
@@ -201,19 +199,20 @@ void Parameter::readConfigData(const vf::basics::ConfigurationFile &configData)
 
     //////////////////////////////////////////////////////////////////////////
     // CUDA streams and optimized communication
-    if(this->getNumprocs() > 1) {
+    if (this->getNumprocs() > 1) {
         if (configData.contains("useStreams")) {
-            if (configData.getValue<bool>("useStreams")) 
-                this->setUseStreams();
+            if (configData.getValue<bool>("useStreams"))
+                this->setUseStreams(true);
         }
 
-        if (configData.contains("useReducedCommunicationInInterpolation")){
-            this->useReducedCommunicationAfterFtoC = configData.getValue<bool>("useReducedCommunicationInInterpolation");
+        if (configData.contains("useReducedCommunicationInInterpolation")) {
+            this->useReducedCommunicationAfterFtoC =
+                configData.getValue<bool>("useReducedCommunicationInInterpolation");
         }
     }
     //////////////////////////////////////////////////////////////////////////
 
-    //read Geometry (STL)
+    // read Geometry (STL)
     if (configData.contains("ReadGeometry"))
         this->setReadGeo(configData.getValue<bool>("ReadGeometry"));
 
@@ -449,124 +448,117 @@ void Parameter::readConfigData(const vf::basics::ConfigurationFile &configData)
 
 void Parameter::initLBMSimulationParameter()
 {
-    //host
-    for (int i = coarse; i <= fine; i++)
-    {
-        parH[i]                        = std::make_shared<LBMSimulationParameter>();
-        parH[i]->numberofthreads       = 64;// 128;
-        parH[i]->gridNX                = getGridX().at(i);
-        parH[i]->gridNY                = getGridY().at(i);
-        parH[i]->gridNZ                = getGridZ().at(i);
-        parH[i]->vis                   = ic.vis*pow(2.f,i);
-        parH[i]->diffusivity           = ic.Diffusivity*pow(2.f,i);
-        parH[i]->omega                 = 1.0f/(3.0f*parH[i]->vis+0.5f);//omega :-) not s9 = -1.0f/(3.0f*parH[i]->vis+0.5f);//
-        parH[i]->nx                    = parH[i]->gridNX + 2 * STARTOFFX;
-        parH[i]->ny                    = parH[i]->gridNY + 2 * STARTOFFY;
-        parH[i]->nz                    = parH[i]->gridNZ + 2 * STARTOFFZ;
-        parH[i]->size_Mat              = parH[i]->nx * parH[i]->ny * parH[i]->nz;
-        parH[i]->sizePlaneXY           = parH[i]->nx * parH[i]->ny;
-        parH[i]->sizePlaneYZ           = parH[i]->ny * parH[i]->nz;
-        parH[i]->sizePlaneXZ           = parH[i]->nx * parH[i]->nz;
-        parH[i]->mem_size_real         = sizeof(real     ) * parH[i]->size_Mat;
-        parH[i]->mem_size_int          = sizeof(unsigned int) * parH[i]->size_Mat;
-        parH[i]->mem_size_bool         = sizeof(bool        ) * parH[i]->size_Mat;
-        parH[i]->mem_size_real_yz      = sizeof(real     ) * parH[i]->ny * parH[i]->nz;
-        parH[i]->evenOrOdd             = true;
-        parH[i]->startz                = parH[i]->gridNZ * ic.myid;
-        parH[i]->endz                  = parH[i]->gridNZ * ic.myid + parH[i]->gridNZ;
-        parH[i]->Lx                    = (real)((1.f*parH[i]->gridNX - 1.f)/(pow(2.f,i)));
-        parH[i]->Ly                    = (real)((1.f*parH[i]->gridNY - 1.f)/(pow(2.f,i)));
-        parH[i]->Lz                    = (real)((1.f*parH[i]->gridNZ - 1.f)/(pow(2.f,i)));
-        parH[i]->dx                    = (real)(1.f/(pow(2.f,i)));
-        parH[i]->XdistKn               = getDistX().at(i);
-        parH[i]->YdistKn               = getDistY().at(i);
-        parH[i]->ZdistKn               = getDistZ().at(i);
-        if (i == coarse)
-        {
-            parH[i]->distX                 = (real)getDistX().at(i);
-            parH[i]->distY                 = (real)getDistY().at(i);
-            parH[i]->distZ                 = (real)getDistZ().at(i);
-            parH[i]->mTtoWx                = (real)1.0f;
-            parH[i]->mTtoWy                = (real)1.0f;
-            parH[i]->mTtoWz                = (real)1.0f;
-            parH[i]->cTtoWx                = (real)0.0f;
-            parH[i]->cTtoWy                = (real)0.0f;
-            parH[i]->cTtoWz                = (real)0.0f;
+    // host
+    for (int i = coarse; i <= fine; i++) {
+        parH[i]                   = std::make_shared<LBMSimulationParameter>();
+        parH[i]->numberofthreads  = 64; // 128;
+        parH[i]->gridNX           = getGridX().at(i);
+        parH[i]->gridNY           = getGridY().at(i);
+        parH[i]->gridNZ           = getGridZ().at(i);
+        parH[i]->vis              = ic.vis * pow(2.f, i);
+        parH[i]->diffusivity      = ic.Diffusivity * pow(2.f, i);
+        parH[i]->omega            = 1.0f / (3.0f * parH[i]->vis + 0.5f); // omega :-) not s9 = -1.0f/(3.0f*parH[i]->vis+0.5f);//
+        parH[i]->nx               = parH[i]->gridNX + 2 * STARTOFFX;
+        parH[i]->ny               = parH[i]->gridNY + 2 * STARTOFFY;
+        parH[i]->nz               = parH[i]->gridNZ + 2 * STARTOFFZ;
+        parH[i]->size_Mat         = parH[i]->nx * parH[i]->ny * parH[i]->nz;
+        parH[i]->sizePlaneXY      = parH[i]->nx * parH[i]->ny;
+        parH[i]->sizePlaneYZ      = parH[i]->ny * parH[i]->nz;
+        parH[i]->sizePlaneXZ      = parH[i]->nx * parH[i]->nz;
+        parH[i]->mem_size_real    = sizeof(real) * parH[i]->size_Mat;
+        parH[i]->mem_size_int     = sizeof(unsigned int) * parH[i]->size_Mat;
+        parH[i]->mem_size_bool    = sizeof(bool) * parH[i]->size_Mat;
+        parH[i]->mem_size_real_yz = sizeof(real) * parH[i]->ny * parH[i]->nz;
+        parH[i]->evenOrOdd        = true;
+        parH[i]->startz           = parH[i]->gridNZ * ic.myid;
+        parH[i]->endz             = parH[i]->gridNZ * ic.myid + parH[i]->gridNZ;
+        parH[i]->Lx               = (real)((1.f * parH[i]->gridNX - 1.f) / (pow(2.f, i)));
+        parH[i]->Ly               = (real)((1.f * parH[i]->gridNY - 1.f) / (pow(2.f, i)));
+        parH[i]->Lz               = (real)((1.f * parH[i]->gridNZ - 1.f) / (pow(2.f, i)));
+        parH[i]->dx               = (real)(1.f / (pow(2.f, i)));
+        parH[i]->XdistKn          = getDistX().at(i);
+        parH[i]->YdistKn          = getDistY().at(i);
+        parH[i]->ZdistKn          = getDistZ().at(i);
+        if (i == coarse) {
+            parH[i]->distX  = (real)getDistX().at(i);
+            parH[i]->distY  = (real)getDistY().at(i);
+            parH[i]->distZ  = (real)getDistZ().at(i);
+            parH[i]->mTtoWx = (real)1.0f;
+            parH[i]->mTtoWy = (real)1.0f;
+            parH[i]->mTtoWz = (real)1.0f;
+            parH[i]->cTtoWx = (real)0.0f;
+            parH[i]->cTtoWy = (real)0.0f;
+            parH[i]->cTtoWz = (real)0.0f;
             ////MGs Trafo///////////////////////////////////////////////////////////////
-            //parH[i]->cStartx               = (real)parH[i]->XdistKn;
-            //parH[i]->cStarty               = (real)parH[i]->XdistKn;
-            //parH[i]->cStartz               = (real)parH[i]->XdistKn;
+            // parH[i]->cStartx               = (real)parH[i]->XdistKn;
+            // parH[i]->cStarty               = (real)parH[i]->XdistKn;
+            // parH[i]->cStartz               = (real)parH[i]->XdistKn;
             ////////////////////////////////////////////////////////////////////////////
-        } 
-        else
-        {
-            //Geller
-            parH[i]->distX                 = ((real)getDistX().at(i) + 0.25f) * parH[i-1]->dx;
-            parH[i]->distY                 = ((real)getDistY().at(i) + 0.25f) * parH[i-1]->dx;
-            parH[i]->distZ                 = ((real)getDistZ().at(i) + 0.25f) * parH[i-1]->dx;
-            //parH[i]->distX                 = ((real)getDistX().at(i) + 0.25f) * parH[i-1]->dx + parH[i-1]->distX;
-            //parH[i]->distY                 = ((real)getDistY().at(i) + 0.25f) * parH[i-1]->dx + parH[i-1]->distY;
-            //parH[i]->distZ                 = ((real)getDistZ().at(i) + 0.25f) * parH[i-1]->dx + parH[i-1]->distZ;
-            parH[i]->mTtoWx                = (real)pow(0.5f,i);
-            parH[i]->mTtoWy                = (real)pow(0.5f,i);
-            parH[i]->mTtoWz                = (real)pow(0.5f,i);
-            parH[i]->cTtoWx                = (real)(STARTOFFX/2.f + (parH[i]->gridNX+1.f)/4.f); //funzt nur fuer zwei level
-            parH[i]->cTtoWy                = (real)(STARTOFFY/2.f + (parH[i]->gridNY+1.f)/4.f); //funzt nur fuer zwei level
-            parH[i]->cTtoWz                = (real)(STARTOFFZ/2.f + (parH[i]->gridNZ+1.f)/4.f); //funzt nur fuer zwei level
+        } else {
+            // Geller
+            parH[i]->distX = ((real)getDistX().at(i) + 0.25f) * parH[i - 1]->dx;
+            parH[i]->distY = ((real)getDistY().at(i) + 0.25f) * parH[i - 1]->dx;
+            parH[i]->distZ = ((real)getDistZ().at(i) + 0.25f) * parH[i - 1]->dx;
+            // parH[i]->distX                 = ((real)getDistX().at(i) + 0.25f) * parH[i-1]->dx + parH[i-1]->distX;
+            // parH[i]->distY                 = ((real)getDistY().at(i) + 0.25f) * parH[i-1]->dx + parH[i-1]->distY;
+            // parH[i]->distZ                 = ((real)getDistZ().at(i) + 0.25f) * parH[i-1]->dx + parH[i-1]->distZ;
+            parH[i]->mTtoWx = (real)pow(0.5f, i);
+            parH[i]->mTtoWy = (real)pow(0.5f, i);
+            parH[i]->mTtoWz = (real)pow(0.5f, i);
+            parH[i]->cTtoWx = (real)(STARTOFFX / 2.f + (parH[i]->gridNX + 1.f) / 4.f); // funzt nur fuer zwei level
+            parH[i]->cTtoWy = (real)(STARTOFFY / 2.f + (parH[i]->gridNY + 1.f) / 4.f); // funzt nur fuer zwei level
+            parH[i]->cTtoWz = (real)(STARTOFFZ / 2.f + (parH[i]->gridNZ + 1.f) / 4.f); // funzt nur fuer zwei level
             ////MGs Trafo///////////////////////////////////////////////////////////////
-            //parH[i]->cStartx               = (real)parH[i]->XdistKn;
-            //parH[i]->cStarty               = (real)parH[i]->XdistKn;
-            //parH[i]->cStartz               = (real)parH[i]->XdistKn;
+            // parH[i]->cStartx               = (real)parH[i]->XdistKn;
+            // parH[i]->cStarty               = (real)parH[i]->XdistKn;
+            // parH[i]->cStartz               = (real)parH[i]->XdistKn;
             ////////////////////////////////////////////////////////////////////////////
         }
     }
 
-    //device
-    for (int i = coarse; i <= fine; i++)
-    {
-        parD[i]                        = std::make_shared<LBMSimulationParameter>();
-        parD[i]->numberofthreads       = parH[i]->numberofthreads;
-        parD[i]->gridNX                = parH[i]->gridNX;
-        parD[i]->gridNY                = parH[i]->gridNY;
-        parD[i]->gridNZ                = parH[i]->gridNZ;
-        parD[i]->vis                   = parH[i]->vis;
-        parD[i]->diffusivity           = parH[i]->diffusivity;
-        parD[i]->omega                 = parH[i]->omega;
-        parD[i]->nx                    = parH[i]->nx;
-        parD[i]->ny                    = parH[i]->ny;
-        parD[i]->nz                    = parH[i]->nz;
-        parD[i]->size_Mat              = parH[i]->size_Mat;
-        parD[i]->sizePlaneXY           = parH[i]->sizePlaneXY;
-        parD[i]->sizePlaneYZ           = parH[i]->sizePlaneYZ;
-        parD[i]->sizePlaneXZ           = parH[i]->sizePlaneXZ;
-        parD[i]->mem_size_real         = sizeof(real     ) * parD[i]->size_Mat;
-        parD[i]->mem_size_int          = sizeof(unsigned int) * parD[i]->size_Mat;
-        parD[i]->mem_size_bool         = sizeof(bool        ) * parD[i]->size_Mat;
-        parD[i]->mem_size_real_yz      = sizeof(real     ) * parD[i]->ny * parD[i]->nz;
-        parD[i]->evenOrOdd             = parH[i]->evenOrOdd;
-        parD[i]->startz                = parH[i]->startz;
-        parD[i]->endz                  = parH[i]->endz;
-        parD[i]->Lx                    = parH[i]->Lx;
-        parD[i]->Ly                    = parH[i]->Ly;
-        parD[i]->Lz                    = parH[i]->Lz;
-        parD[i]->dx                    = parH[i]->dx;
-        parD[i]->XdistKn               = parH[i]->XdistKn;
-        parD[i]->YdistKn               = parH[i]->YdistKn;
-        parD[i]->ZdistKn               = parH[i]->ZdistKn;
-        parD[i]->distX                 = parH[i]->distX;
-        parD[i]->distY                 = parH[i]->distY;
-        parD[i]->distZ                 = parH[i]->distZ;
+    // device
+    for (int i = coarse; i <= fine; i++) {
+        parD[i]                   = std::make_shared<LBMSimulationParameter>();
+        parD[i]->numberofthreads  = parH[i]->numberofthreads;
+        parD[i]->gridNX           = parH[i]->gridNX;
+        parD[i]->gridNY           = parH[i]->gridNY;
+        parD[i]->gridNZ           = parH[i]->gridNZ;
+        parD[i]->vis              = parH[i]->vis;
+        parD[i]->diffusivity      = parH[i]->diffusivity;
+        parD[i]->omega            = parH[i]->omega;
+        parD[i]->nx               = parH[i]->nx;
+        parD[i]->ny               = parH[i]->ny;
+        parD[i]->nz               = parH[i]->nz;
+        parD[i]->size_Mat         = parH[i]->size_Mat;
+        parD[i]->sizePlaneXY      = parH[i]->sizePlaneXY;
+        parD[i]->sizePlaneYZ      = parH[i]->sizePlaneYZ;
+        parD[i]->sizePlaneXZ      = parH[i]->sizePlaneXZ;
+        parD[i]->mem_size_real    = sizeof(real) * parD[i]->size_Mat;
+        parD[i]->mem_size_int     = sizeof(unsigned int) * parD[i]->size_Mat;
+        parD[i]->mem_size_bool    = sizeof(bool) * parD[i]->size_Mat;
+        parD[i]->mem_size_real_yz = sizeof(real) * parD[i]->ny * parD[i]->nz;
+        parD[i]->evenOrOdd        = parH[i]->evenOrOdd;
+        parD[i]->startz           = parH[i]->startz;
+        parD[i]->endz             = parH[i]->endz;
+        parD[i]->Lx               = parH[i]->Lx;
+        parD[i]->Ly               = parH[i]->Ly;
+        parD[i]->Lz               = parH[i]->Lz;
+        parD[i]->dx               = parH[i]->dx;
+        parD[i]->XdistKn          = parH[i]->XdistKn;
+        parD[i]->YdistKn          = parH[i]->YdistKn;
+        parD[i]->ZdistKn          = parH[i]->ZdistKn;
+        parD[i]->distX            = parH[i]->distX;
+        parD[i]->distY            = parH[i]->distY;
+        parD[i]->distZ            = parH[i]->distZ;
     }
 }
 
 void Parameter::copyMeasurePointsArrayToVector(int lev)
 {
-    int valuesPerClockCycle = (int)(getclockCycleForMP()/getTimestepForMP());
-    for(int i = 0; i < (int)parH[lev]->MP.size(); i++)
-    {
-        for(int j = 0; j < valuesPerClockCycle; j++)
-        {
-            int index = i*valuesPerClockCycle+j;
+    int valuesPerClockCycle = (int)(getclockCycleForMP() / getTimestepForMP());
+    for (int i = 0; i < (int)parH[lev]->MP.size(); i++) {
+        for (int j = 0; j < valuesPerClockCycle; j++) {
+            int index = i * valuesPerClockCycle + j;
             parH[lev]->MP[i].Vx.push_back(parH[lev]->VxMP[index]);
             parH[lev]->MP[i].Vy.push_back(parH[lev]->VyMP[index]);
             parH[lev]->MP[i].Vz.push_back(parH[lev]->VzMP[index]);
@@ -575,9 +567,8 @@ void Parameter::copyMeasurePointsArrayToVector(int lev)
     }
 }
 
-
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//set-methods
+// set-methods
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 void Parameter::setForcing(real forcingX, real forcingY, real forcingZ)
 {
@@ -591,1982 +582,805 @@ void Parameter::setQuadricLimiters(real quadricLimiterP, real quadricLimiterM, r
     this->hostQuadricLimiters[1] = quadricLimiterM;
     this->hostQuadricLimiters[2] = quadricLimiterD;
 }
-void Parameter::setPhi(real inPhi)
-{
-    Phi = inPhi;
-}
-void Parameter::setAngularVelocity(real inAngVel)
-{
-    angularVelocity = inAngVel;
-}
-void Parameter::setStepEnsight(unsigned int step)
-{
-    this->stepEnsight = step;
-}
-void Parameter::setOutputCount(unsigned int outputCount)
-{
-    this->outputCount = outputCount;
-}
+void Parameter::setPhi(real inPhi) { Phi = inPhi; }
+void Parameter::setAngularVelocity(real inAngVel) { angularVelocity = inAngVel; }
+void Parameter::setStepEnsight(unsigned int step) { this->stepEnsight = step; }
+void Parameter::setOutputCount(unsigned int outputCount) { this->outputCount = outputCount; }
 void Parameter::setlimitOfNodesForVTK(unsigned int limitOfNodesForVTK)
 {
     this->limitOfNodesForVTK = limitOfNodesForVTK;
 }
-void Parameter::setStartTurn(unsigned int inStartTurn)
-{
-    startTurn = inStartTurn;
-}
-void Parameter::setDiffOn(bool isDiff)
-{
-    diffOn = isDiff;
-}
-void Parameter::setCompOn(bool isComp)
-{
-    compOn = isComp;
-}
-void Parameter::setDiffMod(int DiffMod)
-{
-    diffMod = DiffMod;
-}
-void Parameter::setD3Qxx(int d3qxx)
-{
-    this->D3Qxx = d3qxx;
-}
+void Parameter::setStartTurn(unsigned int inStartTurn) { startTurn = inStartTurn; }
+void Parameter::setDiffOn(bool isDiff) { diffOn = isDiff; }
+void Parameter::setCompOn(bool isComp) { compOn = isComp; }
+void Parameter::setDiffMod(int DiffMod) { diffMod = DiffMod; }
+void Parameter::setD3Qxx(int d3qxx) { this->D3Qxx = d3qxx; }
 void Parameter::setMaxLevel(int maxlevel)
 {
-    this->maxlevel = maxlevel-1;
+    this->maxlevel = maxlevel - 1;
     this->fine     = this->maxlevel;
     parH.resize(this->maxlevel + 1);
     parD.resize(this->maxlevel + 1);
 }
-void Parameter::setParticleBasicLevel(int pbl)
-{
-    this->particleBasicLevel = pbl;
-}
-void Parameter::setParticleInitLevel(int pil)
+void Parameter::setParticleBasicLevel(int pbl) { this->particleBasicLevel = pbl; }
+void Parameter::setParticleInitLevel(int pil) { this->particleInitLevel = pil; }
+void Parameter::setNumberOfParticles(int nop) { this->numberOfParticles = nop; }
+void Parameter::setCalcParticles(bool calcParticles) { this->calcParticles = calcParticles; }
+void Parameter::setStartXHotWall(real startXHotWall) { this->startXHotWall = startXHotWall; }
+void Parameter::setEndXHotWall(real endXHotWall) { this->endXHotWall = endXHotWall; }
+void Parameter::setTEnd(unsigned int tend) { ic.tend = tend; }
+void Parameter::setTOut(unsigned int tout) { ic.tout = tout; }
+void Parameter::setTStartOut(unsigned int tStartOut) { ic.tStartOut = tStartOut; }
+void Parameter::setTimestepOfCoarseLevel(unsigned int timestep) { this->timestep = timestep; }
+void Parameter::setCalcTurbulenceIntensity(bool calcVelocityAndFluctuations)
 {
-    this->particleInitLevel = pil;
+    this->calcVelocityAndFluctuations = calcVelocityAndFluctuations;
 }
-void Parameter::setNumberOfParticles(int nop)
+void Parameter::setCalcMedian(bool calcMedian) { ic.calcMedian = calcMedian; }
+void Parameter::setCalcDragLift(bool calcDragLift) { this->calcDragLift = calcDragLift; }
+void Parameter::setCalcCp(bool calcCp) { this->calcCp = calcCp; }
+void Parameter::setWriteVeloASCIIfiles(bool writeVeloASCII) { this->writeVeloASCII = writeVeloASCII; }
+void Parameter::setCalcPlaneConc(bool calcPlaneConc) { this->calcPlaneConc = calcPlaneConc; }
+void Parameter::setTimeCalcMedStart(int CalcMedStart) { ic.tCalcMedStart = CalcMedStart; }
+void Parameter::setTimeCalcMedEnd(int CalcMedEnd) { ic.tCalcMedEnd = CalcMedEnd; }
+void Parameter::setOutputPath(std::string oPath) { ic.oPath = oPath; }
+void Parameter::setOutputPrefix(std::string oPrefix)
 {
-    this->numberOfParticles = nop;
+    // std::string test = fname;
+    ic.oPrefix = oPrefix;
 }
-void Parameter::setCalcParticles(bool calcParticles)
+void Parameter::setFName(std::string fname)
 {
-    this->calcParticles = calcParticles;
+    // std::string test = fname;
+    ic.fname = fname;
 }
-void Parameter::setStartXHotWall(real startXHotWall)
+void Parameter::setPrintFiles(bool printfiles) { ic.printFiles = printfiles; }
+void Parameter::setReadGeo(bool readGeo) { ic.readGeo = readGeo; }
+void Parameter::setDiffusivity(real Diffusivity) { ic.Diffusivity = Diffusivity; }
+void Parameter::setTemperatureInit(real Temp) { ic.Temp = Temp; }
+void Parameter::setTemperatureBC(real TempBC) { ic.TempBC = TempBC; }
+void Parameter::setViscosity(real Viscosity) { ic.vis = Viscosity; }
+void Parameter::setVelocity(real Velocity) { ic.u0 = Velocity; }
+void Parameter::setViscosityRatio(real ViscosityRatio) { ic.vis_ratio = ViscosityRatio; }
+void Parameter::setVelocityRatio(real VelocityRatio) { ic.u0_ratio = VelocityRatio; }
+void Parameter::setDensityRatio(real DensityRatio) { ic.delta_rho = DensityRatio; }
+void Parameter::setPressRatio(real PressRatio) { ic.delta_press = PressRatio; }
+void Parameter::setRealX(real RealX) { ic.RealX = RealX; }
+void Parameter::setRealY(real RealY) { ic.RealY = RealY; }
+void Parameter::setPressInID(unsigned int PressInID) { ic.PressInID = PressInID; }
+void Parameter::setPressOutID(unsigned int PressOutID) { ic.PressOutID = PressOutID; }
+void Parameter::setPressInZ(unsigned int PressInZ) { ic.PressInZ = PressInZ; }
+void Parameter::setPressOutZ(unsigned int PressOutZ) { ic.PressOutZ = PressOutZ; }
+void Parameter::setMaxDev(int maxdev) { ic.maxdev = maxdev; }
+void Parameter::setMyID(int myid) { ic.myid = myid; }
+void Parameter::setNumprocs(int numprocs) { ic.numprocs = numprocs; }
+void Parameter::setDevices(std::vector<uint> devices) { ic.devices = devices; }
+void Parameter::setGeometryFileC(std::string GeometryFileC) { ic.geometryFileC = GeometryFileC; }
+void Parameter::setGeometryFileM(std::string GeometryFileM) { ic.geometryFileM = GeometryFileM; }
+void Parameter::setGeometryFileF(std::string GeometryFileF) { ic.geometryFileF = GeometryFileF; }
+void Parameter::setRe(real Re) { ic.Re = Re; }
+void Parameter::setFactorPressBC(real factorPressBC) { ic.factorPressBC = factorPressBC; }
+void Parameter::setIsGeo(bool isGeo) { ic.isGeo = isGeo; }
+void Parameter::setIsGeoNormal(bool isGeoNormal) { ic.isGeoNormal = isGeoNormal; }
+void Parameter::setIsInflowNormal(bool isInflowNormal) { ic.isInflowNormal = isInflowNormal; }
+void Parameter::setIsOutflowNormal(bool isOutflowNormal) { ic.isOutflowNormal = isOutflowNormal; }
+void Parameter::setIsProp(bool isProp) { ic.isProp = isProp; }
+void Parameter::setIsCp(bool isCp) { ic.isCp = isCp; }
+void Parameter::setConcFile(bool concFile) { ic.isConc = concFile; }
+void Parameter::setStreetVelocityFile(bool streetVelocityFile) { ic.streetVelocityFile = streetVelocityFile; }
+void Parameter::setUseMeasurePoints(bool useMeasurePoints) { ic.isMeasurePoints = useMeasurePoints; }
+void Parameter::setUseWale(bool useWale) { ic.isWale = useWale; }
+void Parameter::setUseInitNeq(bool useInitNeq) { ic.isInitNeq = useInitNeq; }
+void Parameter::setSimulatePorousMedia(bool simulatePorousMedia) { ic.simulatePorousMedia = simulatePorousMedia; }
+
+void Parameter::setIsF3(bool isF3) { this->isF3 = isF3; }
+
+void Parameter::setIsBodyForce(bool isBodyForce) { this->isBodyForce = isBodyForce; }
+
+void Parameter::setGridX(std::vector<int> GridX) { ic.GridX = GridX; }
+void Parameter::setGridY(std::vector<int> GridY) { ic.GridY = GridY; }
+void Parameter::setGridZ(std::vector<int> GridZ) { ic.GridZ = GridZ; }
+void Parameter::setDistX(std::vector<int> DistX) { ic.DistX = DistX; }
+void Parameter::setDistY(std::vector<int> DistY) { ic.DistY = DistY; }
+void Parameter::setDistZ(std::vector<int> DistZ) { ic.DistZ = DistZ; }
+void Parameter::setScaleLBMtoSI(std::vector<real> scaleLBMtoSI) { ic.scaleLBMtoSI = scaleLBMtoSI; }
+void Parameter::setTranslateLBMtoSI(std::vector<real> translateLBMtoSI) { ic.translateLBMtoSI = translateLBMtoSI; }
+void Parameter::setMinCoordX(std::vector<real> MinCoordX) { ic.minCoordX = MinCoordX; }
+void Parameter::setMinCoordY(std::vector<real> MinCoordY) { ic.minCoordY = MinCoordY; }
+void Parameter::setMinCoordZ(std::vector<real> MinCoordZ) { ic.minCoordZ = MinCoordZ; }
+void Parameter::setMaxCoordX(std::vector<real> MaxCoordX) { ic.maxCoordX = MaxCoordX; }
+void Parameter::setMaxCoordY(std::vector<real> MaxCoordY) { ic.maxCoordY = MaxCoordY; }
+void Parameter::setMaxCoordZ(std::vector<real> MaxCoordZ) { ic.maxCoordZ = MaxCoordZ; }
+void Parameter::setTempH(TempforBoundaryConditions *TempH) { this->TempH = TempH; }
+void Parameter::setTempD(TempforBoundaryConditions *TempD) { this->TempD = TempD; }
+void Parameter::setTempVelH(TempVelforBoundaryConditions *TempVelH) { this->TempVelH = TempVelH; }
+void Parameter::setTempVelD(TempVelforBoundaryConditions *TempVelD) { this->TempVelD = TempVelD; }
+void Parameter::setTempPressH(TempPressforBoundaryConditions *TempPressH) { this->TempPressH = TempPressH; }
+void Parameter::setTempPressD(TempPressforBoundaryConditions *TempPressD) { this->TempPressD = TempPressD; }
+// void Parameter::setkInflowQ(unsigned int kInflowQ)
+//{
+//   this->kInflowQ = kInflowQ;
+//}
+// void Parameter::setkOutflowQ(unsigned int kOutflowQ)
+//{
+//   this->kOutflowQ = kOutflowQ;
+//}
+// void Parameter::setQinflowH(QforBoundaryConditions* QinflowH)
+//{
+//   this->QinflowH = QinflowH;
+//}
+// void Parameter::setQinflowD(QforBoundaryConditions* QinflowD)
+//{
+//   this->QinflowD = QinflowD;
+//}
+// void Parameter::setQoutflowH(QforBoundaryConditions* QoutflowH)
+//{
+//   this->QoutflowH = QoutflowH;
+//}
+// void Parameter::setQoutflowD(QforBoundaryConditions* QoutflowD)
+//{
+//   this->QoutflowD = QoutflowD;
+//}
+void Parameter::setkFull(std::string kFull) { ic.kFull = kFull; }
+void Parameter::setgeoFull(std::string geoFull) { ic.geoFull = geoFull; }
+void Parameter::setgeoVec(std::string geoVec) { ic.geoVec = geoVec; }
+void Parameter::setcoordX(std::string coordX) { ic.coordX = coordX; }
+void Parameter::setcoordY(std::string coordY) { ic.coordY = coordY; }
+void Parameter::setcoordZ(std::string coordZ) { ic.coordZ = coordZ; }
+void Parameter::setneighborX(std::string neighborX) { ic.neighborX = neighborX; }
+void Parameter::setneighborY(std::string neighborY) { ic.neighborY = neighborY; }
+void Parameter::setneighborZ(std::string neighborZ) { ic.neighborZ = neighborZ; }
+void Parameter::setneighborWSB(std::string neighborWSB) { ic.neighborWSB = neighborWSB; }
+void Parameter::setscaleCFC(std::string scaleCFC) { ic.scaleCFC = scaleCFC; }
+void Parameter::setscaleCFF(std::string scaleCFF) { ic.scaleCFF = scaleCFF; }
+void Parameter::setscaleFCC(std::string scaleFCC) { ic.scaleFCC = scaleFCC; }
+void Parameter::setscaleFCF(std::string scaleFCF) { ic.scaleFCF = scaleFCF; }
+void Parameter::setscaleOffsetCF(std::string scaleOffsetCF) { ic.scaleOffsetCF = scaleOffsetCF; }
+void Parameter::setscaleOffsetFC(std::string scaleOffsetFC) { ic.scaleOffsetFC = scaleOffsetFC; }
+void Parameter::setgeomBoundaryBcQs(std::string geomBoundaryBcQs) { ic.geomBoundaryBcQs = geomBoundaryBcQs; }
+void Parameter::setgeomBoundaryBcValues(std::string geomBoundaryBcValues)
 {
-    this->startXHotWall = startXHotWall;
+    ic.geomBoundaryBcValues = geomBoundaryBcValues;
 }
-void Parameter::setEndXHotWall(real endXHotWall)
+void Parameter::setnoSlipBcPos(std::string noSlipBcPos) { ic.noSlipBcPos = noSlipBcPos; }
+void Parameter::setnoSlipBcQs(std::string noSlipBcQs) { ic.noSlipBcQs = noSlipBcQs; }
+void Parameter::setnoSlipBcValue(std::string noSlipBcValue) { ic.noSlipBcValue = noSlipBcValue; }
+void Parameter::setnoSlipBcValues(std::string noSlipBcValues) { ic.noSlipBcValues = noSlipBcValues; }
+void Parameter::setslipBcPos(std::string slipBcPos) { ic.slipBcPos = slipBcPos; }
+void Parameter::setslipBcQs(std::string slipBcQs) { ic.slipBcQs = slipBcQs; }
+void Parameter::setslipBcValue(std::string slipBcValue) { ic.slipBcValue = slipBcValue; }
+void Parameter::setpressBcPos(std::string pressBcPos) { ic.pressBcPos = pressBcPos; }
+void Parameter::setpressBcQs(std::string pressBcQs) { ic.pressBcQs = pressBcQs; }
+void Parameter::setpressBcValue(std::string pressBcValue) { ic.pressBcValue = pressBcValue; }
+void Parameter::setpressBcValues(std::string pressBcValues) { ic.pressBcValues = pressBcValues; }
+void Parameter::setvelBcQs(std::string velBcQs) { ic.velBcQs = velBcQs; }
+void Parameter::setvelBcValues(std::string velBcValues) { ic.velBcValues = velBcValues; }
+void Parameter::setinletBcQs(std::string inletBcQs) { ic.inletBcQs = inletBcQs; }
+void Parameter::setinletBcValues(std::string inletBcValues) { ic.inletBcValues = inletBcValues; }
+void Parameter::setoutletBcQs(std::string outletBcQs) { ic.outletBcQs = outletBcQs; }
+void Parameter::setoutletBcValues(std::string outletBcValues) { ic.outletBcValues = outletBcValues; }
+void Parameter::settopBcQs(std::string topBcQs) { ic.topBcQs = topBcQs; }
+void Parameter::settopBcValues(std::string topBcValues) { ic.topBcValues = topBcValues; }
+void Parameter::setbottomBcQs(std::string bottomBcQs) { ic.bottomBcQs = bottomBcQs; }
+void Parameter::setbottomBcValues(std::string bottomBcValues) { ic.bottomBcValues = bottomBcValues; }
+void Parameter::setfrontBcQs(std::string frontBcQs) { ic.frontBcQs = frontBcQs; }
+void Parameter::setfrontBcValues(std::string frontBcValues) { ic.frontBcValues = frontBcValues; }
+void Parameter::setbackBcQs(std::string backBcQs) { ic.backBcQs = backBcQs; }
+void Parameter::setbackBcValues(std::string backBcValues) { ic.backBcValues = backBcValues; }
+void Parameter::setwallBcQs(std::string wallBcQs) { ic.wallBcQs = wallBcQs; }
+void Parameter::setwallBcValues(std::string wallBcValues) { ic.wallBcValues = wallBcValues; }
+void Parameter::setperiodicBcQs(std::string periodicBcQs) { ic.periodicBcQs = periodicBcQs; }
+void Parameter::setperiodicBcValues(std::string periodicBcValues) { ic.periodicBcValues = periodicBcValues; }
+void Parameter::setpropellerQs(std::string propellerQs) { ic.propellerQs = propellerQs; }
+void Parameter::setpropellerValues(std::string propellerValues) { ic.propellerValues = propellerValues; }
+void Parameter::setpropellerCylinder(std::string propellerCylinder) { ic.propellerCylinder = propellerCylinder; }
+void Parameter::setmeasurePoints(std::string measurePoints) { ic.measurePoints = measurePoints; }
+void Parameter::setnumberNodes(std::string numberNodes) { ic.numberNodes = numberNodes; }
+void Parameter::setLBMvsSI(std::string LBMvsSI) { ic.LBMvsSI = LBMvsSI; }
+void Parameter::setcpTop(std::string cpTop) { ic.cpTop = cpTop; }
+void Parameter::setcpBottom(std::string cpBottom) { ic.cpBottom = cpBottom; }
+void Parameter::setcpBottom2(std::string cpBottom2) { ic.cpBottom2 = cpBottom2; }
+void Parameter::setConcentration(std::string concFile) { ic.concentration = concFile; }
+void Parameter::setStreetVelocity(std::string streetVelocity) { ic.streetVelocity = streetVelocity; }
+void Parameter::setclockCycleForMP(real clockCycleForMP) { ic.clockCycleForMP = clockCycleForMP; }
+void Parameter::setTimeDoCheckPoint(unsigned int tDoCheckPoint) { ic.tDoCheckPoint = tDoCheckPoint; }
+void Parameter::setTimeDoRestart(unsigned int tDoRestart) { ic.tDoRestart = tDoRestart; }
+void Parameter::setDoCheckPoint(bool doCheckPoint) { ic.doCheckPoint = doCheckPoint; }
+void Parameter::setDoRestart(bool doRestart) { ic.doRestart = doRestart; }
+void Parameter::settimestepForMP(unsigned int timestepForMP) { ic.timeStepForMP = timestepForMP; }
+void Parameter::setObj(std::string str, bool isObj)
 {
-    this->endXHotWall = endXHotWall;
+    if (str == "geo") {
+        this->setIsGeo(isObj);
+    } else if (str == "prop") {
+        this->setIsProp(isObj);
+    } else if (str == "cp") {
+        this->setIsCp(isObj);
+    } else if (str == "geoNormal") {
+        this->setIsGeoNormal(isObj);
+    } else if (str == "inflowNormal") {
+        this->setIsInflowNormal(isObj);
+    } else if (str == "outflowNormal") {
+        this->setIsOutflowNormal(isObj);
+    }
 }
-void Parameter::setTEnd(unsigned int tend)
+void Parameter::setGeometryValues(bool GeometryValues) { ic.GeometryValues = GeometryValues; }
+void Parameter::setCalc2ndOrderMoments(bool is2ndOrderMoments) { ic.is2ndOrderMoments = is2ndOrderMoments; }
+void Parameter::setCalc3rdOrderMoments(bool is3rdOrderMoments) { ic.is3rdOrderMoments = is3rdOrderMoments; }
+void Parameter::setCalcHighOrderMoments(bool isHighOrderMoments) { ic.isHighOrderMoments = isHighOrderMoments; }
+void Parameter::setMemsizeGPU(double admem, bool reset)
 {
-    ic.tend = tend;
+    if (reset == true) {
+        this->memsizeGPU = 0.;
+    } else {
+        this->memsizeGPU += admem;
+    }
 }
-void Parameter::setTOut(unsigned int tout)
+// 1D domain decomposition
+void Parameter::setPossNeighborFiles(std::vector<std::string> possNeighborFiles, std::string sor)
 {
-    ic.tout = tout;
+    if (sor == "send") {
+        this->possNeighborFilesSend = possNeighborFiles;
+    } else if (sor == "recv") {
+        this->possNeighborFilesRecv = possNeighborFiles;
+    }
 }
-void Parameter::setTStartOut(unsigned int tStartOut)
+void Parameter::setNumberOfProcessNeighbors(unsigned int numberOfProcessNeighbors, int level, std::string sor)
 {
-    ic.tStartOut = tStartOut;
+    if (sor == "send") {
+        parH[level]->sendProcessNeighbor.resize(numberOfProcessNeighbors);
+        parD[level]->sendProcessNeighbor.resize(numberOfProcessNeighbors);
+    } else if (sor == "recv") {
+        parH[level]->recvProcessNeighbor.resize(numberOfProcessNeighbors);
+        parD[level]->recvProcessNeighbor.resize(numberOfProcessNeighbors);
+    }
 }
-void Parameter::setTimestepOfCoarseLevel(unsigned int timestep)
+void Parameter::setIsNeighbor(bool isNeigbor) { this->isNeigbor = isNeigbor; }
+// 3D domain decomposition
+void Parameter::setPossNeighborFilesX(std::vector<std::string> possNeighborFiles, std::string sor)
 {
-    this->timestep = timestep; 
+    if (sor == "send") {
+        this->possNeighborFilesSendX = possNeighborFiles;
+    } else if (sor == "recv") {
+        this->possNeighborFilesRecvX = possNeighborFiles;
+    }
 }
-void Parameter::setCalcTurbulenceIntensity(bool calcVelocityAndFluctuations) 
+void Parameter::setPossNeighborFilesY(std::vector<std::string> possNeighborFiles, std::string sor)
 {
-    this->calcVelocityAndFluctuations = calcVelocityAndFluctuations;
+    if (sor == "send") {
+        this->possNeighborFilesSendY = possNeighborFiles;
+    } else if (sor == "recv") {
+        this->possNeighborFilesRecvY = possNeighborFiles;
+    }
 }
-void Parameter::setCalcMedian(bool calcMedian)
+void Parameter::setPossNeighborFilesZ(std::vector<std::string> possNeighborFiles, std::string sor)
 {
-    ic.calcMedian = calcMedian;
+    if (sor == "send") {
+        this->possNeighborFilesSendZ = possNeighborFiles;
+    } else if (sor == "recv") {
+        this->possNeighborFilesRecvZ = possNeighborFiles;
+    }
 }
-void Parameter::setCalcDragLift(bool calcDragLift)
+void Parameter::setNumberOfProcessNeighborsX(unsigned int numberOfProcessNeighbors, int level, std::string sor)
 {
-    this->calcDragLift = calcDragLift;
+    if (sor == "send") {
+        parH[level]->sendProcessNeighborX.resize(numberOfProcessNeighbors);
+        parD[level]->sendProcessNeighborX.resize(numberOfProcessNeighbors);
+        //////////////////////////////////////////////////////////////////////////
+        if (getDiffOn() == true) {
+            parH[level]->sendProcessNeighborADX.resize(numberOfProcessNeighbors);
+            parD[level]->sendProcessNeighborADX.resize(numberOfProcessNeighbors);
+        }
+        //////////////////////////////////////////////////////////////////////////
+    } else if (sor == "recv") {
+        parH[level]->recvProcessNeighborX.resize(numberOfProcessNeighbors);
+        parD[level]->recvProcessNeighborX.resize(numberOfProcessNeighbors);
+        //////////////////////////////////////////////////////////////////////////
+        if (getDiffOn() == true) {
+            parH[level]->recvProcessNeighborADX.resize(numberOfProcessNeighbors);
+            parD[level]->recvProcessNeighborADX.resize(numberOfProcessNeighbors);
+        }
+        //////////////////////////////////////////////////////////////////////////
+    }
 }
-void Parameter::setCalcCp(bool calcCp)
+void Parameter::setNumberOfProcessNeighborsY(unsigned int numberOfProcessNeighbors, int level, std::string sor)
 {
-    this->calcCp = calcCp;
+    if (sor == "send") {
+        parH[level]->sendProcessNeighborY.resize(numberOfProcessNeighbors);
+        parD[level]->sendProcessNeighborY.resize(numberOfProcessNeighbors);
+        //////////////////////////////////////////////////////////////////////////
+        if (getDiffOn() == true) {
+            parH[level]->sendProcessNeighborADY.resize(numberOfProcessNeighbors);
+            parD[level]->sendProcessNeighborADY.resize(numberOfProcessNeighbors);
+        }
+        //////////////////////////////////////////////////////////////////////////
+    } else if (sor == "recv") {
+        parH[level]->recvProcessNeighborY.resize(numberOfProcessNeighbors);
+        parD[level]->recvProcessNeighborY.resize(numberOfProcessNeighbors);
+        //////////////////////////////////////////////////////////////////////////
+        if (getDiffOn() == true) {
+            parH[level]->recvProcessNeighborADY.resize(numberOfProcessNeighbors);
+            parD[level]->recvProcessNeighborADY.resize(numberOfProcessNeighbors);
+        }
+        //////////////////////////////////////////////////////////////////////////
+    }
 }
-void Parameter::setWriteVeloASCIIfiles(bool writeVeloASCII)
+void Parameter::setNumberOfProcessNeighborsZ(unsigned int numberOfProcessNeighbors, int level, std::string sor)
 {
-    this->writeVeloASCII = writeVeloASCII;
+    if (sor == "send") {
+        parH[level]->sendProcessNeighborZ.resize(numberOfProcessNeighbors);
+        parD[level]->sendProcessNeighborZ.resize(numberOfProcessNeighbors);
+        //////////////////////////////////////////////////////////////////////////
+        if (getDiffOn() == true) {
+            parH[level]->sendProcessNeighborADZ.resize(numberOfProcessNeighbors);
+            parD[level]->sendProcessNeighborADZ.resize(numberOfProcessNeighbors);
+        }
+        //////////////////////////////////////////////////////////////////////////
+    } else if (sor == "recv") {
+        parH[level]->recvProcessNeighborZ.resize(numberOfProcessNeighbors);
+        parD[level]->recvProcessNeighborZ.resize(numberOfProcessNeighbors);
+        //////////////////////////////////////////////////////////////////////////
+        if (getDiffOn() == true) {
+            parH[level]->recvProcessNeighborADZ.resize(numberOfProcessNeighbors);
+            parD[level]->recvProcessNeighborADZ.resize(numberOfProcessNeighbors);
+        }
+        //////////////////////////////////////////////////////////////////////////
+    }
 }
-void Parameter::setCalcPlaneConc(bool calcPlaneConc)
+void Parameter::setIsNeighborX(bool isNeigbor) { this->isNeigborX = isNeigbor; }
+void Parameter::setIsNeighborY(bool isNeigbor) { this->isNeigborY = isNeigbor; }
+void Parameter::setIsNeighborZ(bool isNeigbor) { this->isNeigborZ = isNeigbor; }
+void Parameter::setSendProcessNeighborsAfterFtoCX(int numberOfNodes, int level, int arrayIndex)
 {
-    this->calcPlaneConc = calcPlaneConc;
-}
-void Parameter::setTimeCalcMedStart(int CalcMedStart)
-{		
-    ic.tCalcMedStart = CalcMedStart;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
 }
-void Parameter::setTimeCalcMedEnd(int CalcMedEnd)
+void Parameter::setSendProcessNeighborsAfterFtoCY(int numberOfNodes, int level, int arrayIndex)
 {
-    ic.tCalcMedEnd = CalcMedEnd;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
 }
-void Parameter::setOutputPath(std::string oPath)
+void Parameter::setSendProcessNeighborsAfterFtoCZ(int numberOfNodes, int level, int arrayIndex)
 {
-    ic.oPath = oPath;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParH(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
+    this->getParD(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
 }
-void Parameter::setOutputPrefix(std::string oPrefix)
+void Parameter::setRecvProcessNeighborsAfterFtoCX(int numberOfNodes, int level, int arrayIndex)
 {
-    //std::string test = fname;
-    ic.oPrefix = oPrefix;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
 }
-void Parameter::setFName(std::string fname)
+void Parameter::setRecvProcessNeighborsAfterFtoCY(int numberOfNodes, int level, int arrayIndex)
 {
-    //std::string test = fname;
-    ic.fname = fname;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
 }
-void Parameter::setPrintFiles(bool printfiles)
+void Parameter::setRecvProcessNeighborsAfterFtoCZ(int numberOfNodes, int level, int arrayIndex)
 {
-    ic.printFiles = printfiles;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
+    this->getParH(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
+    this->getParD(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
 }
-void Parameter::setReadGeo(bool readGeo)
+void Parameter::setgeomBoundaryNormalX(std::string geomNormalX) { ic.geomNormalX = geomNormalX; }
+void Parameter::setgeomBoundaryNormalY(std::string geomNormalY) { ic.geomNormalY = geomNormalY; }
+void Parameter::setgeomBoundaryNormalZ(std::string geomNormalZ) { ic.geomNormalZ = geomNormalZ; }
+void Parameter::setInflowBoundaryNormalX(std::string inflowNormalX) { ic.inflowNormalX = inflowNormalX; }
+void Parameter::setInflowBoundaryNormalY(std::string inflowNormalY) { ic.inflowNormalY = inflowNormalY; }
+void Parameter::setInflowBoundaryNormalZ(std::string inflowNormalZ) { ic.inflowNormalZ = inflowNormalZ; }
+void Parameter::setOutflowBoundaryNormalX(std::string outflowNormalX) { ic.outflowNormalX = outflowNormalX; }
+void Parameter::setOutflowBoundaryNormalY(std::string outflowNormalY) { ic.outflowNormalY = outflowNormalY; }
+void Parameter::setOutflowBoundaryNormalZ(std::string outflowNormalZ) { ic.outflowNormalZ = outflowNormalZ; }
+void Parameter::setMainKernel(std::string kernel)
 {
-    ic.readGeo = readGeo;
+    this->mainKernel = kernel;
+    if (kernel.find("Stream") != std::string::npos)
+        this->kernelNeedsFluidNodeIndicesToRun = true;
 }
-void Parameter::setDiffusivity(real Diffusivity)
+void Parameter::setMultiKernelOn(bool isOn) { this->multiKernelOn = isOn; }
+void Parameter::setMultiKernelLevel(std::vector<int> kernelLevel) { this->multiKernelLevel = kernelLevel; }
+void Parameter::setMultiKernel(std::vector<std::string> kernel) { this->multiKernel = kernel; }
+void Parameter::setADKernel(std::string adKernel) { this->adKernel = adKernel; }
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// get-methods
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+double *Parameter::getForcesDouble() { return this->hostForcing; }
+real *Parameter::getForcesHost() { return this->forcingH; }
+real *Parameter::getForcesDev() { return this->forcingD; }
+double *Parameter::getQuadricLimitersDouble() { return this->hostQuadricLimiters; }
+real *Parameter::getQuadricLimitersHost() { return this->quadricLimitersH; }
+real *Parameter::getQuadricLimitersDev() { return this->quadricLimitersD; }
+real Parameter::getPhi() { return Phi; }
+real Parameter::getAngularVelocity() { return angularVelocity; }
+real Parameter::getStartXHotWall() { return this->startXHotWall; }
+real Parameter::getEndXHotWall() { return this->endXHotWall; }
+unsigned int Parameter::getStepEnsight() { return this->stepEnsight; }
+unsigned int Parameter::getOutputCount() { return this->outputCount; }
+unsigned int Parameter::getlimitOfNodesForVTK() { return this->limitOfNodesForVTK; }
+unsigned int Parameter::getStartTurn() { return startTurn; }
+std::shared_ptr<LBMSimulationParameter> Parameter::getParD(int level) { return parD[level]; }
+std::shared_ptr<LBMSimulationParameter> Parameter::getParH(int level) { return parH[level]; }
+unsigned int Parameter::getSizeMat(int level) { return parH[level]->size_Mat; }
+unsigned int Parameter::getMemSizereal(int level) { return parH[level]->mem_size_real; }
+unsigned int Parameter::getMemSizeInt(int level) { return parH[level]->mem_size_int; }
+unsigned int Parameter::getMemSizeBool(int level) { return parH[level]->mem_size_bool; }
+unsigned int Parameter::getMemSizerealYZ(int level) { return parH[level]->mem_size_real_yz; }
+int Parameter::getFine() { return fine; }
+int Parameter::getCoarse() { return coarse; }
+int Parameter::getParticleBasicLevel() { return this->particleBasicLevel; }
+int Parameter::getParticleInitLevel() { return this->particleInitLevel; }
+int Parameter::getNumberOfParticles() { return this->numberOfParticles; }
+bool Parameter::getEvenOrOdd(int level) { return parH[level]->evenOrOdd; }
+bool Parameter::getDiffOn() { return diffOn; }
+bool Parameter::getCompOn() { return compOn; }
+int Parameter::getDiffMod() { return diffMod; }
+int Parameter::getFactorNZ() { return factor_gridNZ; }
+int Parameter::getD3Qxx() { return this->D3Qxx; }
+int Parameter::getMaxLevel() { return this->maxlevel; }
+unsigned int Parameter::getTStart()
 {
-    ic.Diffusivity = Diffusivity;
+    if (getDoRestart()) {
+        return getTimeDoRestart() + 1;
+    } else {
+        return 1;
+    }
 }
-void Parameter::setTemperatureInit(real Temp)
+unsigned int Parameter::getTInit()
 {
-    ic.Temp = Temp;
+    if (getDoRestart()) {
+        return getTimeDoRestart();
+    } else {
+        return 0;
+    }
 }
-void Parameter::setTemperatureBC(real TempBC)
+unsigned int Parameter::getTEnd() { return ic.tend; }
+unsigned int Parameter::getTOut() { return ic.tout; }
+unsigned int Parameter::getTStartOut() { return ic.tStartOut; }
+bool Parameter::getCalcMedian() { return ic.calcMedian; }
+bool Parameter::getCalcDragLift() { return this->calcDragLift; }
+bool Parameter::getCalcCp() { return this->calcCp; }
+bool Parameter::getCalcParticle() { return this->calcParticles; }
+bool Parameter::getWriteVeloASCIIfiles() { return this->writeVeloASCII; }
+bool Parameter::getCalcPlaneConc() { return this->calcPlaneConc; }
+int Parameter::getTimeCalcMedStart() { return ic.tCalcMedStart; }
+int Parameter::getTimeCalcMedEnd() { return ic.tCalcMedEnd; }
+std::string Parameter::getOutputPath() { return ic.oPath; }
+std::string Parameter::getOutputPrefix() { return ic.oPrefix; }
+std::string Parameter::getFName() { return ic.fname; }
+bool Parameter::getPrintFiles() { return ic.printFiles; }
+bool Parameter::getReadGeo() { return ic.readGeo; }
+bool Parameter::getCalcTurbulenceIntensity() { return this->calcVelocityAndFluctuations; }
+real Parameter::getDiffusivity() { return ic.Diffusivity; }
+real Parameter::getTemperatureInit() { return ic.Temp; }
+real Parameter::getTemperatureBC() { return ic.TempBC; }
+real Parameter::getViscosity() { return ic.vis; }
+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::getPressRatio() { return ic.delta_press; }
+real Parameter::getRealX() { return ic.RealX; }
+real Parameter::getRealY() { return ic.RealY; }
+unsigned int Parameter::getPressInID() { return ic.PressInID; }
+unsigned int Parameter::getPressOutID() { return ic.PressOutID; }
+unsigned int Parameter::getPressInZ() { return ic.PressInZ; }
+unsigned int Parameter::getPressOutZ() { return ic.PressOutZ; }
+int Parameter::getMaxDev() { return ic.maxdev; }
+int Parameter::getMyID() { return ic.myid; }
+int Parameter::getNumprocs() { return ic.numprocs; }
+std::vector<uint> Parameter::getDevices() { return ic.devices; }
+std::string Parameter::getGeometryFileC() { return ic.geometryFileC; }
+std::string Parameter::getGeometryFileM() { return ic.geometryFileM; }
+std::string Parameter::getGeometryFileF() { return ic.geometryFileF; }
+real Parameter::getRe() { return ic.Re; }
+real Parameter::getFactorPressBC() { return ic.factorPressBC; }
+std::vector<int> Parameter::getGridX() { return ic.GridX; }
+std::vector<int> Parameter::getGridY() { return ic.GridY; }
+std::vector<int> Parameter::getGridZ() { return ic.GridZ; }
+std::vector<int> Parameter::getDistX() { return ic.DistX; }
+std::vector<int> Parameter::getDistY() { return ic.DistY; }
+std::vector<int> Parameter::getDistZ() { return ic.DistZ; }
+std::vector<real> Parameter::getScaleLBMtoSI() { return ic.scaleLBMtoSI; }
+std::vector<real> Parameter::getTranslateLBMtoSI() { return ic.translateLBMtoSI; }
+std::vector<real> Parameter::getMinCoordX() { return ic.minCoordX; }
+std::vector<real> Parameter::getMinCoordY() { return ic.minCoordY; }
+std::vector<real> Parameter::getMinCoordZ() { return ic.minCoordZ; }
+std::vector<real> Parameter::getMaxCoordX() { return ic.maxCoordX; }
+std::vector<real> Parameter::getMaxCoordY() { return ic.maxCoordY; }
+std::vector<real> Parameter::getMaxCoordZ() { return ic.maxCoordZ; }
+TempforBoundaryConditions *Parameter::getTempH() { return this->TempH; }
+TempforBoundaryConditions *Parameter::getTempD() { return this->TempD; }
+TempVelforBoundaryConditions *Parameter::getTempVelH() { return this->TempVelH; }
+TempVelforBoundaryConditions *Parameter::getTempVelD() { return this->TempVelD; }
+TempPressforBoundaryConditions *Parameter::getTempPressH() { return this->TempPressH; }
+TempPressforBoundaryConditions *Parameter::getTempPressD() { return this->TempPressD; }
+// unsigned int Parameter::getkInflowQ()
+//{
+//   return this->kInflowQ;
+//}
+// unsigned int Parameter::getkOutflowQ()
+//{
+//   return this->kOutflowQ;
+//}
+// QforBoundaryConditions* Parameter::getQinflowH()
+//{
+//   return this->QinflowH;
+//}
+// QforBoundaryConditions* Parameter::getQinflowD()
+//{
+//   return this->QinflowD;
+//}
+// QforBoundaryConditions* Parameter::getQoutflowH()
+//{
+//   return this->QoutflowH;
+//}
+// QforBoundaryConditions* Parameter::getQoutflowD()
+//{
+//   return this->QoutflowD;
+//}
+std::string Parameter::getkFull() { return ic.kFull; }
+std::string Parameter::getgeoFull() { return ic.geoFull; }
+std::string Parameter::getgeoVec() { return ic.geoVec; }
+std::string Parameter::getcoordX() { return ic.coordX; }
+std::string Parameter::getcoordY() { return ic.coordY; }
+std::string Parameter::getcoordZ() { return ic.coordZ; }
+std::string Parameter::getneighborX() { return ic.neighborX; }
+std::string Parameter::getneighborY() { return ic.neighborY; }
+std::string Parameter::getneighborZ() { return ic.neighborZ; }
+std::string Parameter::getneighborWSB() { return ic.neighborWSB; }
+std::string Parameter::getscaleCFC() { return ic.scaleCFC; }
+std::string Parameter::getscaleCFF() { return ic.scaleCFF; }
+std::string Parameter::getscaleFCC() { return ic.scaleFCC; }
+std::string Parameter::getscaleFCF() { return ic.scaleFCF; }
+std::string Parameter::getscaleOffsetCF() { return ic.scaleOffsetCF; }
+std::string Parameter::getscaleOffsetFC() { return ic.scaleOffsetFC; }
+std::string Parameter::getgeomBoundaryBcQs() { return ic.geomBoundaryBcQs; }
+std::string Parameter::getgeomBoundaryBcValues() { return ic.geomBoundaryBcValues; }
+std::string Parameter::getnoSlipBcPos() { return ic.noSlipBcPos; }
+std::string Parameter::getnoSlipBcQs() { return ic.noSlipBcQs; }
+std::string Parameter::getnoSlipBcValue() { return ic.noSlipBcValue; }
+std::string Parameter::getnoSlipBcValues() { return ic.noSlipBcValues; }
+std::string Parameter::getslipBcPos() { return ic.slipBcPos; }
+std::string Parameter::getslipBcQs() { return ic.slipBcQs; }
+std::string Parameter::getslipBcValue() { return ic.slipBcValue; }
+std::string Parameter::getpressBcPos() { return ic.pressBcPos; }
+std::string Parameter::getpressBcQs() { return ic.pressBcQs; }
+std::string Parameter::getpressBcValue() { return ic.pressBcValue; }
+std::string Parameter::getpressBcValues() { return ic.pressBcValues; }
+std::string Parameter::getvelBcQs() { return ic.velBcQs; }
+std::string Parameter::getvelBcValues() { return ic.velBcValues; }
+std::string Parameter::getinletBcQs() { return ic.inletBcQs; }
+std::string Parameter::getinletBcValues() { return ic.inletBcValues; }
+std::string Parameter::getoutletBcQs() { return ic.outletBcQs; }
+std::string Parameter::getoutletBcValues() { return ic.outletBcValues; }
+std::string Parameter::gettopBcQs() { return ic.topBcQs; }
+std::string Parameter::gettopBcValues() { return ic.topBcValues; }
+std::string Parameter::getbottomBcQs() { return ic.bottomBcQs; }
+std::string Parameter::getbottomBcValues() { return ic.bottomBcValues; }
+std::string Parameter::getfrontBcQs() { return ic.frontBcQs; }
+std::string Parameter::getfrontBcValues() { return ic.frontBcValues; }
+std::string Parameter::getbackBcQs() { return ic.backBcQs; }
+std::string Parameter::getbackBcValues() { return ic.backBcValues; }
+std::string Parameter::getwallBcQs() { return ic.wallBcQs; }
+std::string Parameter::getwallBcValues() { return ic.wallBcValues; }
+std::string Parameter::getperiodicBcQs() { return ic.periodicBcQs; }
+std::string Parameter::getperiodicBcValues() { return ic.periodicBcValues; }
+std::string Parameter::getpropellerQs() { return ic.propellerQs; }
+std::string Parameter::getpropellerValues() { return ic.propellerValues; }
+std::string Parameter::getpropellerCylinder() { return ic.propellerCylinder; }
+std::string Parameter::getmeasurePoints() { return ic.measurePoints; }
+std::string Parameter::getLBMvsSI() { return ic.LBMvsSI; }
+std::string Parameter::getnumberNodes() { return ic.numberNodes; }
+std::string Parameter::getcpTop() { return ic.cpTop; }
+std::string Parameter::getcpBottom() { return ic.cpBottom; }
+std::string Parameter::getcpBottom2() { return ic.cpBottom2; }
+std::string Parameter::getConcentration() { return ic.concentration; }
+std::string Parameter::getStreetVelocityFilePath() { return ic.streetVelocity; }
+real Parameter::getclockCycleForMP() { return ic.clockCycleForMP; }
+unsigned int Parameter::getTimeDoCheckPoint() { return ic.tDoCheckPoint; }
+unsigned int Parameter::getTimeDoRestart() { return ic.tDoRestart; }
+bool Parameter::getDoCheckPoint() { return ic.doCheckPoint; }
+bool Parameter::getDoRestart() { return ic.doRestart; }
+bool Parameter::getIsGeo() { return ic.isGeo; }
+bool Parameter::getIsGeoNormal() { return ic.isGeoNormal; }
+bool Parameter::getIsInflowNormal() { return ic.isInflowNormal; }
+bool Parameter::getIsOutflowNormal() { return ic.isOutflowNormal; }
+bool Parameter::getIsCp() { return ic.isCp; }
+bool Parameter::getConcFile() { return ic.isConc; }
+bool Parameter::isStreetVelocityFile() { return ic.streetVelocityFile; }
+bool Parameter::getUseMeasurePoints() { return ic.isMeasurePoints; }
+bool Parameter::getUseWale() { return ic.isWale; }
+bool Parameter::getUseInitNeq() { return ic.isInitNeq; }
+bool Parameter::getSimulatePorousMedia() { return ic.simulatePorousMedia; }
+
+bool Parameter::getIsF3() { return this->isF3; }
+
+bool Parameter::getIsBodyForce() { return this->isBodyForce; }
+
+bool Parameter::getIsGeometryValues() { return ic.GeometryValues; }
+bool Parameter::getCalc2ndOrderMoments() { return ic.is2ndOrderMoments; }
+bool Parameter::getCalc3rdOrderMoments() { return ic.is3rdOrderMoments; }
+bool Parameter::getCalcHighOrderMoments() { return ic.isHighOrderMoments; }
+bool Parameter::getIsProp() { return ic.isProp; }
+bool Parameter::overWritingRestart(uint t) { return t == getTimeDoRestart(); }
+unsigned int Parameter::getTimestepForMP() { return ic.timeStepForMP; }
+unsigned int Parameter::getTimestepOfCoarseLevel() { return this->timestep; }
+double Parameter::getMemsizeGPU() { return this->memsizeGPU; }
+// 1D domain decomposition
+std::vector<std::string> Parameter::getPossNeighborFiles(std::string sor)
 {
-    ic.TempBC = TempBC;
+    if (sor == "send") {
+        return this->possNeighborFilesSend;
+    } else if (sor == "recv") {
+        return this->possNeighborFilesRecv;
+    }
+    throw std::runtime_error("Parameter string invalid.");
 }
-void Parameter::setViscosity(real Viscosity)
+unsigned int Parameter::getNumberOfProcessNeighbors(int level, std::string sor)
 {
-    ic.vis = Viscosity;
+    if (sor == "send") {
+        return (unsigned int)parH[level]->sendProcessNeighbor.size();
+    } else if (sor == "recv") {
+        return (unsigned int)parH[level]->recvProcessNeighbor.size();
+    }
+    throw std::runtime_error("Parameter string invalid.");
 }
-void Parameter::setVelocity(real Velocity)
+bool Parameter::getIsNeighbor() { return this->isNeigbor; }
+// 3D domain decomposition
+std::vector<std::string> Parameter::getPossNeighborFilesX(std::string sor)
 {
-    ic.u0 = Velocity;
+    if (sor == "send") {
+        return this->possNeighborFilesSendX;
+    } else if (sor == "recv") {
+        return this->possNeighborFilesRecvX;
+    }
+    throw std::runtime_error("Parameter string invalid.");
 }
-void Parameter::setViscosityRatio(real ViscosityRatio)
+std::vector<std::string> Parameter::getPossNeighborFilesY(std::string sor)
 {
-    ic.vis_ratio = ViscosityRatio;
+    if (sor == "send") {
+        return this->possNeighborFilesSendY;
+    } else if (sor == "recv") {
+        return this->possNeighborFilesRecvY;
+    }
+    throw std::runtime_error("Parameter string invalid.");
 }
-void Parameter::setVelocityRatio(real VelocityRatio)
+std::vector<std::string> Parameter::getPossNeighborFilesZ(std::string sor)
 {
-    ic.u0_ratio = VelocityRatio;
+    if (sor == "send") {
+        return this->possNeighborFilesSendZ;
+    } else if (sor == "recv") {
+        return this->possNeighborFilesRecvZ;
+    }
+    throw std::runtime_error("Parameter string invalid.");
 }
-void Parameter::setDensityRatio(real DensityRatio)
+unsigned int Parameter::getNumberOfProcessNeighborsX(int level, std::string sor)
 {
-    ic.delta_rho = DensityRatio;
+    if (sor == "send") {
+        return (unsigned int)parH[level]->sendProcessNeighborX.size();
+    } else if (sor == "recv") {
+        return (unsigned int)parH[level]->recvProcessNeighborX.size();
+    }
+    throw std::runtime_error("getNumberOfProcessNeighborsX: Parameter string invalid.");
 }
-void Parameter::setPressRatio(real PressRatio)
+unsigned int Parameter::getNumberOfProcessNeighborsY(int level, std::string sor)
 {
-    ic.delta_press = PressRatio;
+    if (sor == "send") {
+        return (unsigned int)parH[level]->sendProcessNeighborY.size();
+    } else if (sor == "recv") {
+        return (unsigned int)parH[level]->recvProcessNeighborY.size();
+    }
+    throw std::runtime_error("getNumberOfProcessNeighborsY: Parameter string invalid.");
 }
-void Parameter::setRealX(real RealX)
+unsigned int Parameter::getNumberOfProcessNeighborsZ(int level, std::string sor)
 {
-    ic.RealX = RealX;
-}
-void Parameter::setRealY(real RealY)
-{
-    ic.RealY = RealY;
-}
-void Parameter::setPressInID(unsigned int PressInID)
-{
-    ic.PressInID = PressInID;
-}
-void Parameter::setPressOutID(unsigned int PressOutID)
-{
-    ic.PressOutID = PressOutID;
-}
-void Parameter::setPressInZ(unsigned int PressInZ)
-{
-    ic.PressInZ = PressInZ;
-}
-void Parameter::setPressOutZ(unsigned int PressOutZ)
-{
-    ic.PressOutZ = PressOutZ;
-}
-void Parameter::setMaxDev(int maxdev)
-{
-    ic.maxdev = maxdev;
-}
-void Parameter::setMyID(int myid)
-{
-    ic.myid = myid;
-}
-void Parameter::setNumprocs(int numprocs)
-{
-    ic.numprocs = numprocs;
-}
-void Parameter::setDevices(std::vector<uint> devices)
-{
-    ic.devices = devices;
-}
-void Parameter::setGeometryFileC(std::string GeometryFileC)
-{
-    ic.geometryFileC = GeometryFileC;
-}
-void Parameter::setGeometryFileM(std::string GeometryFileM)
-{
-    ic.geometryFileM = GeometryFileM;
-}
-void Parameter::setGeometryFileF(std::string GeometryFileF)
-{
-    ic.geometryFileF = GeometryFileF;
-}
-void Parameter::setRe(real Re)
-{
-    ic.Re = Re;
-}
-void Parameter::setFactorPressBC(real factorPressBC)
-{
-    ic.factorPressBC = factorPressBC;
-}
-void Parameter::setIsGeo(bool isGeo)
-{
-    ic.isGeo = isGeo;
-}
-void Parameter::setIsGeoNormal(bool isGeoNormal)
-{
-    ic.isGeoNormal = isGeoNormal;
-}
-void Parameter::setIsInflowNormal(bool isInflowNormal)
-{
-    ic.isInflowNormal = isInflowNormal;
-}
-void Parameter::setIsOutflowNormal(bool isOutflowNormal)
-{
-    ic.isOutflowNormal = isOutflowNormal;
-}
-void Parameter::setIsProp(bool isProp)
-{
-    ic.isProp = isProp;
-}
-void Parameter::setIsCp(bool isCp)
-{
-    ic.isCp = isCp;
-}
-void Parameter::setConcFile(bool concFile)
-{
-    ic.isConc = concFile;
-}
-void Parameter::setStreetVelocityFile(bool streetVelocityFile)
-{
-    ic.streetVelocityFile = streetVelocityFile;
-}
-void Parameter::setUseMeasurePoints(bool useMeasurePoints)
-{
-    ic.isMeasurePoints = useMeasurePoints;
-}
-void Parameter::setUseWale(bool useWale)
-{
-    ic.isWale = useWale;
-}
-void Parameter::setUseInitNeq(bool useInitNeq)
-{
-    ic.isInitNeq = useInitNeq;
-}
-void Parameter::setSimulatePorousMedia(bool simulatePorousMedia)
-{
-    ic.simulatePorousMedia = simulatePorousMedia;
-}
-
-void Parameter::setIsF3(bool isF3)
-{
-    this->isF3 = isF3; 
-}
-
-void Parameter::setIsBodyForce(bool isBodyForce) 
-{
-    this->isBodyForce = isBodyForce;
-}
-
-void Parameter::setGridX(std::vector<int> GridX)
-{
-    ic.GridX = GridX;
-}
-void Parameter::setGridY(std::vector<int> GridY)
-{
-    ic.GridY = GridY;
-}
-void Parameter::setGridZ(std::vector<int> GridZ)
-{
-    ic.GridZ = GridZ;
-}
-void Parameter::setDistX(std::vector<int> DistX)
-{
-    ic.DistX = DistX;
-}
-void Parameter::setDistY(std::vector<int> DistY)
-{
-    ic.DistY = DistY;
-}
-void Parameter::setDistZ(std::vector<int> DistZ)
-{
-    ic.DistZ = DistZ;
-}
-void Parameter::setScaleLBMtoSI(std::vector<real> scaleLBMtoSI)
-{
-    ic.scaleLBMtoSI = scaleLBMtoSI;
-}
-void Parameter::setTranslateLBMtoSI(std::vector<real> translateLBMtoSI)
-{
-    ic.translateLBMtoSI = translateLBMtoSI;
-}
-void Parameter::setMinCoordX(std::vector<real> MinCoordX)
-{
-    ic.minCoordX = MinCoordX;
-}
-void Parameter::setMinCoordY(std::vector<real> MinCoordY)
-{
-    ic.minCoordY = MinCoordY;
-}
-void Parameter::setMinCoordZ(std::vector<real> MinCoordZ)
-{
-    ic.minCoordZ = MinCoordZ;
-}
-void Parameter::setMaxCoordX(std::vector<real> MaxCoordX)
-{
-    ic.maxCoordX = MaxCoordX;
-}
-void Parameter::setMaxCoordY(std::vector<real> MaxCoordY)
-{
-    ic.maxCoordY = MaxCoordY;
-}
-void Parameter::setMaxCoordZ(std::vector<real> MaxCoordZ)
-{
-    ic.maxCoordZ = MaxCoordZ;
-}
-void Parameter::setTempH(TempforBoundaryConditions* TempH)
-{
-    this->TempH = TempH;
-}
-void Parameter::setTempD(TempforBoundaryConditions* TempD)
-{
-    this->TempD = TempD;
-}
-void Parameter::setTempVelH(TempVelforBoundaryConditions* TempVelH)
-{
-    this->TempVelH = TempVelH;
-}
-void Parameter::setTempVelD(TempVelforBoundaryConditions* TempVelD)
-{
-    this->TempVelD = TempVelD;
-}
-void Parameter::setTempPressH(TempPressforBoundaryConditions* TempPressH)
-{
-    this->TempPressH = TempPressH;
-}
-void Parameter::setTempPressD(TempPressforBoundaryConditions* TempPressD)
-{
-    this->TempPressD = TempPressD;
-}
-//void Parameter::setkInflowQ(unsigned int kInflowQ)
-//{
-//   this->kInflowQ = kInflowQ;
-//}
-//void Parameter::setkOutflowQ(unsigned int kOutflowQ)
-//{
-//   this->kOutflowQ = kOutflowQ;
-//}
-//void Parameter::setQinflowH(QforBoundaryConditions* QinflowH)
-//{
-//   this->QinflowH = QinflowH;
-//}
-//void Parameter::setQinflowD(QforBoundaryConditions* QinflowD)
-//{
-//   this->QinflowD = QinflowD;
-//}
-//void Parameter::setQoutflowH(QforBoundaryConditions* QoutflowH)
-//{
-//   this->QoutflowH = QoutflowH;
-//}
-//void Parameter::setQoutflowD(QforBoundaryConditions* QoutflowD)
-//{
-//   this->QoutflowD = QoutflowD;
-//}
-void Parameter::setkFull(std::string kFull)
-{
-    ic.kFull = kFull;
-}
-void Parameter::setgeoFull(std::string geoFull)
-{
-    ic.geoFull = geoFull;
-}
-void Parameter::setgeoVec(std::string geoVec)
-{
-    ic.geoVec = geoVec;
-}
-void Parameter::setcoordX(std::string coordX)
-{
-    ic.coordX = coordX;
-}
-void Parameter::setcoordY(std::string coordY)
-{
-    ic.coordY = coordY;
-}
-void Parameter::setcoordZ(std::string coordZ)
-{
-    ic.coordZ = coordZ;
-}
-void Parameter::setneighborX(std::string neighborX)
-{
-    ic.neighborX = neighborX;
-}
-void Parameter::setneighborY(std::string neighborY)
-{
-    ic.neighborY = neighborY;
-}
-void Parameter::setneighborZ(std::string neighborZ)
-{
-    ic.neighborZ = neighborZ;
-}
-void Parameter::setneighborWSB(std::string neighborWSB)
-{
-    ic.neighborWSB = neighborWSB;
-}
-void Parameter::setscaleCFC(std::string scaleCFC)
-{
-    ic.scaleCFC = scaleCFC;
-}
-void Parameter::setscaleCFF(std::string scaleCFF)
-{
-    ic.scaleCFF = scaleCFF;
-}
-void Parameter::setscaleFCC(std::string scaleFCC)
-{
-    ic.scaleFCC = scaleFCC;
-}
-void Parameter::setscaleFCF(std::string scaleFCF)
-{
-    ic.scaleFCF = scaleFCF;
-}
-void Parameter::setscaleOffsetCF(std::string scaleOffsetCF)
-{
-    ic.scaleOffsetCF = scaleOffsetCF;
-}
-void Parameter::setscaleOffsetFC(std::string scaleOffsetFC)
-{
-    ic.scaleOffsetFC = scaleOffsetFC;
-}
-void Parameter::setgeomBoundaryBcQs(std::string geomBoundaryBcQs)
-{
-    ic.geomBoundaryBcQs = geomBoundaryBcQs;
-}
-void Parameter::setgeomBoundaryBcValues(std::string geomBoundaryBcValues)
-{
-    ic.geomBoundaryBcValues = geomBoundaryBcValues;
-}
-void Parameter::setnoSlipBcPos(std::string noSlipBcPos)
-{
-    ic.noSlipBcPos = noSlipBcPos;
-}
-void Parameter::setnoSlipBcQs(std::string noSlipBcQs)
-{
-    ic.noSlipBcQs = noSlipBcQs;
-}
-void Parameter::setnoSlipBcValue(std::string noSlipBcValue)
-{
-    ic.noSlipBcValue = noSlipBcValue;
-}
-void Parameter::setnoSlipBcValues(std::string noSlipBcValues)
-{
-    ic.noSlipBcValues = noSlipBcValues;
-}
-void Parameter::setslipBcPos(std::string slipBcPos)
-{
-    ic.slipBcPos = slipBcPos;
-}
-void Parameter::setslipBcQs(std::string slipBcQs)
-{
-    ic.slipBcQs = slipBcQs;
-}
-void Parameter::setslipBcValue(std::string slipBcValue)
-{
-    ic.slipBcValue = slipBcValue;
-}
-void Parameter::setpressBcPos(std::string pressBcPos)
-{
-    ic.pressBcPos = pressBcPos;
-}
-void Parameter::setpressBcQs(std::string pressBcQs)
-{
-    ic.pressBcQs = pressBcQs;
-}
-void Parameter::setpressBcValue(std::string pressBcValue)
-{
-    ic.pressBcValue = pressBcValue;
-}
-void Parameter::setpressBcValues(std::string pressBcValues)
-{
-    ic.pressBcValues = pressBcValues;
-}
-void Parameter::setvelBcQs(std::string velBcQs)
-{
-    ic.velBcQs = velBcQs;
-}
-void Parameter::setvelBcValues(std::string velBcValues)
-{
-    ic.velBcValues = velBcValues;
-}
-void Parameter::setinletBcQs(std::string inletBcQs)
-{
-    ic.inletBcQs = inletBcQs;
-}
-void Parameter::setinletBcValues(std::string inletBcValues)
-{
-    ic.inletBcValues = inletBcValues;
-}
-void Parameter::setoutletBcQs(std::string outletBcQs)
-{
-    ic.outletBcQs = outletBcQs;
-}
-void Parameter::setoutletBcValues(std::string outletBcValues)
-{
-    ic.outletBcValues = outletBcValues;
-}
-void Parameter::settopBcQs(std::string topBcQs)
-{
-    ic.topBcQs = topBcQs;
-}
-void Parameter::settopBcValues(std::string topBcValues)
-{
-    ic.topBcValues = topBcValues;
-}
-void Parameter::setbottomBcQs(std::string bottomBcQs)
-{
-    ic.bottomBcQs = bottomBcQs;
-}
-void Parameter::setbottomBcValues(std::string bottomBcValues)
-{
-    ic.bottomBcValues = bottomBcValues;
-}
-void Parameter::setfrontBcQs(std::string frontBcQs)
-{
-    ic.frontBcQs = frontBcQs;
-}
-void Parameter::setfrontBcValues(std::string frontBcValues)
-{
-    ic.frontBcValues = frontBcValues;
-}
-void Parameter::setbackBcQs(std::string backBcQs)
-{
-    ic.backBcQs = backBcQs;
-}
-void Parameter::setbackBcValues(std::string backBcValues)
-{
-    ic.backBcValues = backBcValues;
-}
-void Parameter::setwallBcQs(std::string wallBcQs)
-{
-    ic.wallBcQs = wallBcQs;
-}
-void Parameter::setwallBcValues(std::string wallBcValues)
-{
-    ic.wallBcValues = wallBcValues;
-}
-void Parameter::setperiodicBcQs(std::string periodicBcQs)
-{
-    ic.periodicBcQs = periodicBcQs;
-}
-void Parameter::setperiodicBcValues(std::string periodicBcValues)
-{
-    ic.periodicBcValues = periodicBcValues;
-}
-void Parameter::setpropellerQs(std::string propellerQs)
-{
-    ic.propellerQs = propellerQs;
-}
-void Parameter::setpropellerValues(std::string propellerValues)
-{
-    ic.propellerValues = propellerValues;
-}
-void Parameter::setpropellerCylinder(std::string propellerCylinder)
-{
-    ic.propellerCylinder = propellerCylinder;
-}
-void Parameter::setmeasurePoints(std::string measurePoints)
-{
-    ic.measurePoints = measurePoints;
-}
-void Parameter::setnumberNodes(std::string numberNodes)
-{
-    ic.numberNodes = numberNodes;
-}
-void Parameter::setLBMvsSI(std::string LBMvsSI)
-{
-    ic.LBMvsSI = LBMvsSI;
-}
-void Parameter::setcpTop(std::string cpTop)
-{
-    ic.cpTop = cpTop;
-}
-void Parameter::setcpBottom(std::string cpBottom)
-{
-    ic.cpBottom = cpBottom;
-}
-void Parameter::setcpBottom2(std::string cpBottom2)
-{
-    ic.cpBottom2 = cpBottom2;
-}
-void Parameter::setConcentration(std::string concFile)
-{
-    ic.concentration = concFile;
-}
-void Parameter::setStreetVelocity(std::string streetVelocity)
-{
-    ic.streetVelocity = streetVelocity;
-}
-void Parameter::setclockCycleForMP(real clockCycleForMP)
-{
-    ic.clockCycleForMP = clockCycleForMP;
-}
-void Parameter::setTimeDoCheckPoint(unsigned int tDoCheckPoint)
-{
-    ic.tDoCheckPoint = tDoCheckPoint;
-}
-void Parameter::setTimeDoRestart(unsigned int tDoRestart)
-{
-    ic.tDoRestart = tDoRestart;
-}
-void Parameter::setDoCheckPoint(bool doCheckPoint)
-{
-    ic.doCheckPoint = doCheckPoint;
-}
-void Parameter::setDoRestart(bool doRestart)
-{
-    ic.doRestart = doRestart;
-}
-void Parameter::settimestepForMP(unsigned int timestepForMP)
-{
-    ic.timeStepForMP = timestepForMP;
-}
-void Parameter::setObj(std::string str, bool isObj)
-{
-    if (str == "geo")
-    {
-        this->setIsGeo(isObj);
-    }
-    else if (str == "prop")
-    {
-        this->setIsProp(isObj);
-    }
-    else if (str == "cp")
-    {
-        this->setIsCp(isObj);
-    }
-    else if (str == "geoNormal")
-    {
-        this->setIsGeoNormal(isObj);
-    }
-    else if (str == "inflowNormal")
-    {
-        this->setIsInflowNormal(isObj);
-    }
-    else if (str == "outflowNormal")
-    {
-        this->setIsOutflowNormal(isObj);
-    }
-}
-void Parameter::setGeometryValues(bool GeometryValues)
-{
-    ic.GeometryValues = GeometryValues;
-}
-void Parameter::setCalc2ndOrderMoments(bool is2ndOrderMoments)
-{
-    ic.is2ndOrderMoments = is2ndOrderMoments;
-}
-void Parameter::setCalc3rdOrderMoments(bool is3rdOrderMoments)
-{
-    ic.is3rdOrderMoments = is3rdOrderMoments;
-}
-void Parameter::setCalcHighOrderMoments(bool isHighOrderMoments)
-{
-    ic.isHighOrderMoments = isHighOrderMoments;
-}
-void Parameter::setMemsizeGPU(double admem, bool reset)
-{
-    if (reset == true)
-    {
-        this->memsizeGPU = 0.;
-    } 
-    else
-    {
-        this->memsizeGPU += admem;
-    }
-}
-//1D domain decomposition
-void Parameter::setPossNeighborFiles(std::vector<std::string> possNeighborFiles, std::string sor)
-{
-    if (sor=="send")
-    {
-        this->possNeighborFilesSend = possNeighborFiles;
-    } 
-    else if (sor == "recv")
-    {
-        this->possNeighborFilesRecv = possNeighborFiles;
-    }
-}
-void Parameter::setNumberOfProcessNeighbors(unsigned int numberOfProcessNeighbors, int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        parH[level]->sendProcessNeighbor.resize(numberOfProcessNeighbors);
-        parD[level]->sendProcessNeighbor.resize(numberOfProcessNeighbors);
-    } 
-    else if (sor == "recv")
-    {
-        parH[level]->recvProcessNeighbor.resize(numberOfProcessNeighbors);
-        parD[level]->recvProcessNeighbor.resize(numberOfProcessNeighbors);
-    }
-}
-void Parameter::setIsNeighbor(bool isNeigbor)
-{
-    this->isNeigbor = isNeigbor;
-}
-//3D domain decomposition
-void Parameter::setPossNeighborFilesX(std::vector<std::string> possNeighborFiles, std::string sor)
-{
-    if (sor=="send")
-    {
-        this->possNeighborFilesSendX = possNeighborFiles;
-    } 
-    else if (sor == "recv")
-    {
-        this->possNeighborFilesRecvX = possNeighborFiles;
-    }
-}
-void Parameter::setPossNeighborFilesY(std::vector<std::string> possNeighborFiles, std::string sor)
-{
-    if (sor=="send")
-    {
-        this->possNeighborFilesSendY = possNeighborFiles;
-    } 
-    else if (sor == "recv")
-    {
-        this->possNeighborFilesRecvY = possNeighborFiles;
-    }
-}
-void Parameter::setPossNeighborFilesZ(std::vector<std::string> possNeighborFiles, std::string sor)
-{
-    if (sor=="send")
-    {
-        this->possNeighborFilesSendZ = possNeighborFiles;
-    } 
-    else if (sor == "recv")
-    {
-        this->possNeighborFilesRecvZ = possNeighborFiles;
-    }
-}
-void Parameter::setNumberOfProcessNeighborsX(unsigned int numberOfProcessNeighbors, int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        parH[level]->sendProcessNeighborX.resize(numberOfProcessNeighbors);
-        parD[level]->sendProcessNeighborX.resize(numberOfProcessNeighbors);
-        //////////////////////////////////////////////////////////////////////////
-        if (getDiffOn()==true){
-            parH[level]->sendProcessNeighborADX.resize(numberOfProcessNeighbors);
-            parD[level]->sendProcessNeighborADX.resize(numberOfProcessNeighbors);
-        }
-        //////////////////////////////////////////////////////////////////////////
-    } 
-    else if (sor == "recv")
-    {
-        parH[level]->recvProcessNeighborX.resize(numberOfProcessNeighbors);
-        parD[level]->recvProcessNeighborX.resize(numberOfProcessNeighbors);
-        //////////////////////////////////////////////////////////////////////////
-        if (getDiffOn()==true){
-            parH[level]->recvProcessNeighborADX.resize(numberOfProcessNeighbors);
-            parD[level]->recvProcessNeighborADX.resize(numberOfProcessNeighbors);
-        }
-        //////////////////////////////////////////////////////////////////////////
-    }
-}
-void Parameter::setNumberOfProcessNeighborsY(unsigned int numberOfProcessNeighbors, int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        parH[level]->sendProcessNeighborY.resize(numberOfProcessNeighbors);
-        parD[level]->sendProcessNeighborY.resize(numberOfProcessNeighbors);
-        //////////////////////////////////////////////////////////////////////////
-        if (getDiffOn()==true){
-            parH[level]->sendProcessNeighborADY.resize(numberOfProcessNeighbors);
-            parD[level]->sendProcessNeighborADY.resize(numberOfProcessNeighbors);
-        }
-        //////////////////////////////////////////////////////////////////////////
-    } 
-    else if (sor == "recv")
-    {
-        parH[level]->recvProcessNeighborY.resize(numberOfProcessNeighbors);
-        parD[level]->recvProcessNeighborY.resize(numberOfProcessNeighbors);
-        //////////////////////////////////////////////////////////////////////////
-        if (getDiffOn()==true){
-            parH[level]->recvProcessNeighborADY.resize(numberOfProcessNeighbors);
-            parD[level]->recvProcessNeighborADY.resize(numberOfProcessNeighbors);
-        }
-        //////////////////////////////////////////////////////////////////////////
-    }
-}
-void Parameter::setNumberOfProcessNeighborsZ(unsigned int numberOfProcessNeighbors, int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        parH[level]->sendProcessNeighborZ.resize(numberOfProcessNeighbors);
-        parD[level]->sendProcessNeighborZ.resize(numberOfProcessNeighbors);
-        //////////////////////////////////////////////////////////////////////////
-        if (getDiffOn()==true){
-            parH[level]->sendProcessNeighborADZ.resize(numberOfProcessNeighbors);
-            parD[level]->sendProcessNeighborADZ.resize(numberOfProcessNeighbors);
-        }
-        //////////////////////////////////////////////////////////////////////////
-    } 
-    else if (sor == "recv")
-    {
-        parH[level]->recvProcessNeighborZ.resize(numberOfProcessNeighbors);
-        parD[level]->recvProcessNeighborZ.resize(numberOfProcessNeighbors);
-        //////////////////////////////////////////////////////////////////////////
-        if (getDiffOn()==true){
-            parH[level]->recvProcessNeighborADZ.resize(numberOfProcessNeighbors);
-            parD[level]->recvProcessNeighborADZ.resize(numberOfProcessNeighbors);
-        }
-        //////////////////////////////////////////////////////////////////////////
-    }
-}
-void Parameter::setIsNeighborX(bool isNeigbor)
-{
-    this->isNeigborX = isNeigbor;
-}
-void Parameter::setIsNeighborY(bool isNeigbor)
-{
-    this->isNeigborY = isNeigbor;
-}
-void Parameter::setIsNeighborZ(bool isNeigbor)
-{
-    this->isNeigborZ = isNeigbor; }
-void Parameter::setSendProcessNeighborsAfterFtoCX(int numberOfNodes, int level, int arrayIndex) {
-    this->getParH(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParH(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParH(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-}
-void Parameter::setSendProcessNeighborsAfterFtoCY(int numberOfNodes, int level, int arrayIndex)
-{
-    this->getParH(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParH(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParH(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-}
-void Parameter::setSendProcessNeighborsAfterFtoCZ(int numberOfNodes, int level, int arrayIndex)
-{
-    this->getParH(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParH(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParH(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-    this->getParD(level)->sendProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-}
-void Parameter::setRecvProcessNeighborsAfterFtoCX(int numberOfNodes, int level, int arrayIndex)
-{
-    this->getParH(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParH(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParH(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCX[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-}
-void Parameter::setRecvProcessNeighborsAfterFtoCY(int numberOfNodes, int level, int arrayIndex)
-{
-    this->getParH(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParH(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParH(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCY[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-}
-void Parameter::setRecvProcessNeighborsAfterFtoCZ(int numberOfNodes, int level, int arrayIndex)
-{
-    this->getParH(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfNodes = numberOfNodes;
-    this->getParH(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].memsizeFs     = sizeof(real) * numberOfNodes;
-    this->getParH(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-    this->getParD(level)->recvProcessNeighborsAfterFtoCZ[arrayIndex].numberOfFs    = this->D3Qxx * numberOfNodes;
-}
-void Parameter::setgeomBoundaryNormalX(std::string geomNormalX)
-{
-    ic.geomNormalX = geomNormalX;
-}
-void Parameter::setgeomBoundaryNormalY(std::string geomNormalY)
-{
-    ic.geomNormalY = geomNormalY;
-}
-void Parameter::setgeomBoundaryNormalZ(std::string geomNormalZ)
-{
-    ic.geomNormalZ = geomNormalZ;
-}
-void Parameter::setInflowBoundaryNormalX(std::string inflowNormalX)
-{
-    ic.inflowNormalX = inflowNormalX;
-}
-void Parameter::setInflowBoundaryNormalY(std::string inflowNormalY)
-{
-    ic.inflowNormalY = inflowNormalY;
-}
-void Parameter::setInflowBoundaryNormalZ(std::string inflowNormalZ)
-{
-    ic.inflowNormalZ = inflowNormalZ;
-}
-void Parameter::setOutflowBoundaryNormalX(std::string outflowNormalX)
-{
-    ic.outflowNormalX = outflowNormalX;
-}
-void Parameter::setOutflowBoundaryNormalY(std::string outflowNormalY)
-{
-    ic.outflowNormalY = outflowNormalY;
-}
-void Parameter::setOutflowBoundaryNormalZ(std::string outflowNormalZ)
-{
-    ic.outflowNormalZ = outflowNormalZ;
-}
-void Parameter::setMainKernel(std::string kernel)
-{
-    this->mainKernel = kernel;
-    if (kernel.find("Stream") != std::string::npos)
-        this->kernelNeedsFluidNodeIndicesToRun = true;
-}
-void Parameter::setMultiKernelOn(bool isOn)
-{
-    this->multiKernelOn = isOn;
-}
-void Parameter::setMultiKernelLevel(std::vector< int> kernelLevel)
-{
-    this->multiKernelLevel = kernelLevel;
-}
-void Parameter::setMultiKernel(std::vector< std::string> kernel)
-{
-    this->multiKernel = kernel;
-}
-void Parameter::setADKernel(std::string adKernel)
-{
-    this->adKernel = adKernel;
-}
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//get-methods
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-double* Parameter::getForcesDouble()
-{
-    return this->hostForcing;
-}
-real* Parameter::getForcesHost()
-{
-    return this->forcingH;
-}
-real* Parameter::getForcesDev()
-{
-    return this->forcingD;
-}
-double * Parameter::getQuadricLimitersDouble()
-{
-    return this->hostQuadricLimiters;
-}
-real * Parameter::getQuadricLimitersHost()
-{
-    return this->quadricLimitersH;
-}
-real * Parameter::getQuadricLimitersDev()
-{
-    return this->quadricLimitersD;
-}
-real Parameter::getPhi()
-{
-    return Phi;
-}
-real Parameter::getAngularVelocity()
-{
-    return angularVelocity;
-}
-real Parameter::getStartXHotWall()
-{
-    return this->startXHotWall;
-}
-real Parameter::getEndXHotWall()
-{
-    return this->endXHotWall;
-}
-unsigned int Parameter::getStepEnsight()
-{
-    return this->stepEnsight;
-}
-unsigned int Parameter::getOutputCount()
-{
-    return this->outputCount;
-}
-unsigned int Parameter::getlimitOfNodesForVTK()
-{
-    return this->limitOfNodesForVTK;
-}
-unsigned int Parameter::getStartTurn()
-{
-    return startTurn;
-}
-std::shared_ptr<LBMSimulationParameter> Parameter::getParD(int level)
-{
-    return parD[level];
-}
-std::shared_ptr<LBMSimulationParameter> Parameter::getParH(int level)
-{
-    return parH[level];
-}
-unsigned int Parameter::getSizeMat(int level)
-{
-    return parH[level]->size_Mat;
-}
-unsigned int Parameter::getMemSizereal(int level)
-{
-    return parH[level]->mem_size_real;
-}
-unsigned int Parameter::getMemSizeInt(int level)
-{
-    return parH[level]->mem_size_int;
-}
-unsigned int Parameter::getMemSizeBool(int level)
-{
-    return parH[level]->mem_size_bool;
-}
-unsigned int Parameter::getMemSizerealYZ(int level)
-{
-    return parH[level]->mem_size_real_yz;
-}
-int Parameter::getFine()
-{
-    return fine;
-}
-int Parameter::getCoarse()
-{
-    return coarse;
-}
-int Parameter::getParticleBasicLevel()
-{
-    return this->particleBasicLevel;
-}
-int Parameter::getParticleInitLevel()
-{
-    return this->particleInitLevel;
-}
-int Parameter::getNumberOfParticles()
-{
-    return this->numberOfParticles;
-}
-bool Parameter::getEvenOrOdd(int level)
-{
-    return parH[level]->evenOrOdd;
-}
-bool Parameter::getDiffOn()
-{
-    return diffOn;
-}
-bool Parameter::getCompOn()
-{
-    return compOn;
-}
-int Parameter::getDiffMod()
-{
-    return diffMod;
-}
-int Parameter::getFactorNZ()
-{
-    return factor_gridNZ;
-}
-int Parameter::getD3Qxx()
-{
-    return this->D3Qxx;
-}
-int Parameter::getMaxLevel()
-{
-    return this->maxlevel;
-}
-unsigned int Parameter::getTStart()
-{
-    if (getDoRestart())
-    {
-        return getTimeDoRestart() + 1;
-    } 
-    else
-    {
-        return 1;
-    }
-}
-unsigned int Parameter::getTInit()
-{
-    if (getDoRestart())
-    {
-        return getTimeDoRestart();
-    } 
-    else
-    {
-        return 0;
-    }
-}
-unsigned int Parameter::getTEnd()
-{
-    return ic.tend;
-}
-unsigned int Parameter::getTOut()
-{
-    return ic.tout;
-}
-unsigned int Parameter::getTStartOut()
-{
-    return ic.tStartOut;
-}
-bool Parameter::getCalcMedian()
-{
-    return ic.calcMedian;
-}
-bool Parameter::getCalcDragLift()
-{
-    return this->calcDragLift;
-}
-bool Parameter::getCalcCp()
-{
-    return this->calcCp;
-}
-bool Parameter::getCalcParticle()
-{
-    return this->calcParticles;
-}
-bool Parameter::getWriteVeloASCIIfiles()
-{
-    return this->writeVeloASCII;
-}
-bool Parameter::getCalcPlaneConc()
-{
-    return this->calcPlaneConc;
-}
-int Parameter::getTimeCalcMedStart()
-{
-    return ic.tCalcMedStart;
-}
-int Parameter::getTimeCalcMedEnd()
-{
-    return ic.tCalcMedEnd;
-}
-std::string Parameter::getOutputPath()
-{
-    return ic.oPath;
-}
-std::string Parameter::getOutputPrefix()
-{
-    return ic.oPrefix;
-}
-std::string Parameter::getFName()
-{
-    return ic.fname;
-}
-bool Parameter::getPrintFiles()
-{
-    return ic.printFiles;
-}
-bool Parameter::getReadGeo()
-{
-    return ic.readGeo; 
-}
-bool Parameter::getCalcTurbulenceIntensity() 
-{ 
-    return this->calcVelocityAndFluctuations; 
-}
-real Parameter::getDiffusivity()
-{
-    return ic.Diffusivity;
-}
-real Parameter::getTemperatureInit()
-{
-    return ic.Temp;
-}
-real Parameter::getTemperatureBC()
-{
-    return ic.TempBC;
-}
-real Parameter::getViscosity()
-{
-    return ic.vis;
-}
-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::getPressRatio()
-{
-    return ic.delta_press;
-}
-real Parameter::getRealX()
-{
-    return ic.RealX;
-}
-real Parameter::getRealY()
-{
-    return ic.RealY;
-}
-unsigned int Parameter::getPressInID()
-{
-    return ic.PressInID;
-}
-unsigned int Parameter::getPressOutID()
-{
-    return ic.PressOutID;
-}
-unsigned int Parameter::getPressInZ()
-{
-    return ic.PressInZ;
-}
-unsigned int Parameter::getPressOutZ()
-{
-    return ic.PressOutZ;
-}
-int Parameter::getMaxDev()
-{
-    return ic.maxdev;
-}
-int Parameter::getMyID()
-{
-    return ic.myid;
-}
-int Parameter::getNumprocs()
-{
-    return ic.numprocs;
-}
-std::vector<uint> Parameter::getDevices()
-{
-    return ic.devices;
-}
-std::string Parameter::getGeometryFileC()
-{
-    return ic.geometryFileC;
-}
-std::string Parameter::getGeometryFileM()
-{
-    return ic.geometryFileM;
-}
-std::string Parameter::getGeometryFileF()
-{
-    return ic.geometryFileF;
-}
-real Parameter::getRe()
-{
-    return ic.Re;
-}
-real Parameter::getFactorPressBC()
-{
-    return ic.factorPressBC;
-}
-std::vector<int> Parameter::getGridX()
-{
-    return ic.GridX;
-}
-std::vector<int> Parameter::getGridY()
-{
-    return ic.GridY;
-}
-std::vector<int> Parameter::getGridZ()
-{
-    return ic.GridZ;
-}
-std::vector<int> Parameter::getDistX()
-{
-    return ic.DistX;
-}
-std::vector<int> Parameter::getDistY()
-{
-    return ic.DistY;
-}
-std::vector<int> Parameter::getDistZ()
-{
-    return ic.DistZ;
-}
-std::vector<real> Parameter::getScaleLBMtoSI()
-{
-    return ic.scaleLBMtoSI;
-}
-std::vector<real> Parameter::getTranslateLBMtoSI()
-{
-    return ic.translateLBMtoSI;
-}
-std::vector<real> Parameter::getMinCoordX()
-{
-    return ic.minCoordX;
-}
-std::vector<real> Parameter::getMinCoordY()
-{
-    return ic.minCoordY;
-}
-std::vector<real> Parameter::getMinCoordZ()
-{
-    return ic.minCoordZ;
-}
-std::vector<real> Parameter::getMaxCoordX()
-{
-    return ic.maxCoordX;
-}
-std::vector<real> Parameter::getMaxCoordY()
-{
-    return ic.maxCoordY;
-}
-std::vector<real> Parameter::getMaxCoordZ()
-{
-    return ic.maxCoordZ;
-}
-TempforBoundaryConditions* Parameter::getTempH()
-{
-    return this->TempH;
-}
-TempforBoundaryConditions* Parameter::getTempD()
-{
-    return this->TempD;
-}
-TempVelforBoundaryConditions* Parameter::getTempVelH()
-{
-    return this->TempVelH;
-}
-TempVelforBoundaryConditions* Parameter::getTempVelD()
-{
-    return this->TempVelD;
-}
-TempPressforBoundaryConditions* Parameter::getTempPressH()
-{
-    return this->TempPressH;
-}
-TempPressforBoundaryConditions* Parameter::getTempPressD()
-{
-    return this->TempPressD;
-}
-//unsigned int Parameter::getkInflowQ()
-//{
-//   return this->kInflowQ;
-//}
-//unsigned int Parameter::getkOutflowQ()
-//{
-//   return this->kOutflowQ;
-//}
-//QforBoundaryConditions* Parameter::getQinflowH()
-//{
-//   return this->QinflowH;
-//}
-//QforBoundaryConditions* Parameter::getQinflowD()
-//{
-//   return this->QinflowD;
-//}
-//QforBoundaryConditions* Parameter::getQoutflowH()
-//{
-//   return this->QoutflowH;
-//}
-//QforBoundaryConditions* Parameter::getQoutflowD()
-//{
-//   return this->QoutflowD;
-//}
-std::string Parameter::getkFull()
-{
-    return ic.kFull;
-}
-std::string Parameter::getgeoFull()
-{
-    return ic.geoFull;
-}
-std::string Parameter::getgeoVec()
-{
-    return ic.geoVec;
-}
-std::string Parameter::getcoordX()
-{
-    return ic.coordX;
-}
-std::string Parameter::getcoordY()
-{
-    return ic.coordY;
-}
-std::string Parameter::getcoordZ()
-{
-    return ic.coordZ;
-}
-std::string Parameter::getneighborX()
-{
-    return ic.neighborX;
-}
-std::string Parameter::getneighborY()
-{
-    return ic.neighborY;
-}
-std::string Parameter::getneighborZ()
-{
-    return ic.neighborZ;
-}
-std::string Parameter::getneighborWSB()
-{
-    return ic.neighborWSB;
-}
-std::string Parameter::getscaleCFC()
-{
-    return ic.scaleCFC;
-}
-std::string Parameter::getscaleCFF()
-{
-    return ic.scaleCFF;
-}
-std::string Parameter::getscaleFCC()
-{
-    return ic.scaleFCC;
-}
-std::string Parameter::getscaleFCF()
-{
-    return ic.scaleFCF;
-}
-std::string Parameter::getscaleOffsetCF()
-{
-    return ic.scaleOffsetCF;
-}
-std::string Parameter::getscaleOffsetFC()
-{
-    return ic.scaleOffsetFC;
-}
-std::string Parameter::getgeomBoundaryBcQs()
-{
-    return ic.geomBoundaryBcQs;
-}
-std::string Parameter::getgeomBoundaryBcValues()
-{
-    return ic.geomBoundaryBcValues;
-}
-std::string Parameter::getnoSlipBcPos()
-{
-    return ic.noSlipBcPos;
-}
-std::string Parameter::getnoSlipBcQs()
-{
-    return ic.noSlipBcQs;
-}
-std::string Parameter::getnoSlipBcValue()
-{
-    return ic.noSlipBcValue;
-}
-std::string Parameter::getnoSlipBcValues()
-{
-    return ic.noSlipBcValues;
-}
-std::string Parameter::getslipBcPos()
-{
-    return ic.slipBcPos;
-}
-std::string Parameter::getslipBcQs()
-{
-    return ic.slipBcQs;
-}
-std::string Parameter::getslipBcValue()
-{
-    return ic.slipBcValue;
-}
-std::string Parameter::getpressBcPos()
-{
-    return ic.pressBcPos;
-}
-std::string Parameter::getpressBcQs()
-{
-    return ic.pressBcQs;
-}
-std::string Parameter::getpressBcValue()
-{
-    return ic.pressBcValue;
-}
-std::string Parameter::getpressBcValues()
-{
-    return ic.pressBcValues;
-}
-std::string Parameter::getvelBcQs()
-{
-    return ic.velBcQs;
-}
-std::string Parameter::getvelBcValues()
-{
-    return ic.velBcValues;
-}
-std::string Parameter::getinletBcQs()
-{
-    return ic.inletBcQs;
-}
-std::string Parameter::getinletBcValues()
-{
-    return ic.inletBcValues;
-}
-std::string Parameter::getoutletBcQs()
-{
-    return ic.outletBcQs;
-}
-std::string Parameter::getoutletBcValues()
-{
-    return ic.outletBcValues;
-}
-std::string Parameter::gettopBcQs()
-{
-    return ic.topBcQs;
-}
-std::string Parameter::gettopBcValues()
-{
-    return ic.topBcValues;
-}
-std::string Parameter::getbottomBcQs()
-{
-    return ic.bottomBcQs;
-}
-std::string Parameter::getbottomBcValues()
-{
-    return ic.bottomBcValues;
-}
-std::string Parameter::getfrontBcQs()
-{
-    return ic.frontBcQs;
-}
-std::string Parameter::getfrontBcValues()
-{
-    return ic.frontBcValues;
-}
-std::string Parameter::getbackBcQs()
-{
-    return ic.backBcQs;
-}
-std::string Parameter::getbackBcValues()
-{
-    return ic.backBcValues;
-}
-std::string Parameter::getwallBcQs()
-{
-    return ic.wallBcQs;
-}
-std::string Parameter::getwallBcValues()
-{
-    return ic.wallBcValues;
-}
-std::string Parameter::getperiodicBcQs()
-{
-    return ic.periodicBcQs;
-}
-std::string Parameter::getperiodicBcValues()
-{
-    return ic.periodicBcValues;
-}
-std::string Parameter::getpropellerQs()
-{
-    return ic.propellerQs;
-}
-std::string Parameter::getpropellerValues()
-{
-    return ic.propellerValues;
-}
-std::string Parameter::getpropellerCylinder()
-{
-    return ic.propellerCylinder;
-}
-std::string Parameter::getmeasurePoints()
-{
-    return ic.measurePoints;
-}
-std::string Parameter::getLBMvsSI()
-{
-    return ic.LBMvsSI;
-}
-std::string Parameter::getnumberNodes()
-{
-    return ic.numberNodes;
-}
-std::string Parameter::getcpTop()
-{
-    return ic.cpTop;
-}
-std::string Parameter::getcpBottom()
-{
-    return ic.cpBottom;
-}
-std::string Parameter::getcpBottom2()
-{
-    return ic.cpBottom2;
-}
-std::string Parameter::getConcentration()
-{
-    return ic.concentration;
-}
-std::string Parameter::getStreetVelocityFilePath()
-{
-    return ic.streetVelocity;
-}
-real Parameter::getclockCycleForMP()
-{
-    return ic.clockCycleForMP;
-}
-unsigned int Parameter::getTimeDoCheckPoint()
-{
-    return ic.tDoCheckPoint;
-}
-unsigned int Parameter::getTimeDoRestart()
-{
-    return ic.tDoRestart;
-}
-bool Parameter::getDoCheckPoint()
-{
-    return ic.doCheckPoint;
-}
-bool Parameter::getDoRestart()
-{
-    return ic.doRestart;
-}
-bool Parameter::getIsGeo()
-{
-    return ic.isGeo;
-}
-bool Parameter::getIsGeoNormal()
-{
-    return ic.isGeoNormal;
-}
-bool Parameter::getIsInflowNormal()
-{
-    return ic.isInflowNormal;
-}
-bool Parameter::getIsOutflowNormal()
-{
-    return ic.isOutflowNormal;
-}
-bool Parameter::getIsCp()
-{
-    return ic.isCp;
-}
-bool Parameter::getConcFile()
-{
-    return ic.isConc;
-}
-bool Parameter::isStreetVelocityFile()
-{
-    return ic.streetVelocityFile;
-}
-bool Parameter::getUseMeasurePoints()
-{
-    return ic.isMeasurePoints;
-}
-bool Parameter::getUseWale()
-{
-    return ic.isWale;
-}
-bool Parameter::getUseInitNeq()
-{
-    return ic.isInitNeq;
-}
-bool Parameter::getSimulatePorousMedia()
-{
-    return ic.simulatePorousMedia;
-}
-
-bool Parameter::getIsF3()
-{
-    return this->isF3; 
+    if (sor == "send") {
+        return (unsigned int)parH[level]->sendProcessNeighborZ.size();
+    } else if (sor == "recv") {
+        return (unsigned int)parH[level]->recvProcessNeighborZ.size();
+    }
+    throw std::runtime_error("getNumberOfProcessNeighborsZ: Parameter string invalid.");
 }
 
-bool Parameter::getIsBodyForce() 
-{ 
-    return this->isBodyForce; 
-}
-
-bool Parameter::getIsGeometryValues()
-{
-    return ic.GeometryValues;
-}
-bool Parameter::getCalc2ndOrderMoments()
-{
-    return ic.is2ndOrderMoments;
-}
-bool Parameter::getCalc3rdOrderMoments()
-{
-    return ic.is3rdOrderMoments;
-}
-bool Parameter::getCalcHighOrderMoments()
-{
-    return ic.isHighOrderMoments;
-}
-bool Parameter::getIsProp()
-{
-    return ic.isProp;
-}
-bool Parameter::overWritingRestart(uint t)
-{
-    return t == getTimeDoRestart();
-}
-unsigned int Parameter::getTimestepForMP()
-{
-    return ic.timeStepForMP;
-}
-unsigned int Parameter::getTimestepOfCoarseLevel()
-{
-    return this->timestep;
-}
-double Parameter::getMemsizeGPU()
-{
-    return this->memsizeGPU;
-}
-//1D domain decomposition
-std::vector<std::string> Parameter::getPossNeighborFiles(std::string sor)
-{
-    if (sor=="send")
-    {
-        return this->possNeighborFilesSend;
-    } 
-    else if (sor == "recv")
-    {
-        return this->possNeighborFilesRecv;
-    }
-    throw std::runtime_error("Parameter string invalid.");
-}
-unsigned int Parameter::getNumberOfProcessNeighbors(int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        return (unsigned int)parH[level]->sendProcessNeighbor.size();
-    } 
-    else if (sor == "recv")
-    {
-        return (unsigned int)parH[level]->recvProcessNeighbor.size();
-    }
-    throw std::runtime_error("Parameter string invalid.");
-}
-bool Parameter::getIsNeighbor()
-{
-    return this->isNeigbor;
-}
-//3D domain decomposition
-std::vector<std::string> Parameter::getPossNeighborFilesX(std::string sor)
-{
-    if (sor=="send")
-    {
-        return this->possNeighborFilesSendX;
-    } 
-    else if (sor == "recv")
-    {
-        return this->possNeighborFilesRecvX;
-    }
-    throw std::runtime_error("Parameter string invalid.");
-}
-std::vector<std::string> Parameter::getPossNeighborFilesY(std::string sor)
-{
-    if (sor=="send")
-    {
-        return this->possNeighborFilesSendY;
-    } 
-    else if (sor == "recv")
-    {
-        return this->possNeighborFilesRecvY;
-    }
-    throw std::runtime_error("Parameter string invalid.");
-}
-std::vector<std::string> Parameter::getPossNeighborFilesZ(std::string sor)
-{
-    if (sor=="send")
-    {
-        return this->possNeighborFilesSendZ;
-    } 
-    else if (sor == "recv")
-    {
-        return this->possNeighborFilesRecvZ;
-    }
-    throw std::runtime_error("Parameter string invalid.");
-}
-unsigned int Parameter::getNumberOfProcessNeighborsX(int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        return (unsigned int)parH[level]->sendProcessNeighborX.size();
-    } 
-    else if (sor == "recv")
-    {
-        return (unsigned int)parH[level]->recvProcessNeighborX.size();
-    }
-    throw std::runtime_error("getNumberOfProcessNeighborsX: Parameter string invalid.");
-}
-unsigned int Parameter::getNumberOfProcessNeighborsY(int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        return (unsigned int)parH[level]->sendProcessNeighborY.size();
-    } 
-    else if (sor == "recv")
-    {
-        return (unsigned int)parH[level]->recvProcessNeighborY.size();
-    }
-    throw std::runtime_error("getNumberOfProcessNeighborsY: Parameter string invalid.");
-}
-unsigned int Parameter::getNumberOfProcessNeighborsZ(int level, std::string sor)
-{
-    if (sor=="send")
-    {
-        return (unsigned int)parH[level]->sendProcessNeighborZ.size();
-    } 
-    else if (sor == "recv")
-    {
-        return (unsigned int)parH[level]->recvProcessNeighborZ.size();
-    }
-    throw std::runtime_error("getNumberOfProcessNeighborsZ: Parameter string invalid.");
-}
-
-bool Parameter::getIsNeighborX()
-{
-    return this->isNeigborX;
-}
-bool Parameter::getIsNeighborY()
-{
-    return this->isNeigborY;
-}
-bool Parameter::getIsNeighborZ()
-{
-    return this->isNeigborZ;
-}
-std::string Parameter::getgeomBoundaryNormalX()
-{
-    return ic.geomNormalX;
-}
-std::string Parameter::getgeomBoundaryNormalY()
-{
-    return ic.geomNormalY;
-}
-std::string Parameter::getgeomBoundaryNormalZ()
-{
-    return ic.geomNormalZ;
-}
-std::string Parameter::getInflowBoundaryNormalX()
-{
-    return ic.inflowNormalX;
-}
-std::string Parameter::getInflowBoundaryNormalY()
-{
-    return ic.inflowNormalY;
-}
-std::string Parameter::getInflowBoundaryNormalZ()
-{
-    return ic.inflowNormalZ;
-}
-std::string Parameter::getOutflowBoundaryNormalX()
-{
-    return ic.outflowNormalX;
-}
-std::string Parameter::getOutflowBoundaryNormalY()
-{
-    return ic.outflowNormalY;
-}
-std::string Parameter::getOutflowBoundaryNormalZ()
-{
-    return ic.outflowNormalZ;
-}
-curandState* Parameter::getRandomState()
-{
-    return this->devState;
-}
-
-std::string Parameter::getMainKernel()
-{
-    return mainKernel;
-}
-bool Parameter::getMultiKernelOn()
-{
-    return multiKernelOn;
-}
-std::vector< int> Parameter::getMultiKernelLevel()
-{
-    return multiKernelLevel;
-}
-std::vector<std::string> Parameter::getMultiKernel()
-{
-    return multiKernel;
-}
-std::string Parameter::getADKernel()
-{
-    return adKernel;
-}
+bool Parameter::getIsNeighborX() { return this->isNeigborX; }
+bool Parameter::getIsNeighborY() { return this->isNeigborY; }
+bool Parameter::getIsNeighborZ() { return this->isNeigborZ; }
+std::string Parameter::getgeomBoundaryNormalX() { return ic.geomNormalX; }
+std::string Parameter::getgeomBoundaryNormalY() { return ic.geomNormalY; }
+std::string Parameter::getgeomBoundaryNormalZ() { return ic.geomNormalZ; }
+std::string Parameter::getInflowBoundaryNormalX() { return ic.inflowNormalX; }
+std::string Parameter::getInflowBoundaryNormalY() { return ic.inflowNormalY; }
+std::string Parameter::getInflowBoundaryNormalZ() { return ic.inflowNormalZ; }
+std::string Parameter::getOutflowBoundaryNormalX() { return ic.outflowNormalX; }
+std::string Parameter::getOutflowBoundaryNormalY() { return ic.outflowNormalY; }
+std::string Parameter::getOutflowBoundaryNormalZ() { return ic.outflowNormalZ; }
+curandState *Parameter::getRandomState() { return this->devState; }
+
+std::string Parameter::getMainKernel() { return mainKernel; }
+bool Parameter::getMultiKernelOn() { return multiKernelOn; }
+std::vector<int> Parameter::getMultiKernelLevel() { return multiKernelLevel; }
+std::vector<std::string> Parameter::getMultiKernel() { return multiKernel; }
+std::string Parameter::getADKernel() { return adKernel; }
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-void Parameter::setInitialCondition(std::function<void(real,real,real,real&,real&,real&,real&)> initialCondition)
+void Parameter::setInitialCondition(
+    std::function<void(real, real, real, real &, real &, real &, real &)> initialCondition)
 {
     this->initialCondition = initialCondition;
 }
 
-std::function<void(real,real,real,real&,real&,real&,real&)>& Parameter::getInitialCondition()
+std::function<void(real, real, real, real &, real &, real &, real &)> &Parameter::getInitialCondition()
 {
     return this->initialCondition;
 }
 
-real Parameter::TrafoXtoWorld(int CoordX, int level)
-{
-    return (parH[level]->mTtoWx*CoordX+parH[level]->cTtoWx);
-}
-real Parameter::TrafoYtoWorld(int CoordY, int level)
-{
-    return (parH[level]->mTtoWy*CoordY+parH[level]->cTtoWy);
-}
-real Parameter::TrafoZtoWorld(int CoordZ, int level)
-{
-    return (parH[level]->mTtoWz*CoordZ+parH[level]->cTtoWz);
-}
+real Parameter::TrafoXtoWorld(int CoordX, int level) { return (parH[level]->mTtoWx * CoordX + parH[level]->cTtoWx); }
+real Parameter::TrafoYtoWorld(int CoordY, int level) { return (parH[level]->mTtoWy * CoordY + parH[level]->cTtoWy); }
+real Parameter::TrafoZtoWorld(int CoordZ, int level) { return (parH[level]->mTtoWz * CoordZ + parH[level]->cTtoWz); }
 real Parameter::TrafoXtoMGsWorld(int CoordX, int level)
 {
     real temp = 0;
-    for (int i = 0; i <= level; i++)
-    {
+    for (int i = 0; i <= level; i++) {
         temp += (parH[i]->XdistKn + 0.25f) * 2.f * parH[i]->dx;
     }
-    temp += (real)((CoordX ) * parH[level]->dx);
+    temp += (real)((CoordX)*parH[level]->dx);
     return temp;
 }
 real Parameter::TrafoYtoMGsWorld(int CoordY, int level)
 {
     real temp = 0;
-    for (int i = 0; i <= level; i++)
-    {
+    for (int i = 0; i <= level; i++) {
         temp += (parH[i]->YdistKn + 0.25f) * 2.f * parH[i]->dx;
     }
-    temp += (real)((CoordY ) * parH[level]->dx);
+    temp += (real)((CoordY)*parH[level]->dx);
     return temp;
 }
 real Parameter::TrafoZtoMGsWorld(int CoordZ, int level)
 {
     real temp = 0;
-    for (int i = 0; i <= level; i++)
-    {
+    for (int i = 0; i <= level; i++) {
         temp += (parH[i]->ZdistKn + 0.25f) * 2.f * parH[i]->dx;
     }
-    temp += (real)((CoordZ) * parH[level]->dx);
+    temp += (real)((CoordZ)*parH[level]->dx);
     return temp;
 }
 
-void Parameter::setUseStreams() {
-    this->useStreams = true;
-    this->cudaStreamManager = std::make_unique<CudaStreamManager>();
+void Parameter::setUseStreams(bool useStreams)
+{
+    if (useStreams) {
+        if (this->getNumprocs() != 1) {
+            this->useStreams        = useStreams;
+            this->cudaStreamManager = std::make_unique<CudaStreamManager>();
+            return;
+        } else {
+            std::cout << "Can't use streams with only one process!" << std::endl;
+        }
+    }
+    this->useStreams = false;
 }
 
 bool Parameter::getUseStreams() { return this->useStreams; }
@@ -2575,7 +1389,8 @@ std::unique_ptr<CudaStreamManager> &Parameter::getStreamManager() { return this-
 
 bool Parameter::getKernelNeedsFluidNodeIndicesToRun() { return this->kernelNeedsFluidNodeIndicesToRun; }
 
-void Parameter::findEdgeNodesCommMultiGPU() { 
+void Parameter::findEdgeNodesCommMultiGPU()
+{
     for (uint level = 0; level < parH.size(); level++) {
         findEdgeNodesXY(level);
         findEdgeNodesXZ(level);
@@ -2587,25 +1402,23 @@ void Parameter::findEdgeNodesXY(int level)
 {
     int indexOfProcessNeighborSend;
     int indexInSendBuffer;
-    for (uint i = 0; i < (unsigned int)(this->getNumberOfProcessNeighborsX(level, "recv")); i++)
-    {
+    for (uint i = 0; i < (unsigned int)(this->getNumberOfProcessNeighborsX(level, "recv")); i++) {
         for (int j = 0; j < parH[level]->recvProcessNeighborX[i].numberOfNodes; j++) {
-            int index = parH[level]->recvProcessNeighborX[i].index[j];
+            int index       = parH[level]->recvProcessNeighborX[i].index[j];
             bool foundIndex = findIndexInSendNodesXY(level, index, indexOfProcessNeighborSend, indexInSendBuffer);
-            if (foundIndex){
+            if (foundIndex) {
                 this->parH[level]->edgeNodesXtoY.emplace_back(i, j, indexOfProcessNeighborSend, indexInSendBuffer);
             }
-        }		
+        }
     }
 }
 
 bool Parameter::findIndexInSendNodesXY(int level, int index, int &indexOfProcessNeighborSend, int &indexInSendBuffer)
 {
-    for (uint k = 0; k < (unsigned int)(this->getNumberOfProcessNeighborsY(level, "send")); k++)
-    {
-        for (int l = 0; l < parH[level]->sendProcessNeighborY[k].numberOfNodes; l++)
-        {
-            if (parH[level]->sendProcessNeighborY[k].index[l] == index) {;
+    for (uint k = 0; k < (unsigned int)(this->getNumberOfProcessNeighborsY(level, "send")); k++) {
+        for (int l = 0; l < parH[level]->sendProcessNeighborY[k].numberOfNodes; l++) {
+            if (parH[level]->sendProcessNeighborY[k].index[l] == index) {
+                ;
                 indexOfProcessNeighborSend = k;
                 indexInSendBuffer          = l;
                 return true;
@@ -2619,12 +1432,11 @@ void Parameter::findEdgeNodesXZ(int level)
 {
     int indexOfProcessNeighborSend;
     int indexInSendBuffer;
-    for (uint i = 0; i < (unsigned int)(this->getNumberOfProcessNeighborsX(level, "recv")); i++)
-    {
+    for (uint i = 0; i < (unsigned int)(this->getNumberOfProcessNeighborsX(level, "recv")); i++) {
         for (int j = 0; j < parH[level]->recvProcessNeighborX[i].numberOfNodes; j++) {
             int index       = parH[level]->recvProcessNeighborX[i].index[j];
             bool foundIndex = findIndexInSendNodesXZ(level, index, indexOfProcessNeighborSend, indexInSendBuffer);
-            if (foundIndex){
+            if (foundIndex) {
                 this->parH[level]->edgeNodesXtoZ.emplace_back(i, j, indexOfProcessNeighborSend, indexInSendBuffer);
             }
         }
@@ -2633,8 +1445,8 @@ void Parameter::findEdgeNodesXZ(int level)
 
 bool Parameter::findIndexInSendNodesXZ(int level, int index, int &indexOfProcessNeighborSend, int &indexInSendBuffer)
 {
-    for (uint k = 0; k < (unsigned int)(this->getNumberOfProcessNeighborsZ(level, "send")); k++){
-        for (int l = 0; l < parH[level]->sendProcessNeighborZ[k].numberOfNodes; l++){
+    for (uint k = 0; k < (unsigned int)(this->getNumberOfProcessNeighborsZ(level, "send")); k++) {
+        for (int l = 0; l < parH[level]->sendProcessNeighborZ[k].numberOfNodes; l++) {
             if (parH[level]->sendProcessNeighborZ[k].index[l] == index) {
                 indexOfProcessNeighborSend = k;
                 indexInSendBuffer          = l;
@@ -2645,15 +1457,15 @@ bool Parameter::findIndexInSendNodesXZ(int level, int index, int &indexOfProcess
     return false;
 }
 
-void Parameter::findEdgeNodesYZ(int level) 
+void Parameter::findEdgeNodesYZ(int level)
 {
     int indexOfProcessNeighborSend;
     int indexInSendBuffer;
-    for (uint i = 0; i < (unsigned int)(this->getNumberOfProcessNeighborsY(level, "recv")); i++){
+    for (uint i = 0; i < (unsigned int)(this->getNumberOfProcessNeighborsY(level, "recv")); i++) {
         for (int j = 0; j < parH[level]->recvProcessNeighborY[i].numberOfNodes; j++) {
-            int index = parH[level]->recvProcessNeighborY[i].index[j];
+            int index       = parH[level]->recvProcessNeighborY[i].index[j];
             bool foundIndex = findIndexInSendNodesYZ(level, index, indexOfProcessNeighborSend, indexInSendBuffer);
-            if (foundIndex){
+            if (foundIndex) {
                 this->parH[level]->edgeNodesYtoZ.emplace_back(i, j, indexOfProcessNeighborSend, indexInSendBuffer);
             }
         }
@@ -2662,8 +1474,8 @@ void Parameter::findEdgeNodesYZ(int level)
 
 bool Parameter::findIndexInSendNodesYZ(int level, int index, int &indexOfProcessNeighborSend, int &indexInSendBuffer)
 {
-    for (uint k = 0; k < (unsigned int)(this->getNumberOfProcessNeighborsZ(level, "send")); k++){
-        for (int l = 0; l < parH[level]->sendProcessNeighborZ[k].numberOfNodes; l++){
+    for (uint k = 0; k < (unsigned int)(this->getNumberOfProcessNeighborsZ(level, "send")); k++) {
+        for (int l = 0; l < parH[level]->sendProcessNeighborZ[k].numberOfNodes; l++) {
             if (parH[level]->sendProcessNeighborZ[k].index[l] == index) {
                 indexOfProcessNeighborSend = k;
                 indexInSendBuffer          = l;
@@ -2676,10 +1488,8 @@ bool Parameter::findIndexInSendNodesYZ(int level, int index, int &indexOfProcess
 
 void Parameter::initProcessNeighborsAfterFtoCX(int level)
 {
-    this->getParH(level)->sendProcessNeighborsAfterFtoCX.resize(
-        this->getParH(level)->sendProcessNeighborX.size());
-    this->getParH(level)->recvProcessNeighborsAfterFtoCX.resize(
-        this->getParH(level)->recvProcessNeighborX.size());
+    this->getParH(level)->sendProcessNeighborsAfterFtoCX.resize(this->getParH(level)->sendProcessNeighborX.size());
+    this->getParH(level)->recvProcessNeighborsAfterFtoCX.resize(this->getParH(level)->recvProcessNeighborX.size());
     this->getParD(level)->sendProcessNeighborsAfterFtoCX.resize(
         this->getParH(level)->sendProcessNeighborsAfterFtoCX.size());
     this->getParD(level)->recvProcessNeighborsAfterFtoCX.resize(
@@ -2688,10 +1498,8 @@ void Parameter::initProcessNeighborsAfterFtoCX(int level)
 
 void Parameter::initProcessNeighborsAfterFtoCY(int level)
 {
-    this->getParH(level)->sendProcessNeighborsAfterFtoCY.resize(
-        this->getParH(level)->sendProcessNeighborY.size());
-    this->getParH(level)->recvProcessNeighborsAfterFtoCY.resize(
-        this->getParH(level)->recvProcessNeighborY.size());
+    this->getParH(level)->sendProcessNeighborsAfterFtoCY.resize(this->getParH(level)->sendProcessNeighborY.size());
+    this->getParH(level)->recvProcessNeighborsAfterFtoCY.resize(this->getParH(level)->recvProcessNeighborY.size());
     this->getParD(level)->sendProcessNeighborsAfterFtoCY.resize(
         this->getParH(level)->sendProcessNeighborsAfterFtoCY.size());
     this->getParD(level)->recvProcessNeighborsAfterFtoCY.resize(
@@ -2700,10 +1508,8 @@ void Parameter::initProcessNeighborsAfterFtoCY(int level)
 
 void Parameter::initProcessNeighborsAfterFtoCZ(int level)
 {
-    this->getParH(level)->sendProcessNeighborsAfterFtoCZ.resize(
-        this->getParH(level)->sendProcessNeighborZ.size());
-    this->getParH(level)->recvProcessNeighborsAfterFtoCZ.resize(
-        this->getParH(level)->recvProcessNeighborZ.size());
+    this->getParH(level)->sendProcessNeighborsAfterFtoCZ.resize(this->getParH(level)->sendProcessNeighborZ.size());
+    this->getParH(level)->recvProcessNeighborsAfterFtoCZ.resize(this->getParH(level)->recvProcessNeighborZ.size());
     this->getParD(level)->sendProcessNeighborsAfterFtoCZ.resize(
         this->getParH(level)->sendProcessNeighborsAfterFtoCZ.size());
     this->getParD(level)->recvProcessNeighborsAfterFtoCZ.resize(
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
index 67e5f44f19ba8f502d5af59750860a59978a5a87..940b2493f96a8eab73d07d6a19031d708bc865dd 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
@@ -890,12 +890,18 @@ private:
     // initial condition
     std::function<void(real, real, real, real &, real &, real &, real &)> initialCondition;
 
+
+    ////////////////////////////////////////////////////////////////////////////
     // cuda streams
+
+    //! determines whether streams and thus communication hiding should be used
     bool useStreams{ false };
     std::unique_ptr<CudaStreamManager> cudaStreamManager;
 
 public:
-    void setUseStreams();
+    //! \brief sets whether streams and thus communication hiding should be used        
+    //! \details This function is only useful for simulations on multiple GPUs. If there is only one MPI process, the passed value is automatically overwritten with false.
+    void setUseStreams(bool useStreams);
     bool getUseStreams();
     std::unique_ptr<CudaStreamManager> &getStreamManager();
     bool getKernelNeedsFluidNodeIndicesToRun();