diff --git a/apps/gpu/ActuatorLine/ActuatorLine.cpp b/apps/gpu/ActuatorLine/ActuatorLine.cpp
index ed8d2477139313d2cbe167492b6f5a247d6e5dc8..f1da073fe2ad6ac80020fb4f4be69bfd60709034 100644
--- a/apps/gpu/ActuatorLine/ActuatorLine.cpp
+++ b/apps/gpu/ActuatorLine/ActuatorLine.cpp
@@ -68,7 +68,7 @@
 #include "gpu/core/DataStructureInitializer/GridProvider.h"
 #include "gpu/core/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
 #include "gpu/core/DataStructureInitializer/GridReaderFiles/GridReader.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
 #include "gpu/core/LBM/Simulation.h"
diff --git a/apps/gpu/ActuatorLineRegression/ActuatorLineRegression.cpp b/apps/gpu/ActuatorLineRegression/ActuatorLineRegression.cpp
index 222b5e3c53f1cd7ea98def212f21c8715e73cbdc..6b815a6a4257b74d699df338c620f925e9235cae 100644
--- a/apps/gpu/ActuatorLineRegression/ActuatorLineRegression.cpp
+++ b/apps/gpu/ActuatorLineRegression/ActuatorLineRegression.cpp
@@ -75,7 +75,7 @@
 #include "gpu/core/PreCollisionInteractor/Probes/PointProbe.h"
 #include "gpu/core/PreCollisionInteractor/Probes/PlaneProbe.h"
 #include "gpu/core/PreCollisionInteractor/Probes/Probe.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/TurbulenceModels/TurbulenceModelFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
 #include "gpu/core/Kernel/KernelTypes.h"
diff --git a/apps/gpu/Basel/main.cpp b/apps/gpu/Basel/main.cpp
index dd3762c1253ee2a77e196a3c3ee886281fa7fb64..0d8a821d1bb3dd5e14c008673cdab81c353c0d95 100644
--- a/apps/gpu/Basel/main.cpp
+++ b/apps/gpu/Basel/main.cpp
@@ -26,7 +26,7 @@
 #include "gpu/core/Parameter/Parameter.h"
 #include "gpu/core/Output/FileWriter.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 
 #include "global.h"
 
diff --git a/apps/gpu/BaselMultiGPU/main.cpp b/apps/gpu/BaselMultiGPU/main.cpp
index 31988ab6068ea46e94cc248c882c65dc44535e73..87a230da5c012bac7487e7e634de2b4c3f8bf712 100644
--- a/apps/gpu/BaselMultiGPU/main.cpp
+++ b/apps/gpu/BaselMultiGPU/main.cpp
@@ -26,7 +26,7 @@
 #include "gpu/core/Parameter/Parameter.h"
 #include "gpu/core/Output/FileWriter.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 
 #include "global.h"
 
diff --git a/apps/gpu/BaselNU/main.cpp b/apps/gpu/BaselNU/main.cpp
index 48092b4f3aecce458989f3a158d889a7911c01d9..3a54000a2fdf86be1e2133d3323a79550a4c9a77 100644
--- a/apps/gpu/BaselNU/main.cpp
+++ b/apps/gpu/BaselNU/main.cpp
@@ -26,7 +26,7 @@
 #include "gpu/core/Parameter/Parameter.h"
 #include "gpu/core/Output/FileWriter.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryCondtions/BoundaryConditionFactory.h"
 
 #include "global.h"
 
diff --git a/apps/gpu/BoundaryLayer/BoundaryLayer.cpp b/apps/gpu/BoundaryLayer/BoundaryLayer.cpp
index 817a04cc019ef21c3959b756b8c471d512206fde..a5bc05310d17af7d943b1db921b7eb908cc6b96c 100644
--- a/apps/gpu/BoundaryLayer/BoundaryLayer.cpp
+++ b/apps/gpu/BoundaryLayer/BoundaryLayer.cpp
@@ -80,8 +80,8 @@
 #include "gpu/core/PreCollisionInteractor/Probes/PlanarAverageProbe.h"
 #include "gpu/core/PreCollisionInteractor/Probes/WallModelProbe.h"
 #include "gpu/core/PreCollisionInteractor/PrecursorWriter.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/TurbulenceModels/TurbulenceModelFactory.h"
 #include "gpu/core/Kernel/KernelTypes.h"
 
diff --git a/apps/gpu/DrivenCavity/DrivenCavity.cpp b/apps/gpu/DrivenCavity/DrivenCavity.cpp
index 5c5c2effe14b441d8f4bfe9a497b361aa8225609..2b6e0cd307c1d46b9ce8dbbd0deef45a8c506433 100644
--- a/apps/gpu/DrivenCavity/DrivenCavity.cpp
+++ b/apps/gpu/DrivenCavity/DrivenCavity.cpp
@@ -57,8 +57,8 @@
 
 //////////////////////////////////////////////////////////////////////////
 
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/DataStructureInitializer/GridProvider.h"
 #include "gpu/core/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
diff --git a/apps/gpu/DrivenCavityMultiGPU/DrivenCavityMultiGPU.cpp b/apps/gpu/DrivenCavityMultiGPU/DrivenCavityMultiGPU.cpp
index 82d035f33ade61989e573c2fb0dd4b775e5f6b90..ecfbc67f6786562090665de8aedaabd8e642cb27 100755
--- a/apps/gpu/DrivenCavityMultiGPU/DrivenCavityMultiGPU.cpp
+++ b/apps/gpu/DrivenCavityMultiGPU/DrivenCavityMultiGPU.cpp
@@ -42,8 +42,8 @@
 
 #include "gpu/core/Kernel/KernelFactory/KernelFactoryImp.h"
 #include "gpu/core/PreProcessor/PreProcessorFactory/PreProcessorFactoryImp.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/Kernel/KernelTypes.h"
 
 #include "gpu/core/GPU/CudaMemoryManager.h"
diff --git a/apps/gpu/DrivenCavityUniform/DrivenCavity.cpp b/apps/gpu/DrivenCavityUniform/DrivenCavity.cpp
index eab4daa6b8274250ad6dd94fbb6fc2e922147e86..ee18b8a52786807c57067967ccfcca18f9c5ca63 100644
--- a/apps/gpu/DrivenCavityUniform/DrivenCavity.cpp
+++ b/apps/gpu/DrivenCavityUniform/DrivenCavity.cpp
@@ -57,8 +57,8 @@
 
 //////////////////////////////////////////////////////////////////////////
 
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/DataStructureInitializer/GridProvider.h"
 #include "gpu/core/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
diff --git a/apps/gpu/MusselOyster/MusselOyster.cpp b/apps/gpu/MusselOyster/MusselOyster.cpp
index 0c145e5a3c6a498b26b288f614faafec2212df86..a74b4c8f8d0307ca4db9aa56fb1f8c82b7628e4f 100644
--- a/apps/gpu/MusselOyster/MusselOyster.cpp
+++ b/apps/gpu/MusselOyster/MusselOyster.cpp
@@ -43,7 +43,7 @@
 #include "gpu/core/LBM/Simulation.h"
 #include "gpu/core/Output/FileWriter.h"
 #include "gpu/core/Parameter/Parameter.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryCondtions/BoundaryConditionFactory.h"
 #include "gpu/core/Kernel/KernelTypes.h"
 
 //////////////////////////////////////////////////////////////////////////
diff --git a/apps/gpu/SphereGPU/Sphere.cpp b/apps/gpu/SphereGPU/Sphere.cpp
index 39faecec821ecf1904369bf945cacba00c89ccc3..03931b346450265434900dc36b5e7dbe2f7475bc 100644
--- a/apps/gpu/SphereGPU/Sphere.cpp
+++ b/apps/gpu/SphereGPU/Sphere.cpp
@@ -66,8 +66,8 @@
 #include "gpu/core/LBM/Simulation.h"
 #include "gpu/core/Output/FileWriter.h"
 #include "gpu/core/Parameter/Parameter.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/PreCollisionInteractor/Probes/PointProbe.h"
 #include "gpu/core/PreCollisionInteractor/Probes/PlaneProbe.h"
 #include "gpu/core/Kernel/KernelTypes.h"
@@ -106,6 +106,7 @@ int main(int argc, char *argv[])
             para = std::make_shared<Parameter>();
         }
 
+        vf::parallel::Communicator& communicator = *vf::parallel::MPICommunicator::getInstance();
 
         //////////////////////////////////////////////////////////////////////////
         // create grid
@@ -219,7 +220,6 @@ int main(int argc, char *argv[])
         //////////////////////////////////////////////////////////////////////////
         // setup to copy mesh to simulation
         //////////////////////////////////////////////////////////////////////////
-        vf::parallel::Communicator &communicator = *vf::parallel::MPICommunicator::getInstance();
         auto cudaMemoryManager = std::make_shared<CudaMemoryManager>(para);
         SPtr<GridProvider> gridGenerator = GridProvider::makeGridGenerator(gridBuilder, para, cudaMemoryManager, communicator);
 
diff --git a/apps/gpu/SphereRefined/SphereRefined.cpp b/apps/gpu/SphereRefined/SphereRefined.cpp
index dff610850dd58890cdb2eafbfe45e20375ce7439..6e3670c7a3c5b7696a9a8e805523f468c132d132 100644
--- a/apps/gpu/SphereRefined/SphereRefined.cpp
+++ b/apps/gpu/SphereRefined/SphereRefined.cpp
@@ -58,7 +58,7 @@
 
 //////////////////////////////////////////////////////////////////////////
 
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
 #include "gpu/core/DataStructureInitializer/GridProvider.h"
 #include "gpu/core/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
diff --git a/apps/gpu/SphereScaling/SphereScaling.cpp b/apps/gpu/SphereScaling/SphereScaling.cpp
index fbecb20195659844aded8144ff92b740dfb63e87..f2350e14fe2221449b7eee21a0b02558b1a69b97 100755
--- a/apps/gpu/SphereScaling/SphereScaling.cpp
+++ b/apps/gpu/SphereScaling/SphereScaling.cpp
@@ -45,8 +45,8 @@
 
 #include "gpu/core/Kernel/KernelFactory/KernelFactoryImp.h"
 #include "gpu/core/PreProcessor/PreProcessorFactory/PreProcessorFactoryImp.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/Kernel/KernelTypes.h"
 
 #include "gpu/core/GPU/CudaMemoryManager.h"
diff --git a/apps/gpu/TGV_3D/TGV_3D.cpp b/apps/gpu/TGV_3D/TGV_3D.cpp
index 088c013b282c282e96f2fb4081b69727c3f44798..b3725af2e1687b573b02238c008e0411a0b2670a 100644
--- a/apps/gpu/TGV_3D/TGV_3D.cpp
+++ b/apps/gpu/TGV_3D/TGV_3D.cpp
@@ -67,7 +67,7 @@
 #include "gpu/core/DataStructureInitializer/GridProvider.h"
 #include "gpu/core/DataStructureInitializer/GridReaderFiles/GridReader.h"
 #include "gpu/core/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
 #include "gpu/core/LBM/Simulation.h"
 #include "gpu/core/Output/FileWriter.h"
diff --git a/apps/gpu/TGV_3D_GridRef/TGV_3D_GridRef.cpp b/apps/gpu/TGV_3D_GridRef/TGV_3D_GridRef.cpp
index 02ed3f120e57ab1e1efc35d28345f09c87ae1946..997d3c8572ac46bf53f032eae182c3dc43283f9e 100644
--- a/apps/gpu/TGV_3D_GridRef/TGV_3D_GridRef.cpp
+++ b/apps/gpu/TGV_3D_GridRef/TGV_3D_GridRef.cpp
@@ -71,7 +71,7 @@
 #include "gpu/core/DataStructureInitializer/GridProvider.h"
 #include "gpu/core/DataStructureInitializer/GridReaderFiles/GridReader.h"
 #include "gpu/core/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
 #include "gpu/core/LBM/Simulation.h"
diff --git a/apps/gpu/TGV_3D_MultiGPU/TGV_3D_MultiGPU.cpp b/apps/gpu/TGV_3D_MultiGPU/TGV_3D_MultiGPU.cpp
index 1c7f4a81e924b3ab4bbe9f70c7aa67d9d9b466e0..48e72e6382fa7944fb413bb573a980b3cc3085d0 100644
--- a/apps/gpu/TGV_3D_MultiGPU/TGV_3D_MultiGPU.cpp
+++ b/apps/gpu/TGV_3D_MultiGPU/TGV_3D_MultiGPU.cpp
@@ -63,7 +63,7 @@
 
 #include "gpu/core/Kernel/KernelFactory/KernelFactoryImp.h"
 #include "gpu/core/PreProcessor/PreProcessorFactory/PreProcessorFactoryImp.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 
 #include "gpu/core/GPU/CudaMemoryManager.h"
 
diff --git a/apps/gpu/WTG_RUB/WTG_RUB.cpp b/apps/gpu/WTG_RUB/WTG_RUB.cpp
index 6cc1114aaebfa1080cc6c832ca312b28f66d0dbd..8de3357854fb2d28208f1956c4798544a12c84f3 100644
--- a/apps/gpu/WTG_RUB/WTG_RUB.cpp
+++ b/apps/gpu/WTG_RUB/WTG_RUB.cpp
@@ -72,7 +72,7 @@
 #include "gpu/core/Parameter/Parameter.h"
 #include "gpu/core/Output/FileWriter.h"
 #include "gpu/core/GPU/CudaMemoryManager.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/Kernel/KernelTypes.h"
 
 #include <parallel/MPICommunicator.h>
diff --git a/apps/gpu/gridGeneratorTest/gridGenerator.cpp b/apps/gpu/gridGeneratorTest/gridGenerator.cpp
index 0edb0155430b7eb3f72128587452e8911b0e4755..b8a46f11ec0fbee082f5ccf504e7135028971dea 100644
--- a/apps/gpu/gridGeneratorTest/gridGenerator.cpp
+++ b/apps/gpu/gridGeneratorTest/gridGenerator.cpp
@@ -17,7 +17,7 @@
 
 #include "gpu/core/Kernel/KernelFactory/KernelFactoryImp.h"
 #include "gpu/core/PreProcessor/PreProcessorFactory/PreProcessorFactoryImp.h"
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 
 #include "gpu/core/GPU/CudaMemoryManager.h"
 
diff --git a/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp b/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp
index 3b1365678749e3b92d40adf9a4e92095b61d405c..9d6f62f985b29c669d93381352593d54a969e7f3 100644
--- a/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp
+++ b/apps/gpu/tests/NumericalTests/Utilities/VirtualFluidSimulationFactory/VirtualFluidSimulationFactory.cpp
@@ -8,7 +8,7 @@
 #include "gpu/core/GPU/CudaMemoryManager.h"
 #include "gpu/core/Parameter/Parameter.h"
 
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/LBM/Simulation.h"
 
 #include <parallel/MPICommunicator.h>
diff --git a/pythonbindings/src/gpu/submodules/boundary_conditions.cpp b/pythonbindings/src/gpu/submodules/boundary_conditions.cpp
index 26fdd3e712714074928f452c179b977e3769eec3..21e3e85f6aaf3b802dc418161aa4789e2ac304b6 100644
--- a/pythonbindings/src/gpu/submodules/boundary_conditions.cpp
+++ b/pythonbindings/src/gpu/submodules/boundary_conditions.cpp
@@ -32,7 +32,7 @@
 //=======================================================================================
 #include <pybind11/pybind11.h>
 #include <gpu/GridGenerator/grid/BoundaryConditions/Side.h>
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 
 namespace boundary_conditions
 {
diff --git a/pythonbindings/src/gpu/submodules/simulation.cpp b/pythonbindings/src/gpu/submodules/simulation.cpp
index 38a5369470672b1851500793784d2129c520e6d7..54f64887d678b1712102479a4c09540cdde4e9d5 100644
--- a/pythonbindings/src/gpu/submodules/simulation.cpp
+++ b/pythonbindings/src/gpu/submodules/simulation.cpp
@@ -39,7 +39,7 @@
 #include <gpu/core/GPU/CudaMemoryManager.h>
 #include <gpu/core/DataStructureInitializer/GridProvider.h>
 #include <gpu/core/Output/DataWriter.h>
-#include "gpu/core/Factories/BoundaryConditionFactory.h"
+#include "gpu/core/BoundaryConditions/BoundaryConditionFactory.h"
 #include "gpu/core/TurbulenceModels/TurbulenceModelFactory.h"
 #include "gpu/core/GridScaling/GridScalingFactory.h"
 #include "parallel/Communicator.h"
diff --git a/src/basics/CMakeLists.txt b/src/basics/CMakeLists.txt
index 760d0f8260e1126b4cbe8933eda2780d43f36665..0d4559558e2ca027fb60c9c054b545595d18df4b 100644
--- a/src/basics/CMakeLists.txt
+++ b/src/basics/CMakeLists.txt
@@ -1,7 +1,7 @@
 
 include(buildInfo.cmake)
 
-vf_add_library(PUBLIC_LINK logger PRIVATE_LINK parallel EXCLUDE buildInfo.in.cpp)
+vf_add_library(PUBLIC_LINK logger PRIVATE_LINK EXCLUDE buildInfo.in.cpp)
 
 vf_get_library_name (library_name)
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/geometry3d)
diff --git a/src/basics/Timer/Timer.cpp b/src/basics/Timer/Timer.cpp
index c8856f72adffe0c407ff29ee74246638ce5c8280..9b10481a55726cdacb00fb6d1c41815865aafa80 100644
--- a/src/basics/Timer/Timer.cpp
+++ b/src/basics/Timer/Timer.cpp
@@ -26,18 +26,36 @@
 //  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 Timer.cpp
