diff --git a/.gitignore b/.gitignore
index f87c8efbbd3b3877bd77212d6c2184db2aa409f1..fbab1b2097fad956dceb05769613cb82053b27e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ __pycache__/
 .idea/
 .ccache/
 .cache/
+.devcontainer/devcontainer.json
 
 # simulation results
 output/
diff --git a/CMake/cmake_config_files/ARAGORNUBUNTU.config.cmake b/CMake/cmake_config_files/ARAGORNUBUNTU.config.cmake
index c8432efe045c386174a9e2a04988ed51ed794bf3..90debb1a4c270109d4dfbb455f21253b3a6754b8 100644
--- a/CMake/cmake_config_files/ARAGORNUBUNTU.config.cmake
+++ b/CMake/cmake_config_files/ARAGORNUBUNTU.config.cmake
@@ -6,6 +6,9 @@
 
 set(CMAKE_CUDA_ARCHITECTURES 86)     # Nvidia GeForce RTX 3060
 
+set(PATH_NUMERICAL_TESTS "D:/out/numericalTests/")
+list(APPEND VF_COMPILER_DEFINITION "PATH_NUMERICAL_TESTS=${PATH_NUMERICAL_TESTS}")
+
 set(GPU_APP "apps/gpu/LBM/")
 list(APPEND USER_APPS 
     "${GPU_APP}DrivenCavityMultiGPU"
diff --git a/CMake/cmake_config_files/KI4ALLGPU.config.cmake b/CMake/cmake_config_files/KI4ALLGPU.config.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..111a3b3881d7a07eada02fb1e826e88b64b3591e
--- /dev/null
+++ b/CMake/cmake_config_files/KI4ALLGPU.config.cmake
@@ -0,0 +1,16 @@
+#################################################################################
+# VirtualFluids MACHINE FILE
+# Responsible: Anna Wellmann
+# OS:          Ubuntu 20.04 (Docker container)
+#################################################################################
+
+set(CMAKE_CUDA_ARCHITECTURES 80)     # Nvidia Tesla A100
+
+set(GPU_APP "apps/gpu/LBM/")
+list(APPEND USER_APPS 
+    "${GPU_APP}ChannelFlow"
+    "${GPU_APP}SphereScaling"
+)
+
+# run docker container with:
+# docker run -it -v `pwd`:`pwd` -w `pwd` --gpus all --hostname ki4allgpu --name virtual-fluids-environment <containerid>
\ No newline at end of file
diff --git a/apps/gpu/LBM/ChannelFlow/CMakeLists.txt b/apps/gpu/LBM/ChannelFlow/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f5b1bfd40dc723a7c050091d6d1c82d5f9addbd5
--- /dev/null
+++ b/apps/gpu/LBM/ChannelFlow/CMakeLists.txt
@@ -0,0 +1,7 @@
+PROJECT(ChannelFlow LANGUAGES CUDA CXX)
+
+vf_add_library(BUILDTYPE binary PRIVATE_LINK basics VirtualFluids_GPU GridGenerator MPI::MPI_CXX FILES ChannelFlow.cpp)
+
+set_source_files_properties(ChannelFlow.cpp PROPERTIES LANGUAGE CUDA)
+
+set_target_properties(ChannelFlow PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
diff --git a/apps/gpu/LBM/ChannelFlow/ChannelFlow.cpp b/apps/gpu/LBM/ChannelFlow/ChannelFlow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..98982f6d9da4c95ca12319f56ffcc4a1e83d33af
--- /dev/null
+++ b/apps/gpu/LBM/ChannelFlow/ChannelFlow.cpp
@@ -0,0 +1,272 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
+//
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file ChannelFlow.cpp
+//! \ingroup Applications
+//! \author Anna Wellmann
+//=======================================================================================
+#include <numeric>
+#define _USE_MATH_DEFINES
+#include <exception>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+#include "mpi.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "Core/DataTypes.h"
+#include "Core/LbmOrGks.h"
+#include "Core/Logger/Logger.h"
+#include "Core/VectorTypes.h"
+#include "PointerDefinitions.h"
+#include "config/ConfigurationFile.h"
+#include "logger/Logger.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "GridGenerator/grid/BoundaryConditions/Side.h"
+#include "GridGenerator/grid/GridBuilder/LevelGridBuilder.h"
+#include "GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
+#include "GridGenerator/grid/GridFactory.h"
+
+#include "GridGenerator/geometries/Sphere/Sphere.h"
+#include "GridGenerator/geometries/TriangularMesh/TriangularMesh.h"
+#include "GridGenerator/utilities/communication.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.h"
+#include "VirtualFluids_GPU/Communication/Communicator.h"
+#include "VirtualFluids_GPU/DataStructureInitializer/GridProvider.h"
+#include "VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
+#include "VirtualFluids_GPU/GPU/CudaMemoryManager.h"
+#include "VirtualFluids_GPU/LBM/Simulation.h"
+#include "VirtualFluids_GPU/Output/FileWriter.h"
+#include "VirtualFluids_GPU/Parameter/Parameter.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+int main(int argc, char *argv[])
+{
+    try {
+        //////////////////////////////////////////////////////////////////////////
+        // Simulation parameters
+        //////////////////////////////////////////////////////////////////////////
+
+        const real channelWidth = 1.0;
+        const real Re = 10000.0;
+        const uint nx = 700;          // 700 nodes need ~60 GB on A100 (single precision)
+        const real velocityLB = 0.05; // LB units
+
+        const uint timeStepOut = 10000;
+        const uint timeStepEnd = 100000;
+
+        //////////////////////////////////////////////////////////////////////////
+        // setup simulation parameters (without config file)
+        //////////////////////////////////////////////////////////////////////////
+
+        vf::gpu::Communicator &communicator = vf::gpu::Communicator::getInstance();
+        const int numberOfProcesses = communicator.getNummberOfProcess();
+        SPtr<Parameter> para = std::make_shared<Parameter>(numberOfProcesses, communicator.getPID());
+        std::vector<uint> devices(10);
+        std::iota(devices.begin(), devices.end(), 0);
+        para->setDevices(devices);
+        para->setMaxDev(communicator.getNummberOfProcess());
+        BoundaryConditionFactory bcFactory = BoundaryConditionFactory();
+
+        //////////////////////////////////////////////////////////////////////////
+        // setup logger
+        //////////////////////////////////////////////////////////////////////////
+
+        std::ofstream logFile("output/log_process" + std::to_string(vf::gpu::Communicator::getInstance().getPID()) +
+                              ".txt");
+        logging::Logger::addStream(&logFile);
+        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);
+
+        vf::logging::Logger::changeLogPath("output/vflog_process" +
+                                           std::to_string(vf::gpu::Communicator::getInstance().getPID()) + ".txt");
+        vf::logging::Logger::initalizeLogger();
+
+        //////////////////////////////////////////////////////////////////////////
+        // setup gridGenerator
+        //////////////////////////////////////////////////////////////////////////
+
+        auto gridFactory = GridFactory::make();
+        gridFactory->setTriangularMeshDiscretizationMethod(TriangularMeshDiscretizationMethod::POINT_IN_OBJECT);
+        auto gridBuilder = MultipleGridBuilder::makeShared(gridFactory);
+
+        //////////////////////////////////////////////////////////////////////////
+        // create grid
+        //////////////////////////////////////////////////////////////////////////
+
+        const real yGridMin = 0.0 * channelWidth;
+        const real yGridMax = 1.0 * channelWidth;
+        const real zGridMin = 0.0 * channelWidth;
+        const real zGridMax = 1.0 * channelWidth;
+
+        real dx = channelWidth / real(nx);
+
+        //////////////////////////////////////////////////////////////////////////
+        // compute parameters in lattice units
+        //////////////////////////////////////////////////////////////////////////
+
+        const real viscosityLB = (channelWidth / dx) * velocityLB / Re; // LB units
+
+        VF_LOG_INFO("LB parameters:");
+        VF_LOG_INFO("velocity LB [dx/dt]              = {}", velocityLB);
+        VF_LOG_INFO("viscosity LB [dx/dt]             = {}", viscosityLB);
+
+        //////////////////////////////////////////////////////////////////////////
+        // set parameters
+        //////////////////////////////////////////////////////////////////////////
+
+        para->setPrintFiles(true);
+
+        para->setVelocityLB(velocityLB);
+        para->setViscosityLB(viscosityLB);
+
+        para->setVelocityRatio((real)1.0);
+        para->setDensityRatio((real)1.0);
+
+        para->setTimestepOut(timeStepOut);
+        para->setTimestepEnd(timeStepEnd);
+
+        para->setOutputPrefix("ChannelFlow");
+        para->setMainKernel("CumulantK17CompChimStream");
+
+        const uint generatePart = vf::gpu::Communicator::getInstance().getPID();
+        real overlap = (real)8.0 * dx;
+
+        if (numberOfProcesses > 1) {
+
+            //////////////////////////////////////////////////////////////////////////
+            // add coarse grids
+            //////////////////////////////////////////////////////////////////////////
+
+            real subdomainMinX = channelWidth * generatePart;
+            real subdomainMinXoverlap = subdomainMinX;
+            real subdomainMaxX = subdomainMinX + channelWidth;
+            real subdomainMaxXoverlap = subdomainMaxX;
+
+            if (generatePart != 0)
+                subdomainMinXoverlap -= overlap;
+
+            if (generatePart != numberOfProcesses - 1)
+                subdomainMaxXoverlap += overlap;
+
+            gridBuilder->addCoarseGrid(subdomainMinXoverlap, yGridMin, zGridMin, subdomainMaxXoverlap, yGridMax,
+                                       zGridMax, dx);
+
+            //////////////////////////////////////////////////////////////////////////
+            // set subdomain dimensions
+            //////////////////////////////////////////////////////////////////////////
+
+            gridBuilder->setSubDomainBox(
+                std::make_shared<BoundingBox>(subdomainMinX, subdomainMaxX, yGridMin, yGridMax, zGridMin, zGridMax));
+
+            //////////////////////////////////////////////////////////////////////////
+            // build grids
+            //////////////////////////////////////////////////////////////////////////
+
+            gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
+
+            //////////////////////////////////////////////////////////////////////////
+            // configure communication neighbors
+            //////////////////////////////////////////////////////////////////////////
+
+            if (generatePart != 0) {
+                gridBuilder->findCommunicationIndices(CommunicationDirections::MX, LBM);
+                gridBuilder->setCommunicationProcess(CommunicationDirections::MX, generatePart - 1);
+            }
+
+            if (generatePart != numberOfProcesses - 1) {
+                gridBuilder->findCommunicationIndices(CommunicationDirections::PX, LBM);
+                gridBuilder->setCommunicationProcess(CommunicationDirections::PX, generatePart + 1);
+            }
+
+            //////////////////////////////////////////////////////////////////////////
+            // set boundary conditions
+            //////////////////////////////////////////////////////////////////////////
+
+            gridBuilder->setPeriodicBoundaryCondition(false, false, false);
+
+            if (generatePart == 0) {
+                gridBuilder->setVelocityBoundaryCondition(SideType::MX, velocityLB, 0.0, 0.0);
+            }
+            if (generatePart == numberOfProcesses - 1) {
+                gridBuilder->setPressureBoundaryCondition(SideType::PX,
+                                                          0.0); // set pressure boundary condition last
+                bcFactory.setPressureBoundaryCondition(BoundaryConditionFactory::PressureBC::OutflowNonReflective);
+            }
+            gridBuilder->setNoSlipBoundaryCondition(SideType::MY);
+            gridBuilder->setNoSlipBoundaryCondition(SideType::PY);
+            gridBuilder->setNoSlipBoundaryCondition(SideType::MZ);
+            gridBuilder->setNoSlipBoundaryCondition(SideType::PZ);
+            bcFactory.setNoSlipBoundaryCondition(BoundaryConditionFactory::NoSlipBC::NoSlipCompressible);
+            bcFactory.setVelocityBoundaryCondition(
+                BoundaryConditionFactory::VelocityBC::VelocityAndPressureCompressible);
+        } else {
+            VF_LOG_CRITICAL("This app has no setup for a single GPU");
+        }
+
+        //////////////////////////////////////////////////////////////////////////
+        // setup to copy mesh to simulation
+        //////////////////////////////////////////////////////////////////////////
+
+        auto cudaMemoryManager = std::make_shared<CudaMemoryManager>(para);
+        SPtr<GridProvider> gridGenerator =
+            GridProvider::makeGridGenerator(gridBuilder, para, cudaMemoryManager, communicator);
+
+        //////////////////////////////////////////////////////////////////////////
+        // run simulation
+        //////////////////////////////////////////////////////////////////////////
+
+        Simulation sim(para, cudaMemoryManager, communicator, *gridGenerator, &bcFactory);
+        sim.run();
+
+    } catch (const spdlog::spdlog_ex &ex) {
+        std::cout << "Log initialization failed: " << ex.what() << std::endl;
+    } catch (const std::bad_alloc &e) {
+        VF_LOG_CRITICAL("Bad Alloc: {}", e.what());
+    } catch (const std::exception &e) {
+        VF_LOG_CRITICAL("exception: {}", e.what());
+    } catch (...) {
+        VF_LOG_CRITICAL("Unknown exception!");
+    }
+
+    return 0;
+}
diff --git a/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp b/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp
index 535a3972580726ccdd1536dd4b8011eba98176c1..23bcb582dd863acd813519eed4ec1402105c3618 100644
--- a/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp
+++ b/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp
@@ -8,7 +8,7 @@
 #include "VirtualFluids_GPU/GPU/CudaMemoryManager.h"
 #include "VirtualFluids_GPU/Parameter/Parameter.h"
 
-#include "VirtualFluids_GPU/BoundaryConditions/BoundaryConditionFactory.h"
+#include "VirtualFluids_GPU/Factories/BoundaryConditionFactory.h"
 #include "VirtualFluids_GPU/Communication/Communicator.h"
 #include "VirtualFluids_GPU/LBM/Simulation.h"
 
diff --git a/src/mpi/NullCommunicator.cpp b/src/mpi/NullCommunicator.cpp
index 0f407d0dccab79b551e8671bcaa150f6aab36789..267942895df0afbfae7e2d528feb67ff7a2c6519 100644
--- a/src/mpi/NullCommunicator.cpp
+++ b/src/mpi/NullCommunicator.cpp
@@ -33,43 +33,65 @@
 
 #include "NullCommunicator.h"
 
-namespace vf::mpi 
+namespace vf::mpi
 {
 
-// std::shared_ptr<Communicator> NullCommunicator::getInstance()
-// {
-//     std::lock_guard<std::mutex> myLock(instantiation_mutex);
-//     if (!instance){
-//         instance = std::shared_ptr<NullCommunicator>(new NullCommunicator);
-//     }
-//     return instance;
-// }
-//////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getBundleID() { return 0; }
-//////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getNumberOfBundles() { return 0; }
-//////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getProcessID() { return 0; }
-//////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getNumberOfProcesses() { return 0; }
-//////////////////////////////////////////////////////////////////////////
-void *NullCommunicator::getNativeCommunicator() { return NULL; }
-//////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getRoot() { return 0; }
-//////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getBundleRoot() { return 0; }
-//////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getProcessRoot() { return 0; }
-//////////////////////////////////////////////////////////////////////////
-std::vector<std::string> NullCommunicator::gather(const std::string & /*str*/) { return std::vector<std::string>(); }
-//////////////////////////////////////////////////////////////////////////
-std::vector<double> NullCommunicator::gatherDoubles(std::vector<double> & /*values*/) { return std::vector<double>(); }
-//////////////////////////////////////////////////////////////////////////
-void NullCommunicator::allGatherInts(std::vector<int> &svalues, std::vector<int> &rvalues) {}
-//////////////////////////////////////////////////////////////////////////
-void NullCommunicator::sendSerializedObject(std::stringstream &ss, int target) {}
-//////////////////////////////////////////////////////////////////////////
-void NullCommunicator::receiveSerializedObject(std::stringstream &ss, int source) {}
+    std::shared_ptr<Communicator> NullCommunicator::getInstance()
+    {
+        std::lock_guard<std::mutex> myLock(instantiation_mutex);
+        if (!instance){
+            instance = std::shared_ptr<NullCommunicator>(new NullCommunicator);
+        }
+        return instance;
+    }
+    //////////////////////////////////////////////////////////////////////////
+    int NullCommunicator::getBundleID() { return 0; }
+    //////////////////////////////////////////////////////////////////////////
+    int NullCommunicator::getNumberOfBundles() { return 0; }
+    //////////////////////////////////////////////////////////////////////////
+    int NullCommunicator::getProcessID() { return 0; }
+    //////////////////////////////////////////////////////////////////////////
+    int NullCommunicator::getNumberOfProcesses() { return 0; }
+    //////////////////////////////////////////////////////////////////////////
+    void *NullCommunicator::getNativeCommunicator() { return NULL; }
+    //////////////////////////////////////////////////////////////////////////
+    int NullCommunicator::getRoot() { return 0; }
+    //////////////////////////////////////////////////////////////////////////
+    int NullCommunicator::getBundleRoot() { return 0; }
+    //////////////////////////////////////////////////////////////////////////
+    int NullCommunicator::getProcessRoot() { return 0; }
+    //////////////////////////////////////////////////////////////////////////
+    std::vector<std::string> NullCommunicator::gather(const std::string & /*str*/) { return std::vector<std::string>(); }
+    //////////////////////////////////////////////////////////////////////////
 
+    void NullCommunicator::sendSerializedObject(std::stringstream &ss, int target) {}
+    //////////////////////////////////////////////////////////////////////////
+    void NullCommunicator::receiveSerializedObject(std::stringstream &ss, int source) {}
 
+    int NullCommunicator::getProcessID(int bundle, int rank) { return 0; }
+    bool NullCommunicator::isRoot() {return true; }
+
+    int NullCommunicator::getNumberOfProcessesInBundle(int bundle) {return 0;}
+    void NullCommunicator::barrier() {}
+    void NullCommunicator::abort(int errorcode) {}
+
+
+    std::vector<int> NullCommunicator::gather(std::vector<int> &values){ return std::vector<int>(); }
+    std::vector<float> NullCommunicator::gather(std::vector<float> &values){ return std::vector<float>(); }
+    std::vector<double> NullCommunicator::gather(std::vector<double> &values){ return std::vector<double>(); }
+    std::vector<unsigned long long> NullCommunicator::gather(std::vector<unsigned long long> &values){ return std::vector<unsigned long long>(); }
+
+    void NullCommunicator::allGather(std::vector<int> &svalues, std::vector<int> &rvalues){ }
+    void NullCommunicator::allGather(std::vector<float> &svalues, std::vector<float> &rvalues){ }
+    void NullCommunicator::allGather(std::vector<double> &svalues, std::vector<double> &rvalues){ }
+    void NullCommunicator::allGather(std::vector<unsigned long long> &svalues, std::vector<unsigned long long> &rvalues){ }
+
+    void NullCommunicator::broadcast(int &value){ }
+    void NullCommunicator::broadcast(float &value){ }
+    void NullCommunicator::broadcast(double &value){ }
+    void NullCommunicator::broadcast(long int &value){ }
+    void NullCommunicator::broadcast(std::vector<int> &values){ }
+    void NullCommunicator::broadcast(std::vector<float> &values){ }
+    void NullCommunicator::broadcast(std::vector<double> &values){ }
+    void NullCommunicator::broadcast(std::vector<long int> &values){ }
 }
diff --git a/src/mpi/NullCommunicator.h b/src/mpi/NullCommunicator.h
index 1a3ba3eac5c840d8e6e6c474d7dec9dfe6be6750..836f801ab6d15e377da8a34dfed8016b05f86e3a 100644
--- a/src/mpi/NullCommunicator.h
+++ b/src/mpi/NullCommunicator.h
@@ -36,7 +36,7 @@
 
 #include "Communicator.h"
 
-namespace vf::mpi 
+namespace vf::mpi
 {
 
 //! \brief A class implements Communicator for shared memory.
@@ -44,22 +44,45 @@ namespace vf::mpi
 class NullCommunicator : public Communicator
 {
 public:
-    // static std::shared_ptr<Communicator> getInstance();
-    int getBundleID() override;
-    int getNumberOfBundles() override;
-    int getProcessID() override;
-    int getNumberOfProcesses() override;
-    void *getNativeCommunicator() override;
-    int getRoot() override;
-    int getBundleRoot() override;
-    int getProcessRoot() override;
-    std::vector<std::string> gather(const std::string &str) override;
-    std::vector<double> gatherDoubles(std::vector<double> &values);
-    void allGatherInts(std::vector<int> &svalues, std::vector<int> &rvalues);
-    void sendSerializedObject(std::stringstream &ss, int target) override;
-    void receiveSerializedObject(std::stringstream &ss, int source) override;
+    static std::shared_ptr<Communicator> getInstance();
 
-    
+    int getBundleID();
+    int getNumberOfBundles();
+    int getProcessID();
+    int getProcessID(int bundle, int rank);
+    int getNumberOfProcesses();
+    bool isRoot();
+    void *getNativeCommunicator();
+
+    void sendSerializedObject(std::stringstream &ss, int target);
+    void receiveSerializedObject(std::stringstream &ss, int source);
+
+    int getRoot();
+    int getBundleRoot();
+    int getProcessRoot();
+    int getNumberOfProcessesInBundle(int bundle);
+    void barrier();
+    void abort(int errorcode);
+
+    std::vector<std::string> gather(const std::string &str);
+    std::vector<int> gather(std::vector<int> &values);
+    std::vector<float> gather(std::vector<float> &values);
+    std::vector<double> gather(std::vector<double> &values);
+    std::vector<unsigned long long> gather(std::vector<unsigned long long> &values);
+
+    void allGather(std::vector<int> &svalues, std::vector<int> &rvalues);
+    void allGather(std::vector<float> &svalues, std::vector<float> &rvalues);
+    void allGather(std::vector<double> &svalues, std::vector<double> &rvalues);
+    void allGather(std::vector<unsigned long long> &svalues, std::vector<unsigned long long> &rvalues);
+
+    void broadcast(int &value);
+    void broadcast(float &value);
+    void broadcast(double &value);
+    void broadcast(long int &value);
+    void broadcast(std::vector<int> &values);
+    void broadcast(std::vector<float> &values);
+    void broadcast(std::vector<double> &values);
+    void broadcast(std::vector<long int> &values);
 };
 
 }