-//! \ingroup Timer
-//! \author Stephan Lenz
+//! \author Soeren Peters
 //=======================================================================================
 #include "Timer.h"
-#include "TimerImp.h"
 
-#include <memory>
+namespace vf::basics
+{
+
+void Timer::start()
+{
+    this->startTime = std::chrono::high_resolution_clock::now();
+}
+
+void Timer::end()
+{
+    this->endTime = std::chrono::high_resolution_clock::now();
+}
 
-SPtr<Timer> Timer::makeStart()
+double timeInSeconds(Timer::timePoint end, Timer::timePoint start)
 {
-    SPtr<Timer> t = std::make_shared<TimerImp>();
-    t->start();
-    return t;
+    return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000000.0;
 }
+
+double Timer::getTimeInSeconds() const
+{
+    return timeInSeconds(endTime, startTime);
+}
+
+double Timer::getCurrentRuntimeInSeconds() const
+{
+    return timeInSeconds(std::chrono::high_resolution_clock::now(), startTime);
+}
+
+} // namespace vf::basics
diff --git a/src/basics/Timer/Timer.h b/src/basics/Timer/Timer.h
index 6de04b2f3d5573ac6266bd2c35cf18cd232384dd..74a28f2af540302356792d03b2fb0a854c35eeda 100644
--- a/src/basics/Timer/Timer.h
+++ b/src/basics/Timer/Timer.h
@@ -26,29 +26,32 @@
 //  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 Timer.h
-//! \ingroup Timer
-//! \author Stephan Lenz
+//! \author Soeren Peters
 //=======================================================================================
-#ifndef TIMER_H
-#define TIMER_H
+#ifndef BASICS_TIMER_H
+#define BASICS_TIMER_H
 
-#include "basics_export.h"
+#include <chrono>
 
-#include "DataTypes.h"
-#include "PointerDefinitions.h"
+namespace vf::basics
+{
 
-class BASICS_EXPORT Timer
+class Timer
 {
 public:
-    virtual ~Timer() = default;
-    static SPtr<Timer> makeStart();
+    using timePoint = std::chrono::high_resolution_clock::time_point;
+
+    void start();
+    void end();
 
-    virtual void start() = 0;
-    virtual void end()   = 0;
+    double getTimeInSeconds() const;
+    double getCurrentRuntimeInSeconds() const;
 
-    virtual real getTimeInSeconds() const           = 0;
-    virtual real getCurrentRuntimeInSeconds() const = 0;
+private:
+    timePoint startTime;
+    timePoint endTime;
 };
 
+} // namespace vf::basics
+
 #endif
diff --git a/src/basics/Timer/TimerImp.cpp b/src/basics/Timer/TimerImp.cpp
deleted file mode 100644
index 76f9ac36793f2e2543abe9086f2780ee94b50eb7..0000000000000000000000000000000000000000
--- a/src/basics/Timer/TimerImp.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//=======================================================================================
-// ____          ____    __    ______     __________   __      __       __        __
-// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
-//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
-//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
-//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
-//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
-//      \    \  |    |   ________________________________________________________________
-//       \    \ |    |  |  ______________________________________________________________|
-//        \    \|    |  |  |         __          __     __     __     ______      _______
-//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
-//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
-//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
-//
-//  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 TimerImp.cpp
-//! \ingroup Timer
-//! \author Stephan Lenz
-//=======================================================================================
-#include "TimerImp.h"
-
-void TimerImp::start() { this->startTime = std::chrono::high_resolution_clock::now(); }
-
-void TimerImp::end() { this->endTime = std::chrono::high_resolution_clock::now(); }
-
-real TimerImp::getTimeInSeconds() const
-{
-    return real(std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count() / 1000000.0);
-}
-
-real TimerImp::getCurrentRuntimeInSeconds() const
-{
-    return real(
-        std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - startTime)
-            .count() /
-        1000000.0);
-}
diff --git a/src/basics/geometry3d/Axis.cpp b/src/basics/geometry3d/Axis.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d83ca8fbeab7994ede3bd9a0032b7e1583fecb9
--- /dev/null
+++ b/src/basics/geometry3d/Axis.cpp
@@ -0,0 +1,14 @@
+#include "Axis.h"
+
+std::string axis::to_string(Axis axis)
+{
+    switch (axis) {
+        case x:
+            return "x";
+        case y:
+            return "y";
+        case z:
+            return "z";
+    }
+    return "Axis not found.";
+}
\ No newline at end of file
diff --git a/src/basics/geometry3d/Axis.h b/src/basics/geometry3d/Axis.h
new file mode 100644
index 0000000000000000000000000000000000000000..4bd924db197f35c73a45420031d490f0be957020
--- /dev/null
+++ b/src/basics/geometry3d/Axis.h
@@ -0,0 +1,23 @@
+#ifndef AXIS
+#define AXIS
+
+#include <array>
+#include <map>
+#include <string>
+
+enum Axis {
+    x = 0,
+    y = 1,
+    z = 2,
+};
+
+const std::map<Axis, std::array<double, 3>> unitVectors{ { x, { 1, 0, 0 } },
+                                                         { y, { 0, 1, 0 } },
+                                                         { z, { 0, 0, 1 } } };
+
+namespace axis
+{
+std::string to_string(Axis axis);
+}
+
+#endif
diff --git a/src/basics/geometry3d/GbTriFaceMesh3D.cpp b/src/basics/geometry3d/GbTriFaceMesh3D.cpp
index 7da89fc9bf0565ec7862939ffa652b3ff1880a4f..b3c263ee7af29c538f4f3c2baa7113a82692c6ec 100644
--- a/src/basics/geometry3d/GbTriFaceMesh3D.cpp
+++ b/src/basics/geometry3d/GbTriFaceMesh3D.cpp
@@ -32,11 +32,12 @@
 //=======================================================================================
 #include <geometry3d/GbTriFaceMesh3D.h>
 
+#include <basics/Timer/Timer.h>
 #include <basics/utilities/UbFileInputASCII.h>
 #include <basics/utilities/UbLogger.h>
 #include <basics/utilities/UbRandom.h>
-#include <basics/utilities/UbTiming.h>
 #include <basics/writer/WbWriter.h>
+
 #include <geometry3d/CoordinateTransformation3D.h>
 #include <geometry3d/GbCuboid3D.h>
 #include <geometry3d/GbHalfSpace3D.h>
@@ -651,7 +652,7 @@ void GbTriFaceMesh3D::addSurfaceTriangleSet(vector<UbTupleFloat3> &pts, vector<U
 //      if( !kdTree)
 //      {
 //         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
-//         UbTimer timer; timer.start();
+//         vf::basics::Timer timer; timer.start();
 //         if(kdtreeSplitAlg == KDTREE_SAHPLIT     )
 //         {
 //            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
@@ -663,7 +664,7 @@ void GbTriFaceMesh3D::addSurfaceTriangleSet(vector<UbTupleFloat3> &pts, vector<U
 //            this->kdTree = new Kd::Tree<double>( *this, Kd::SpatialMedianSplit<double>() );
 //         }
 //         else throw UbException(UB_EXARGS, "unknown kdtree split option)" );
-//         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.stop()<<"seconds");
+//         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in "<<timer.getCurrentRuntimeInSeconds()<<"seconds");
 //      }
 //
 //      //eigentlicher PIO-Test
@@ -738,7 +739,7 @@ bool GbTriFaceMesh3D::isPointInGbObject3D(const double &x1, const double &x2, co
         // Baum erstellen, wen noch keiner vorhanden
         if (!kdTree) {
             UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
-            UbTimer timer;
+            vf::basics::Timer timer;
             timer.start();
             if (kdtreeSplitAlg == KDTREE_SAHPLIT) {
                 UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
@@ -748,7 +749,7 @@ bool GbTriFaceMesh3D::isPointInGbObject3D(const double &x1, const double &x2, co
                 this->kdTree = new Kd::Tree<double>(*this, Kd::SpatialMedianSplit<double>());
             } else
                 throw UbException(UB_EXARGS, "unknown kdtree split option)");
-            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.stop() << "seconds");
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.getCurrentRuntimeInSeconds() << "seconds");
         }
 
         // eigentlicher PIO-Test
@@ -820,7 +821,7 @@ bool GbTriFaceMesh3D::isPointInGbObject3D(const double &x1, const double &x2, co
         // Baum erstellen, wen noch keiner vorhanden
         if (!kdTree) {
             UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
-            UbTimer timer;
+            vf::basics::Timer timer;
             timer.start();
             if (kdtreeSplitAlg == KDTREE_SAHPLIT) {
                 UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
@@ -831,7 +832,7 @@ bool GbTriFaceMesh3D::isPointInGbObject3D(const double &x1, const double &x2, co
                 this->kdTree = new Kd::Tree<double>(*this, Kd::SpatialMedianSplit<double>());
             } else
                 throw UbException(UB_EXARGS, "unknown kdtree split option)");
-            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.stop() << "seconds");
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.getCurrentRuntimeInSeconds() << "seconds");
             //cout << "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.stop() << "seconds" << std::endl;
         }
 
@@ -905,7 +906,7 @@ bool GbTriFaceMesh3D::isPointInGbObject3D(const double &x1, const double &x2, co
         // Baum erstellen, wen noch keiner vorhanden
         if (!kdTree) {
             UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
-            UbTimer timer;
+            vf::basics::Timer timer;
             timer.start();
             if (kdtreeSplitAlg == KDTREE_SAHPLIT) {
                 UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
@@ -915,7 +916,7 @@ bool GbTriFaceMesh3D::isPointInGbObject3D(const double &x1, const double &x2, co
                 this->kdTree = new Kd::Tree<double>(*this, Kd::SpatialMedianSplit<double>());
             } else
                 throw UbException(UB_EXARGS, "unknown kdtree split option)");
-            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.stop() << "seconds");
+            UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.getCurrentRuntimeInSeconds() << "seconds");
         }
 
         // eigentlicher PIO-Test
@@ -951,7 +952,7 @@ bool GbTriFaceMesh3D::intersectLine(const double &p1_x1, const double &p1_x2, co
     // Baum erstellen, wen noch keiner vorhanden
     if (!kdTree) {
         UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree start");
-        UbTimer timer;
+        vf::basics::Timer timer;
         timer.start();
         if (kdtreeSplitAlg == KDTREE_SAHPLIT) {
             UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - build KdTree with SAHSplit");
@@ -961,7 +962,7 @@ bool GbTriFaceMesh3D::intersectLine(const double &p1_x1, const double &p1_x2, co
             this->kdTree = new Kd::Tree<double>(*this, Kd::SpatialMedianSplit<double>());
         } else
             throw UbException(UB_EXARGS, "unknown kdtree split option)");
-        UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.stop() << "seconds");
+        UBLOG(logDEBUG3, "GbTriFaceMesh3D::calculateValues - built kdTree in " << timer.getCurrentRuntimeInSeconds() << "seconds");
     }
 
     int iSec = kdTree->intersectLine(UbTupleDouble3(p1_x1, p1_x2, p1_x3), UbTupleDouble3(p2_x1, p2_x2, p2_x3),
diff --git a/src/basics/utilities/UbNupsTimer.h b/src/basics/utilities/UbNupsTimer.h
deleted file mode 100644
index 1545b5b694a57d112b485cf766ce26e22f30d939..0000000000000000000000000000000000000000
--- a/src/basics/utilities/UbNupsTimer.h
+++ /dev/null
@@ -1,125 +0,0 @@
-//=======================================================================================
-// ____          ____    __    ______     __________   __      __       __        __
-// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
-//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
-//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
-//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
-//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
-//      \    \  |    |   ________________________________________________________________
-//       \    \ |    |  |  ______________________________________________________________|
-//        \    \|    |  |  |         __          __     __     __     ______      _______
-//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
-//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
-//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
-//
-//  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 UbNupsTimer.h
-//! \ingroup utilities
-//! \author Soeren Freudiger, Sebastian Geller
-//=======================================================================================
-#ifndef UBNUPSTIMER_H
-#define UBNUPSTIMER_H
-
-#include <basics/utilities/UbTiming.h>
-#include <sstream>
-#include <vector>
-
-/*=========================================================================*/
-/*  UbNupsTimer                                                             */
-/*                                                                         */
-/**
-This Class provides the base for ...
-<BR><BR>
-@author <A HREF="mailto:muffmolch@gmx.de">S. Freudiger</A>
-@version 1.0 - 01.11.04
-*/
-class UbNupsTimer : public UbTiming
-{
-public:
-    UbNupsTimer() : UbTiming()
-    {
-        mTempNodes = 0.0;
-        mNofNodes.resize(0);
-        mDurations.resize(0);
-    }
-    /*==========================================================*/
-    UbNupsTimer(std::string name) : UbTiming(name)
-    {
-        mNofNodes.resize(0);
-        mDurations.resize(0);
-        mTempNodes = 0.0;
-    }
-    /*==========================================================*/
-    void initTiming() override
-    {
-        UbTiming::initTiming();
-        mNofNodes.resize(0);
-        mDurations.resize(0);
-        mTempNodes = 0.0;
-    }
-    /*==========================================================*/
-    void startNUPSTiming(double nofNodes)
-    {
-        mTempNodes = nofNodes;
-        UbTiming::startTiming();
-    }
-    /*==========================================================*/
-    void endTiming() override
-    {
-        UbTiming::endTiming();
-        // save #node and time informations
-        mNofNodes.push_back(mTempNodes);
-        mDurations.push_back(UbTiming::getDuration());
-        // reset internal timecounter
-        UbTiming::initTiming();
-    }
-    /*==========================================================*/
-    double getAverageNups()
-    {
-        double averageNups = 0.0;
-        for (int i = 0; i < (int)mNofNodes.size(); i++)
-            averageNups += mNofNodes.at(i) / mDurations.at(i);
-
-        return averageNups / (double)mNofNodes.size();
-    }
-    /*==========================================================*/
-    double getSumOfDuration()
-    {
-        double duration = 0.0;
-        for (int i = 0; i < (int)mDurations.size(); i++)
-            duration += mDurations.at(i);
-        return duration;
-    }
-    /*==========================================================*/
-    std::string getNupsString()
-    {
-        std::stringstream ss;
-        ss << "saved nups informations" << std::endl;
-        for (int i = 0; i < (int)mNofNodes.size(); i++)
-            ss << mNofNodes.at(i) << "nodes/" << mDurations.at(i) << "sec=" << mNofNodes.at(i) / mDurations.at(i)
-               << "nups\n";
-        return ss.str();
-    }
-
-protected:
-private:
-    std::vector<double> mNofNodes;
-    std::vector<double> mDurations;
-
-    double mTempNodes;
-};
-
-#endif
diff --git a/src/basics/utilities/UbTiming.h b/src/basics/utilities/UbTiming.h
deleted file mode 100644
index 9ea6ed16fc3b547bb20e34cc0e5c1e080e09cc6f..0000000000000000000000000000000000000000
--- a/src/basics/utilities/UbTiming.h
+++ /dev/null
@@ -1,375 +0,0 @@
-//=======================================================================================
-// ____          ____    __    ______     __________   __      __       __        __
-// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
-//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
-//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
-//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
-//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
-//      \    \  |    |   ________________________________________________________________
-//       \    \ |    |  |  ______________________________________________________________|
-//        \    \|    |  |  |         __          __     __     __     ______      _______
-//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
-//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
-//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
-//
-//  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 UbTiming.h
-//! \ingroup utilities
-//! \author Soeren Freudiger, Sebastian Geller
-//=======================================================================================
-#ifndef UBTIMING_H
-#define UBTIMING_H
-
-#include <ctime>
-#include <iostream>
-#include <limits>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#if defined(VF_MPI)
-#include <parallel/Communicator.h>
-#endif
-
-class UbTiming
-{
-public:
-    UbTiming()
-    {
-        this->duration  = 0.0;
-        this->deltaT    = 0.0;
-        this->startTime = 0;
-        this->name      = "noname";
-    }
-    /*==========================================================*/
-    UbTiming(const std::string &name)
-    {
-        this->duration  = 0.0;
-        this->deltaT    = 0.0;
-        this->startTime = 0;
-        this->name      = name;
-    }
-    /*==========================================================*/
-    virtual ~UbTiming() = default;
-    /*==========================================================*/
-    virtual void initTiming() { this->duration = 0.0; }
-    /*==========================================================*/
-    virtual void startTiming()
-    {
-#if defined(VF_MPI)
-        this->startTime = vf::parallel::Communicator::getInstance()->Wtime();
-#else
-        this->startTime = (double)clock();
-#endif // VF_MPI
-    }
-    /*==========================================================*/
-    virtual void initAndStartTiming()
-    {
-        this->initTiming();
-        this->startTiming();
-    }
-    /*==========================================================*/
-    virtual void endTiming() { this->stopTiming(); }
-    /*==========================================================*/
-    virtual void stopTiming()
-    {
-#if defined(VF_MPI)
-        this->deltaT = vf::parallel::Communicator::getInstance()->Wtime() - this->startTime;
-#else
-        this->deltaT    = ((double)clock() - this->startTime) / (double)CLOCKS_PER_SEC;
-#endif // VF_MPI
-
-        this->duration += this->deltaT;
-    }
-    /*==========================================================*/
-    virtual double getDuration() const { return this->duration; }
-    /*==========================================================*/
-    virtual void setName(const std::string &name) { this->name = name; }
-    /*==========================================================*/
-    virtual std::string getName() const { return this->name; }
-    /*==========================================================*/
-    void start()
-    {
-        this->duration = 0.0;
-
-#if defined(VF_MPI)
-        this->startTime = vf::parallel::Communicator::getInstance()->Wtime();
-#else
-        this->startTime = (double)clock();
-#endif // VF_MPI
-    }
-    /*==========================================================*/
-    void pause()
-    {
-#if defined(VF_MPI)
-        this->duration += vf::parallel::Communicator::getInstance()->Wtime() - this->startTime;
-#else
-        this->duration += ((double)clock() - this->startTime) / (double)CLOCKS_PER_SEC;
-#endif // VF_MPI
-    }
-    /*==========================================================*/
-    void unpause()
-    {
-#if defined(VF_MPI)
-        this->startTime = vf::parallel::Communicator::getInstance()->Wtime();
-#else
-        this->startTime = (double)clock();
-#endif // VF_MPI
-    }
-    /*==========================================================*/
-    void stop()
-    {
-#if defined(VF_MPI)
-        this->duration += vf::parallel::Communicator::getInstance()->Wtime() - this->startTime;
-#else
-        this->duration += ((double)clock() - this->startTime) / (double)CLOCKS_PER_SEC;
-#endif // VF_MPI
-    }
-
-protected:
-    std::string name;
-
-    double startTime;
-    double duration;
-    double deltaT;
-};
-
-#include <basics/utilities/UbSystem.h> //for definitons of system/OS type
-
-#ifdef UBSYSTEM_APPLE // Apple hack
-#include <cstdio>
-#include <ctime>
-#include <mach/mach_time.h>
-inline void mach_absolute_difference(const uint64_t &end, const uint64_t &start, struct timespec *tp)
-{
-    uint64_t difference                   = end - start;
-    static mach_timebase_info_data_t info = { 0, 0 };
-
-    if (info.denom == 0)
-        mach_timebase_info(&info);
-
-    uint64_t elapsednano = difference * (info.numer / info.denom);
-
-    tp->tv_sec  = elapsednano * 1e-9;
-    tp->tv_nsec = elapsednano - (tp->tv_sec * 1e9);
-}
-#elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
-#include <ctime>
-#include <pthread.h>
-#include <unistd.h> // for sysconf
-#endif
-
-/*=========================================================================*/
-//! \brief Time Measuring
-//! \details
-//! example:
-//! \code
-//! t=0  start
-//! t=1
-//! t=2  stop  -> return 2; getLapTime=2; getTotalTime 2; getLapTimes:  2
-//! t=3
-//! t=4
-//! t=5  stop  -> return 3; getLapTime=3; getTotalTime 5; getLapTimes:  2,3
-//! t=6  stop  -> return 1; getLapTime=1; getTotalTime 6; getLapTimes:  2,3,1
-//! t=7
-//! t=8  start ->no consideration of time 7 and 8
-//! t=9
-//! t=10 stop  -> return 2; getLapTime=2; getTotalTime 8; getLapTimes:  2,3,1,2
-//! t=11 resetAndStart -> Timer is reset and restarted
-//! t=12
-//! t=13
-//! t=14 stop  -> return 3; getLapTime=3; getTotalTime 3; getLapTimes:  3
-//! \endcode
-
-class UbTimer
-{
-public:
-    UbTimer(const bool &storeLapTimes = false) : name("unamed"), storeLapTimes(storeLapTimes) {}
-    /*==========================================================*/
-    UbTimer(const std::string &name, const bool &storeLapTimes = false) : name(name), storeLapTimes(storeLapTimes) {}
-    /*==========================================================*/
-    virtual ~UbTimer() = default;
-    /*==========================================================*/
-    double getLapTime() const { return this->lapTime; }
-    std::vector<double> getLapTimes() const { return this->lapTimes; }
-    void setName(const std::string &name) { this->name = name; }
-    std::string getName() const { return this->name; }
-    bool isRunning() const { return isMeasuring; }
-    bool isStoringLapTimes() const { return storeLapTimes; }
-    /*==========================================================*/
-    void setStoreLapTimes(const bool &storeLapTimes) { this->storeLapTimes = storeLapTimes; }
-    /*==========================================================*/
-    void start()
-    {
-        this->isMeasuring = true;
-
-#if defined(VF_MPI)
-        this->startTime = vf::parallel::Communicator::getInstance()->Wtime();
-#elif defined(UBSYSTEM_APPLE)
-        this->startTime = mach_absolute_time();
-#elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
-        timespec tp;
-        clock_gettime(CLOCK_REALTIME, &tp);
-        this->startTime = (double)(tp.tv_sec) * 1.0e9 + (double)(tp.tv_nsec);
-#else
-        this->startTime = (double)clock();
-#endif // VF_MPI
-    }
-    /*==========================================================*/
-    void resetAndStart()
-    {
-        this->reset();
-        this->start();
-    }
-    /*==========================================================*/
-    // stop: - stops the calculation and returns the time elapsed since last start/stop
-    //      - timing continues
-    double stop()
-    {
-        // if start() was never activated before:
-        if (!isMeasuring)
-            return 0.0;
-
-#if defined(VF_MPI)
-        double actTime = vf::parallel::Communicator::getInstance()->Wtime();
-        this->lapTime  = actTime - this->startTime;
-#elif defined(UBSYSTEM_APPLE)
-        double actTime  = mach_absolute_time();
-        timespec tp;
-        mach_absolute_difference(actTime, this->startTime, &tp);
-        this->lapTime = tp.tv_sec + tp.tv_nsec * 1e-9;
-#elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
-        timespec tp;
-        clock_gettime(CLOCK_REALTIME, &tp);
-        double actTime = (double)(tp.tv_sec) * 1.0e9 + (double)(tp.tv_nsec);
-        this->lapTime  = (actTime - this->startTime) * 1.0e-9;
-#else
-        double actTime  = (double)clock();
-        this->lapTime   = (actTime - this->startTime) / (double)CLOCKS_PER_SEC;
-#endif // VF_MPI
-
-        this->startTime = actTime;
-        this->totalTime += this->lapTime;
-        if (storeLapTimes)
-            lapTimes.push_back(this->lapTime);
-
-        return lapTime;
-    }
-    /*==========================================================*/
-    void reset()
-    {
-        this->isMeasuring = false;
-
-        this->startTime = 0.0;
-        this->totalTime = 0.0;
-        this->lapTime   = 0.0;
-
-        lapTimes.resize(0);
-    }
-    /*==========================================================*/
-    double getCurrentLapTime() const
-    {
-        // if start() was never activated before:
-        if (!isMeasuring)
-            return 0.0;
-
-#if defined(VF_MPI)
-        return vf::parallel::Communicator::getInstance()->Wtime() - this->startTime;
-#elif defined(UBSYSTEM_APPLE)
-        timespec tp;
-        mach_absolute_difference(mach_absolute_time(), this->startTime, &tp);
-        return tp.tv_sec + tp.tv_nsec * 1e-9;
-#elif defined(UBSYSTEM_LINUX) || defined(UBSYSTEM_AIX)
-        timespec tp;
-        clock_gettime(CLOCK_REALTIME, &tp);
-        return ((double)(tp.tv_sec) * 1.0e9 + (double)(tp.tv_nsec) - this->startTime) * 1.0e-9;
-#else
-        return ((double)clock() - this->startTime) / (double)CLOCKS_PER_SEC;
-#endif // VF_MPI
-    }
-    /*==========================================================*/
-    double getTotalTime() const { return this->totalTime; }
-    /*==========================================================*/
-    std::string toString()
-    {
-        std::stringstream text;
-        text << *this;
-        return text.str();
-    }
-
-    // ueberladene Operatoren
-    /*==========================================================*/
-    friend inline std::ostream &operator<<(std::ostream &os, const UbTimer &timer)
-    {
-        os << "UbTimer[totalTime=" << timer.totalTime << "sec, lapTimes(";
-        for (std::size_t i = 0; i < timer.lapTimes.size(); i++)
-            os << timer.lapTimes[i] << ",";
-        os << ")]";
-        return os;
-    }
-
-protected:
-    std::string name;
-    bool isMeasuring{ false };
-    bool storeLapTimes;
-
-    double startTime{ 0.0 };
-    double totalTime{ 0.0 };
-    double lapTime{ 0.0 };
-
-    std::vector<double> lapTimes;
-};
-
-/*=========================================================================*/
-//! \brief Time Measuring
-//!
-//! \details UbProressTimer measures the time from its instantiation to destruction and spend the elapsed time on "os"
-//! in [s] example: \code
-//!  {
-//!     UbProgressTimer timer;
-//!     UbSystem::sleepS(10);
-//!  } //--> 10s
-//! \endcode
-
-class UbProgressTimer : public UbTimer
-{
-public:
-    UbProgressTimer(const UbProgressTimer &rhs) = delete;
-
-    explicit UbProgressTimer(std::ostream &os = std::cout) : UbTimer(), os(os) { this->start(); }
-    /*==========================================================*/
-    ~UbProgressTimer() override
-    {
-        //  A) Throwing an exception from a destructor is a Bad Thing.
-        //  B) The progress_timer destructor does output which may throw.
-        //  C) A progress_timer is usually not critical to the application.
-        //  Therefore, wrap the I/O in a try block, catch and ignore all exceptions.
-        try {
-            // use istream instead of ios_base to workaround GNU problem (Greg Chicares)
-            std::istream::fmtflags old_flags = os.setf(std::istream::fixed, std::istream::floatfield);
-            std::streamsize old_prec         = os.precision(2);
-            os << stop() << " s" << std::endl;
-            os.flags(old_flags);
-            os.precision(old_prec);
-        } catch (...) {
-        } // eat any exceptions
-    }
-
-private:
-    std::ostream &os;
-};
-
-#endif // UBTIMING_H
diff --git a/src/cpu/VirtualFluids.h b/src/cpu/VirtualFluids.h
index 9a460f34b064bf7eac75fc9292104e352342253e..0eb71d5ef218246795003c717e1b53be5c3248be 100644
--- a/src/cpu/VirtualFluids.h
+++ b/src/cpu/VirtualFluids.h
@@ -74,14 +74,12 @@
 #include <basics/utilities/UbLimits.h>
 #include <basics/utilities/UbLogger.h>
 #include <basics/utilities/UbMath.h>
-#include <basics/utilities/UbNupsTimer.h>
 #include <basics/utilities/UbObservable.h>
 #include <basics/utilities/UbObserver.h>
 #include <basics/utilities/UbRandom.h>
 #include <basics/utilities/UbScheduler.h>
 #include <basics/utilities/UbStringInputASCII.h>
 #include <basics/utilities/UbSystem.h>
-#include <basics/utilities/UbTiming.h>
 #include <basics/utilities/UbTuple.h>
 #include <basics/writer/WbWriter.h>
 #include <basics/writer/WbWriterAvsASCII.h>
diff --git a/src/cpu/core/Interactors/D3Q27TriFaceMeshInteractor.cpp b/src/cpu/core/Interactors/D3Q27TriFaceMeshInteractor.cpp
index d4dc0b3499f5dd936ead549c463e980cab88f4cc..a503b573cc55480c1d67597692bc2e8e78c0b989 100644
--- a/src/cpu/core/Interactors/D3Q27TriFaceMeshInteractor.cpp
+++ b/src/cpu/core/Interactors/D3Q27TriFaceMeshInteractor.cpp
@@ -2,11 +2,13 @@
 #include <basics/utilities/UbLogger.h>
 #include <basics/utilities/UbMath.h>
 
-#include "basics/writer/WbWriterVtkXmlASCII.h"
+#include <basics/writer/WbWriterVtkXmlASCII.h>
 #include <basics/writer/WbWriterVtkASCII.h>
 #include <basics/writer/WbWriterVtkBinary.h>
 #include <basics/writer/WbWriterVtkXmlBinary.h>
 
+#include <basics/Timer/Timer.h>
+
 #include "BCArray3D.h"
 #include "BCSet.h"
 #include "Block3D.h"
@@ -14,7 +16,6 @@
 #include "Grid3D.h"
 #include "LBMKernel.h"
 #include "VelocityBC.h"
-#include "basics/utilities/UbTiming.h"
 #include <geometry3d/GbCuboid3D.h>
 #include <geometry3d/GbHalfSpace3D.h>
 #include <geometry3d/GbMeshTools3D.h>
@@ -241,7 +242,7 @@ void D3Q27TriFaceMeshInteractor::setQs(const real &timeStep)
     int onePercent = UbMath::integerRounding(triangles.size() * c1o100);
     if (onePercent == 0)
         onePercent = 1;
-    UbTimer setQTimer;
+    vf::basics::Timer setQTimer;
     setQTimer.start();
     UBLOG(logDEBUG3, " - setQs for " << (int)triangles.size() << " triangles");
 
@@ -746,7 +747,7 @@ void D3Q27TriFaceMeshInteractor::initInteractor2(const real &timeStep)
     int onePercent = UbMath::integerRounding(triangles.size() * c1o100);
     if (onePercent == 0)
         onePercent = 1;
-    UbTimer setQTimer;
+    vf::basics::Timer setQTimer;
     setQTimer.start();
     UBLOG(logDEBUG3, " - setQs for " << (int)triangles.size() << " triangles");
 
@@ -1106,10 +1107,10 @@ void D3Q27TriFaceMeshInteractor::initInteractor2(const real &timeStep)
             boundingCubeTriangle.finalize();
         }
     }
-    setQTimer.stop();
+    setQTimer.end();
 
     UBLOG(logDEBUG1, " - setQs for " /*<< this->getName()*/ << " - " << (int)triangles.size()
-                                                            << " triangles: 100% done in " << setQTimer.getTotalTime()
+                                                            << " triangles: 100% done in " << setQTimer.getTimeInSeconds()
                                                             << "sec");
     UBLOG(logDEBUG1, "       * rejected blocks with tribox overlap test : " << counterTriBoxOverlap);
     UBLOG(logDEBUG1, "       * rejected nodes  with AABB           test : " << counterAABBTriFace);
@@ -1135,8 +1136,8 @@ void D3Q27TriFaceMeshInteractor::initInteractor2(const real &timeStep)
 
         UBLOG(logDEBUG1, " - setSolids for " << blocksForSolidCheck.size() << " blocks");
 
-        UbTimer scanLineTimer;
-        UbTimer solidTimer;
+        vf::basics::Timer scanLineTimer;
+        vf::basics::Timer solidTimer;
         solidTimer.start();
 
         for (BlockSolidCheckMethodIterator pos = blocksForSolidCheck.begin(); pos != blocksForSolidCheck.end(); ++pos) {
@@ -1244,24 +1245,24 @@ void D3Q27TriFaceMeshInteractor::initInteractor2(const real &timeStep)
 
                 // block hat  in initInteractor mind eine BC erhalten -> transBlock
                 this->bcBlocks.push_back(block);
-                scanLineTimer.stop();
+                scanLineTimer.end();
 
                 //            bvd->getTimer().stop();
             } else
                 throw UbException(UB_EXARGS, "unknown option for in object test");
         }
 
-        solidTimer.stop();
+        solidTimer.end();
 
         UBLOG(logDEBUG1, " - setSolids for " << blocksForSolidCheck.size() << " blocks: 100% done in "
-                                             << solidTimer.getTotalTime() << "s");
+                                             << solidTimer.getTimeInSeconds() << "s");
         UBLOG(logDEBUG1, "       * pointInObject for " << pointInObjectCounter << " blocks in "
-                                                       << solidTimer.getTotalTime() - scanLineTimer.getTotalTime()
+                                                       << solidTimer.getTimeInSeconds() - scanLineTimer.getTimeInSeconds()
                                                        << "s");
         UBLOG(logDEBUG1, "       * flood fill    for " << scanlineCounter << " blocks in "
-                                                       << scanLineTimer.getTotalTime() << " secs");
+                                                       << scanLineTimer.getTimeInSeconds() << " secs");
         UBLOG(logDEBUG1, "LBMTriFaceMeshInteractor::initInteractor for \""
-                             << mesh->getName() << "\" done in " << setQTimer.getTotalTime() + solidTimer.getTotalTime()
+                             << mesh->getName() << "\" done in " << setQTimer.getTimeInSeconds() + solidTimer.getTimeInSeconds()
                              << "s");
     }
 
diff --git a/src/cpu/core/LBM/K15CompressibleNavierStokes.cpp b/src/cpu/core/LBM/K15CompressibleNavierStokes.cpp
index 45d99c21d6f67a71e509d7808227ac0e8ffc56a0..3ddb0b2ce02fbd964bd72da28f6871f9fdd2ad3c 100644
--- a/src/cpu/core/LBM/K15CompressibleNavierStokes.cpp
+++ b/src/cpu/core/LBM/K15CompressibleNavierStokes.cpp
@@ -71,7 +71,7 @@ void K15CompressibleNavierStokes::calculate(int step)
    using namespace std;
    using namespace vf::lbm::dir;
 
-   //timer.resetAndStart();
+   //timer.start();
 
    //initializing of forcing stuff 
    if (withForcing)
@@ -909,13 +909,12 @@ void K15CompressibleNavierStokes::calculate(int step)
 
 
 
-   //timer.stop();
+   //timer.end();
 }
 //////////////////////////////////////////////////////////////////////////
 real K15CompressibleNavierStokes::getCalculationTime()
 {
-   //return timer.getDuration();
-   return timer.getTotalTime();
+   return timer.getTimeInSeconds();
 }
 //////////////////////////////////////////////////////////////////////////
 void K15CompressibleNavierStokes::setBulkOmegaToOmega(bool value)
diff --git a/src/cpu/core/LBM/K15CompressibleNavierStokes.h b/src/cpu/core/LBM/K15CompressibleNavierStokes.h
index 1135e5c324c8e6fc23e2d0101151ef33ce16b6e7..fd0b4e9e6005a844108778a7b9fdfa7dd7dded28 100644
--- a/src/cpu/core/LBM/K15CompressibleNavierStokes.h
+++ b/src/cpu/core/LBM/K15CompressibleNavierStokes.h
@@ -1,10 +1,11 @@
 #ifndef K15CompressibleNavierStokes_h__
 #define K15CompressibleNavierStokes_h__
 
+#include <basics/Timer/Timer.h>
+
 #include "LBMKernel.h"
 #include "BCSet.h"
 #include "D3Q27System.h"
-#include "basics/utilities/UbTiming.h"
 #include "basics/container/CbArray4D.h"
 #include "basics/container/CbArray3D.h"
 
@@ -28,7 +29,7 @@ protected:
    virtual void initDataSet();
    real f[D3Q27System::ENDF+1];
 
-   UbTimer timer;
+   vf::basics::Timer timer;
 
    real OxyyMxzz;
    Parameter parameter;
diff --git a/src/cpu/core/LBM/K16IncompressibleNavierStokes.cpp b/src/cpu/core/LBM/K16IncompressibleNavierStokes.cpp
index f3e197ba37ac7be6c4273504ec89c5741f60a396..9c3c00dea19bc1b27f8415350f2339dc16ddfb5b 100644
--- a/src/cpu/core/LBM/K16IncompressibleNavierStokes.cpp
+++ b/src/cpu/core/LBM/K16IncompressibleNavierStokes.cpp
@@ -61,7 +61,7 @@ void K16IncompressibleNavierStokes::calculate(int step)
    using namespace std;
    using namespace vf::lbm::dir;
 
-   //timer.resetAndStart();
+   //timer.start();
 
    //initializing of forcing stuff 
    if (withForcing)
@@ -893,8 +893,7 @@ void K16IncompressibleNavierStokes::calculate(int step)
 //////////////////////////////////////////////////////////////////////////
 real K16IncompressibleNavierStokes::getCalculationTime()
 {
-   //return timer.getDuration();
-   return timer.getTotalTime();
+   return timer.getTimeInSeconds();
 }
 //////////////////////////////////////////////////////////////////////////
 void K16IncompressibleNavierStokes::setRelaxationParameter(Parameter p)
diff --git a/src/cpu/core/LBM/K16IncompressibleNavierStokes.h b/src/cpu/core/LBM/K16IncompressibleNavierStokes.h
index a67b0617801fb315b3fdcb58258099bf0839ba85..f7c8a1dc0329150f1847c12c2c2c52c636e46b21 100644
--- a/src/cpu/core/LBM/K16IncompressibleNavierStokes.h
+++ b/src/cpu/core/LBM/K16IncompressibleNavierStokes.h
@@ -3,17 +3,18 @@
 #ifndef K16IncompressibleNavierStokes_H
 #define K16IncompressibleNavierStokes_H
 
+#include <basics/Timer/Timer.h>
+
 #include "LBMKernel.h"
 #include "BCSet.h"
 #include "D3Q27System.h"
-#include "basics/utilities/UbTiming.h"
 #include "basics/container/CbArray4D.h"
 #include "basics/container/CbArray3D.h"
 
 //! \brief   Cascaded Cumulant LBM kernel. 
 //! \details CFD solver that use Cascaded Cumulant Lattice Boltzmann method for D3Q27 model
 //! \author  K. Kutscher, M. Geier
-class K16IncompressibleNavierStokes :  public LBMKernel
+class K16IncompressibleNavierStokes : public LBMKernel
 {
 public:
    //! This option set relaxation parameter: NORMAL  
@@ -29,7 +30,7 @@ protected:
    virtual void initDataSet();
    real f[D3Q27System::ENDF+1];
 
-   UbTimer timer;
+   vf::basics::Timer timer;
 
    real OxyyMxzz;
    Parameter parameter;
diff --git a/src/cpu/core/Simulation/Simulation.cpp b/src/cpu/core/Simulation/Simulation.cpp
index e3b0169847d43efd62bdf7dabf80fdc009027d46..c4766c8cfd0865880fa2df2a76e9a28036915dea 100644
--- a/src/cpu/core/Simulation/Simulation.cpp
+++ b/src/cpu/core/Simulation/Simulation.cpp
@@ -49,7 +49,10 @@
 #define OMP_SCHEDULE guided
 
 // #define TIMING
-// #include "UbTiming.h"
+#ifdef TIMING
+#include <basics/Timer/Timer.h>
+using namespace vf::basics;
+#endif
 
 #include <basics/utilities/UbException.h>
 
@@ -254,7 +257,7 @@ void Simulation::run()
         int threshold;
 
 #ifdef TIMING
-        UbTimer timer;
+        Timer timer;
         real time[6];
 #endif
 
@@ -272,8 +275,8 @@ void Simulation::run()
                     for (straightStartLevel = maxInitLevel, threshold = 1; (staggeredStep & threshold) != threshold; straightStartLevel--, threshold <<= 1)
                         ;
                 }
-#ifdef TIMING
-                timer.resetAndStart();
+#ifdef TIMING   
+                timer.start();
 #endif
                 //////////////////////////////////////////////////////////////////////////
                 applyPreCollisionBC(straightStartLevel, maxInitLevel);
@@ -282,8 +285,9 @@ void Simulation::run()
                 calculateBlocks(straightStartLevel, maxInitLevel, calcStep);
                 //////////////////////////////////////////////////////////////////////////
 #ifdef TIMING
-                time[0] = timer.stop();
+                time[0] = timer.getCurrentRuntimeInSeconds();
                 UBLOG(logINFO, "calculateBlocks time = " << time[0]);
+                timer.start();
 #endif
                 //////////////////////////////////////////////////////////////////////////
                 //////////////////////////////////////////////////////////////////////////
@@ -291,31 +295,35 @@ void Simulation::run()
                 exchangeBlockData(straightStartLevel, maxInitLevel);
                 //////////////////////////////////////////////////////////////////////////
 #ifdef TIMING
-                time[1] = timer.stop();
+                time[1] = timer.getCurrentRuntimeInSeconds();
                 UBLOG(logINFO, "exchangeBlockData time = " << time[1]);
+                timer.start();
 #endif
                 //////////////////////////////////////////////////////////////////////////
                 applyPostCollisionBC(straightStartLevel, maxInitLevel);
                 //////////////////////////////////////////////////////////////////////////
 #ifdef TIMING
-                time[2] = timer.stop();
+                time[2] = timer.getCurrentRuntimeInSeconds();
                 UBLOG(logINFO, "applyBCs time = " << time[2]);
+                timer.start();
 #endif
                 //////////////////////////////////////////////////////////////////////////
                 // swap distributions in kernel
                 swapDistributions(straightStartLevel, maxInitLevel);
                 //////////////////////////////////////////////////////////////////////////
 #ifdef TIMING
-                time[3] = timer.stop();
+                time[3] = timer.getCurrentRuntimeInSeconds();
                 UBLOG(logINFO, "swapDistributions time = " << time[3]);
+                timer.start();
 #endif
                 //////////////////////////////////////////////////////////////////////////
                 if (refinement) {
                     if (straightStartLevel < maxInitLevel) exchangeBlockData(straightStartLevel, maxInitLevel);
                         //////////////////////////////////////////////////////////////////////////
 #ifdef TIMING
-                    time[4] = timer.stop();
+                    time[4] = timer.getCurrentRuntimeInSeconds();
                     UBLOG(logINFO, "refinement exchangeBlockData time = " << time[4]);
+                    timer.start();
 #endif
                     //////////////////////////////////////////////////////////////////////////
                     // now ghost nodes have actual values
@@ -323,8 +331,9 @@ void Simulation::run()
                     interpolation(straightStartLevel, maxInitLevel);
                     //////////////////////////////////////////////////////////////////////////
 #ifdef TIMING
-                    time[5] = timer.stop();
+                    time[5] = timer.getCurrentRuntimeInSeconds();
                     UBLOG(logINFO, "refinement interpolation time = " << time[5]);
+                    timer.start();
 #endif
                     //////////////////////////////////////////////////////////////////////////
                 }
@@ -362,7 +371,10 @@ void Simulation::calculateBlocks(int startLevel, int maxInitLevel, int calcStep)
         SPtr<Block3D> blockTemp;
         // startLevel bis maxInitLevel
         for (int level = startLevel; level <= maxInitLevel; level++) {
-            // timer.resetAndStart();
+#ifdef TIMING
+            Timer timer;
+            timer.start();
+#endif
             // call LBM kernel
             int size = (int)blocks[level].size();
 #ifdef _OPENMP
@@ -378,9 +390,11 @@ void Simulation::calculateBlocks(int startLevel, int maxInitLevel, int calcStep)
                     std::exit(EXIT_FAILURE);
                 }
             }
-            // timer.stop();
-            // UBLOG(logINFO, "level = " << level << " blocks = " << blocks[level].size() << " collision time = " <<
-            // timer.getTotalTime());
+#ifdef TIMING
+            timer.end();
+            UBLOG(logINFO, "level = " << level << " blocks = " << blocks[level].size()
+                                      << " collision time = " << timer.getTimeInSeconds());
+#endif
         }
     }
 }
diff --git a/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.cpp b/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.cpp
index 81d7217c4b848ae3a6510fc1920c7621ee71c0aa..9fd7a3bef5375969d7f79da0b5d8478d369eb241 100644
--- a/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.cpp
+++ b/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.cpp
@@ -42,7 +42,7 @@ NUPSCounterSimulationObserver::NUPSCounterSimulationObserver(SPtr<Grid3D> grid,
     : SimulationObserver(grid, s), numOfThreads(numOfThreads), nup(0), nup_t(0), nupsStep(0.0), comm(comm)
 {
     if (comm->getProcessID() == comm->getRoot()) {
-        timer.resetAndStart();
+        timer.start();
 
         real nop          = comm->getNumberOfProcesses();
         int minInitLevel    = grid->getCoarsestInitializedLevel();
@@ -70,16 +70,17 @@ void NUPSCounterSimulationObserver::update(real step)
 void NUPSCounterSimulationObserver::collectData(real step)
 {
     if (comm->getProcessID() == comm->getRoot()) {
-        real time   = timer.stop();
-        real nups_t = nup_t * (step - nupsStep) / time;
-        real nups   = nup * (step - nupsStep) / time;
-        real tnups  = nups / (real)numOfThreads;
+        timer.end();
+        double time = timer.getCurrentRuntimeInSeconds();
+        double nups_t = nup_t * (step - nupsStep) / time;
+        double nups = nup * (step - nupsStep) / time;
+        double tnups = nups / (double)numOfThreads;
         UBLOG(logINFO, "Calculation step = " << step);
         UBLOG(logINFO, "Total performance = " << nups_t << " NUPS");
         UBLOG(logINFO, "Performance per update = " << nups << " NUPS");
         UBLOG(logINFO, "Performance per thread = " << tnups << " NUPS");
         UBLOG(logINFO, "Time for " << step - nupsStep << " steps = " << time << " s");
         nupsStep = step;
-        timer.resetAndStart();
+        timer.start();
     }
 }
diff --git a/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.h b/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.h
index f0585bbdb911e3dd33262d1a790a10b97da789de..29be2c4c40eeb363ca5eabeadb17b79fb556345d 100644
--- a/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.h
+++ b/src/cpu/core/SimulationObservers/NUPSCounterSimulationObserver.h
@@ -37,7 +37,8 @@
 #include <PointerDefinitions.h>
 
 #include "SimulationObserver.h"
-#include "basics/utilities/UbTiming.h"
+
+#include <basics/Timer/Timer.h>
 
 namespace vf::parallel {class Communicator;}
 class Grid3D;
@@ -63,7 +64,7 @@ protected:
     //! Collect data for calculation of NUPS
     //! \param step is a time step
     void collectData(real step);
-    UbTimer timer;
+    vf::basics::Timer timer;
     int numOfThreads;
     real numberOfNodes;
     real numberOfBlocks;
diff --git a/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.cpp b/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.cpp
index 14b35e69b7fb6e2f76f93909e1ebe81af320bc74..949220d07df0ea14c098db03509b629393a59e1c 100644
--- a/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.cpp
+++ b/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.cpp
@@ -72,12 +72,12 @@ SPtr<Object> Conglomerate::clone() const
     return conglomerate;
 }
 
-double Conglomerate::getX1Centroid()
+double Conglomerate::getX1Centroid() const
 {
     return (getX1Minimum() + getX1Maximum()) * 0.5;
 }
 
-double Conglomerate::getX1Minimum()
+double Conglomerate::getX1Minimum() const
 {
     double minimum = addObjects[0]->getX1Minimum();
     for(uint i = 1; i < numberOfAddObjects; i++)
@@ -85,7 +85,7 @@ double Conglomerate::getX1Minimum()
     return minimum;
 }
 
-double Conglomerate::getX1Maximum()
+double Conglomerate::getX1Maximum() const
 {
     double maximum = addObjects[0]->getX1Maximum();
     for (uint i = 1; i < numberOfAddObjects; i++)
@@ -93,12 +93,12 @@ double Conglomerate::getX1Maximum()
     return maximum;
 }
 
-double Conglomerate::getX2Centroid()
+double Conglomerate::getX2Centroid() const
 {
     return (getX2Minimum() + getX2Maximum()) * 0.5;
 }
 
-double Conglomerate::getX2Minimum()
+double Conglomerate::getX2Minimum() const
 {
     double minimum = addObjects[0]->getX2Minimum();
     for (uint i = 1; i < numberOfAddObjects; i++)
@@ -106,7 +106,7 @@ double Conglomerate::getX2Minimum()
     return minimum;
 }    
 
-double Conglomerate::getX2Maximum()
+double Conglomerate::getX2Maximum() const
 {
     double maximum = addObjects[0]->getX2Maximum();
     for (uint i = 1; i < numberOfAddObjects; i++)
@@ -114,12 +114,12 @@ double Conglomerate::getX2Maximum()
     return maximum;
 }
 
-double Conglomerate::getX3Centroid()
+double Conglomerate::getX3Centroid() const
 {
     return (getX3Minimum() + getX3Maximum()) * 0.5;
 }
 
-double Conglomerate::getX3Minimum()
+double Conglomerate::getX3Minimum() const
 {
     double minimum = addObjects[0]->getX3Minimum();
     for (uint i = 1; i < numberOfAddObjects; i++)
@@ -127,7 +127,7 @@ double Conglomerate::getX3Minimum()
     return minimum;
 }    
 
-double Conglomerate::getX3Maximum()
+double Conglomerate::getX3Maximum() const
 {
     double maximum = addObjects[0]->getX3Maximum();
     for (uint i = 1; i < numberOfAddObjects; i++)
@@ -162,13 +162,13 @@ bool Conglomerate::isPointInObject(const double& x1, const double& x2, const dou
     return false;
 }
 
-void Conglomerate::scale(double delta)
+void Conglomerate::changeSizeByDelta(double delta)
 {
     for (uint i = 0; i < numberOfAddObjects; i++)
-        addObjects[i]->scale(delta);
+        addObjects[i]->changeSizeByDelta(delta);
 
     for (uint i = 0; i < numberOfSubtractObjects; i++)
-        subtractObjects[i]->scale(delta);
+        subtractObjects[i]->changeSizeByDelta(delta);
 }
 
 void Conglomerate::findInnerNodes(SPtr<GridImp> grid)
diff --git a/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.h b/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.h
index 0b3f7ad7b67554b72ad78188d68d9570bf21e090..a8eb1a7ca1ea97cf0e0b7ad41201ac60ef6f35d1 100644
--- a/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.h
+++ b/src/gpu/GridGenerator/geometries/Conglomerate/Conglomerate.h
@@ -53,17 +53,17 @@ public:
 
     SPtr<Object> clone() const override;
 
-    double getX1Centroid() override;
-    double getX1Minimum() override;
-    double getX1Maximum() override;
-    double getX2Centroid() override;
-    double getX2Minimum() override;
-    double getX2Maximum() override;
-    double getX3Centroid() override;
-    double getX3Minimum() override;
-    double getX3Maximum() override;
-
-    void scale(double delta) override;
+    double getX1Centroid() const override;
+    double getX1Minimum() const override;
+    double getX1Maximum() const override;
+    double getX2Centroid() const override;
+    double getX2Minimum() const override;
+    double getX2Maximum() const override;
+    double getX3Centroid() const override;
+    double getX3Minimum() const override;
+    double getX3Maximum() const override;
+
+    void changeSizeByDelta(double delta) override;
 
     bool isPointInObject(const double& x1, const double& x2, const double& x3, const double& minOffset, const double& maxOffset) override;
 
diff --git a/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.cpp b/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.cpp
index fde944bc8a035caf0bbf19de01ec8d9f9005031d..de8afcd87802cc18f9e76ceb3d514997519dc404 100644
--- a/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.cpp
+++ b/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.cpp
@@ -46,47 +46,47 @@ SPtr<Object> Cuboid::clone() const
     return std::make_shared<Cuboid>(minX1, minX2, minX3, maxX1, maxX2, maxX3);
 }
 
-double Cuboid::getX1Centroid()
+double Cuboid::getX1Centroid() const
 {
    return getCenter(minX1, maxX1);
 }
 
-double Cuboid::getX1Minimum()
+double Cuboid::getX1Minimum() const
 {
     return getMinimum(minX1, maxX1);
 }
 
-double Cuboid::getX1Maximum()
+double Cuboid::getX1Maximum() const
 {
     return getMaximum(minX1, maxX1);
 }
 
-double Cuboid::getX2Centroid()
+double Cuboid::getX2Centroid() const
 {
     return getCenter(minX2, maxX2);
 }
 
-double Cuboid::getX2Minimum()
+double Cuboid::getX2Minimum() const
 {
     return getMinimum(minX2, maxX2);
 }    
 
-double Cuboid::getX2Maximum()
+double Cuboid::getX2Maximum() const
 {
     return getMaximum(minX2, maxX2);
 }
 
-double Cuboid::getX3Centroid()
+double Cuboid::getX3Centroid() const
 {
     return getCenter(minX3, maxX3);
 }
 
-double Cuboid::getX3Minimum()
-{    
+double Cuboid::getX3Minimum() const
+{
     return getMinimum(minX3, maxX3);
 }    
 
-double Cuboid::getX3Maximum()
+double Cuboid::getX3Maximum() const
 {
     return getMaximum(minX3, maxX3);
 }
@@ -131,7 +131,7 @@ bool Cuboid::isBetween(const real& coord, const real& start, const real& end)
 }
 
 
-void Cuboid::scale(double delta)
+void Cuboid::changeSizeByDelta(double delta)
 {
     this->minX1 -= delta;
     this->minX2 -= delta;
diff --git a/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.h b/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.h
index 7ff5c14c2f17b4ed80f4f1e0c03d26ea1a2eb196..35d5d04c77f0b0928f214160910e69c6290172f0 100644
--- a/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.h
+++ b/src/gpu/GridGenerator/geometries/Cuboid/Cuboid.h
@@ -44,17 +44,17 @@ public:
 
     SPtr<Object> clone() const override;
 
-    double getX1Centroid() override;
-    double getX1Minimum() override;
-    double getX1Maximum() override;
-    double getX2Centroid() override;
-    double getX2Minimum() override;
-    double getX2Maximum() override;
-    double getX3Centroid() override;
-    double getX3Minimum() override;
-    double getX3Maximum() override;
+    double getX1Centroid() const override;
+    double getX1Minimum() const override;
+    double getX1Maximum() const override;
+    double getX2Centroid() const override;
+    double getX2Minimum() const override;
+    double getX2Maximum() const override;
+    double getX3Centroid() const override;
+    double getX3Minimum() const override;
+    double getX3Maximum() const override;
 
-    void scale(double delta) override;
+    void changeSizeByDelta(double delta) override;
 
     bool isPointInObject(const double& x1, const double& x2, const double& x3, const double& minOffset, const double& maxOffset) override;
 
diff --git a/src/gpu/GridGenerator/geometries/Cylinder/Cylinder.cpp b/src/gpu/GridGenerator/geometries/Cylinder/Cylinder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a82e8e01f71f315d9eba3d69f268bfe268ebce43
--- /dev/null
+++ b/src/gpu/GridGenerator/geometries/Cylinder/Cylinder.cpp
@@ -0,0 +1,133 @@
+#include "Cylinder.h"
+#include <numeric>
+
+Cylinder::Cylinder(double centerX, double centerY, double centerZ, double radius, double height, Axis rotationalAxis)
+    : center({ centerX, centerY, centerZ }), radius(radius), height(height), rotationalAxis(rotationalAxis)
+{
+}
+
+Cylinder::Cylinder(std::array<double, 3> center, double radius, double height, Axis axis)
+    : center(center), radius(radius), height(height), rotationalAxis(axis)
+{
+}
+
+SPtr<Object> Cylinder::clone() const
+{
+    return std::make_shared<Cylinder>(center, radius, height, rotationalAxis);
+}
+
+double Cylinder::getCentroidCoordinate(Axis coordinateDirection) const
+{
+    return center.at(coordinateDirection);
+}
+
+double Cylinder::getMinimunCoordinate(Axis coordinateDirection) const
+{
+    const auto unitVector = unitVectors.at(rotationalAxis);
+    return center.at(coordinateDirection) - 0.5 * height * unitVector.at(coordinateDirection) +
+           radius * (unitVector.at(coordinateDirection) - 1);
+}
+
+double Cylinder::getMaximumCoordinate(Axis coordinateDirection) const
+{
+    const auto unitVector = unitVectors.at(rotationalAxis);
+    return center.at(coordinateDirection) + 0.5 * height * unitVector.at(coordinateDirection) -
+           radius * (unitVector.at(coordinateDirection) - 1);
+}
+
+double Cylinder::getX1Centroid() const
+{
+    return getCentroidCoordinate(x);
+}
+
+double Cylinder::getX1Minimum() const
+{
+    return getMinimunCoordinate(x);
+}
+
+double Cylinder::getX1Maximum() const
+{
+    return getMaximumCoordinate(x);
+}
+
+double Cylinder::getX2Centroid() const
+{
+    return getCentroidCoordinate(y);
+}
+
+double Cylinder::getX2Minimum() const
+{
+    return getMinimunCoordinate(y);
+}
+
+double Cylinder::getX2Maximum() const
+{
+    return getMaximumCoordinate(y);
+}
+
+double Cylinder::getX3Centroid() const
+{
+    return getCentroidCoordinate(z);
+}
+
+double Cylinder::getX3Minimum() const
+{
+    return getMinimunCoordinate(z);
+}
+
+double Cylinder::getX3Maximum() const
+{
+    return getMaximumCoordinate(z);
+}
+
+double Cylinder::getRadius() const
+{
+    return radius;
+}
+
+double Cylinder::getHeight() const
+{
+    return height;
+}
+
+Axis Cylinder::getRotationalAxis() const
+{
+    return rotationalAxis;
+}
+
+bool Cylinder::isInCircle(double delta1, double delta2, double offset) const
+{
+    return (delta1 * delta1 + delta2 * delta2) < ((this->radius - offset) * (this->radius - offset));
+}
+
+bool Cylinder::isPointInObject(const double &x1, const double &x2, const double &x3, const double &minOffset,
+                               const double &maxOffset)
+{
+    double offset = maxOffset;
+    if (x1 < center.at(x) || x2 < center.at(y) || x3 < center.at(z)) offset = minOffset;
+
+    const double deltaX1 = x1 - center.at(x);
+    const double deltaX2 = x2 - center.at(y);
+    const double deltaX3 = x3 - center.at(z);
+
+    switch (rotationalAxis) {
+        case x:
+            if (deltaX1 > 0.5 * height || deltaX1 < -0.5 * height) return false;
+            return isInCircle(deltaX2, deltaX3, offset);
+        case y:
+            if (deltaX2 > 0.5 * height || deltaX2 < -0.5 * height) return false;
+            return isInCircle(deltaX1, deltaX3, offset);
+        case z:
+            if (deltaX3 > 0.5 * height || deltaX3 < -0.5 * height) return false;
+            return isInCircle(deltaX1, deltaX2, offset);
+    }
+
+    VF_LOG_CRITICAL("Unknown rotational axis in Cylinder.");
+    return false;
+}
+
+void Cylinder::changeSizeByDelta(double delta)
+{
+    this->radius += delta;
+    this->height += 2 * delta;
+}
\ No newline at end of file
diff --git a/src/basics/Timer/TimerImp.h b/src/gpu/GridGenerator/geometries/Cylinder/Cylinder.h
similarity index 56%
rename from src/basics/Timer/TimerImp.h
rename to src/gpu/GridGenerator/geometries/Cylinder/Cylinder.h
index e180ae084cb19b939f6e7a82cae7a0db3cc1ea15..7a42ec86f2aa185ae11c488a0d86f5952157f2c2 100644
--- a/src/basics/Timer/TimerImp.h
+++ b/src/gpu/GridGenerator/geometries/Cylinder/Cylinder.h
@@ -26,33 +26,61 @@
 //  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 TimerImp.h
-//! \ingroup Timer
-//! \author Stephan Lenz
+//! \file Cylinder.h
+//! \ingroup geometries
+//! \author Anna Wellmann
 //=======================================================================================
-#ifndef TIMER_IMP_H
-#define TIMER_IMP_H
 
-#include "Timer.h"
 
-#include <chrono>
+#ifndef CYLINDER_H
+#define CYLINDER_H
 
-#include "DataTypes.h"
+#include <map>
 
-class BASICS_EXPORT TimerImp : public Timer
+#include <basics/geometry3d/GbCylinder3D.h>
+#include <basics/geometry3d/Axis.h>
+
+#include "geometries/Object.h"
+
+class GRIDGENERATOR_EXPORT Cylinder : public Object
 {
 public:
-    using timePoint = std::chrono::high_resolution_clock::time_point;
 
-    void start() override;
-    void end() override;
+    Cylinder(double centerX, double centerY, double centerZ, double radius, double height, Axis rotationalAxis);
+    Cylinder(std::array<double, 3> center, double radius, double height, Axis axis);
+
+    SPtr<Object> clone() const override;
+
+    double getX1Centroid() const override;
+    double getX1Minimum() const override;
+    double getX1Maximum() const override;
+    double getX2Centroid() const override;
+    double getX2Minimum() const override;
+    double getX2Maximum() const override;
+    double getX3Centroid() const override;
+    double getX3Minimum() const override;
+    double getX3Maximum() const override;
 
-    real getTimeInSeconds() const override;
-    real getCurrentRuntimeInSeconds() const override;
+    double getRadius() const;
+    double getHeight() const;
+    Axis getRotationalAxis() const;
+
+    bool isPointInObject(const double &x1, const double &x2, const double &x3, const double &minOffset,
+                         const double &maxOffset) override;
+    void changeSizeByDelta(double delta) override;
 
 private:
-    timePoint startTime;
-    timePoint endTime;
+    double getCentroidCoordinate(Axis coordinateDirection) const;
+    double getMinimunCoordinate(Axis coordinateDirection) const;
+    double getMaximumCoordinate(Axis coordinateDirection) const;
+
+    bool isInCircle(double delta1, double delta2, double offset) const;
+
+    Axis rotationalAxis;
+    const std::array<double, 3> center;
+
+    double radius;
+    double height;
 };
 
-#endif
+#endif
\ No newline at end of file
diff --git a/src/gpu/GridGenerator/geometries/Cylinder/CylinderTest.cpp b/src/gpu/GridGenerator/geometries/Cylinder/CylinderTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1f23df544c7d92d614405b1681eb0997fc13bebd
--- /dev/null
+++ b/src/gpu/GridGenerator/geometries/Cylinder/CylinderTest.cpp
@@ -0,0 +1,212 @@
+#include <gmock/gmock.h>
+
+#include "Cylinder.h"
+
+
+void testChangeSizeByDelta(Cylinder &cylinder)
+{
+    const double delta = 0.2;
+    const double tolerance = 0.0000000001;
+    const double oldRadius = cylinder.getRadius();
+    const double oldHeight = cylinder.getHeight();
+    const double oldMinimumX1 = cylinder.getX1Minimum();
+    const double oldMinimumX2 = cylinder.getX2Minimum();
+    const double oldMinimumX3 = cylinder.getX3Minimum();
+    const double oldMaximumX1 = cylinder.getX1Maximum();
+    const double oldMaximumX2 = cylinder.getX2Maximum();
+    const double oldMaximumX3 = cylinder.getX3Maximum();
+
+    cylinder.changeSizeByDelta(delta);
+
+    EXPECT_THAT(cylinder.getRadius(), testing::Eq(oldRadius + delta));
+    EXPECT_THAT(cylinder.getHeight(), testing::Eq(oldHeight + 2 * delta));
+    EXPECT_THAT(cylinder.getX1Minimum(), testing::DoubleNear(oldMinimumX1 - delta, tolerance));
+    EXPECT_THAT(cylinder.getX2Minimum(), testing::DoubleNear(oldMinimumX2 - delta, tolerance));
+    EXPECT_THAT(cylinder.getX3Minimum(), testing::DoubleNear(oldMinimumX3 - delta, tolerance));
+    EXPECT_THAT(cylinder.getX1Maximum(), testing::DoubleNear(oldMaximumX1 + delta, tolerance));
+    EXPECT_THAT(cylinder.getX2Maximum(), testing::DoubleNear(oldMaximumX2 + delta, tolerance));
+    EXPECT_THAT(cylinder.getX3Maximum(), testing::DoubleNear(oldMaximumX3 + delta, tolerance));
+}
+
+// CylinderTestAxisNormalToX ////////////////////////////////////////////////
+
+class CylinderTestAxisNormalToX : public testing::Test
+{
+public:
+    std::array<double, 3> center = { 0.1, 0.2, 0.3 };
+    double radius = 2.0;
+    double height = 8.0;
+    Cylinder cylinder = Cylinder(center[0], center[1], center[2], radius, height, Axis::x);
+};
+
+TEST_F(CylinderTestAxisNormalToX, getCentroid)
+{
+    EXPECT_THAT(cylinder.getX1Centroid(), testing::Eq(center[0]));
+    EXPECT_THAT(cylinder.getX2Centroid(), testing::Eq(center[1]));
+    EXPECT_THAT(cylinder.getX3Centroid(), testing::Eq(center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToX, getMinimum)
+{
+    EXPECT_THAT(cylinder.getX1Minimum(), testing::Eq(-0.5 * height + center[0]));
+    EXPECT_THAT(cylinder.getX2Minimum(), testing::Eq(-radius + center[1]));
+    EXPECT_THAT(cylinder.getX3Minimum(), testing::Eq(-radius + center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToX, getMaximum)
+{
+    EXPECT_THAT(cylinder.getX1Maximum(), testing::Eq(0.5 * height + center[0]));
+    EXPECT_THAT(cylinder.getX2Maximum(), testing::Eq(radius + center[1]));
+    EXPECT_THAT(cylinder.getX3Maximum(), testing::Eq(radius + center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToX, isPointInObject)
+{
+    double epsilon = 0.0001;
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2], 0.0, 0.0));
+
+    // x
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] - 0.5 * height + epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] - 0.5 * height - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] + 0.5 * height - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] + 0.5 * height + epsilon, center[1], center[2], 0.0, 0.0));
+
+    // y
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] - radius + epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] - radius - epsilon, center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] + radius - epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] + radius + epsilon, center[2], 0.0, 0.0));
+
+    // z
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] - radius + epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] - radius - epsilon, 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] + radius - epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] + radius + epsilon, 0.0, 0.0));
+}
+
+TEST_F(CylinderTestAxisNormalToX, changeSizeByDelta)
+{
+    testChangeSizeByDelta(cylinder);
+}
+
+// CylinderTestAxisNormalToY ////////////////////////////////////////////////
+
+class CylinderTestAxisNormalToY : public testing::Test
+{
+protected:
+    std::array<double, 3> center = { 0.1, 0.2, 0.3 };
+    double radius = 2.0;
+    double height = 8.0;
+    Cylinder cylinder = Cylinder({ center[0], center[1], center[2] }, radius, height, Axis::y);
+};
+
+TEST_F(CylinderTestAxisNormalToY, getCentroid)
+{
+    EXPECT_THAT(cylinder.getX1Centroid(), testing::Eq(center[0]));
+    EXPECT_THAT(cylinder.getX2Centroid(), testing::Eq(center[1]));
+    EXPECT_THAT(cylinder.getX3Centroid(), testing::Eq(center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToY, getMinimum)
+{
+    EXPECT_THAT(cylinder.getX1Minimum(), testing::Eq(-radius + center[0]));
+    EXPECT_THAT(cylinder.getX2Minimum(), testing::Eq(-0.5 * height + center[1]));
+    EXPECT_THAT(cylinder.getX3Minimum(), testing::Eq(-radius + center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToY, getMaximum)
+{
+    EXPECT_THAT(cylinder.getX1Maximum(), testing::Eq(radius + center[0]));
+    EXPECT_THAT(cylinder.getX2Maximum(), testing::Eq(0.5 * height + center[1]));
+    EXPECT_THAT(cylinder.getX3Maximum(), testing::Eq(radius + center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToY, isPointInObject)
+{
+    double epsilon = 0.0001;
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2], 0.0, 0.0));
+
+    // x
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] - radius + epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] - radius - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] + radius - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] + radius + epsilon, center[1], center[2], 0.0, 0.0));
+
+    // y
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] - 0.5 * height + epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] - 0.5 * height - epsilon, center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] + 0.5 * height - epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] + 0.5 * height + epsilon, center[2], 0.0, 0.0));
+
+    // z
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] - radius + epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] - radius - epsilon, 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] + radius - epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] + radius + epsilon, 0.0, 0.0));
+}
+
+TEST_F(CylinderTestAxisNormalToY, changeSizeByDelta)
+{
+    testChangeSizeByDelta(cylinder);
+}
+
+// CylinderTestAxisNormalToZ ////////////////////////////////////////////////
+
+class CylinderTestAxisNormalToZ : public testing::Test
+{
+protected:
+    std::array<double, 3> center = { 0.1, 0.2, 0.3 };
+    double radius = 2.0;
+    double height = 8.0;
+    Cylinder cylinder = Cylinder({ center[0], center[1], center[2] }, radius, height, Axis::z);
+};
+
+TEST_F(CylinderTestAxisNormalToZ, getCentroid)
+{
+    EXPECT_THAT(cylinder.getX1Centroid(), testing::Eq(center[0]));
+    EXPECT_THAT(cylinder.getX2Centroid(), testing::Eq(center[1]));
+    EXPECT_THAT(cylinder.getX3Centroid(), testing::Eq(center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToZ, getMinimum)
+{
+    EXPECT_THAT(cylinder.getX1Minimum(), testing::Eq(-radius + center[0]));
+    EXPECT_THAT(cylinder.getX2Minimum(), testing::Eq(-radius + center[1]));
+    EXPECT_THAT(cylinder.getX3Minimum(), testing::Eq(-0.5 * height + center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToZ, getMaximum)
+{
+    EXPECT_THAT(cylinder.getX1Maximum(), testing::Eq(radius + center[0]));
+    EXPECT_THAT(cylinder.getX2Maximum(), testing::Eq(radius + center[1]));
+    EXPECT_THAT(cylinder.getX3Maximum(), testing::Eq(0.5 * height + center[2]));
+}
+
+TEST_F(CylinderTestAxisNormalToZ, isPointInObject)
+{
+    double epsilon = 0.0001;
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2], 0.0, 0.0));
+
+    // x
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] - radius + epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] - radius - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] + radius - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] + radius + epsilon, center[1], center[2], 0.0, 0.0));
+
+    // y
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] - radius + epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] - radius - epsilon, center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] + radius - epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] + radius + epsilon, center[2], 0.0, 0.0));
+
+    // z
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] - 0.5 * height + epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] - 0.5 * height - epsilon, 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] + 0.5 * height - epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] + 0.5 * height + epsilon, 0.0, 0.0));
+}
+
+TEST_F(CylinderTestAxisNormalToZ, changeSizeByDelta)
+{
+    testChangeSizeByDelta(cylinder);
+}
diff --git a/src/gpu/GridGenerator/geometries/Object.h b/src/gpu/GridGenerator/geometries/Object.h
index 8bb0a35d5e38df1f7db390fdf5ee750295788395..116bb8fc2f7b972b22f05352fe5128841752d187 100644
--- a/src/gpu/GridGenerator/geometries/Object.h
+++ b/src/gpu/GridGenerator/geometries/Object.h
@@ -46,20 +46,20 @@ public:
     virtual ~Object() = default;
     virtual SPtr<Object> clone() const = 0;
 
-    virtual double getX1Centroid() = 0;
-    virtual double getX1Minimum()  = 0;
-    virtual double getX1Maximum()  = 0;
+    virtual double getX1Centroid() const = 0;
+    virtual double getX1Minimum() const  = 0;
+    virtual double getX1Maximum() const  = 0;
 
-    virtual double getX2Centroid() = 0;
-    virtual double getX2Minimum()  = 0;
-    virtual double getX2Maximum()  = 0;
+    virtual double getX2Centroid() const = 0;
+    virtual double getX2Minimum() const  = 0;
+    virtual double getX2Maximum() const  = 0;
 
-    virtual double getX3Centroid() = 0;
-    virtual double getX3Minimum()  = 0;
-    virtual double getX3Maximum()  = 0;
+    virtual double getX3Centroid() const = 0;
+    virtual double getX3Minimum() const  = 0;
+    virtual double getX3Maximum() const  = 0;
 
 
-    virtual void scale(double delta) = 0;
+    virtual void changeSizeByDelta(double delta) = 0;
 
 
     virtual bool isPointInObject(const double& x1, const double& x2, const double& x3, const double& minOffset, const double& maxOffset) = 0;
diff --git a/src/gpu/GridGenerator/geometries/Sphere/Sphere.cpp b/src/gpu/GridGenerator/geometries/Sphere/Sphere.cpp
index 4669bbcfb9848a910bc86f9331a394daf6c55dd5..2a54c710c32e7d5ec36ce79357ddcb04da52658d 100644
--- a/src/gpu/GridGenerator/geometries/Sphere/Sphere.cpp
+++ b/src/gpu/GridGenerator/geometries/Sphere/Sphere.cpp
@@ -54,47 +54,47 @@ SPtr<Object> Sphere::clone() const
     return std::make_shared<Sphere>(centerX, centerY, centerZ, radius);
 }
 
-double Sphere::getX1Centroid()
+double Sphere::getX1Centroid() const
 {
     return centerX;
 }
 
-double Sphere::getX1Minimum()
+double Sphere::getX1Minimum() const
 {
     return centerX - radius;
 }
 
-double Sphere::getX1Maximum()
+double Sphere::getX1Maximum() const
 {
     return centerX + radius;
 }
 
-double Sphere::getX2Centroid()
+double Sphere::getX2Centroid() const
 {
     return centerY;
 }
 
-double Sphere::getX2Minimum()
+double Sphere::getX2Minimum() const
 {
     return centerY - radius;
 }
 
-double Sphere::getX2Maximum()
+double Sphere::getX2Maximum() const
 {
     return centerY + radius;
 }
 
-double Sphere::getX3Centroid()
+double Sphere::getX3Centroid() const
 {
     return centerZ;
 }
 
-double Sphere::getX3Minimum()
+double Sphere::getX3Minimum() const
 {
     return centerZ - radius;
 }
 
-double Sphere::getX3Maximum()
+double Sphere::getX3Maximum() const
 {
     return centerZ + radius;
 }
@@ -115,7 +115,7 @@ bool Sphere::isPointInObject(const double& x1, const double& x2, const double& x
 }
 
 
-void Sphere::scale(double delta)
+void Sphere::changeSizeByDelta(double delta)
 {
     this->radius += delta;
 }
diff --git a/src/gpu/GridGenerator/geometries/Sphere/Sphere.h b/src/gpu/GridGenerator/geometries/Sphere/Sphere.h
index 9ac8821a9c95fce8de16c22688ef3c585197804a..92f600d203a30ca504542161c6f6305d9d2e9ac0 100644
--- a/src/gpu/GridGenerator/geometries/Sphere/Sphere.h
+++ b/src/gpu/GridGenerator/geometries/Sphere/Sphere.h
@@ -46,20 +46,20 @@ public:
 
     SPtr<Object> clone() const override;
 
-    double getX1Centroid() override;
-    double getX1Minimum() override;
-    double getX1Maximum() override;
-    double getX2Centroid() override;
-    double getX2Minimum() override;
-    double getX2Maximum() override;
-    double getX3Centroid() override;
-    double getX3Minimum() override;
-    double getX3Maximum() override;
+    double getX1Centroid() const override;
+    double getX1Minimum() const override;
+    double getX1Maximum() const override;
+    double getX2Centroid() const override;
+    double getX2Minimum() const override;
+    double getX2Maximum() const override;
+    double getX3Centroid() const override;
+    double getX3Minimum() const override;
+    double getX3Maximum() const override;
 
     bool isPointInObject(const double& x1, const double& x2, const double& x3, const double& minOffset, const double& maxOffset) override;
 
 
-    void scale(double delta) override;
+    void changeSizeByDelta(double delta) override;
     
     int getIntersection(const Vertex &P, const Vertex &direction, Vertex &pointOnObject, real &qVal) override;
 
diff --git a/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.cpp b/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.cpp
index 91bb8f030e76fa6e083e7765feb18c7ccc517ee1..0caaff55becfe5d59d9abc70340f9b6c770f8f45 100644
--- a/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.cpp
+++ b/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.cpp
@@ -97,13 +97,14 @@ void TriangularMesh::findNeighbors()
 {
     VF_LOG_INFO("start finding neighbors ...");
 
-    auto t = Timer::makeStart();
+    vf::basics::Timer t;
+    t.start();
 
     TriangleNeighborFinder finder(triangles, size);
     finder.fillWithNeighborAngles(this);
 
-    t->end();
-    VF_LOG_INFO("time finding neighbors = {}", t->getTimeInSeconds());
+    t.end();
+    VF_LOG_INFO("time finding neighbors = {}", t.getTimeInSeconds());
 }
 
 void TriangularMesh::setTriangles(std::vector<Triangle> triangles)
@@ -185,7 +186,7 @@ bool intersectPlane(const Vertex &normal, const Vertex &pointOnPlane, const Vert
     return false;
 }
 
-void TriangularMesh::scale(double offset)
+void TriangularMesh::changeSizeByDelta(double offset)
 {
     std::vector<Triangle> triangles = this->triangleVec;
 
diff --git a/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.h b/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.h
index 7c050dd70b3908f3e4b021872887c74833594a26..14ff453951b4b74ca28378a7ad7cea31095a4c87 100644
--- a/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.h
+++ b/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMesh.h
@@ -88,16 +88,16 @@ private:
 
 public:
     SPtr<Object> clone() const override;
-    double getX1Centroid() override { throw "Not implemented in TriangularMesh"; }
-    double getX1Minimum() override { return minmax.minX; }
-    double getX1Maximum() override { return minmax.maxX; }
-    double getX2Centroid() override { throw "Not implemented in TriangularMesh"; }
-    double getX2Minimum() override { return minmax.minY; }
-    double getX2Maximum() override { return minmax.maxY; }
-    double getX3Centroid() override { throw "Not implemented in TriangularMesh"; }
-    double getX3Minimum() override { return minmax.minZ; }
-    double getX3Maximum() override { return minmax.maxZ; }
-    void scale(double delta) override;
+    double getX1Centroid() const override { throw "Not implemented in TriangularMesh"; }
+    double getX1Minimum() const override { return minmax.minX; }
+    double getX1Maximum() const override { return minmax.maxX; }
+    double getX2Centroid() const override { throw "Not implemented in TriangularMesh"; }
+    double getX2Minimum() const override { return minmax.minY; }
+    double getX2Maximum() const override { return minmax.maxY; }
+    double getX3Centroid() const override { throw "Not implemented in TriangularMesh"; }
+    double getX3Minimum() const override { return minmax.minZ; }
+    double getX3Maximum() const override { return minmax.maxZ; }
+    void changeSizeByDelta(double delta) override;
     bool isPointInObject(const double& x1, const double& x2, const double& x3, const double& minOffset,
         const double& maxOffset) override {
         return false;
diff --git a/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMeshStrategy.cpp b/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMeshStrategy.cpp
index 6d12a19cc097c0b8e98c59a938380be97dc0b15c..03a0ec30ab60075a08007de65a2e349b2b6d93e7 100644
--- a/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMeshStrategy.cpp
+++ b/src/gpu/GridGenerator/geometries/TriangularMesh/TriangularMeshStrategy.cpp
@@ -61,7 +61,8 @@ void PointInObjectDiscretizationStrategy::doDiscretize(TriangularMesh* triangula
     // trigger the GbTriFaceMesh3D to generate a kd-tree
     triangularMesh->getGbTriFaceMesh3D()->isPointInGbObject3D(0.0, 0.0, 0.0);
 
-    auto timer = Timer::makeStart();
+    vf::basics::Timer timer;
+    timer.start();
 
     real outputTime = 60.0;
     
@@ -78,9 +79,9 @@ void PointInObjectDiscretizationStrategy::doDiscretize(TriangularMesh* triangula
         //else
         //    grid->setNodeTo(i, OuterType);
 
-        if( timer->getCurrentRuntimeInSeconds() > outputTime ){
+        if( timer.getCurrentRuntimeInSeconds() > outputTime ){
             VF_LOG_INFO("    {} / {} nodes tested", index, grid->getSize());
-            timer->start();
+            timer.start();
         }
     }
     VF_LOG_INFO("Done Point-In-Object Test");
diff --git a/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.cpp b/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.cpp
index 5019f2a7547c509df6b7afd034cae179356c74ec..909651be66e1d10974822c62cc3ca158985f420b 100644
--- a/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.cpp
+++ b/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.cpp
@@ -48,47 +48,47 @@ SPtr<Object> VerticalCylinder::clone() const
     return std::make_shared<VerticalCylinder>(centerX, centerY, centerZ, radius, height);
 }
 
-double VerticalCylinder::getX1Centroid()
+double VerticalCylinder::getX1Centroid() const
 {
     return centerX;
 }
 
-double VerticalCylinder::getX1Minimum()
+double VerticalCylinder::getX1Minimum() const
 {
     return centerX - radius;
 }
 
-double VerticalCylinder::getX1Maximum()
+double VerticalCylinder::getX1Maximum() const
 {
     return centerX + radius;
 }
 
-double VerticalCylinder::getX2Centroid()
+double VerticalCylinder::getX2Centroid() const
 {
     return centerY;
 }
 
-double VerticalCylinder::getX2Minimum()
+double VerticalCylinder::getX2Minimum() const
 {
     return centerY - radius;
 }
 
-double VerticalCylinder::getX2Maximum()
+double VerticalCylinder::getX2Maximum() const
 {
     return centerY + radius;
 }
 
-double VerticalCylinder::getX3Centroid()
+double VerticalCylinder::getX3Centroid() const
 {
     return centerZ;
 }
 
-double VerticalCylinder::getX3Minimum()
+double VerticalCylinder::getX3Minimum() const
 {
     return centerZ - 0.5 * height;
 }
 
-double VerticalCylinder::getX3Maximum()
+double VerticalCylinder::getX3Maximum() const
 {
     return centerZ + 0.5 * height;
 }
@@ -111,8 +111,18 @@ bool VerticalCylinder::isPointInObject(const double& x1, const double& x2, const
 }
 
 
-void VerticalCylinder::scale(double delta)
+void VerticalCylinder::changeSizeByDelta(double delta)
 {
     this->radius += delta;
-    this->height += delta;
+    this->height += 2 * delta;
 }
+
+double VerticalCylinder::getRadius() const
+{
+    return radius;
+}
+
+double VerticalCylinder::getHeight() const
+{
+    return height;
+}
\ No newline at end of file
diff --git a/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.h b/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.h
index 64cdecef5824388a31a4f545c85b1194d3f4c77b..f312df8f6b6d666098a8729c6494f4701f40b63c 100644
--- a/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.h
+++ b/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinder.h
@@ -40,26 +40,30 @@ class GRIDGENERATOR_EXPORT VerticalCylinder : public Object
 {
 public:
     VerticalCylinder(const double& centerX, const double& centerY, const double& centerZ, const double& radius, const double& height);
+    // the axis is in the z-direction
 
     static SPtr<VerticalCylinder> makeShared(double centerX, double centerY, double centerZ, double radius, double height);
 
     SPtr<Object> clone() const override;
 
-    double getX1Centroid() override;
-    double getX1Minimum() override;
-    double getX1Maximum() override;
-    double getX2Centroid() override;
-    double getX2Minimum() override;
-    double getX2Maximum() override;
-    double getX3Centroid() override;
-    double getX3Minimum() override;
-    double getX3Maximum() override;
+    double getX1Centroid() const override;
+    double getX1Minimum() const override;
+    double getX1Maximum() const override;
+    double getX2Centroid() const override;
+    double getX2Minimum() const override;
+    double getX2Maximum() const override;
+    double getX3Centroid() const override;
+    double getX3Minimum() const override;
+    double getX3Maximum() const override;
+
+    double getRadius() const;
+    double getHeight() const;
 
     bool isPointInObject(const double& x1, const double& x2, const double& x3, const double& minOffset, const double& maxOffset) override;
 
 
-    void scale(double delta) override;
-   
+    void changeSizeByDelta(double delta) override;
+
 protected:
     double centerX;
     double centerY;
diff --git a/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinderTest.cpp b/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinderTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a079b00e732643af8d1575cc55705b0ddc2498fe
--- /dev/null
+++ b/src/gpu/GridGenerator/geometries/VerticalCylinder/VerticalCylinderTest.cpp
@@ -0,0 +1,58 @@
+#include <gmock/gmock.h>
+#include <array>
+
+#include "VerticalCylinder.h"
+
+class VerticalCylinderTest : public testing::Test
+{
+protected:
+    std::array<double, 3> center = { 0.1, 0.2, 0.3 };
+    double radius = 2.0;
+    double height = 8.0;
+    VerticalCylinder cylinder = VerticalCylinder(center[0], center[1], center[2], radius, height);
+};
+
+TEST_F(VerticalCylinderTest, getCentroid)
+{
+    EXPECT_THAT(cylinder.getX1Centroid(), testing::Eq(center[0]));
+    EXPECT_THAT(cylinder.getX2Centroid(), testing::Eq(center[1]));
+    EXPECT_THAT(cylinder.getX3Centroid(), testing::Eq(center[2]));
+}
+
+TEST_F(VerticalCylinderTest, getMinimum)
+{
+    EXPECT_THAT(cylinder.getX1Minimum(), testing::Eq(-radius + center[0]));
+    EXPECT_THAT(cylinder.getX2Minimum(), testing::Eq(-radius + center[1]));
+    EXPECT_THAT(cylinder.getX3Minimum(), testing::Eq(-0.5 * height + center[2]));
+}
+
+TEST_F(VerticalCylinderTest, getMaximum)
+{
+    EXPECT_THAT(cylinder.getX1Maximum(), testing::Eq(radius + center[0]));
+    EXPECT_THAT(cylinder.getX2Maximum(), testing::Eq(radius + center[1]));
+    EXPECT_THAT(cylinder.getX3Maximum(), testing::Eq(0.5 * height + center[2]));
+}
+
+TEST_F(VerticalCylinderTest, isPointInObject)
+{
+    double epsilon = 0.0001;
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2], 0.0, 0.0));
+
+    // x
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] - radius + epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] - radius - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0] + radius - epsilon, center[1], center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0] + radius + epsilon, center[1], center[2], 0.0, 0.0));
+
+    // y
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] - radius + epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] - radius - epsilon, center[2], 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1] + radius - epsilon, center[2], 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1] + radius + epsilon, center[2], 0.0, 0.0));
+
+    // z
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] - 0.5 * height + epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] - 0.5 * height - epsilon, 0.0, 0.0));
+    EXPECT_TRUE(cylinder.isPointInObject(center[0], center[1], center[2] + 0.5 * height - epsilon, 0.0, 0.0));
+    EXPECT_FALSE(cylinder.isPointInObject(center[0], center[1], center[2] + 0.5 * height + epsilon, 0.0, 0.0));
+}
\ No newline at end of file
diff --git a/src/gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.cpp b/src/gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.cpp
index 31eec205fd92cd1aa991cccd72fac489debf31cd..2cf20863c199a47a27e51ae8a5364daa6e81c9a5 100644
--- a/src/gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.cpp
+++ b/src/gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.cpp
@@ -86,7 +86,7 @@ void MultipleGridBuilder::addGeometry(SPtr<Object> solidObject, uint level)
 {
     this->solidObject = solidObject;
     auto gridShape = solidObject->clone();
-    gridShape->scale(4.0);
+    gridShape->changeSizeByDelta(4.0);
 
     this->addGrid(gridShape, level);
 }
@@ -151,9 +151,9 @@ void MultipleGridBuilder::addIntermediateGridsToList(uint levelDifference, uint
         uint level = getNumberOfLevels();
         for (int i = levelDifference - 1; i >= 0; i--)
         {
-            const real scalingFactor = nodesBetweenGrids * spacings[i] * calculateDelta(levelFine);
+            const real deltaToNewSize = nodesBetweenGrids * spacings[i] * calculateDelta(levelFine);
             SPtr<Object> gridShapeClone = gridShape->clone();
-            gridShapeClone->scale(scalingFactor);
+            gridShapeClone->changeSizeByDelta(deltaToNewSize);
 
             const auto grid = makeGrid(gridShapeClone, level++, 0);
             grids.push_back(grid);
diff --git a/src/gpu/GridGenerator/io/SimulationFileWriter/SimulationFileWriter.cpp b/src/gpu/GridGenerator/io/SimulationFileWriter/SimulationFileWriter.cpp
index d3a467b0511f7f4b40d06b4c6d9b57ff09b9694a..333462abd76e548a26fb72392ecbd635619a8b4e 100644
--- a/src/gpu/GridGenerator/io/SimulationFileWriter/SimulationFileWriter.cpp
+++ b/src/gpu/GridGenerator/io/SimulationFileWriter/SimulationFileWriter.cpp
@@ -60,11 +60,12 @@ void SimulationFileWriter::write(const std::string& folder, SPtr<GridBuilder> bu
     SimulationFileWriter::folder = folder;
 
     VF_LOG_INFO("Start writing simulation files to {}", folder);
-    auto timer = Timer::makeStart();
+    vf::basics::Timer timer;
+    timer.start();
 
     write(builder, format);
 
-    VF_LOG_INFO("    Time writing files: {} sec", timer->getCurrentRuntimeInSeconds());
+    VF_LOG_INFO("    Time writing files: {} sec", timer.getCurrentRuntimeInSeconds());
     VF_LOG_INFO("Done writing simulation Files!");
 }
 
diff --git a/src/gpu/core/BoundaryConditions/BCKernelManagerTest.cpp b/src/gpu/core/BoundaryConditions/BCKernelManagerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1f20350d314360df8675a0bf62ed03017980e8f9
--- /dev/null
+++ b/src/gpu/core/BoundaryConditions/BCKernelManagerTest.cpp
@@ -0,0 +1,141 @@
+
+#include <gmock/gmock.h>
+#include <stdexcept>
+
+#include "BoundaryConditionKernelManager.h"
+#include "BoundaryConditions/BoundaryConditionFactory.h"
+#include "Parameter/Parameter.h"
+#include <basics/PointerDefinitions.h>
+
+class BoundaryConditionKernelManagerTest_BCsNotSpecified : public testing::Test
+{
+protected:
+    BoundaryConditionFactory bcFactory;
+    SPtr<Parameter> para = std::make_shared<Parameter>();
+
+    void SetUp() override
+    {
+        para->initLBMSimulationParameter();
+    }
+};
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->velocityBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory));
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
+{
+    para->getParD(0)->velocityBC.numberOfBCnodes = 1;
+    EXPECT_THROW(BoundaryConditionKernelManager(para, &bcFactory), std::runtime_error);
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->noSlipBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory));
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->noSlipBC.numberOfBCnodes = 1;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory)); // no throw, as a default is specified
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->slipBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory));
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
+{
+    para->getParD(0)->slipBC.numberOfBCnodes = 1;
+    EXPECT_THROW(BoundaryConditionKernelManager(para, &bcFactory), std::runtime_error);
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->pressureBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory));
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_withBoundaryNodes_throws)
+{
+    para->getParD(0)->pressureBC.numberOfBCnodes = 1;
+    EXPECT_THROW(BoundaryConditionKernelManager(para, &bcFactory), std::runtime_error);
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->geometryBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory));
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->geometryBC.numberOfBCnodes = 1;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory)); // no throw, as a default is specified
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->stressBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory));
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
+{
+    para->getParD(0)->stressBC.numberOfBCnodes = 1;
+    EXPECT_THROW(BoundaryConditionKernelManager(para, &bcFactory), std::runtime_error);
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
+{
+    para->getParD(0)->precursorBC.numberOfBCnodes = 0;
+    EXPECT_NO_THROW(BoundaryConditionKernelManager(para, &bcFactory));
+}
+
+TEST_F(BoundaryConditionKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
+{
+    para->getParD(0)->precursorBC.numberOfBCnodes = 1;
+    EXPECT_THROW(BoundaryConditionKernelManager(para, &bcFactory), std::runtime_error);
+}
+
+class BoundaryConditionFactoryMock : public BoundaryConditionFactory
+{
+public:
+    mutable uint numberOfCalls = 0;
+
+    [[nodiscard]] boundaryCondition getVelocityBoundaryConditionPost(bool) const override
+    {
+        return [this](LBMSimulationParameter *, QforBoundaryConditions *) { numberOfCalls++; };
+    }
+};
+
+class BoundaryConditionKernelManagerTest_runBCs : public testing::Test
+{
+protected:
+    BoundaryConditionFactoryMock bcFactory;
+    SPtr<Parameter> para = std::make_shared<Parameter>();
+    UPtr<BoundaryConditionKernelManager> sut;
+
+    void SetUp() override
+    {
+        para->initLBMSimulationParameter();
+        sut = std::make_unique<BoundaryConditionKernelManager>(para, &bcFactory);
+    }
+};
+
+TEST_F(BoundaryConditionKernelManagerTest_runBCs, runVelocityBCKernelPost)
+{
+    para->getParD(0)->velocityBC.numberOfBCnodes = 1;
+    sut->runVelocityBCKernelPost(0);
+    EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(1));
+
+    bcFactory.numberOfCalls = 0;
+    para->getParD(0)->velocityBC.numberOfBCnodes = 0;
+    sut->runVelocityBCKernelPost(0);
+    EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(0));
+}
diff --git a/src/gpu/core/Factories/BoundaryConditionFactory.cpp b/src/gpu/core/BoundaryConditions/BoundaryConditionFactory.cpp
similarity index 100%
rename from src/gpu/core/Factories/BoundaryConditionFactory.cpp
rename to src/gpu/core/BoundaryConditions/BoundaryConditionFactory.cpp
diff --git a/src/gpu/core/Factories/BoundaryConditionFactory.h b/src/gpu/core/BoundaryConditions/BoundaryConditionFactory.h
similarity index 100%
rename from src/gpu/core/Factories/BoundaryConditionFactory.h
rename to src/gpu/core/BoundaryConditions/BoundaryConditionFactory.h
diff --git a/src/gpu/core/Factories/BoundaryConditionFactoryTest.cpp b/src/gpu/core/BoundaryConditions/BoundaryConditionFactoryTest.cpp
similarity index 100%
rename from src/gpu/core/Factories/BoundaryConditionFactoryTest.cpp
rename to src/gpu/core/BoundaryConditions/BoundaryConditionFactoryTest.cpp
diff --git a/src/gpu/core/KernelManager/BCKernelManager.cpp b/src/gpu/core/BoundaryConditions/BoundaryConditionKernelManager.cpp
similarity index 94%
rename from src/gpu/core/KernelManager/BCKernelManager.cpp
rename to src/gpu/core/BoundaryConditions/BoundaryConditionKernelManager.cpp
index 1c1e65fa34720a1f9d19b5ef02e4afda167b323f..60cd1f1138f7aa9362c07332f7307cd13d5ce3c1 100644
--- a/src/gpu/core/KernelManager/BCKernelManager.cpp
+++ b/src/gpu/core/BoundaryConditions/BoundaryConditionKernelManager.cpp
@@ -36,15 +36,15 @@
 #include <stdexcept>
 #include <string>
 
-#include "BCKernelManager.h"
-#include "Factories/BoundaryConditionFactory.h"
+#include "BoundaryConditionKernelManager.h"
+#include "BoundaryConditions/BoundaryConditionFactory.h"
 #include "GridGenerator/TransientBCSetter/TransientBCSetter.h"
 #include "Calculation/Cp.h"
 #include "Calculation/DragLift.h"
 #include "GPU/GPU_Interface.h"
 #include "Parameter/Parameter.h"
 
-BCKernelManager::BCKernelManager(SPtr<Parameter> parameter, BoundaryConditionFactory *bcFactory) : para(parameter)
+BoundaryConditionKernelManager::BoundaryConditionKernelManager(SPtr<Parameter> parameter, BoundaryConditionFactory *bcFactory) : para(parameter)
 {
     this->velocityBoundaryConditionPost = bcFactory->getVelocityBoundaryConditionPost();
     this->noSlipBoundaryConditionPost   = bcFactory->getNoSlipBoundaryConditionPost();
@@ -70,7 +70,7 @@ BCKernelManager::BCKernelManager(SPtr<Parameter> parameter, BoundaryConditionFac
                            "precursorBoundaryConditionPost");
 }
 
-void BCKernelManager::runVelocityBCKernelPre(const int level) const
+void BoundaryConditionKernelManager::runVelocityBCKernelPre(const int level) const
 {
     if (para->getParD(level)->velocityBC.numberOfBCnodes > 0)
     {
@@ -124,7 +124,7 @@ void BCKernelManager::runVelocityBCKernelPre(const int level) const
     }
 }
 
-void BCKernelManager::runVelocityBCKernelPost(const int level) const
+void BoundaryConditionKernelManager::runVelocityBCKernelPost(const int level) const
 {
      if (para->getParD(level)->velocityBC.numberOfBCnodes > 0)
      {
@@ -146,7 +146,7 @@ void BCKernelManager::runVelocityBCKernelPost(const int level) const
      }
 }
 
-void BCKernelManager::runGeoBCKernelPre(const int level, unsigned int t, CudaMemoryManager* cudaMemoryManager) const{
+void BoundaryConditionKernelManager::runGeoBCKernelPre(const int level, unsigned int t, CudaMemoryManager* cudaMemoryManager) const{
     if (para->getParD(level)->geometryBC.numberOfBCnodes > 0){
         if (para->getCalcDragLift())
         {
@@ -254,7 +254,7 @@ void BCKernelManager::runGeoBCKernelPre(const int level, unsigned int t, CudaMem
     }
 }
 
-void BCKernelManager::runGeoBCKernelPost(const int level) const
+void BoundaryConditionKernelManager::runGeoBCKernelPost(const int level) const
 {
     if (para->getParD(level)->geometryBC.numberOfBCnodes > 0)
     {
@@ -318,7 +318,7 @@ void BCKernelManager::runGeoBCKernelPost(const int level) const
     }
 }
 
-void BCKernelManager::runOutflowBCKernelPre(const int level) const{
+void BoundaryConditionKernelManager::runOutflowBCKernelPre(const int level) const{
     if (para->getParD(level)->outflowBC.numberOfBCnodes > 0)
     {
         QPressNoRhoDev27(para->getParD(level).get(), &(para->getParD(level)->outflowBC));
@@ -345,14 +345,14 @@ void BCKernelManager::runOutflowBCKernelPre(const int level) const{
     }
 }
 
-void BCKernelManager::runPressureBCKernelPre(const int level) const{
+void BoundaryConditionKernelManager::runPressureBCKernelPre(const int level) const{
     if (para->getParD(level)->pressureBC.numberOfBCnodes > 0)
     {
         this->pressureBoundaryConditionPre(para->getParD(level).get(), &(para->getParD(level)->pressureBC));
     }
 }
 
-void BCKernelManager::runPressureBCKernelPost(const int level) const{
+void BoundaryConditionKernelManager::runPressureBCKernelPost(const int level) const{
     if (para->getParD(level)->pressureBC.numberOfBCnodes > 0)
     {
         // QPressDev27_IntBB(
@@ -371,28 +371,28 @@ void BCKernelManager::runPressureBCKernelPost(const int level) const{
     }
 }
 
-void BCKernelManager::runStressWallModelKernelPost(const int level) const{
+void BoundaryConditionKernelManager::runStressWallModelKernelPost(const int level) const{
     if (para->getParD(level)->stressBC.numberOfBCnodes > 0)
     {
         stressBoundaryConditionPost(para.get(), &(para->getParD(level)->stressBC), level);
     }
 }
 
-void BCKernelManager::runSlipBCKernelPost(const int level) const{
+void BoundaryConditionKernelManager::runSlipBCKernelPost(const int level) const{
     if (para->getParD(level)->slipBC.numberOfBCnodes > 0)
     {
         slipBoundaryConditionPost(para->getParD(level).get(), &(para->getParD(level)->slipBC));
     }
 }
 
-void BCKernelManager::runNoSlipBCKernelPost(const int level) const{
+void BoundaryConditionKernelManager::runNoSlipBCKernelPost(const int level) const{
     if (para->getParD(level)->noSlipBC.numberOfBCnodes > 0)
     {
         noSlipBoundaryConditionPost(para->getParD(level).get(), &(para->getParD(level)->noSlipBC));
     }
 }
 
-void BCKernelManager::runPrecursorBCKernelPost(int level, uint t, CudaMemoryManager* cudaMemoryManager)
+void BoundaryConditionKernelManager::runPrecursorBCKernelPost(int level, uint t, CudaMemoryManager* cudaMemoryManager)
 {
     if(para->getParH(level)->precursorBC.numberOfBCnodes == 0) return;
 
diff --git a/src/gpu/core/KernelManager/BCKernelManager.h b/src/gpu/core/BoundaryConditions/BoundaryConditionKernelManager.h
similarity index 96%
rename from src/gpu/core/KernelManager/BCKernelManager.h
rename to src/gpu/core/BoundaryConditions/BoundaryConditionKernelManager.h
index 1dd48f0221743f6ac6461c9db3c8a7a9fc97404d..ece5947b461c2ebfa5c4100c77fa60aedcba5c9f 100644
--- a/src/gpu/core/KernelManager/BCKernelManager.h
+++ b/src/gpu/core/BoundaryConditions/BoundaryConditionKernelManager.h
@@ -26,12 +26,10 @@
 //  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 BCKernelManager.h
-//! \ingroup KernelManager
 //! \author Martin Schoenherr, Anna Wellmann
 //=======================================================================================
-#ifndef BCKernelManager_H
-#define BCKernelManager_H
+#ifndef BoundaryConditionKernelManager_H
+#define BoundaryConditionKernelManager_H
 
 #include <functional>
 #include <memory>
@@ -54,13 +52,13 @@ using precursorBoundaryCondition = std::function<void(LBMSimulationParameter *,
 //! \class BCKernelManager
 //! \brief manage the cuda kernel calls to boundary conditions
 //! \details This class stores the boundary conditions and manages the calls to the boundary condition kernels.
-class BCKernelManager
+class BoundaryConditionKernelManager
 {
 public:
     //! Class constructor
     //! \param parameter shared pointer to instance of class Parameter
     //! \throws std::runtime_error when the user forgets to specify a boundary condition
-    BCKernelManager(SPtr<Parameter> parameter, BoundaryConditionFactory *bcFactory);
+    BoundaryConditionKernelManager(SPtr<Parameter> parameter, BoundaryConditionFactory *bcFactory);
 
     //! \brief calls the device function of the velocity boundary condition (post-collision)
     void runVelocityBCKernelPost(const int level) const;
diff --git a/src/gpu/core/CMakeLists.txt b/src/gpu/core/CMakeLists.txt
index c3e38fd157a18ea889716ff66d469986f606dbd3..e7c17fd5335bf00c0dc3ac5180d2d2e46537d17e 100644
--- a/src/gpu/core/CMakeLists.txt
+++ b/src/gpu/core/CMakeLists.txt
@@ -21,7 +21,7 @@ if(BUILD_VF_UNIT_TESTS)
     target_include_directories(gpu_coreTests PRIVATE "${VF_THIRD_DIR}/cuda_samples/")
     target_include_directories(gpu_coreTests PRIVATE "${VF_ROOT_DIR}/src/gpu/GridGenerator/")
     set_source_files_properties(Communication/ExchangeData27Test.cpp PROPERTIES LANGUAGE CUDA)
-    set_source_files_properties(Factories/BoundaryConditionFactoryTest.cpp PROPERTIES LANGUAGE CUDA)
+    set_source_files_properties(BoundaryConditions/BoundaryConditionFactoryTest.cpp PROPERTIES LANGUAGE CUDA)
     set_source_files_properties(DataStructureInitializer/GridReaderGenerator/GridGeneratorTest.cpp PROPERTIES LANGUAGE CUDA)
     set_source_files_properties(DataStructureInitializer/GridReaderGenerator/IndexRearrangementForStreamsTest.cpp PROPERTIES LANGUAGE CUDA)
     set_source_files_properties(Kernel/Kernels/BasicKernels/FluidFlow/Compressible/CumulantK17/CumulantK17Test.cpp PROPERTIES LANGUAGE CUDA)
diff --git a/src/gpu/core/Calculation/UpdateGrid27.cpp b/src/gpu/core/Calculation/UpdateGrid27.cpp
index 72400631a55b5e42d628354876fb268ba45e14fb..be4d637c2e62e4bfc9ef8cc29c906955fd3945fc 100644
--- a/src/gpu/core/Calculation/UpdateGrid27.cpp
+++ b/src/gpu/core/Calculation/UpdateGrid27.cpp
@@ -4,9 +4,9 @@
 
 #include "Communication/ExchangeData27.h"
 #include "Parameter/CudaStreamManager.h"
-#include "KernelManager/BCKernelManager.h"
 #include "Kernel/ADKernelManager.h"
 #include "GridScaling/GridScalingKernelManager.h"
+#include "BoundaryConditions/BoundaryConditionKernelManager.h"
 #include "TurbulenceModels/TurbulenceModelFactory.h"
 #include "Kernel/Kernel.h"
 
@@ -355,7 +355,7 @@ UpdateGrid27::UpdateGrid27(SPtr<Parameter> para, vf::parallel::Communicator &com
     this->collision = getFunctionForCollisionAndExchange(para->getUseStreams(), para->getNumprocs(), para->getKernelNeedsFluidNodeIndicesToRun());
     this->refinement = getFunctionForRefinementAndExchange(para->getUseStreams(), para->getNumprocs(), para->getMaxLevel(), para->useReducedCommunicationAfterFtoC);
 
-    this->bcKernelManager = std::make_shared<BCKernelManager>(para, bcFactory);
+    this->bcKernelManager = std::make_shared<BoundaryConditionKernelManager>(para, bcFactory);
     this->adKernelManager = std::make_shared<ADKernelManager>(para, adkernels);
     this->gridScalingKernelManager = std::make_shared<GridScalingKernelManager>(para, scalingFactory);
 }
diff --git a/src/gpu/core/Calculation/UpdateGrid27.h b/src/gpu/core/Calculation/UpdateGrid27.h
index bcc0a9e5a2edabeec8e2ebb3fb7996a506055b50..dc98fcd348581c6b323f1846b41f683aa25329bc 100644
--- a/src/gpu/core/Calculation/UpdateGrid27.h
+++ b/src/gpu/core/Calculation/UpdateGrid27.h
@@ -15,7 +15,7 @@ namespace vf::parallel
 class Communicator;
 }
 
-class BCKernelManager;
+class BoundaryConditionKernelManager;
 class ADKernelManager;
 class GridScalingKernelManager;
 class Kernel;
@@ -82,7 +82,7 @@ private:
     SPtr<CudaMemoryManager> cudaMemoryManager;
     std::vector<SPtr<Kernel>> kernels;
     //! \property lbKernelManager is a shared pointer to an object of LBKernelManager
-    std::shared_ptr<BCKernelManager> bcKernelManager;
+    std::shared_ptr<BoundaryConditionKernelManager> bcKernelManager;
     //! \property adKernelManager is a shared pointer to an object of ADKernelManager
     std::shared_ptr<ADKernelManager> adKernelManager;
     //! \property gridScalingKernelManager is a shared pointer to an object of GridScalingKernelManager
diff --git a/src/gpu/core/DataStructureInitializer/GridReaderGenerator/GridGeneratorTest.cpp b/src/gpu/core/DataStructureInitializer/GridReaderGenerator/GridGeneratorTest.cpp
index fbacf99d460fe64a83aa5aec0db4b43600d00941..463701ca86971218416e58c781a4c438fbd16fe4 100644
--- a/src/gpu/core/DataStructureInitializer/GridReaderGenerator/GridGeneratorTest.cpp
+++ b/src/gpu/core/DataStructureInitializer/GridReaderGenerator/GridGeneratorTest.cpp
@@ -30,7 +30,7 @@ public:
     {
         uint process = 0;
         if (direction != CommunicationDirections::MX)
-            process = INVALID_INDEX;
+            process = (uint)INVALID_INDEX;
         return process;
     }
 
diff --git a/src/gpu/core/KernelManager/BCKernelManagerTest.cpp b/src/gpu/core/KernelManager/BCKernelManagerTest.cpp
deleted file mode 100644
index 3cb6138ca203f70fb65dad44cb1d317c098cb3b2..0000000000000000000000000000000000000000
--- a/src/gpu/core/KernelManager/BCKernelManagerTest.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-
-#include <gmock/gmock.h>
-#include <stdexcept>
-
-#include "BCKernelManager.h"
-#include "Factories/BoundaryConditionFactory.h"
-#include "Parameter/Parameter.h"
-#include <basics/PointerDefinitions.h>
-
-class BCKernelManagerTest_BCsNotSpecified : public testing::Test
-{
-protected:
-    BoundaryConditionFactory bcFactory;
-    SPtr<Parameter> para = std::make_shared<Parameter>();
-
-    void SetUp() override
-    {
-        para->initLBMSimulationParameter();
-    }
-};
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->velocityBC.numberOfBCnodes = 0;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, velocityBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
-{
-    para->getParD(0)->velocityBC.numberOfBCnodes = 1;
-    EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->noSlipBC.numberOfBCnodes = 0;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, noSlipBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->noSlipBC.numberOfBCnodes = 1;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); // no throw, as a default is specified
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->slipBC.numberOfBCnodes = 0;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, slipBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
-{
-    para->getParD(0)->slipBC.numberOfBCnodes = 1;
-    EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_noBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->pressureBC.numberOfBCnodes = 0;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, pressureBoundaryConditionPreNotSpecified_withBoundaryNodes_throws)
-{
-    para->getParD(0)->pressureBC.numberOfBCnodes = 1;
-    EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->geometryBC.numberOfBCnodes = 0;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, geometryBoundaryConditionPostNotSpecified_withBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->geometryBC.numberOfBCnodes = 1;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory)); // no throw, as a default is specified
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->stressBC.numberOfBCnodes = 0;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, stressBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
-{
-    para->getParD(0)->stressBC.numberOfBCnodes = 1;
-    EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_noBoundaryNodes_doesNotThrow)
-{
-    para->getParD(0)->precursorBC.numberOfBCnodes = 0;
-    EXPECT_NO_THROW(BCKernelManager(para, &bcFactory));
-}
-
-TEST_F(BCKernelManagerTest_BCsNotSpecified, precursorBoundaryConditionPostNotSpecified_withBoundaryNodes_throws)
-{
-    para->getParD(0)->precursorBC.numberOfBCnodes = 1;
-    EXPECT_THROW(BCKernelManager(para, &bcFactory), std::runtime_error);
-}
-
-class BoundaryConditionFactoryMock : public BoundaryConditionFactory
-{
-public:
-    mutable uint numberOfCalls = 0;
-
-    [[nodiscard]] boundaryCondition getVelocityBoundaryConditionPost(bool) const override
-    {
-        return [this](LBMSimulationParameter *, QforBoundaryConditions *) { numberOfCalls++; };
-    }
-};
-
-class BCKernelManagerTest_runBCs : public testing::Test
-{
-protected:
-    BoundaryConditionFactoryMock bcFactory;
-    SPtr<Parameter> para = std::make_shared<Parameter>();
-    UPtr<BCKernelManager> sut;
-
-    void SetUp() override
-    {
-        para->initLBMSimulationParameter();
-        sut = std::make_unique<BCKernelManager>(para, &bcFactory);
-    }
-};
-
-TEST_F(BCKernelManagerTest_runBCs, runVelocityBCKernelPost)
-{
-    para->getParD(0)->velocityBC.numberOfBCnodes = 1;
-    sut->runVelocityBCKernelPost(0);
-    EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(1));
-
-    bcFactory.numberOfCalls = 0;
-    para->getParD(0)->velocityBC.numberOfBCnodes = 0;
-    sut->runVelocityBCKernelPost(0);
-    EXPECT_THAT(bcFactory.numberOfCalls, testing::Eq(0));
-}
diff --git a/src/gpu/core/Parameter/ParameterTest.cpp b/src/gpu/core/Parameter/ParameterTest.cpp
index 4fac8fa73f94f977231f0bad9f99f5b0e5ad52cf..a73233d4315ebbf677be49f260646ccb2dae3955 100644
--- a/src/gpu/core/Parameter/ParameterTest.cpp
+++ b/src/gpu/core/Parameter/ParameterTest.cpp
@@ -10,8 +10,8 @@
 #include "basics/config/ConfigurationFile.h"
 
 #include "DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
-#include "Factories/BoundaryConditionFactory.h"
 #include "GridScaling/GridScalingFactory.h"
+#include "BoundaryConditions/BoundaryConditionFactory.h"
 #include "GPU/CudaMemoryManager.h"
 #include "gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
 #include "gpu/core/Kernel/KernelTypes.h"