diff --git a/.gitignore b/.gitignore
index d3e29c184e8e90ec5899b7b7241bd9fb34385cc9..a750e16f2b49f42e1a4fbff5092680574aefc488 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ cmake-build-debug/
 run/
 buildGCC
 buildWSL
+pybuild/
 
 # Python
 _skbuild/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2cf3e6a6497efc437fee5a3281fa72c75ee59eae..281644f5614054f167c577898d4b8eb4788b2076 100755
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -130,16 +130,16 @@ gcc_12_python:
   artifacts:
     expire_in: 1 hrs
     paths:
-      - build/
-      - dist/
-      - _skbuild/
+      - pybuild/ # build in separate folder to avoid conflicts with c++ build
 
   before_script:
     - export CCACHE_BASEDIR=$CI_PROJECT_DIR
     - export CCACHE_DIR=$CI_PROJECT_DIR/cache
 
   script:
-    - python3 setup.py bdist_wheel build_ext --build-temp=_skbuild -- -DBUILD_VF_CPU=ON -DBUILD_VF_DOUBLE_ACCURACY=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache
+    - export SKBUILD_BUILD_DIR="pybuild"
+    - export SKBUILD_CMAKE_ARGS="-DBUILD_VF_CPU=ON;-DBUILD_VF_DOUBLE_ACCURACY=ON;-DCMAKE_CXX_COMPILER_LAUNCHER=ccache;-DCMAKE_CUDA_COMPILER_LAUNCHER=ccache;-DCMAKE_C_COMPILER_LAUNCHER=ccache;-G=Ninja"
+    - pip install . -v
 
 ###############################################################################
 ##                            Container Upload                               ##
@@ -208,9 +208,6 @@ gcc_12_python_bindings_test:
   needs: ["gcc_12_python"]
 
   before_script:
-    - export PYTHONPATH="Python"
-    - export VF_WHEEL=$(find dist/*.whl)
-    - pip3 install $VF_WHEEL
     - pip3 install -r Python/requirements.txt
 
   script:
@@ -275,6 +272,7 @@ trigger-regression-tests:
 regression_test_4gpu:
   image: python:latest
   stage: test
+  needs: []
 
   rules:
     - if: $REMOTE_USER && $REMOTE_HOST && $PRIVATE_KEY && $CI_PIPELINE_SOURCE == "schedule"
@@ -287,7 +285,10 @@ regression_test_4gpu:
     - pip install "fieldcompare[all]"
 
   script:
-    - hpc-rocket launch --watch regression-tests/multigpu_test/rocket4GPU.yml
+    - hpc-rocket launch regression-tests/multigpu_test/rocket4GPU.yml |& tee hpcrocket4GPU.log
+    - hpc-rocket watch regression-tests/multigpu_test/rocket4GPU.yml $(python regression-tests/multigpu_test/utilities/parsejobid.py hpcrocket4GPU.log)
+    - hpc-rocket finalize regression-tests/multigpu_test/rocket4GPU.yml
+    - cat output/4GPU/slurm4GPU.out
     - git clone --depth 1 --filter=blob:none --sparse https://github.com/irmb/test_data
     - cd test_data
     - git sparse-checkout set regression_tests/gpu/DrivenCavity_4GPU_2Levels regression_tests/gpu/SphereScaling_4GPU_2Levels
@@ -295,10 +296,19 @@ regression_test_4gpu:
     - fieldcompare dir output/4GPU test_data/regression_tests/gpu/DrivenCavity_4GPU_2Levels --include-files "DrivenCavityMultiGPU*.vtu"
     - fieldcompare dir output/4GPU test_data/regression_tests/gpu/SphereScaling_4GPU_2Levels --include-files "SphereScaling*.vtu"
 
+  after_script:
+    - hpc-rocket cancel regression-tests/multigpu_test/rocket4GPU.yml $(python regression-tests/multigpu_test/utilities/parsejobid.py hpcrocket4GPU.log)
+
+  artifacts:
+    when: always
+    paths:
+      - output/4GPU/slurm4GPU.out
+    expire_in: 1 week
 ###############################################################################
 regression_test_8gpu:
   image: python:latest
   stage: test
+  needs: []
 
   rules:
     - if: $REMOTE_USER && $REMOTE_HOST && $PRIVATE_KEY && $CI_PIPELINE_SOURCE == "schedule"
@@ -311,13 +321,25 @@ regression_test_8gpu:
     - pip install "fieldcompare[all]"
 
   script:
-    - hpc-rocket launch --watch regression-tests/multigpu_test/rocket8GPU.yml
+    - hpc-rocket launch regression-tests/multigpu_test/rocket8GPU.yml |& tee hpcrocket8GPU.log
+    - hpc-rocket watch regression-tests/multigpu_test/rocket8GPU.yml $(python regression-tests/multigpu_test/utilities/parsejobid.py hpcrocket8GPU.log)
+    - hpc-rocket finalize regression-tests/multigpu_test/rocket8GPU.yml
+    - cat output/8GPU/slurm8GPU.out
     - git clone --depth 1 --filter=blob:none --sparse https://github.com/irmb/test_data
     - cd test_data
     - git sparse-checkout set regression_tests/gpu/DrivenCavity_8GPU_2Levels regression_tests/gpu/SphereScaling_8GPU_2Levels
     - cd ..
     - fieldcompare dir output/8GPU test_data/regression_tests/gpu/DrivenCavity_8GPU_2Levels --include-files "DrivenCavityMultiGPU*.vtu"
     - fieldcompare dir output/8GPU test_data/regression_tests/gpu/SphereScaling_8GPU_2Levels --include-files "SphereScaling*.vtu"
+  
+  after_script:
+    - hpc-rocket cancel regression-tests/multigpu_test/rocket8GPU.yml $(python regression-tests/multigpu_test/utilities/parsejobid.py hpcrocket8GPU.log)
+
+  artifacts:
+    when: always
+    paths:
+      - output/8GPU/slurm8GPU.out
+    expire_in: 1 week
 ###############################################################################
 ##                            Benchmark                                      ##
 ###############################################################################
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8822b504af3ff680f12f6d16e2e4c5b7a615ac00..d82fe2b93c5103beb6a960ea4bd29914f0d982c4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -91,9 +91,12 @@ include(${VF_CMAKE_DIR}/Cache.cmake)
 include(CMakePrintHelpers)
 include(${VF_CMAKE_DIR}/VirtualFluidsMacros.cmake)
 
-IF( BUILD_VF_DOUBLE_ACCURACY )
+if(BUILD_VF_DOUBLE_ACCURACY)
     list(APPEND VF_COMPILER_DEFINITION VF_DOUBLE_ACCURACY)
-ENDIF()
+    message(STATUS "Configure VirtualFluids with double precision")
+else()
+    message(STATUS "Configure VirtualFluids with single precision")
+endif()
 
 # set gpu features
 if(BUILD_VF_GPU)
diff --git a/MANIFEST.in b/MANIFEST.in
index adafcf99560acd9da79aa060194df8263b6e77e0..196bdc09019d6028792a565d0776e2c267d3c15a 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1 +1 @@
-include pythonbindings/*/bindings*
\ No newline at end of file
+include pythonbindings/*/*.cpython*
\ No newline at end of file
diff --git a/Python/actuator_line/actuator_line.py b/Python/actuator_line/actuator_line.py
index d0589f402456e8ffe8320ce7f780738aef22fbe4..b8e7efb59673c3b3c9206bfda535bdd1f85e451d 100644
--- a/Python/actuator_line/actuator_line.py
+++ b/Python/actuator_line/actuator_line.py
@@ -104,8 +104,8 @@ length = np.array([6,4,1])*boundary_layer_height
 dx = boundary_layer_height/nodes_per_height
 dt = dx * mach / (np.sqrt(3) * velocity)
 velocity_ratio = dx/dt
-velocity_LB = velocity / velocity_ratio # LB units
-viscosity_LB = viscosity / (velocity_ratio * dx) # LB units
+velocity_LB = velocity / velocity_ratio  # LB units
+viscosity_LB = viscosity / (velocity_ratio * dx)  # LB units
 pressure_gradient = u_star * u_star / boundary_layer_height
 pressure_gradient_LB = pressure_gradient * (dt*dt)/dx
 
@@ -142,7 +142,7 @@ tm_factory.read_config_file(config)
 grid_scaling_factory = gpu.GridScalingFactory()
 grid_scaling_factory.set_scaling_factory(gpu.GridScaling.ScaleCompressible)
 
-grid_builder.add_coarse_grid(0.0, 0.0, 0.0, *length, dx)
+grid_builder.add_coarse_grid(0.0, 0.0, 0.0, length[0], length[1], length[2], dx)
 grid_builder.set_periodic_boundary_condition(not read_precursor, True, False)
 grid_builder.build_grids(False)
 
@@ -162,7 +162,7 @@ bc_factory.set_slip_boundary_condition(gpu.SlipBC.SlipBounceBack)
 bc_factory.set_pressure_boundary_condition(gpu.PressureBC.OutflowNonReflective)
 if read_precursor:
     bc_factory.set_precursor_boundary_condition(gpu.PrecursorBC.DistributionsPrecursor if use_distributions else gpu.PrecursorBC.VelocityPrecursor)
-para.set_outflow_pressure_correction_factor(0.0); 
+para.set_outflow_pressure_correction_factor(0.0)
 #%%
 # don't use python init functions, they are very slow! Just kept as an example.
 # Define lambda in bindings and set it here.
@@ -176,7 +176,7 @@ para.set_outflow_pressure_correction_factor(0.0);
 para.set_initial_condition_perturbed_log_law(u_star, z0, length[0], length[2], boundary_layer_height, velocity_ratio)
 
 #%%
-turb_pos = np.array([3,3,3])*turbine_diameter
+turb_pos = np.array([3, 3, 3])*turbine_diameter
 epsilon = 1.5*dx
 density = 1.225
 level = 0
@@ -185,7 +185,7 @@ n_blade_nodes = 32
 omega = 1
 blade_radii = np.arange(n_blade_nodes, dtype=np.float32)/(0.5*turbine_diameter)
 alm = gpu.ActuatorFarm(n_blades, density, n_blade_nodes, epsilon, level, dt, dx, True)
-alm.add_turbine(turb_pos[0],turb_pos[1],turb_pos[2], turbine_diameter, omega, 0, 0, blade_radii)
+alm.add_turbine(turb_pos[0], turb_pos[1], turb_pos[2], turbine_diameter, omega, 0, 0, blade_radii)
 para.add_actuator(alm)
 #%%
 planar_average_probe = gpu.probes.PlanarAverageProbe("horizontalPlanes", para.get_output_path(), 0, int(t_start_tmp_averaging/dt), int(t_averaging/dt) , int(t_start_out_probe/dt), int(t_out_probe/dt), 'z')
diff --git a/Python/boundary_layer/boundary_layer.py b/Python/boundary_layer/boundary_layer.py
index 25b3cd895f8a3a80f9fd6438e00d3e924fc13779..0ebdbb43894e6bdae55cca1f788a33c3739fb0c6 100644
--- a/Python/boundary_layer/boundary_layer.py
+++ b/Python/boundary_layer/boundary_layer.py
@@ -116,7 +116,7 @@ logger.vf_log_info(f"viscosity [10^8 dx^2/dt] = {viscosity_LB*1e8}")
 logger.vf_log_info(f"u* /(dx/dt) = {u_star*dt/dx}")
 logger.vf_log_info(f"dpdx  = {pressure_gradient}")
 logger.vf_log_info(f"dpdx /(dx/dt^2) = {pressure_gradient_LB}")
-    
+
 #%%
 
 #%%
@@ -136,6 +136,8 @@ para.set_timestep_start_out(int(t_start_out/dt))
 para.set_timestep_out(int(t_out/dt))
 para.set_timestep_end(int(t_end/dt))
 para.set_is_body_force(config.get_bool_value("bodyForce"))
+para.set_devices(np.arange(10))
+para.set_max_dev(communicator.get_number_of_process())
 #%%
 tm_factory = gpu.TurbulenceModelFactory(para)
 tm_factory.read_config_file(config)
@@ -161,13 +163,7 @@ bc_factory.set_pressure_boundary_condition(gpu.PressureBC.OutflowNonReflective)
 bc_factory.set_precursor_boundary_condition(gpu.PrecursorBC.DistributionsPrecursor if use_distributions else gpu.PrecursorBC.VelocityPrecursor)
 para.set_outflow_pressure_correction_factor(0.0); 
 #%%
-def init_func(coord_x, coord_y, coord_z):
-    return [
-        0.0, 
-        (u_star/0.4 * np.log(np.maximum(coord_z,z0)/z0) + 2.0*np.sin(np.pi*16*coord_x/length[0])*np.sin(np.pi*8*coord_z/boundary_layer_height)/(np.square(coord_z/boundary_layer_height)+1))  * dt / dx, 
-        2.0*np.sin(np.pi*16.*coord_x/length[0])*np.sin(np.pi*8.*coord_z/boundary_layer_height)/(np.square(coord_z/boundary_layer_height)+1.)  * dt / dx, 
-        8.0*u_star/0.4*(np.sin(np.pi*8.0*coord_y/boundary_layer_height)*np.sin(np.pi*8.0*coord_z/boundary_layer_height)+np.sin(np.pi*8.0*coord_x/length[0]))/(np.square(length[2]/2.0-coord_z)+1.) * dt / dx]
-para.set_initial_condition(init_func)
+para.set_initial_condition_perturbed_log_law(u_star, z0, length[0], length[2], boundary_layer_height, dx/dx)
 
 #%%
 planar_average_probe = gpu.probes.PlanarAverageProbe("horizontalPlanes", para.get_output_path(), 0, int(t_start_tmp_averaging/dt), int(t_averaging/dt) , int(t_start_out_probe/dt), int(t_out_probe/dt), 'z')
diff --git a/apps/cpu/AcousticPulse/ap.cpp b/apps/cpu/AcousticPulse/ap.cpp
index 77ddfbf626e25b8c5d17d438255e37b4977dbddd..ac69eee6d2d158a2ea8eea27da8bf968b92f5f06 100644
--- a/apps/cpu/AcousticPulse/ap.cpp
+++ b/apps/cpu/AcousticPulse/ap.cpp
@@ -179,9 +179,9 @@ void run()
       }
 
       //set connectors  
-     //SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetInterpolationProcessor());
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
-      //dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iProcessor)->setBulkViscosity(nuLB, bulckViscosity);
+     //SPtr<Interpolator> iProcessor(new CompressibleOffsetInterpolator());
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
+      //dynamicPointerCast<CompressibleOffsetMomentsInterpolator>(iProcessor)->setBulkViscosity(nuLB, bulckViscosity);
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
 
       UBLOG(logINFO, "SetConnectorsBlockVisitor:start");
diff --git a/apps/cpu/BoxBenchmark/bb.cpp b/apps/cpu/BoxBenchmark/bb.cpp
index 7d5c0ec2f4fdf4627b87a32727925f62a3bc89e9..0f0c7d6c1ddd066f36f95d8f87be7afae3ddf2c8 100644
--- a/apps/cpu/BoxBenchmark/bb.cpp
+++ b/apps/cpu/BoxBenchmark/bb.cpp
@@ -130,7 +130,7 @@ void run(string configname)
          ppblocks.reset();
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          //SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //grid->accept(setConnsVisitor);
 
@@ -192,7 +192,7 @@ void run(string configname)
          rcp.restart((int)restartStep);
          grid->setTimeStep(restartStep);
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/ConvectionOfVortex/cov.cpp b/apps/cpu/ConvectionOfVortex/cov.cpp
index baa136d6a3a96e1e4ce86ce187f116e2c560530c..bfe29fc9bb6c18782212f8cb9a080d1815b8c6a1 100644
--- a/apps/cpu/ConvectionOfVortex/cov.cpp
+++ b/apps/cpu/ConvectionOfVortex/cov.cpp
@@ -164,15 +164,15 @@ void run()
       ppblocks.reset();
 
       //set connectors  
-      //SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetInterpolationProcessor());
-      //SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
-      //dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iProcessor)->setBulkOmegaToOmega(true);
-      //SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetSquarePressureInterpolationProcessor());
+      //SPtr<Interpolator> iProcessor(new CompressibleOffsetInterpolator());
+      //SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
+      //dynamicPointerCast<CompressibleOffsetMomentsInterpolator>(iProcessor)->setBulkOmegaToOmega(true);
+      //SPtr<Interpolator> iProcessor(new CompressibleOffsetSquarePressureInterpolator());
 
       OneDistributionSetConnectorsBlockVisitor setConnsVisitor(comm);
       grid->accept(setConnsVisitor);
 
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
       SetInterpolationConnectorsBlockVisitor setInterConnsVisitor(comm, nuLB, iProcessor);
       grid->accept(setInterConnsVisitor);
 
diff --git a/apps/cpu/CouetteFlow/cflow.cpp b/apps/cpu/CouetteFlow/cflow.cpp
index e81c3bb008948814d79577311498dbfd5f1a76f2..112c0c96bd3c9bde56c3ef53f0047569fec031b2 100644
--- a/apps/cpu/CouetteFlow/cflow.cpp
+++ b/apps/cpu/CouetteFlow/cflow.cpp
@@ -243,7 +243,7 @@ void bflow(string configname)
 
 
       //set connectors
-      //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+      //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
       //SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, k, iProcessor);
       //grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/DHIT/dhit.cpp b/apps/cpu/DHIT/dhit.cpp
index 850a531a9ac490ed195ad17ce298ca5cf027151a..e06db26b8706bad1f94fec432868daabea8d1cce 100644
--- a/apps/cpu/DHIT/dhit.cpp
+++ b/apps/cpu/DHIT/dhit.cpp
@@ -117,7 +117,7 @@ void run(string configname)
       ppblocks.reset();
 
       //set connectors
-      InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+      InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
       grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/DLR-F16-Porous/f16.cpp b/apps/cpu/DLR-F16-Porous/f16.cpp
index 7ddd135b2996c794e2802e235fdedc2a3013cdf3..791c1c926dbdf86bf1c2f1634288696248cdb305 100644
--- a/apps/cpu/DLR-F16-Porous/f16.cpp
+++ b/apps/cpu/DLR-F16-Porous/f16.cpp
@@ -656,8 +656,8 @@ void run(string configname)
          ////////////////////////////////////////////////////////////////////////////
       }
       ////set connectors
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
-      dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iProcessor)->setBulkViscosity(nuLB, bulckViscosity);
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
+      dynamicPointerCast<CompressibleOffsetMomentsInterpolator>(iProcessor)->setBulkViscosity(nuLB, bulckViscosity);
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
       grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/DLR-F16-Solid/f16.cpp b/apps/cpu/DLR-F16-Solid/f16.cpp
index 328da5dc54b5a2db751eb71ad1ce8810cb471470..2a9893ef28efba2ee163e6e9d8c62ffadd68568a 100644
--- a/apps/cpu/DLR-F16-Solid/f16.cpp
+++ b/apps/cpu/DLR-F16-Solid/f16.cpp
@@ -634,8 +634,8 @@ void run(string configname)
       }
       
       ////set connectors
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
-      dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iProcessor)->setBulkViscosity(nuLB, bulckViscosity);
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
+      dynamicPointerCast<CompressibleOffsetMomentsInterpolator>(iProcessor)->setBulkViscosity(nuLB, bulckViscosity);
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
       grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/DLR-F16/f16.cpp b/apps/cpu/DLR-F16/f16.cpp
index 2bbc1b8ed63be110d4b6ccc98cdcdb88337d4760..17fef2d15f4026d4b7035a896d78664350f6b86c 100644
--- a/apps/cpu/DLR-F16/f16.cpp
+++ b/apps/cpu/DLR-F16/f16.cpp
@@ -978,8 +978,8 @@ void run(string configname)
 
 
          ////set connectors
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -1101,7 +1101,7 @@ void run(string configname)
          
                  
          ////////////////////////////////////////////////////////////////////////////
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/FlowAroundCylinder/cylinder.cfg b/apps/cpu/FlowAroundCylinder/cylinder.cfg
index 97ece40e65d4ffe47a75e5377db49bd0018bbff6..1869a668ad6a8a456a5b131234c082b05d9b17be 100644
--- a/apps/cpu/FlowAroundCylinder/cylinder.cfg
+++ b/apps/cpu/FlowAroundCylinder/cylinder.cfg
@@ -1,8 +1,8 @@
-pathOut = d:/temp/cylinder_test_naming
+pathOut = ./output/FlowAroundCylinder
 
 numOfThreads = 8
 availMem = 15e9
-refineLevel = 0
+refineLevel = 1
 blockNx = 25 41 41
 uLB = 0.001
 #dx = 0.005
diff --git a/apps/cpu/FlowAroundCylinder/cylinder.cpp b/apps/cpu/FlowAroundCylinder/cylinder.cpp
index f8c2ac4674a7bfa98d42c0be4ebf20365f579695..5956a48a8bdf08d11047400f25302005d080d872 100644
--- a/apps/cpu/FlowAroundCylinder/cylinder.cpp
+++ b/apps/cpu/FlowAroundCylinder/cylinder.cpp
@@ -291,12 +291,13 @@ void run(string configname)
       }
 
 	  //set connectors
-	  //InterpolationProcessorPtr iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
+	  //InterpolationProcessorPtr iProcessor(new CompressibleOffsetMomentsInterpolator());
 	  //SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
       OneDistributionSetConnectorsBlockVisitor setConnsVisitor(comm);
 	  grid->accept(setConnsVisitor);
 
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
+    //   SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor_old());
       SetInterpolationConnectorsBlockVisitor setInterConnsVisitor(comm, nueLB, iProcessor);
       grid->accept(setInterConnsVisitor);
 
diff --git a/apps/cpu/Hagen_Poiseuille_flow/pflow.cpp b/apps/cpu/Hagen_Poiseuille_flow/pflow.cpp
index 074e8c3aa9b338fa00db0718862d20c7e99f5e55..5d5e47fddeecaf06b3b23590833ff2dc12d610fb 100644
--- a/apps/cpu/Hagen_Poiseuille_flow/pflow.cpp
+++ b/apps/cpu/Hagen_Poiseuille_flow/pflow.cpp
@@ -553,8 +553,8 @@ void pflowdp(string configname)
          //////////////////////////////////////
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -657,7 +657,7 @@ void pflowdp(string configname)
          grid->setTimeStep(restartStep);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Hagen_Poiseuille_flow2/pflow2.cpp b/apps/cpu/Hagen_Poiseuille_flow2/pflow2.cpp
index 40bf20ecabe23637b6271edd6ac6c4fd951f4760..f298d697f554f002f42438955ecbb3a3308ed219 100644
--- a/apps/cpu/Hagen_Poiseuille_flow2/pflow2.cpp
+++ b/apps/cpu/Hagen_Poiseuille_flow2/pflow2.cpp
@@ -194,7 +194,7 @@ void pflowdp(string configname)
          //////////////////////////////////////
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -280,7 +280,7 @@ void pflowdp(string configname)
          grid->accept(bcVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/HerschelBulkleyModel/hbflow.cpp b/apps/cpu/HerschelBulkleyModel/hbflow.cpp
index 83686a88495ef5fc2a3ce8529453f2d59d30dab7..6abe6b5c55ce3fb3c54d5dd169a06b47026b9b3e 100644
--- a/apps/cpu/HerschelBulkleyModel/hbflow.cpp
+++ b/apps/cpu/HerschelBulkleyModel/hbflow.cpp
@@ -290,7 +290,7 @@ void bflow(string configname)
 
 
       //set connectors
-      //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+      //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
       //SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, k, iProcessor);
       //grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/InterfaceTest/itest.cpp b/apps/cpu/InterfaceTest/itest.cpp
index face949bd7d68c8d4fe94d7e32dc728b7818f42f..723802f6d3160dd79c28c2347ed311d360020d77 100644
--- a/apps/cpu/InterfaceTest/itest.cpp
+++ b/apps/cpu/InterfaceTest/itest.cpp
@@ -94,9 +94,9 @@ void run()
       ppblocks.reset();
 
       //set connectors
-      //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
-      InterpolationProcessorPtr iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
-      dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iProcessor)->setBulkOmegaToOmega(true);
+      //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
+      InterpolationProcessorPtr iProcessor(new CompressibleOffsetMomentsInterpolator());
+      dynamicPointerCast<CompressibleOffsetMomentsInterpolator>(iProcessor)->setBulkOmegaToOmega(true);
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
 
       UBLOG(logINFO, "SetConnectorsBlockVisitor:start");
diff --git a/apps/cpu/LaminarTubeFlow/ltf.cpp b/apps/cpu/LaminarTubeFlow/ltf.cpp
index c70c2c19e7a02129ff00f8ca3bd0d7e53894831c..315bee6f263b3d5395499c0ed925c3790d7bfcdf 100644
--- a/apps/cpu/LaminarTubeFlow/ltf.cpp
+++ b/apps/cpu/LaminarTubeFlow/ltf.cpp
@@ -311,7 +311,7 @@ void run(string configname)
       OneDistributionSetConnectorsBlockVisitor setConnsVisitor(comm);
       grid->accept(setConnsVisitor);
 
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
       SetInterpolationConnectorsBlockVisitor setInterConnsVisitor(comm, nuLB, iProcessor);
       grid->accept(setInterConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/Multiphase (Droplet Test).cpp.backup b/apps/cpu/Multiphase/Multiphase (Droplet Test).cpp.backup
index 533fb619c2bb82783b99110894079594b5ddba47..b783a354fd39f66ba82383f2387daf92ecbde758 100644
--- a/apps/cpu/Multiphase/Multiphase (Droplet Test).cpp.backup	
+++ b/apps/cpu/Multiphase/Multiphase (Droplet Test).cpp.backup	
@@ -370,8 +370,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -420,8 +420,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/Multiphase (Jet breakup on Phoenix).cpp.backup b/apps/cpu/Multiphase/Multiphase (Jet breakup on Phoenix).cpp.backup
index 954d4b539411adb36ea47724ab612fcd8d70be87..ebf91e6cb54f1a067535ae512f85e706a2d88980 100644
--- a/apps/cpu/Multiphase/Multiphase (Jet breakup on Phoenix).cpp.backup	
+++ b/apps/cpu/Multiphase/Multiphase (Jet breakup on Phoenix).cpp.backup	
@@ -396,8 +396,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -446,8 +446,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/CumulantKernel-Before Cumulant modifications.cpp b/apps/cpu/Multiphase/backup/CumulantKernel-Before Cumulant modifications.cpp
index 860a1f1128fb161ee502bf8e1989748722a7941b..a667643c51186f3494d4e80018c482494ed8af30 100644
--- a/apps/cpu/Multiphase/backup/CumulantKernel-Before Cumulant modifications.cpp	
+++ b/apps/cpu/Multiphase/backup/CumulantKernel-Before Cumulant modifications.cpp	
@@ -1,6 +1,6 @@
 #include "MultiphaseCumulantLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <math.h>
 #include <omp.h>
diff --git a/apps/cpu/Multiphase/backup/Multiphase (Droplet Test).cpp b/apps/cpu/Multiphase/backup/Multiphase (Droplet Test).cpp
index 3362f66d5b07d1b94fd6c2623af58011ae425905..e6efac95353e04e93aae0a9dfcde0422259a2832 100644
--- a/apps/cpu/Multiphase/backup/Multiphase (Droplet Test).cpp	
+++ b/apps/cpu/Multiphase/backup/Multiphase (Droplet Test).cpp	
@@ -370,8 +370,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -420,8 +420,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/Multiphase (Final before automation).cpp b/apps/cpu/Multiphase/backup/Multiphase (Final before automation).cpp
index 5ed66edace35c61fa3244c445fa479db13ccec8f..61d37660015ae6b6134e6d30c83010f75ec362e6 100644
--- a/apps/cpu/Multiphase/backup/Multiphase (Final before automation).cpp	
+++ b/apps/cpu/Multiphase/backup/Multiphase (Final before automation).cpp	
@@ -474,8 +474,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -524,8 +524,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/Multiphase (Flow Focusing).cpp b/apps/cpu/Multiphase/backup/Multiphase (Flow Focusing).cpp
index a6355a2aa56e0bd85d919250e750427df7662284..32548c12b0d559928bf789cd2187cb180213dc65 100644
--- a/apps/cpu/Multiphase/backup/Multiphase (Flow Focusing).cpp	
+++ b/apps/cpu/Multiphase/backup/Multiphase (Flow Focusing).cpp	
@@ -448,8 +448,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -498,8 +498,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/Multiphase (Jet breakup on Phoenix).cpp b/apps/cpu/Multiphase/backup/Multiphase (Jet breakup on Phoenix).cpp
index 954d4b539411adb36ea47724ab612fcd8d70be87..ebf91e6cb54f1a067535ae512f85e706a2d88980 100644
--- a/apps/cpu/Multiphase/backup/Multiphase (Jet breakup on Phoenix).cpp	
+++ b/apps/cpu/Multiphase/backup/Multiphase (Jet breakup on Phoenix).cpp	
@@ -396,8 +396,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -446,8 +446,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/Multiphase (T-Junction).cpp b/apps/cpu/Multiphase/backup/Multiphase (T-Junction).cpp
index 1af6f9a19754035d1e4cc1466d80fa0d77de52c7..93844c4a2f9068debe7759943efb3243da923703 100644
--- a/apps/cpu/Multiphase/backup/Multiphase (T-Junction).cpp	
+++ b/apps/cpu/Multiphase/backup/Multiphase (T-Junction).cpp	
@@ -376,8 +376,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -426,8 +426,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/Multiphase (Thermal).cpp b/apps/cpu/Multiphase/backup/Multiphase (Thermal).cpp
index 51ba4463a32740f8b2e07391d1ab174ccb9e7095..68e07b43c2cfff23affee121f9d8b39997d0fd8d 100644
--- a/apps/cpu/Multiphase/backup/Multiphase (Thermal).cpp	
+++ b/apps/cpu/Multiphase/backup/Multiphase (Thermal).cpp	
@@ -417,8 +417,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -467,8 +467,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/Multiphase (Tube).cpp b/apps/cpu/Multiphase/backup/Multiphase (Tube).cpp
index 7e6dfd24a1ba90420891de57a7ba399d5c860e7d..492a906b816129de271189ab8d35fe1a4d180b56 100644
--- a/apps/cpu/Multiphase/backup/Multiphase (Tube).cpp	
+++ b/apps/cpu/Multiphase/backup/Multiphase (Tube).cpp	
@@ -305,8 +305,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -352,8 +352,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/Multiphase.cpp b/apps/cpu/Multiphase/backup/Multiphase.cpp
index 8b09c15f4f5eb829ca37fce160bbb86ebb92f19d..b029e35277729803df53fb0d79d025863e21719b 100644
--- a/apps/cpu/Multiphase/backup/Multiphase.cpp
+++ b/apps/cpu/Multiphase/backup/Multiphase.cpp
@@ -643,8 +643,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          //ConnectorFactoryPtr factory(new Block3DConnectorFactory());
          //ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, factory);
@@ -693,8 +693,8 @@ void run(string configname)
          //grid->accept(bcVisitor);
 
          //set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (New VBased).cpp b/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (New VBased).cpp
index 1cdf5905cbac12297fc3ab9c759cda726673c508..a0bfe97ba310a8858225b5c344f425121ddd2585 100644
--- a/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (New VBased).cpp	
+++ b/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (New VBased).cpp	
@@ -1,6 +1,6 @@
 #include "MultiphaseCumulantLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <math.h>
 #include <omp.h>
diff --git a/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (Original Final).cpp b/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (Original Final).cpp
index 498d91ff8fb8e0a7ae19000225d82a2d7e757387..c0dcd4d0cf26a41da3ff36195d7d6efeabfe016d 100644
--- a/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (Original Final).cpp	
+++ b/apps/cpu/Multiphase/backup/MultiphaseCumulantLBMKernel (Original Final).cpp	
@@ -1,6 +1,6 @@
 #include "MultiphaseCumulantLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <math.h>
 #include <omp.h>
diff --git a/apps/cpu/OrganPipe/OrganPipe.cpp b/apps/cpu/OrganPipe/OrganPipe.cpp
index ad6ec5a1d0892b60f699b74ee4101a9f4ad047e3..b23c159110dce4d1415f4a558d9cd1910e0c2de4 100644
--- a/apps/cpu/OrganPipe/OrganPipe.cpp
+++ b/apps/cpu/OrganPipe/OrganPipe.cpp
@@ -389,9 +389,9 @@ void run(string configname)
          grid->setTimeStep(restartStep);
       }
       ////set connectors
-      //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
-      dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iProcessor)->setBulkViscosity(nu_LB, bulckViscosity);
+      //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
+      dynamicPointerCast<CompressibleOffsetMomentsInterpolator>(iProcessor)->setBulkViscosity(nu_LB, bulckViscosity);
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
       grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/PoiseuilleFlow/pf2.cpp b/apps/cpu/PoiseuilleFlow/pf2.cpp
index f312bc37dacc3caadd9935f450cdcf808c945b4f..c339e06a6c9cac71b4ba9d340ef72027fd999f41 100644
--- a/apps/cpu/PoiseuilleFlow/pf2.cpp
+++ b/apps/cpu/PoiseuilleFlow/pf2.cpp
@@ -149,7 +149,7 @@
 //   grid->accept(initVisitor);
 //
 //   //set connectors
-//   InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+//   InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
 //   SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
 //   grid->accept(setConnsVisitor);
 //
diff --git a/apps/cpu/PoiseuilleFlow/pf3.cpp b/apps/cpu/PoiseuilleFlow/pf3.cpp
index a2eca67d593fd9e21641e99bd3910e4c775f00a9..fa01b68521fadb59c4101a82caef30377b3368fc 100644
--- a/apps/cpu/PoiseuilleFlow/pf3.cpp
+++ b/apps/cpu/PoiseuilleFlow/pf3.cpp
@@ -141,7 +141,7 @@
 //   grid->accept(initVisitor);
 //
 //   //set connectors
-//   InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+//   InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
 //   SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
 //   grid->accept(setConnsVisitor);
 //
diff --git a/apps/cpu/PoiseuilleFlow/pf4.cpp b/apps/cpu/PoiseuilleFlow/pf4.cpp
index 9b249f94e19fd6c53b6410702406c498c101ed42..2e419358e1d5b32ea0f9fc542f8d47b80aa6cae8 100644
--- a/apps/cpu/PoiseuilleFlow/pf4.cpp
+++ b/apps/cpu/PoiseuilleFlow/pf4.cpp
@@ -154,7 +154,7 @@
 //   grid->accept(initVisitor);
 //
 //   //set connectors
-//   InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+//   InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
 //   SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
 //   grid->accept(setConnsVisitor);
 //
diff --git a/apps/cpu/TPMSRow/TPMSRow.cpp b/apps/cpu/TPMSRow/TPMSRow.cpp
index 9adcaadde90454a64221d04e55712ff12c175e54..596b79d0525339d38ee18a3062a219459de8f305 100644
--- a/apps/cpu/TPMSRow/TPMSRow.cpp
+++ b/apps/cpu/TPMSRow/TPMSRow.cpp
@@ -447,7 +447,7 @@ void run(string configname)
                 UBLOG(logINFO, "Restart - end");
         }
         // set connectors
-        SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetInterpolationProcessor());
+        SPtr<Interpolator> iProcessor(new CompressibleOffsetInterpolator());
         //SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu, iProcessor);
         OneDistributionSetConnectorsBlockVisitor setConnsVisitor(comm);
         grid->accept(setConnsVisitor);
diff --git a/apps/cpu/aperm/aperm.cpp b/apps/cpu/aperm/aperm.cpp
index ecff1a453276444b706e31729012dea10597ac61..7591afe4d31c3b0c75097dd44a31477e852dbb00 100644
--- a/apps/cpu/aperm/aperm.cpp
+++ b/apps/cpu/aperm/aperm.cpp
@@ -320,7 +320,7 @@ void run(string configname)
          //////////////////////////////////////
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -467,7 +467,7 @@ void run(string configname)
          }
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/aperm/aperm.cpp.old b/apps/cpu/aperm/aperm.cpp.old
index 54dfe45fd86ff791d3965632a21acac0a3284aea..fd6f916d8155eda8719b3c8cf3382af513206989 100644
--- a/apps/cpu/aperm/aperm.cpp.old
+++ b/apps/cpu/aperm/aperm.cpp.old
@@ -285,7 +285,7 @@ void run(string configname)
          //////////////////////////////////////
 
          //set connectors
-         D3Q27InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         D3Q27InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -487,7 +487,7 @@ void run(string configname)
          }
 
          //set connectors
-         D3Q27InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         D3Q27InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/aperm/aperm.cpp.old2 b/apps/cpu/aperm/aperm.cpp.old2
index bd49f895a277a34608393a7cb53c0b6466526a95..8f0cf83e2f8ae1731dd0e76dccb4a50bddc00ba5 100644
--- a/apps/cpu/aperm/aperm.cpp.old2
+++ b/apps/cpu/aperm/aperm.cpp.old2
@@ -303,7 +303,7 @@ void run(string configname)
          //////////////////////////////////////
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -450,7 +450,7 @@ void run(string configname)
          }
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/bChannelA/bChannelA.cpp b/apps/cpu/bChannelA/bChannelA.cpp
index d50e87437b5fa17353b0f8adb298ec91ecc9d964..01725f2a3b883c0c0a53c6578dc581eadb0c8dc5 100644
--- a/apps/cpu/bChannelA/bChannelA.cpp
+++ b/apps/cpu/bChannelA/bChannelA.cpp
@@ -385,8 +385,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          ////set connectors
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -409,7 +409,7 @@ void run(string configname)
          //migCoProcessor->restart((int)restartStep);
          grid->setTimeStep(restartStep);
          ////////////////////////////////////////////////////////////////////////////
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/f16Test/f16test.cpp b/apps/cpu/f16Test/f16test.cpp
index a73949c8cef45cfa1b576070cb004041f2ac7a0f..2360d962a59015c0c73d869cd97a68d65d3afeee 100644
--- a/apps/cpu/f16Test/f16test.cpp
+++ b/apps/cpu/f16Test/f16test.cpp
@@ -571,8 +571,8 @@ void run(string configname)
          grid->accept(initVisitor);
 
          ////set connectors
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -591,7 +591,7 @@ void run(string configname)
       }
       else
       {
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/levels/levels.cpp b/apps/cpu/levels/levels.cpp
index 0fe328df129ea3f64a135f74f51e425c8d33bd52..a5ac8588023b76b3043d333e6056426147fa4689 100644
--- a/apps/cpu/levels/levels.cpp
+++ b/apps/cpu/levels/levels.cpp
@@ -208,7 +208,7 @@ void run(string configname)
 
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -290,7 +290,7 @@ void run(string configname)
          UBLOG(logINFO, "SetConnectors - start, id="<<myid);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          //D3Q27SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          SPtr<ConnectorFactory> cFactory(new Block3DConnectorFactory());
          ConnectorBlockVisitor setConnsVisitor(comm, nuLB, iProcessor, cFactory);
diff --git a/apps/cpu/mirror/mirror.cpp b/apps/cpu/mirror/mirror.cpp
index 68902fdb7d0dcb74d3eb59d884a0619c8bb0cf6b..b85d9b249ba60e10584d00ba95eda73da915ef5b 100644
--- a/apps/cpu/mirror/mirror.cpp
+++ b/apps/cpu/mirror/mirror.cpp
@@ -488,7 +488,7 @@ void run(string configname)
          grid->accept(initVisitor);
 
          ////set connectors
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -506,7 +506,7 @@ void run(string configname)
       }
       else
       {
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/mpi_benchmark/mpib.cpp b/apps/cpu/mpi_benchmark/mpib.cpp
index 6c13de98b743ad251bb1000dafc609660ca4ba46..797efbc7ed5ea87b31b30cfc3b6258a239fbd5d2 100644
--- a/apps/cpu/mpi_benchmark/mpib.cpp
+++ b/apps/cpu/mpi_benchmark/mpib.cpp
@@ -211,7 +211,7 @@ void run(string configname)
 
       //set connectors
       if (myid==0) UBLOG(logINFO, "SetConnectorsBlockVisitor:start");
-      InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+      InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor);
       grid->accept(setConnsVisitor);
       if (myid==0) UBLOG(logINFO, "SetConnectorsBlockVisitor:end");
diff --git a/apps/cpu/pChannel/pChannel.cpp b/apps/cpu/pChannel/pChannel.cpp
index c2b32108037389ddd18351ff7092cd3d680492ea..72292679f3ef53eaf81e1f26fa54659f5b002584 100644
--- a/apps/cpu/pChannel/pChannel.cpp
+++ b/apps/cpu/pChannel/pChannel.cpp
@@ -536,7 +536,7 @@ void run(string configname)
          grid->accept(initVisitor);
 
          ////set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -559,7 +559,7 @@ void run(string configname)
          migCoProcessor->restart((int)restartStep);
          grid->setTimeStep(restartStep);
          ////////////////////////////////////////////////////////////////////////////
-         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/perm/perm.cpp b/apps/cpu/perm/perm.cpp
index 7fae63025a198a09af2a30da3776f940441dbcc2..ff0af00b8d10af2715542aaee8adf53abf633db4 100644
--- a/apps/cpu/perm/perm.cpp
+++ b/apps/cpu/perm/perm.cpp
@@ -415,7 +415,7 @@ void perm(string configname)
       }
       
       ////set connectors
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
       SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
       grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/poiseuille_example/poiseuille.cpp b/apps/cpu/poiseuille_example/poiseuille.cpp
index d5de62d10edb0ddcfb7790febe494f937317f6e9..52fede221deb1dd8ffa800fae711ff8517895054 100644
--- a/apps/cpu/poiseuille_example/poiseuille.cpp
+++ b/apps/cpu/poiseuille_example/poiseuille.cpp
@@ -79,7 +79,7 @@ int main()
     grid->accept(kernelVisitor);
     interactorsHelper.setBC();
 
-    const auto interpolationProcessor(std::make_shared<CompressibleOffsetMomentsInterpolationProcessor>());
+    const auto interpolationProcessor(std::make_shared<CompressibleOffsetMomentsInterpolator>());
     interpolationProcessor->setBulkViscosity(latticeViscosity, latticeViscosity * bulkViscosityFactor);
 
     SetConnectorsBlockVisitor setConnsVisitor(communicator,
diff --git a/apps/cpu/screw/screw.cpp b/apps/cpu/screw/screw.cpp
index c1eea3f960cf6b4b64757843d08d126e4fac14b9..7ba90a58644e8d19181847dd0825abb57366daf5 100644
--- a/apps/cpu/screw/screw.cpp
+++ b/apps/cpu/screw/screw.cpp
@@ -146,8 +146,8 @@ int main(int argc, char* argv[])
          //////////////////////////////////////
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
-         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
+         //InterpolationProcessorPtr iProcessor(new CompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -220,7 +220,7 @@ int main(int argc, char* argv[])
          grid->accept(bcVisitor);
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/cpu/sphere/sphere.cpp b/apps/cpu/sphere/sphere.cpp
index 8a5ef89b8bf09e765236153f37cb259e075bf15e..1f0f5c116988f9d4bb8d068768d057db376a42d0 100644
--- a/apps/cpu/sphere/sphere.cpp
+++ b/apps/cpu/sphere/sphere.cpp
@@ -267,14 +267,14 @@ void run(string configname)
 
       UBLOG(logINFO, "SetConnectors - start, id=" << myid);
       //set connectors
-      //SPtr<InterpolationProcessor> iProcessor(new  IncompressibleOffsetInterpolationProcessor());
-      //SPtr<CompressibleOffsetMomentsInterpolationProcessor> iProcessor(new  CompressibleOffsetMomentsInterpolationProcessor());
+      //SPtr<Interpolator> iProcessor(new  IncompressibleOffsetInterpolator());
+      //SPtr<CompressibleOffsetMomentsInterpolator> iProcessor(new  CompressibleOffsetMomentsInterpolator());
       //SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nuLB, iProcessor);
 
       OneDistributionSetConnectorsBlockVisitor setConnsVisitor(comm);
       grid->accept(setConnsVisitor);
 
-      SPtr<InterpolationProcessor> iProcessor(new CompressibleOffsetMomentsInterpolationProcessor());
+      SPtr<Interpolator> iProcessor(new CompressibleOffsetMomentsInterpolator());
       SetInterpolationConnectorsBlockVisitor setInterConnsVisitor(comm, nuLB, iProcessor);
       grid->accept(setInterConnsVisitor);
 
diff --git a/apps/cpu/teperm/teperm.cpp b/apps/cpu/teperm/teperm.cpp
index aecdb3745f3da37c03b07eb7b103374a99df4302..9c4c1585ffaee5dce85eb6d1d9d0de993e033d7b 100644
--- a/apps/cpu/teperm/teperm.cpp
+++ b/apps/cpu/teperm/teperm.cpp
@@ -356,7 +356,7 @@ void run(string configname)
          //////////////////////////////////////
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
@@ -501,7 +501,7 @@ void run(string configname)
          }
 
          //set connectors
-         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolationProcessor());
+         InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator());
          SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nu_LB, iProcessor);
          grid->accept(setConnsVisitor);
 
diff --git a/apps/gpu/LBM/ActuatorLine/ActuatorLine.cpp b/apps/gpu/LBM/ActuatorLine/ActuatorLine.cpp
index c1f9790652a796f9e8d84d642e7dd754f690f607..c6bc10a52677a83a8c2a67fc102929a5c44a8483 100644
--- a/apps/gpu/LBM/ActuatorLine/ActuatorLine.cpp
+++ b/apps/gpu/LBM/ActuatorLine/ActuatorLine.cpp
@@ -236,21 +236,28 @@ void multipleLevel(const std::string& configPath)
     para->addActuator( actuator_farm );
 
 
-    // SPtr<PointProbe> pointProbe = std::make_shared<PointProbe>("pointProbe", para->getOutputPath(), 100, 1, 500, 100);
-    // std::vector<real> probeCoordsX = {reference_diameter,2*reference_diameter,5*reference_diameter};
-    // std::vector<real> probeCoordsY = {3*reference_diameter,3*reference_diameter,3*reference_diameter};
-    // std::vector<real> probeCoordsZ = {3*reference_diameter,3*reference_diameter,3*reference_diameter};
-    // pointProbe->addProbePointsFromList(probeCoordsX, probeCoordsY, probeCoordsZ);
-    // // pointProbe->addProbePointsFromXNormalPlane(2*D, 0.0, 0.0, L_y, L_z, (uint)L_y/dx, (uint)L_z/dx);
-
-    // pointProbe->addStatistic(Statistic::Means);
-    // pointProbe->addStatistic(Statistic::Variances);
-    // para->addProbe( pointProbe );
-
-    // SPtr<PlaneProbe> planeProbe = std::make_shared<PlaneProbe>("planeProbe", para->getOutputPath(), 100, 500, 100, 100);
-    // planeProbe->setProbePlane(5*reference_diameter, 0, 0, dx, L_y, L_z);
-    // planeProbe->addStatistic(Statistic::Means);
-    // para->addProbe( planeProbe );
+    SPtr<PointProbe> pointProbe = std::make_shared<PointProbe>("pointProbe", para->getOutputPath(), 100, 1, 500, 100, false);
+    std::vector<real> probeCoordsX = {reference_diameter,2*reference_diameter,5*reference_diameter};
+    std::vector<real> probeCoordsY = {3*reference_diameter,3*reference_diameter,3*reference_diameter};
+    std::vector<real> probeCoordsZ = {3*reference_diameter,3*reference_diameter,3*reference_diameter};
+
+    pointProbe->addProbePointsFromList(probeCoordsX, probeCoordsY, probeCoordsZ);
+    // pointProbe->addProbePointsFromXNormalPlane(2*D, 0.0, 0.0, L_y, L_z, (uint)L_y/dx, (uint)L_z/dx);
+
+    pointProbe->addStatistic(Statistic::Means);
+    pointProbe->addStatistic(Statistic::Variances);
+    para->addProbe( pointProbe );
+
+    SPtr<PointProbe> timeseriesProbe = std::make_shared<PointProbe>("timeProbe", para->getOutputPath(), 100, 1, 500, 100, true);
+    timeseriesProbe->addProbePointsFromList(probeCoordsX, probeCoordsY, probeCoordsZ);
+    timeseriesProbe->addStatistic(Statistic::Instantaneous);
+    timeseriesProbe->addStatistic(Statistic::Means);
+    para->addProbe( timeseriesProbe );
+
+    SPtr<PlaneProbe> planeProbe = std::make_shared<PlaneProbe>("planeProbe", para->getOutputPath(), 100, 500, 100, 100);
+    planeProbe->setProbePlane(5*reference_diameter, 0, 0, dx, L_y, L_z);
+    planeProbe->addStatistic(Statistic::Means);
+    para->addProbe( planeProbe );
 
 
     auto cudaMemoryManager = std::make_shared<CudaMemoryManager>(para);
diff --git a/apps/gpu/LBM/BoundaryLayer/configBoundaryLayer.txt b/apps/gpu/LBM/BoundaryLayer/configBoundaryLayer.txt
index 83e7861a5fb85ea800d187699f1c6c1409422f0a..1b415aa6ce14109c2d93a17ae78463786a7b7608 100644
--- a/apps/gpu/LBM/BoundaryLayer/configBoundaryLayer.txt
+++ b/apps/gpu/LBM/BoundaryLayer/configBoundaryLayer.txt
@@ -23,8 +23,7 @@ Ma = 0.1
 nz = 96 
 
 bodyForce = true
-UseAMD = true
-SGSconstant = 0.2
+TurbulenceModel = QR
 QuadricLimiterP = 100000.0
 QuadricLimiterM = 100000.0
 QuadricLimiterD = 100000.0
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix4GPU_regressionTest.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix4GPU_regressionTest.txt
index c5789cdf96049b7c0a31ce693c29cd2db4952a58..9b8c6e42de49997cc218a2a0ee6f832b903d142b 100644
--- a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix4GPU_regressionTest.txt
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix4GPU_regressionTest.txt
@@ -1,7 +1,7 @@
 ##################################################
 #GPU Mapping
 ##################################################
-Devices="0 1 2 3"
+Devices=0 1 2 3
 NumberOfDevices=4
 
 ##################################################
diff --git a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix8GPU_regressionTest.txt b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix8GPU_regressionTest.txt
index c5789cdf96049b7c0a31ce693c29cd2db4952a58..9b8c6e42de49997cc218a2a0ee6f832b903d142b 100644
--- a/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix8GPU_regressionTest.txt
+++ b/apps/gpu/LBM/DrivenCavityMultiGPU/configPhoenix8GPU_regressionTest.txt
@@ -1,7 +1,7 @@
 ##################################################
 #GPU Mapping
 ##################################################
-Devices="0 1 2 3"
+Devices=0 1 2 3
 NumberOfDevices=4
 
 ##################################################
diff --git a/apps/gpu/LBM/SphereScaling/configPhoenix4GPU_regressionTest.txt b/apps/gpu/LBM/SphereScaling/configPhoenix4GPU_regressionTest.txt
index c5789cdf96049b7c0a31ce693c29cd2db4952a58..9b8c6e42de49997cc218a2a0ee6f832b903d142b 100644
--- a/apps/gpu/LBM/SphereScaling/configPhoenix4GPU_regressionTest.txt
+++ b/apps/gpu/LBM/SphereScaling/configPhoenix4GPU_regressionTest.txt
@@ -1,7 +1,7 @@
 ##################################################
 #GPU Mapping
 ##################################################
-Devices="0 1 2 3"
+Devices=0 1 2 3
 NumberOfDevices=4
 
 ##################################################
diff --git a/apps/gpu/LBM/SphereScaling/configPhoenix8GPU_regressionTest.txt b/apps/gpu/LBM/SphereScaling/configPhoenix8GPU_regressionTest.txt
index c5789cdf96049b7c0a31ce693c29cd2db4952a58..9b8c6e42de49997cc218a2a0ee6f832b903d142b 100644
--- a/apps/gpu/LBM/SphereScaling/configPhoenix8GPU_regressionTest.txt
+++ b/apps/gpu/LBM/SphereScaling/configPhoenix8GPU_regressionTest.txt
@@ -1,7 +1,7 @@
 ##################################################
 #GPU Mapping
 ##################################################
-Devices="0 1 2 3"
+Devices=0 1 2 3
 NumberOfDevices=4
 
 ##################################################
diff --git a/apps/gpu/tests/NumericalTests/Utilities/DataWriter/AnalyticalResults2DToVTKWriter/AnalyticalResults2DToVTKWriterImp.cpp b/apps/gpu/tests/NumericalTests/Utilities/DataWriter/AnalyticalResults2DToVTKWriter/AnalyticalResults2DToVTKWriterImp.cpp
index 126ff07a31c4f434cc82b4bb8b7e1d944b22cae1..15032a8fd4ec6ce8f7684c33ceae0085d92f54c4 100644
--- a/apps/gpu/tests/NumericalTests/Utilities/DataWriter/AnalyticalResults2DToVTKWriter/AnalyticalResults2DToVTKWriterImp.cpp
+++ b/apps/gpu/tests/NumericalTests/Utilities/DataWriter/AnalyticalResults2DToVTKWriter/AnalyticalResults2DToVTKWriterImp.cpp
@@ -40,7 +40,7 @@ void AnalyticalResults2DToVTKWriterImp::writeAnalyticalResult(std::shared_ptr<Pa
         for (int level = para->getCoarse(); level <= para->getFine(); level++) {
 #pragma omp parallel for
             for (int timeStep = 0; timeStep < analyticalResult->getNumberOfTimeSteps(); timeStep++) {
-                const unsigned int numberOfParts = para->getParH(level)->size_Mat / para->getlimitOfNodesForVTK() + 1;
+                const unsigned int numberOfParts = para->getParH(level)->size_Mat / para->getLimitOfNodesForVTK() + 1;
                 std::vector<std::string> fname;
                 unsigned int time =
                     analyticalResult->getTimeSteps().at(timeStep) * analyticalResult->getTimeStepLength();
@@ -93,13 +93,13 @@ void AnalyticalResults2DToVTKWriterImp::writeTimeStep(std::shared_ptr<Parameter>
     std::vector<double> vz = analyticalResult->getVz()[timeStep];
 
     for (unsigned int part = 0; part < fname.size(); part++) {
-        if (((part + 1) * para->getlimitOfNodesForVTK()) > para->getParH(level)->size_Mat)
-            sizeOfNodes = para->getParH(level)->size_Mat - (part * para->getlimitOfNodesForVTK());
+        if (((part + 1) * para->getLimitOfNodesForVTK()) > para->getParH(level)->size_Mat)
+            sizeOfNodes = para->getParH(level)->size_Mat - (part * para->getLimitOfNodesForVTK());
         else
-            sizeOfNodes = para->getlimitOfNodesForVTK();
+            sizeOfNodes = para->getLimitOfNodesForVTK();
 
         //////////////////////////////////////////////////////////////////////////
-        startpos = part * para->getlimitOfNodesForVTK();
+        startpos = part * para->getLimitOfNodesForVTK();
         endpos = startpos + sizeOfNodes;
         //////////////////////////////////////////////////////////////////////////
         cells.clear();
diff --git a/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.cpp b/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.cpp
index cdf82c32ef982dec19df49ae347e5601017a538b..b0368e4e4215aca06cda79faf47403d7a2650f8d 100644
--- a/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.cpp
+++ b/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.cpp
@@ -13,7 +13,7 @@ std::shared_ptr<NumericalTestGridReader> NumericalTestGridReader::getNewInstance
 	return std::shared_ptr<NumericalTestGridReader>(new NumericalTestGridReader(para, initialCondition, cudaManager));
 }
 
-void NumericalTestGridReader::setInitalNodeValues(uint numberOfNodes, int level) const
+void NumericalTestGridReader::setInitialNodeValues(uint numberOfNodes, int level) const
 {
 	initialCondition->init(level);
 	for (uint j = 0; j <= numberOfNodes; j++){
diff --git a/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.h b/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.h
index 84f5d72705db06349f0b31a42eb99ded45bb0e1d..99363655817874672eaf5b898fb087cb20effb02 100644
--- a/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.h
+++ b/apps/gpu/tests/NumericalTests/Utilities/NumericalTestGridReader/NumericalTestGridReader.h
@@ -13,7 +13,7 @@ public:
 	static std::shared_ptr<NumericalTestGridReader> getNewInstance(std::shared_ptr<Parameter> para, std::shared_ptr<InitialCondition> initialCondition, std::shared_ptr<CudaMemoryManager> cudaManager);
 
 protected:
-	virtual void setInitalNodeValues(uint numberOfNodes, int level) const override;
+	virtual void setInitialNodeValues(uint numberOfNodes, int level) const override;
     
 private:
 	NumericalTestGridReader(std::shared_ptr<Parameter> para, std::shared_ptr<InitialCondition> initialCondition, std::shared_ptr<CudaMemoryManager> cudaManager);
diff --git a/pyproject.toml b/pyproject.toml
index 257da6fd95d683081dbff865c864079eae9c675d..df0b13b9c22718ef4172d4698fd29b8e85f0ad22 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,9 +1,46 @@
 [build-system]
-requires = [
-    "setuptools>=42",
-    "scikit-build",
-    "cmake",
-    "ninja; platform_system!='Windows'"
+requires = ["scikit-build-core"]
+build-backend = "scikit_build_core.build"
+
+[project]
+name = "pyfluids"
+version = "0.1.0"
+description = "Python bindings for VirtualFluids"
+readme = "README.md"
+requires-python = ">=3.6"
+classifiers = [
+  "Programming Language :: Python :: 3 :: Only",
+  "Programming Language :: Python :: 3.6",
+  "Programming Language :: Python :: 3.7",
+  "Programming Language :: Python :: 3.8",
+  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.10",
+  "Programming Language :: Python :: 3.11",
 ]
-build-backend = "setup_builder"
-backend-path = ["utilities"]
\ No newline at end of file
+url = "https://git.rz.tu-bs.de/irmb/virtualfluids"
+
+[tool.cmake]
+jobs = 8
+
+[tool.scikit-build]
+build-dir = "build"
+strict-config = true
+logging.level = "INFO"
+
+[tool.scikit-build.wheel]
+packages = ["pythonbindings/pyfluids", "pythonbindings/pyfluids-stubs", "pythonbindings/pymuparser"]
+
+[tool.scikit_build.cmake]
+verbose = true
+build-type = "Release"
+
+[tool.scikit-build.cmake.define]
+BUILD_VF_PYTHON_BINDINGS = "ON"
+BUILD_SHARED_LIBS = "OFF"
+BUILD_VF_UNIT_TESTS = "OFF"
+BUILD_WARNINGS_AS_ERRORS = "OFF"
+
+
+[mypy]
+plugins = "numpy.typing.mypy_plugin"
+
diff --git a/pythonbindings/CMakeLists.txt b/pythonbindings/CMakeLists.txt
index 037b68baf53d5da8a1ccd20155cb0e7be483176b..c9bef9ef080e6e995b903837475f7c2e401152ee 100644
--- a/pythonbindings/CMakeLists.txt
+++ b/pythonbindings/CMakeLists.txt
@@ -6,27 +6,78 @@ endif()
 
 project(VirtualFluidsPython LANGUAGES ${PYFLUIDS_LANGUAGES})
 
-pybind11_add_module(python_bindings MODULE src/VirtualFluids.cpp)
-target_compile_definitions(python_bindings PUBLIC VF_DOUBLE_ACCURACY)
+add_custom_target(python_bindings)
 
-set_target_properties(  python_bindings PROPERTIES
-                        LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/pythonbindings/pyfluids
-                        OUTPUT_NAME "bindings")
+set(PYFLUIDS_DIR ${SKBUILD_PLATLIB_DIR}/pyfluids)
+set(PYMUPRASER_DIR ${SKBUILD_PLATLIB_DIR}/pymuparser)
+
+
+pybind11_add_module(basics_bindings MODULE src/basics/basics.cpp)
+set_target_properties(  basics_bindings PROPERTIES
+                        LIBRARY_OUTPUT_DIRECTORY ${PYFLUIDS_DIR}
+                        OUTPUT_NAME "basics")
+target_link_libraries(basics_bindings PRIVATE basics)
+target_include_directories(basics_bindings PRIVATE ${CMAKE_SOURCE_DIR}/src/)
+target_include_directories(basics_bindings PRIVATE ${CMAKE_BINARY_DIR})
+add_dependencies(python_bindings basics_bindings)
+
+
+pybind11_add_module(logger_bindings MODULE src/logger.cpp)
+set_target_properties(  logger_bindings PROPERTIES
+                        LIBRARY_OUTPUT_DIRECTORY ${PYFLUIDS_DIR}
+                        OUTPUT_NAME "logger")
+target_link_libraries(logger_bindings PRIVATE logger)
+target_include_directories(logger_bindings PRIVATE ${CMAKE_SOURCE_DIR}/src/)
+target_include_directories(logger_bindings PRIVATE ${CMAKE_BINARY_DIR})
+add_dependencies(python_bindings logger_bindings)
+
+
+pybind11_add_module(lbm_bindings MODULE src/lbm.cpp)
+set_target_properties(  lbm_bindings PROPERTIES
+                        LIBRARY_OUTPUT_DIRECTORY ${PYFLUIDS_DIR}
+                        OUTPUT_NAME "lbm")
+target_link_libraries(lbm_bindings PRIVATE lbm)
+target_include_directories(lbm_bindings PRIVATE ${CMAKE_SOURCE_DIR}/src/)
+target_include_directories(lbm_bindings PRIVATE ${CMAKE_BINARY_DIR})
+add_dependencies(python_bindings lbm_bindings)
 
-target_link_libraries(python_bindings PRIVATE basics logger mpi lbm)
 
 IF(BUILD_VF_GPU)
-    set_source_files_properties(src/VirtualFluids.cpp PROPERTIES LANGUAGE CUDA)
+    pybind11_add_module(gpu_bindings MODULE src/gpu/gpu.cpp)
+    set_target_properties(  gpu_bindings PROPERTIES
+                            LIBRARY_OUTPUT_DIRECTORY ${PYFLUIDS_DIR}
+                            OUTPUT_NAME "gpu")
+    target_link_libraries(gpu_bindings PRIVATE basics)
+    set_source_files_properties(src/gpu/gpu.cpp PROPERTIES LANGUAGE CUDA)
+
+    target_include_directories(gpu_bindings PRIVATE ${VF_THIRD_DIR}/cuda_samples/)
 
-    target_include_directories(python_bindings PRIVATE ${VF_THIRD_DIR}/cuda_samples/)
-    target_compile_definitions(python_bindings PRIVATE VF_GPU_PYTHONBINDINGS)
+    target_link_libraries(gpu_bindings PRIVATE GridGenerator VirtualFluids_GPU)
+
+    target_include_directories(gpu_bindings PRIVATE ${CMAKE_SOURCE_DIR}/src/)
+    target_include_directories(gpu_bindings PRIVATE ${CMAKE_BINARY_DIR})
+    add_dependencies(python_bindings gpu_bindings)
 
-    target_link_libraries(python_bindings PRIVATE GridGenerator VirtualFluids_GPU)
 ENDIF()
 
 IF(BUILD_VF_CPU)
-    target_compile_definitions(python_bindings PRIVATE VF_METIS VF_MPI VF_CPU_PYTHONBINDINGS)
-    target_link_libraries(python_bindings PRIVATE simulationconfig VirtualFluidsCore muparser)
+    pybind11_add_module(cpu_bindings MODULE src/cpu/cpu.cpp)
+    set_target_properties(  cpu_bindings PROPERTIES
+                            LIBRARY_OUTPUT_DIRECTORY ${PYFLUIDS_DIR}
+                            OUTPUT_NAME "cpu")
+    target_link_libraries(cpu_bindings PRIVATE simulationconfig VirtualFluidsCore muparser)
+
+    target_include_directories(cpu_bindings PRIVATE ${CMAKE_SOURCE_DIR}/src/)
+    target_include_directories(cpu_bindings PRIVATE ${CMAKE_BINARY_DIR})
+
+    target_compile_definitions(cpu_bindings PUBLIC VF_DOUBLE_ACCURACY) # TODO: remove this and always set it dynamically
+    target_compile_definitions(basics_bindings PUBLIC VF_DOUBLE_ACCURACY)
+    target_compile_definitions(logger_bindings PUBLIC VF_DOUBLE_ACCURACY)
+    target_compile_definitions(lbm_bindings PUBLIC VF_DOUBLE_ACCURACY)
+
+    target_compile_definitions(cpu_bindings PRIVATE VF_METIS VF_MPI)
+    add_dependencies(python_bindings cpu_bindings)
+
 
     # include bindings for muparsers
     pybind11_add_module(pymuparser MODULE src/muParser.cpp)
@@ -40,7 +91,3 @@ IF(BUILD_VF_CPU)
     target_compile_definitions(pymuparser PRIVATE VF_METIS VF_MPI)
     target_link_libraries(pymuparser PRIVATE muparser)
 ENDIF()
-
-
-target_include_directories(python_bindings PRIVATE ${CMAKE_SOURCE_DIR}/src/)
-target_include_directories(python_bindings PRIVATE ${CMAKE_BINARY_DIR})
\ No newline at end of file
diff --git a/pythonbindings/pyfluids-stubs/__init__.pyi b/pythonbindings/pyfluids-stubs/__init__.pyi
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df0d398713cd56ef06bf96637d3aca0f6032dc58 100644
--- a/pythonbindings/pyfluids-stubs/__init__.pyi
+++ b/pythonbindings/pyfluids-stubs/__init__.pyi
@@ -0,0 +1,6 @@
+from . import basics as basics
+from . import logger as logger
+from . import lbm as lbm
+from . import gpu as gpu
+from . import cpu as cpu
+
diff --git a/pythonbindings/pyfluids-stubs/bindings/basics/__init__.pyi b/pythonbindings/pyfluids-stubs/basics/__init__.pyi
similarity index 95%
rename from pythonbindings/pyfluids-stubs/bindings/basics/__init__.pyi
rename to pythonbindings/pyfluids-stubs/basics/__init__.pyi
index a646f7e590e2aba91ab1c367f75b8c6ebe8f79ae..ed74e648a0b6739b31853c9633d63eeac3b91df4 100644
--- a/pythonbindings/pyfluids-stubs/bindings/basics/__init__.pyi
+++ b/pythonbindings/pyfluids-stubs/basics/__init__.pyi
@@ -32,10 +32,13 @@ r"""
 ! \author Henry Korb
 =======================================================================================
 """
-from typing import ClassVar
+from __future__ import annotations
 
-from typing import overload
+from typing import ClassVar, overload
 
+from . import logger as logger
+
+from pyfluids.bindings.basics import logger as logger
 class ConfigurationFile:
     def __init__(self) -> None: ...
     def contains(self, key: str) -> bool: ...
diff --git a/pythonbindings/pyfluids-stubs/bindings/__init__.pyi b/pythonbindings/pyfluids-stubs/bindings/__init__.pyi
deleted file mode 100644
index 4e7f353eab97cc536f8f18e72319af1cd7a1916a..0000000000000000000000000000000000000000
--- a/pythonbindings/pyfluids-stubs/bindings/__init__.pyi
+++ /dev/null
@@ -1,38 +0,0 @@
-r"""
-=======================================================================================
- ____          ____    __    ______     __________   __      __       __        __
- \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
-  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
-   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
-    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
-     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
-      \    \  |    |   ________________________________________________________________
-       \    \ |    |  |  ______________________________________________________________|
-        \    \|    |  |  |         __          __     __     __     ______      _______
-         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
-          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
-           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
-
-  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 __init__.pyi
-! \ingroup bindings
-! \author Henry Korb
-=======================================================================================
-"""
-class ostream_redirect:
-    def __init__(self, stdout: bool = ..., stderr: bool = ...) -> None: ...
-    def __enter__(self) -> None: ...
-    def __exit__(self, *args) -> None: ...
diff --git a/pythonbindings/pyfluids-stubs/bindings/lbm.pyi b/pythonbindings/pyfluids-stubs/bindings/lbm.pyi
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/pythonbindings/pyfluids-stubs/bindings/gpu/__init__.pyi b/pythonbindings/pyfluids-stubs/gpu/__init__.pyi
similarity index 81%
rename from pythonbindings/pyfluids-stubs/bindings/gpu/__init__.pyi
rename to pythonbindings/pyfluids-stubs/gpu/__init__.pyi
index 64a598ee1974b089393b328566def02fb3600005..cc6e3906477e5206a7d3be159cda15909aa1ba68 100644
--- a/pythonbindings/pyfluids-stubs/bindings/gpu/__init__.pyi
+++ b/pythonbindings/pyfluids-stubs/gpu/__init__.pyi
@@ -32,77 +32,88 @@ r"""
 ! \author Henry Korb
 =======================================================================================
 """
-from typing import Any, Callable, ClassVar, List, Optional
+from __future__ import annotations
+from typing import Callable, ClassVar, List, Optional
 
-from typing import overload
-import numpy
-import pyfluids.bindings.basics
-import pyfluids.bindings.gpu.grid_generator as grid_generator
+from typing import overload, Union
+import numpy as np
+import numpy.typing as npt
+import basics
+
+from . import grid_generator as grid_generator
+from . import probes as probes
+
+class PreCollisionInteractor:
+    def __init__(self, *args, **kwargs) -> None: ...
+
+
+class FileCollection:
+    def __init__(self, *args, **kwargs) -> None: ...
 
 class ActuatorFarm(PreCollisionInteractor):
     def __init__(self, number_of_blades_per_turbine: int, density: float, number_of_nodes_per_blade: int, epsilon: float, level: int, delta_t: float, delta_x: float, use_host_arrays: bool) -> None: ...
     def add_turbine(self, posX: float, posY: float, posZ: float, diameter: float, omega: float, azimuth: float, yaw: float, bladeRadii: List[float]) -> None: ...
     def calc_blade_forces(self) -> None: ...
-    def get_all_azimuths(self) -> numpy.ndarray[numpy.float32]: ...
-    def get_all_blade_coords_x(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_azimuths(self) -> npt.NDArray[np.float32]: ...
+    def get_all_blade_coords_x(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_coords_x_device(self) -> int: ...
-    def get_all_blade_coords_y(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_coords_y(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_coords_y_device(self) -> int: ...
-    def get_all_blade_coords_z(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_coords_z(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_coords_z_device(self) -> int: ...
-    def get_all_blade_forces_x(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_forces_x(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_forces_x_device(self) -> int: ...
-    def get_all_blade_forces_y(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_forces_y(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_forces_y_device(self) -> int: ...
-    def get_all_blade_forces_z(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_forces_z(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_forces_z_device(self) -> int: ...
-    def get_all_blade_radii(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_radii(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_radii_device(self) -> int: ...
-    def get_all_blade_velocities_x(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_velocities_x(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_velocities_x_device(self) -> int: ...
-    def get_all_blade_velocities_y(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_velocities_y(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_velocities_y_device(self) -> int: ...
-    def get_all_blade_velocities_z(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_blade_velocities_z(self) -> npt.NDArray[np.float32]: ...
     def get_all_blade_velocities_z_device(self) -> int: ...
-    def get_all_omegas(self) -> numpy.ndarray[numpy.float32]: ...
-    def get_all_turbine_pos_x(self) -> numpy.ndarray[numpy.float32]: ...
-    def get_all_turbine_pos_y(self) -> numpy.ndarray[numpy.float32]: ...
-    def get_all_turbine_pos_z(self) -> numpy.ndarray[numpy.float32]: ...
-    def get_all_yaws(self) -> numpy.ndarray[numpy.float32]: ...
+    def get_all_omegas(self) -> npt.NDArray[np.float32]: ...
+    def get_all_turbine_pos_x(self) -> npt.NDArray[np.float32]: ...
+    def get_all_turbine_pos_y(self) -> npt.NDArray[np.float32]: ...
+    def get_all_turbine_pos_z(self) -> npt.NDArray[np.float32]: ...
+    def get_all_yaws(self) -> npt.NDArray[np.float32]: ...
     def get_turbine_azimuth(self, turbine: int) -> float: ...
-    def get_turbine_blade_coords_x(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_coords_x(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_coords_x_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_coords_y(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_coords_y(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_coords_y_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_coords_z(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_coords_z(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_coords_z_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_forces_x(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_forces_x(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_forces_x_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_forces_y(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_forces_y(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_forces_y_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_forces_z(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_forces_z(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_forces_z_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_radii(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_radii(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_radii_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_velocities_x(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_velocities_x(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_velocities_x_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_velocities_y(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_velocities_y(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_velocities_y_device(self, turbine: int) -> int: ...
-    def get_turbine_blade_velocities_z(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_blade_velocities_z(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_blade_velocities_z_device(self, turbine: int) -> int: ...
     def get_turbine_omega(self, turbine: int) -> float: ...
-    def get_turbine_pos(self, turbine: int) -> numpy.ndarray[numpy.float32]: ...
+    def get_turbine_pos(self, turbine: int) -> npt.NDArray[np.float32]: ...
     def get_turbine_yaw(self, turbine: int) -> float: ...
-    def set_all_azimuths(self, azimuths: numpy.ndarray[numpy.float32]) -> None: ...
-    def set_all_blade_coords(self, blade_coords_x: numpy.ndarray[numpy.float32], blade_coords_y: numpy.ndarray[numpy.float32], blade_coords_z: numpy.ndarray[numpy.float32]) -> None: ...
-    def set_all_blade_forces(self, blade_forces_x: numpy.ndarray[numpy.float32], blade_forces_y: numpy.ndarray[numpy.float32], blade_forces_z: numpy.ndarray[numpy.float32]) -> None: ...
-    def set_all_blade_velocities(self, blade_velocities_x: numpy.ndarray[numpy.float32], blade_velocities_y: numpy.ndarray[numpy.float32], blade_velocities_z: numpy.ndarray[numpy.float32]) -> None: ...
-    def set_all_omegas(self, omegas: numpy.ndarray[numpy.float32]) -> None: ...
-    def set_all_yaws(self, yaws: numpy.ndarray[numpy.float32]) -> None: ...
+    def set_all_azimuths(self, azimuths: npt.NDArray[np.float32]) -> None: ...
+    def set_all_blade_coords(self, blade_coords_x: npt.NDArray[np.float32], blade_coords_y: npt.NDArray[np.float32], blade_coords_z: npt.NDArray[np.float32]) -> None: ...
+    def set_all_blade_forces(self, blade_forces_x: npt.NDArray[np.float32], blade_forces_y: npt.NDArray[np.float32], blade_forces_z: npt.NDArray[np.float32]) -> None: ...
+    def set_all_blade_velocities(self, blade_velocities_x: npt.NDArray[np.float32], blade_velocities_y: npt.NDArray[np.float32], blade_velocities_z: npt.NDArray[np.float32]) -> None: ...
+    def set_all_omegas(self, omegas: npt.NDArray[np.float32]) -> None: ...
+    def set_all_yaws(self, yaws: npt.NDArray[np.float32]) -> None: ...
     def set_turbine_azimuth(self, turbine: int, azimuth: float) -> None: ...
-    def set_turbine_blade_coords(self, turbine: int, blade_coords_x: numpy.ndarray[numpy.float32], blade_coords_y: numpy.ndarray[numpy.float32], blade_coords_z: numpy.ndarray[numpy.float32]) -> None: ...
-    def set_turbine_blade_forces(self, turbine: int, blade_forces_x: numpy.ndarray[numpy.float32], blade_forces_y: numpy.ndarray[numpy.float32], blade_forces_z: numpy.ndarray[numpy.float32]) -> None: ...
-    def set_turbine_blade_velocities(self, turbine: int, blade_velocities_x: numpy.ndarray[numpy.float32], blade_velocities_y: numpy.ndarray[numpy.float32], blade_velocities_z: numpy.ndarray[numpy.float32]) -> None: ...
+    def set_turbine_blade_coords(self, turbine: int, blade_coords_x: npt.NDArray[np.float32], blade_coords_y: npt.NDArray[np.float32], blade_coords_z: npt.NDArray[np.float32]) -> None: ...
+    def set_turbine_blade_forces(self, turbine: int, blade_forces_x: npt.NDArray[np.float32], blade_forces_y: npt.NDArray[np.float32], blade_forces_z: npt.NDArray[np.float32]) -> None: ...
+    def set_turbine_blade_velocities(self, turbine: int, blade_velocities_x: npt.NDArray[np.float32], blade_velocities_y: npt.NDArray[np.float32], blade_velocities_z: npt.NDArray[np.float32]) -> None: ...
     def set_turbine_omega(self, turbine: int, omega: float) -> None: ...
     def set_turbine_yaw(self, turbine: int, yaw: float) -> None: ...
     @property
@@ -116,21 +127,23 @@ class ActuatorFarm(PreCollisionInteractor):
     @property
     def number_of_indices(self) -> int: ...
     @property
-    def number_of_nodes(self) -> int: ...
+    def number_of_grid_nodes(self) -> int: ...
     @property
     def number_of_nodes_per_blade(self) -> int: ...
     @property
     def number_of_turbines(self) -> int: ...
 
+
 class BoundaryConditionFactory:
     def __init__(self) -> None: ...
-    def set_geometry_boundary_condition(self, boundary_condition_type) -> None: ...
-    def set_no_slip_boundary_condition(self, boundary_condition_type) -> None: ...
-    def set_precursor_boundary_condition(self, boundary_condition_type) -> None: ...
-    def set_pressure_boundary_condition(self, boundary_condition_type) -> None: ...
-    def set_slip_boundary_condition(self, boundary_condition_type) -> None: ...
-    def set_stress_boundary_condition(self, boundary_condition_type) -> None: ...
-    def set_velocity_boundary_condition(self, boundary_condition_type) -> None: ...
+    def set_geometry_boundary_condition(self, boundary_condition_type: Union[SlipBC, VelocityBC, NoSlipBC]) -> None: ...
+    def set_no_slip_boundary_condition(self, boundary_condition_type: NoSlipBC) -> None: ...
+    def set_precursor_boundary_condition(self, boundary_condition_type: PrecursorBC) -> None: ...
+    def set_pressure_boundary_condition(self, boundary_condition_type: PressureBC) -> None: ...
+    def set_slip_boundary_condition(self, boundary_condition_type: SlipBC) -> None: ...
+    def set_stress_boundary_condition(self, boundary_condition_type: StressBC) -> None: ...
+    def set_velocity_boundary_condition(self, boundary_condition_type: VelocityBC) -> None: ...
+
 
 class MpiCommunicator:
     def __init__(self, *args, **kwargs) -> None: ...
@@ -139,9 +152,11 @@ class MpiCommunicator:
     def get_number_of_process(self) -> int: ...
     def get_pid(self) -> int: ...
 
+
 class CudaMemoryManager:
     def __init__(self, parameter: Parameter) -> None: ...
 
+
 class FileType:
     __members__: ClassVar[dict] = ...  # read-only
     VTK: ClassVar[FileType] = ...
@@ -157,10 +172,13 @@ class FileType:
     @property
     def name(self) -> str: ...
 
+
 class GridProvider:
     def __init__(self, *args, **kwargs) -> None: ...
     @staticmethod
-    def make_grid_generator(builder: grid_generator.GridBuilder, para: Parameter, cuda_memory_manager: CudaMemoryManager, communicator: Communicator) -> GridProvider: ...
+    def make_grid_generator(builder: grid_generator.GridBuilder, para: Parameter, cuda_memory_manager: CudaMemoryManager, communicator: MpiCommunicator) -> GridProvider: ...
+
+
 
 class GridScaling:
     __members__: ClassVar[dict] = ...  # read-only
@@ -179,10 +197,12 @@ class GridScaling:
     @property
     def name(self) -> str: ...
 
+
 class GridScalingFactory:
     def __init__(self) -> None: ...
     def set_scaling_factory(self, scaling_type) -> None: ...
 
+
 class NoSlipBC:
     __members__: ClassVar[dict] = ...  # read-only
     NoSlip3rdMomentsCompressible: ClassVar[NoSlipBC] = ...
@@ -202,6 +222,7 @@ class NoSlipBC:
     @property
     def name(self) -> str: ...
 
+
 class OutputVariable:
     __members__: ClassVar[dict] = ...  # read-only
     Distributions: ClassVar[OutputVariable] = ...
@@ -218,13 +239,14 @@ class OutputVariable:
     @property
     def name(self) -> str: ...
 
+
 class Parameter:
     @overload
-    def __init__(self, number_of_processes: int, my_ID: int, config_data: Optional[pyfluids.bindings.basics.ConfigurationFile]) -> None: ...
+    def __init__(self, number_of_processes: int, my_ID: int, config_data: Optional[basics.ConfigurationFile]) -> None: ...
     @overload
     def __init__(self, number_of_processes: int, my_ID: int) -> None: ...
     @overload
-    def __init__(self, config_data: pyfluids.bindings.basics.ConfigurationFile) -> None: ...
+    def __init__(self, config_data: basics.ConfigurationFile) -> None: ...
     def add_actuator(self, actuator: PreCollisionInteractor) -> None: ...
     def add_probe(self, probe: PreCollisionInteractor) -> None: ...
     def get_SGS_constant(self) -> float: ...
@@ -245,7 +267,7 @@ class Parameter:
     def set_diff_on(self, is_diff: bool) -> None: ...
     def set_forcing(self, forcing_x: float, forcing_y: float, forcing_z: float) -> None: ...
     def set_has_wall_model_monitor(self, has_wall_monitor: bool) -> None: ...
-    def set_initial_condition(self, init_func: Callable[[float,float,float],List[float]]) -> None: ...
+    def set_initial_condition(self, init_func: Callable[[float, float, float], List[float]]) -> None: ...
     def set_initial_condition_log_law(self, u_star: float, z0: float, velocity_ratio: float) -> None: ...
     def set_initial_condition_perturbed_log_law(self, u_star: float, z0: float, length_x: float, length_z: float, height: float, velocity_ratio: float) -> None: ...
     def set_initial_condition_uniform(self, velocity_x: float, velocity_y: float, velocity_z: float) -> None: ...
@@ -270,8 +292,6 @@ class Parameter:
     def set_viscosity_LB(self, viscosity: float) -> None: ...
     def set_viscosity_ratio(self, viscosity_ratio: float) -> None: ...
 
-class PreCollisionInteractor:
-    def __init__(self, *args, **kwargs) -> None: ...
 
 class PrecursorBC:
     __members__: ClassVar[dict] = ...  # read-only
@@ -290,9 +310,11 @@ class PrecursorBC:
     @property
     def name(self) -> str: ...
 
+
 class PrecursorWriter(PreCollisionInteractor):
     def __init__(self, filename: str, output_path: str, x_pos: float, y_min: float, y_max: float, z_min: float, z_max: float, t_start_out: int, t_save: int, output_variable: OutputVariable, max_timesteps_per_file: int) -> None: ...
 
+
 class PressureBC:
     __members__: ClassVar[dict] = ...  # read-only
     NotSpecified: ClassVar[PressureBC] = ...
@@ -314,6 +336,7 @@ class PressureBC:
     @property
     def name(self) -> str: ...
 
+
 class SideType:
     __members__: ClassVar[dict] = ...  # read-only
     GEOMETRY: ClassVar[SideType] = ...
@@ -335,6 +358,7 @@ class SideType:
     @property
     def name(self) -> str: ...
 
+
 class Simulation:
     @overload
     def __init__(self, parameter: Parameter, memoryManager: CudaMemoryManager, communicator, gridProvider: GridProvider, bcFactory: BoundaryConditionFactory, gridScalingFactory: GridScalingFactory) -> None: ...
@@ -346,6 +370,7 @@ class Simulation:
     def addKineticEnergyAnalyzer(self, t_analyse: int) -> None: ...
     def run(self) -> None: ...
 
+
 class SlipBC:
     __members__: ClassVar[dict] = ...  # read-only
     NotSpecified: ClassVar[SlipBC] = ...
@@ -366,6 +391,7 @@ class SlipBC:
     @property
     def name(self) -> str: ...
 
+
 class StressBC:
     __members__: ClassVar[dict] = ...  # read-only
     NotSpecified: ClassVar[StressBC] = ...
@@ -384,6 +410,7 @@ class StressBC:
     @property
     def name(self) -> str: ...
 
+
 class TurbulenceModel:
     __members__: ClassVar[dict] = ...  # read-only
     AMD: ClassVar[TurbulenceModel] = ...
@@ -402,15 +429,18 @@ class TurbulenceModel:
     @property
     def name(self) -> str: ...
 
+
 class TurbulenceModelFactory:
     def __init__(self, para: Parameter) -> None: ...
-    def read_config_file(self, config_data: pyfluids.bindings.basics.ConfigurationFile) -> None: ...
+    def read_config_file(self, config_data: basics.ConfigurationFile) -> None: ...
     def set_model_constant(self, model_constant: float) -> None: ...
     def set_turbulence_model(self, turbulence_model: TurbulenceModel) -> None: ...
 
+
 class VTKFileCollection(FileCollection):
     def __init__(self, prefix: str) -> None: ...
 
+
 class VelocityBC:
     __members__: ClassVar[dict] = ...  # read-only
     NotSpecified: ClassVar[VelocityBC] = ...
@@ -430,7 +460,5 @@ class VelocityBC:
     @property
     def name(self) -> str: ...
 
-class FileCollection:
-    def __init__(self, *args, **kwargs) -> None: ...
 
 def create_file_collection(prefix: str, type: FileType) -> FileCollection: ...
diff --git a/pythonbindings/pyfluids-stubs/bindings/gpu/grid_generator.pyi b/pythonbindings/pyfluids-stubs/gpu/grid_generator.pyi
similarity index 79%
rename from pythonbindings/pyfluids-stubs/bindings/gpu/grid_generator.pyi
rename to pythonbindings/pyfluids-stubs/gpu/grid_generator.pyi
index 433a20e7efe472bd791b1d2a0f43859676e8fcf0..b1afd89f6455b5fdf5df568c7e03656229d69c1d 100644
--- a/pythonbindings/pyfluids-stubs/bindings/gpu/grid_generator.pyi
+++ b/pythonbindings/pyfluids-stubs/gpu/grid_generator.pyi
@@ -32,15 +32,23 @@ r"""
 ! \author Henry Korb
 =======================================================================================
 """
-from typing import Any, List
+from __future__ import annotations
+
+from typing import List
 
 from typing import overload
-import pyfluids.bindings.basics
-import pyfluids.bindings.gpu
+import gpu
+
+
 
 class BoundingBox:
     def __init__(self, min_x: float, max_x: float, min_y: float, max_y: float, min_z: float, max_z: float) -> None: ...
 
+
+class Object:
+    def __init__(self, *args, **kwargs) -> None: ...
+
+
 class Conglomerate(Object):
     def __init__(self, *args, **kwargs) -> None: ...
     def add(self, object: Object) -> None: ...
@@ -48,27 +56,33 @@ class Conglomerate(Object):
     def make_shared() -> Conglomerate: ...
     def subtract(self, object: Object) -> None: ...
 
+
 class Cuboid(Object):
     def __init__(self, min_x1: float, min_x2: float, min_x3: float, max_x1: float, max_x2: float, max_x3: float) -> None: ...
 
+
 class GridBuilder:
     def __init__(self, *args, **kwargs) -> None: ...
     def get_number_of_grid_levels(self) -> int: ...
 
+
 class GridFactory:
     def __init__(self, *args, **kwargs) -> None: ...
     @staticmethod
     def make() -> GridFactory: ...
 
+
 class LevelGridBuilder(GridBuilder):
     def __init__(self, *args, **kwargs) -> None: ...
-    def set_no_slip_boundary_condition(self, side_type: pyfluids.bindings.gpu.SideType) -> None: ...
+    def set_no_slip_boundary_condition(self, side_type: gpu.SideType) -> None: ...
     def set_periodic_boundary_condition(self, periodic_x: bool, periodic_y: bool, periodic_z: bool) -> None: ...
-    def set_precursor_boundary_condition(self, side_type: pyfluids.bindings.gpu.SideType, file_collection: pyfluids.bindings.gpu.VelocityFileCollection, n_t_read: int, velocity_x: float = ..., velocity_y: float = ..., velocity_z: float = ..., file_level_to_grid_level_map: List[int] = ...) -> None: ...
-    def set_pressure_boundary_condition(self, side_type: pyfluids.bindings.gpu.SideType, rho: float) -> None: ...
-    def set_slip_boundary_condition(self, side_type: pyfluids.bindings.gpu.SideType, normal_x: float, normal_y: float, normal_z: float) -> None: ...
-    def set_stress_boundary_condition(self, side_type: pyfluids.bindings.gpu.SideType, normal_x: float, normal_y: float, normal_z: float, sampling_offset: int, z0: float, dx: float, q: float) -> None: ...
-    def set_velocity_boundary_condition(self, side_type: pyfluids.bindings.gpu.SideType, vx: float, vy: float, vz: float) -> None: ...
+    def set_precursor_boundary_condition(self, side_type: gpu.SideType, file_collection: gpu.FileCollection, n_t_read: int, velocity_x: float = ..., velocity_y: float = ..., velocity_z: float = ..., file_level_to_grid_level_map: List[int] = ...) -> None: ...
+    def set_pressure_boundary_condition(self, side_type: gpu.SideType, rho: float) -> None: ...
+    def set_slip_boundary_condition(self, side_type: gpu.SideType, normal_x: float, normal_y: float, normal_z: float) -> None: ...
+    def set_stress_boundary_condition(self, side_type: gpu.SideType, normal_x: float, normal_y: float, normal_z: float, sampling_offset: int, z0: float, dx: float, q: float = ...) -> None: ...
+    def set_velocity_boundary_condition(self, side_type: gpu.SideType, vx: float, vy: float, vz: float) -> None: ...
+
+
 
 class MultipleGridBuilder(LevelGridBuilder):
     def __init__(self, *args, **kwargs) -> None: ...
@@ -86,14 +100,13 @@ class MultipleGridBuilder(LevelGridBuilder):
     @staticmethod
     def make_shared(grid_factory: GridFactory) -> MultipleGridBuilder: ...
 
-class Object:
-    def __init__(self, *args, **kwargs) -> None: ...
 
 class Sphere(Object):
     def __init__(self, *args, **kwargs) -> None: ...
     @staticmethod
     def make_shared() -> Sphere: ...
 
+
 class TriangularMesh(Object):
     def __init__(self, *args, **kwargs) -> None: ...
     @staticmethod
diff --git a/pythonbindings/pyfluids-stubs/bindings/gpu/probes.pyi b/pythonbindings/pyfluids-stubs/gpu/probes.pyi
similarity index 95%
rename from pythonbindings/pyfluids-stubs/bindings/gpu/probes.pyi
rename to pythonbindings/pyfluids-stubs/gpu/probes.pyi
index af9c40078e6009efebda4450b5c5e23586aa1e83..4c275d1d6f2eb2bc6a63ae0a8a015d5b0eee6472 100644
--- a/pythonbindings/pyfluids-stubs/bindings/gpu/probes.pyi
+++ b/pythonbindings/pyfluids-stubs/gpu/probes.pyi
@@ -32,27 +32,11 @@ r"""
 ! \author Henry Korb
 =======================================================================================
 """
+from __future__ import annotations
 from typing import ClassVar, List
 
-import pyfluids.bindings.gpu
+import gpu
 
-class PlanarAverageProbe(Probe):
-    def __init__(self, probe_name: str, output_path: str, t_start_avg: int, t_start_tmp_avg: int, t_avg: int, t_start_out: int, t_out: int, plane_normal: str) -> None: ...
-
-class PlaneProbe(Probe):
-    def __init__(self, probe_name: str, output_path: str, t_start_avg: int, t_avg: int, t_start_out: int, t_out: int) -> None: ...
-    def set_probe_plane(self, pos_x: float, pos_y: float, pos_z: float, delta_x: float, delta_y: float, delta_z: float) -> None: ...
-
-class PointProbe(Probe):
-    def __init__(self, probe_name: str, output_path: str, t_start_avg: int, t_avg: int, t_start_out: int, t_out: int, output_timeseries: bool) -> None: ...
-    def add_probe_points_from_list(self, point_coords_x: List[float], point_coords_y: List[float], point_coords_z: List[float]) -> None: ...
-    def add_probe_points_from_x_normal_plane(self, pos_x: float, pos0_y: float, pos0_z: float, pos1_y: float, pos1_z: float, n_y: int, n_z: int) -> None: ...
-
-class Probe(pyfluids.bindings.gpu.PreCollisionInteractor):
-    def __init__(self, *args, **kwargs) -> None: ...
-    def add_all_available_statistics(self) -> None: ...
-    def add_statistic(self, variable: Statistic) -> None: ...
-    def set_file_name_to_n_out(self) -> None: ...
 
 class Statistic:
     __members__: ClassVar[dict] = ...  # read-only
@@ -79,6 +63,30 @@ class Statistic:
     @property
     def name(self) -> str: ...
 
+
+class Probe(gpu.PreCollisionInteractor):
+    def __init__(self, *args, **kwargs) -> None: ...
+    def add_all_available_statistics(self) -> None: ...
+    def add_statistic(self, variable: Statistic) -> None: ...
+    def set_file_name_to_n_out(self) -> None: ...
+
+
+class PlanarAverageProbe(Probe):
+    def __init__(self, probe_name: str, output_path: str, t_start_avg: int, t_start_tmp_avg: int, t_avg: int, t_start_out: int, t_out: int, plane_normal: str) -> None: ...
+
+
+class PlaneProbe(Probe):
+    def __init__(self, probe_name: str, output_path: str, t_start_avg: int, t_avg: int, t_start_out: int, t_out: int) -> None: ...
+    def set_probe_plane(self, pos_x: float, pos_y: float, pos_z: float, delta_x: float, delta_y: float, delta_z: float) -> None: ...
+
+
+class PointProbe(Probe):
+    def __init__(self, probe_name: str, output_path: str, t_start_avg: int, t_avg: int, t_start_out: int, t_out: int, output_timeseries: bool) -> None: ...
+    def add_probe_point(self, point_coord_x: float, point_coord_y: float, point_coord_z: float) -> None: ...
+    def add_probe_points_from_list(self, point_coords_x: List[float], point_coords_y: List[float], point_coords_z: List[float]) -> None: ...
+    def add_probe_points_from_x_normal_plane(self, pos_x: float, pos0_y: float, pos0_z: float, pos1_y: float, pos1_z: float, n_y: int, n_z: int) -> None: ...
+
+
 class WallModelProbe(Probe):
     def __init__(self, probe_name: str, output_path: str, t_start_avg: int, t_start_tmp_avg: int, t_avg: int, t_start_out: int, t_out: int) -> None: ...
     def set_evaluate_pressure_gradient(self, eval_press_grad: bool) -> None: ...
diff --git a/pythonbindings/pyfluids-stubs/bindings/logger.pyi b/pythonbindings/pyfluids-stubs/logger.pyi
similarity index 98%
rename from pythonbindings/pyfluids-stubs/bindings/logger.pyi
rename to pythonbindings/pyfluids-stubs/logger.pyi
index fe84eeb18f3245ef72ed023b2de9db7b9131d144..91c1346c2de2313de2c8df4a0b6d5eb4f4ab87bd 100644
--- a/pythonbindings/pyfluids-stubs/bindings/logger.pyi
+++ b/pythonbindings/pyfluids-stubs/logger.pyi
@@ -32,12 +32,16 @@ r"""
 ! \author Henry Korb
 =======================================================================================
 """
+from __future__ import annotations
+
+
 class Logger:
     @staticmethod
     def change_log_path(path: str) -> None: ...
     @staticmethod
     def initialize_logger() -> None: ...
 
+
 def vf_log_critical(message: str) -> None: ...
 def vf_log_debug(message: str) -> None: ...
 def vf_log_info(message: str) -> None: ...
diff --git a/pythonbindings/pyfluids/timeseries_probe_reader.py b/pythonbindings/pyfluids/timeseries_probe_reader.py
new file mode 100644
index 0000000000000000000000000000000000000000..d8aa7af05a82b92a1a9cab9ea791de897ac89c13
--- /dev/null
+++ b/pythonbindings/pyfluids/timeseries_probe_reader.py
@@ -0,0 +1,47 @@
+import numpy as np
+from pathlib import Path
+import pandas as pd
+#%%
+
+
+class TimeseriesProbeReader:
+    def __init__(self, file: Path):
+        self.file = file
+        self.quants, self.positions, self.data = \
+            self.read_file()
+
+    def read_file(self):
+        with open(self.file, "rb") as f:
+            header_length = 0
+            header_length += len(f.readline()) # first line
+            quant_line = f.readline()
+            header_length += len(f.readline()) # number of points
+            number_of_points_line = f.readline()
+            header_length += len(f.readline()) # positions
+            n_points = int(number_of_points_line)
+            positions = np.zeros((n_points, 3))
+            for i in range(n_points):
+                pos_line = f.readline()
+                header_length += len(pos_line)
+                positions[i] = [float(pos) for pos in pos_line.split(b", ")]
+
+        header_length += len(quant_line)
+        header_length += len(number_of_points_line)
+
+        quants = quant_line.decode().split(" ")[1:-1]
+        n_quants = len(quants)
+        data = np.fromfile(self.file, dtype=np.float32, offset=header_length)
+        n_timesteps = len(data)//(n_quants*n_points+1)
+        return quants, positions, data.reshape(n_timesteps, n_points*n_quants+1)
+    
+    def get_data(self):
+        return self.data
+    
+    def get_positions(self):
+        return self.positions
+    
+    def get_quantities(self):
+        return self.quants
+    
+    def to_dataframe(self):
+        return pd.DataFrame(self.data[:,1:], columns=self.quants, index=self.data[:,0])
\ No newline at end of file
diff --git a/pythonbindings/src/basics/basics.cpp b/pythonbindings/src/basics/basics.cpp
index 0b294b7a8de2f4f396dac418b0544b5f99ecec3d..126d8614e1b40ba0658a5335d5eb9d147309eae0 100644
--- a/pythonbindings/src/basics/basics.cpp
+++ b/pythonbindings/src/basics/basics.cpp
@@ -37,12 +37,8 @@ namespace basics
 {
     namespace py = pybind11;
 
-    py::module makeModule(py::module_ &parentModule)
+    PYBIND11_MODULE(basics, m)
     {
-        py::module basicsModule = parentModule.def_submodule("basics");
-
-        configuration::makeModule(basicsModule);
-
-        return basicsModule;
+        configuration::makeModule(m);
     }
 }
\ No newline at end of file
diff --git a/pythonbindings/src/cpu/cpu.cpp b/pythonbindings/src/cpu/cpu.cpp
index 75143d913596c74a26f25ce64f1e6d214a442e34..baced0fc11afd6a12721759780d82f8a26d56cfc 100644
--- a/pythonbindings/src/cpu/cpu.cpp
+++ b/pythonbindings/src/cpu/cpu.cpp
@@ -38,18 +38,16 @@
 #include "submodules/simulationparameters.cpp"
 #include "submodules/writer.cpp"
 
-namespace cpu
+namespace cpu_bindings
 {
     namespace py = pybind11;
-    py::module makeModule(py::module_ &parentModule)
+    PYBIND11_MODULE(cpu, m)
     {
-        py::module cpuModule = parentModule.def_submodule("cpu");
-        boundaryconditions::makeModule(cpuModule);
-        simulation::makeModule(cpuModule);
-        geometry::makeModule(cpuModule);
-        kernel::makeModule(cpuModule);
-        parameters::makeModule(cpuModule);
-        writer::makeModule(cpuModule);
-        return cpuModule;
+        boundaryconditions::makeModule(m);
+        simulation::makeModule(m);
+        geometry::makeModule(m);
+        kernel::makeModule(m);
+        parameters::makeModule(m);
+        writer::makeModule(m);
     }
 }
\ No newline at end of file
diff --git a/pythonbindings/src/gpu/gpu.cpp b/pythonbindings/src/gpu/gpu.cpp
index 9eb160ae7765f16a6437e343cb878bb4b80877bf..8946b1d8af7655682a19e793119b27ab77f6f542 100644
--- a/pythonbindings/src/gpu/gpu.cpp
+++ b/pythonbindings/src/gpu/gpu.cpp
@@ -46,27 +46,25 @@
 #include "submodules/actuator_farm.cpp"
 #include "submodules/grid_scaling_factory.cpp"
 
-namespace gpu
+namespace gpu_bindings
 {
     namespace py = pybind11;
 
-    py::module makeModule(py::module_ &parentModule)
+    PYBIND11_MODULE(gpu, m)
     {
-        py::module gpuModule = parentModule.def_submodule("gpu");
-        simulation::makeModule(gpuModule);
-        parameter::makeModule(gpuModule);
-        pre_collision_interactor::makeModule(gpuModule);
-        actuator_farm::makeModule(gpuModule);
-        boundary_conditions::makeModule(gpuModule);
-        transient_bc_setter::makeModule(gpuModule);
-        communicator::makeModule(gpuModule); 
-        cuda_memory_manager::makeModule(gpuModule);
-        probes::makeModule(gpuModule);
-        precursor_writer::makeModule(gpuModule);
-        grid_generator::makeModule(gpuModule);
-        grid_provider::makeModule(gpuModule);
-        turbulence_model::makeModule(gpuModule);
-        grid_scaling_factory::makeModule(gpuModule);
-        return gpuModule;
+        simulation::makeModule(m);
+        parameter::makeModule(m);
+        pre_collision_interactor::makeModule(m);
+        actuator_farm::makeModule(m);
+        boundary_conditions::makeModule(m);
+        transient_bc_setter::makeModule(m);
+        communicator::makeModule(m); 
+        cuda_memory_manager::makeModule(m);
+        probes::makeModule(m);
+        precursor_writer::makeModule(m);
+        grid_generator::makeModule(m);
+        grid_provider::makeModule(m);
+        turbulence_model::makeModule(m);
+        grid_scaling_factory::makeModule(m);
     }
 }
\ No newline at end of file
diff --git a/pythonbindings/src/gpu/submodules/actuator_farm.cpp b/pythonbindings/src/gpu/submodules/actuator_farm.cpp
index a930616db3e0d0713bdf57157387d75d171603de..86e3f5a42152e60d6b62e32fb894406efc8384ea 100644
--- a/pythonbindings/src/gpu/submodules/actuator_farm.cpp
+++ b/pythonbindings/src/gpu/submodules/actuator_farm.cpp
@@ -30,10 +30,13 @@
 //! \ingroup submodules
 //! \author Henry Korb
 //=======================================================================================
+
 #include <pybind11/pybind11.h>
 #include <pybind11/numpy.h>
 #include <gpu/VirtualFluids_GPU/PreCollisionInteractor/ActuatorFarm.h>
 #include <gpu/VirtualFluids_GPU/PreCollisionInteractor/PreCollisionInteractor.h>
+
+
 class PyActuatorFarm : public ActuatorFarm 
 {
 public:
@@ -43,13 +46,20 @@ public:
         PYBIND11_OVERRIDE_NAME(void, ActuatorFarm, "calc_blade_forces", calcBladeForces); 
     }
 };
+
 namespace actuator_farm
 {
     namespace py = pybind11;
 
+    template<class dtype>
+    dtype* np_to_arr(py::array_t<dtype, py::array::c_style> array){ return static_cast<dtype *>(array.request().ptr); };
+
+    template<class dtype>
+    intptr_t arr_to_cp(dtype* array){ return reinterpret_cast<intptr_t>(array); };
+
     void makeModule(py::module_ &parentModule)
     {
-        using arr = py::array_t<float, py::array::c_style>;
+        using arr = py::array_t<real, py::array::c_style>;
         
         py::class_<ActuatorFarm, PreCollisionInteractor, PyActuatorFarm, std::shared_ptr<ActuatorFarm>>(parentModule, "ActuatorFarm", py::dynamic_attr())
         .def(py::init<  const uint,
@@ -71,7 +81,7 @@ namespace actuator_farm
         .def_property_readonly("number_of_turbines", &ActuatorFarm::getNumberOfTurbines)
         .def_property_readonly("number_of_nodes_per_blade", &ActuatorFarm::getNumberOfNodesPerBlade)
         .def_property_readonly("number_of_blades_per_turbine", &ActuatorFarm::getNumberOfBladesPerTurbine)
-        .def_property_readonly("number_of_nodes", &ActuatorFarm::getNumberOfNodes)
+        .def_property_readonly("number_of_grid_nodes", &ActuatorFarm::getNumberOfGridNodes)
         .def_property_readonly("number_of_indices", &ActuatorFarm::getNumberOfIndices)
         .def_property_readonly("density", &ActuatorFarm::getDensity)
         .def_property_readonly("delta_t", &ActuatorFarm::getDeltaT)
@@ -79,7 +89,9 @@ namespace actuator_farm
 
         .def("add_turbine", &ActuatorFarm::addTurbine, py::arg("posX"), py::arg("posY"), py::arg("posZ"), py::arg("diameter"), py::arg("omega"), py::arg("azimuth"), py::arg("yaw"), py::arg("bladeRadii"))
 
-        .def("get_turbine_pos", [](ActuatorFarm& al, uint turbine){ real position[3] = {al.getTurbinePosX(turbine), al.getTurbinePosY(turbine), al.getTurbinePosZ(turbine)}; return arr(3,  position); }, py::arg("turbine"))
+        .def("get_turbine_pos", [](ActuatorFarm& al, uint turbine){ 
+            real position[3] = {al.getTurbinePosX(turbine), al.getTurbinePosY(turbine), al.getTurbinePosZ(turbine)}; return arr(3,  position);
+            }, py::arg("turbine"))
         .def("get_turbine_azimuth", &ActuatorFarm::getTurbineAzimuth, py::arg("turbine"))
         .def("get_turbine_yaw", &ActuatorFarm::getTurbineYaw, py::arg("turbine"))
         .def("get_turbine_omega", &ActuatorFarm::getTurbineOmega, py::arg("turbine"))
@@ -112,59 +124,53 @@ namespace actuator_farm
         .def("get_turbine_blade_forces_y", [](ActuatorFarm& al, uint turbine){ return arr({al.getNumberOfBladesPerTurbine(), al.getNumberOfNodesPerBlade()}, al.getTurbineBladeForcesYDevice(turbine)); }, py::arg("turbine") )
         .def("get_turbine_blade_forces_z", [](ActuatorFarm& al, uint turbine){ return arr({al.getNumberOfBladesPerTurbine(), al.getNumberOfNodesPerBlade()}, al.getTurbineBladeForcesZDevice(turbine)); }, py::arg("turbine") )
 
-        .def("get_all_blade_radii_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t>(al.getAllBladeRadiiDevice()); } )
-        .def("get_all_blade_coords_x_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeCoordsXDevice()); } )
-        .def("get_all_blade_coords_y_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeCoordsYDevice()); } )
-        .def("get_all_blade_coords_z_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeCoordsZDevice()); } )        
-        .def("get_all_blade_velocities_x_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeVelocitiesXDevice()); } )
-        .def("get_all_blade_velocities_y_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeVelocitiesYDevice()); } )
-        .def("get_all_blade_velocities_z_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeVelocitiesZDevice()); } )
-        .def("get_all_blade_forces_x_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeForcesXDevice()); } )
-        .def("get_all_blade_forces_y_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeForcesYDevice()); } )
-        .def("get_all_blade_forces_z_device", [](ActuatorFarm& al) -> intptr_t { return reinterpret_cast<intptr_t> (al.getAllBladeForcesZDevice()); } )
+        .def("get_all_blade_radii_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeRadiiDevice()); } )
+        .def("get_all_blade_coords_x_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeCoordsXDevice()); } )
+        .def("get_all_blade_coords_y_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeCoordsYDevice()); } )
+        .def("get_all_blade_coords_z_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeCoordsZDevice()); } )        
+        .def("get_all_blade_velocities_x_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeVelocitiesXDevice()); } )
+        .def("get_all_blade_velocities_y_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeVelocitiesYDevice()); } )
+        .def("get_all_blade_velocities_z_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeVelocitiesZDevice()); } )
+        .def("get_all_blade_forces_x_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeForcesXDevice()); } )
+        .def("get_all_blade_forces_y_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeForcesYDevice()); } )
+        .def("get_all_blade_forces_z_device", [](ActuatorFarm& al) -> intptr_t { return arr_to_cp(al.getAllBladeForcesZDevice()); } )
 
-        .def("get_turbine_blade_radii_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeRadiiDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_coords_x_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeCoordsXDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_coords_y_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeCoordsYDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_coords_z_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeCoordsZDevice(turbine)); }, py::arg("turbine") )        
-        .def("get_turbine_blade_velocities_x_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeVelocitiesXDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_velocities_y_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeVelocitiesYDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_velocities_z_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeVelocitiesZDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_forces_x_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeForcesXDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_forces_y_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeForcesYDevice(turbine)); }, py::arg("turbine") )
-        .def("get_turbine_blade_forces_z_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return reinterpret_cast<intptr_t>(al.getTurbineBladeForcesZDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_radii_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeRadiiDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_coords_x_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeCoordsXDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_coords_y_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeCoordsYDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_coords_z_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeCoordsZDevice(turbine)); }, py::arg("turbine") )        
+        .def("get_turbine_blade_velocities_x_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeVelocitiesXDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_velocities_y_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeVelocitiesYDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_velocities_z_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeVelocitiesZDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_forces_x_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeForcesXDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_forces_y_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeForcesYDevice(turbine)); }, py::arg("turbine") )
+        .def("get_turbine_blade_forces_z_device", [](ActuatorFarm& al, uint turbine) -> intptr_t { return arr_to_cp(al.getTurbineBladeForcesZDevice(turbine)); }, py::arg("turbine") )
 
-        .def("set_all_azimuths", [](ActuatorFarm& al, arr azimuths){ al.setAllAzimuths(static_cast<float *>(azimuths.request().ptr)); }, py::arg("azimuths"))
-        .def("set_all_yaws", [](ActuatorFarm& al, arr yaws){ al.setAllYaws(static_cast<float *>(yaws.request().ptr)); }, py::arg("yaws"))
-        .def("set_all_omegas", [](ActuatorFarm& al, arr omegas){ al.setAllOmegas(static_cast<float *>(omegas.request().ptr)); }, py::arg("omegas"))
+        .def("set_all_azimuths", [](ActuatorFarm& al, arr azimuths){ al.setAllAzimuths(np_to_arr(azimuths)); }, py::arg("azimuths"))
+        .def("set_all_yaws", [](ActuatorFarm& al, arr yaws){ al.setAllYaws(np_to_arr(yaws)); }, py::arg("yaws"))
+        .def("set_all_omegas", [](ActuatorFarm& al, arr omegas){ al.setAllOmegas(np_to_arr(omegas)); }, py::arg("omegas"))
 
         .def("set_turbine_azimuth", &ActuatorFarm::setTurbineAzimuth, py::arg("turbine"), py::arg("azimuth"))
         .def("set_turbine_yaw", &ActuatorFarm::setTurbineYaw, py::arg("turbine"), py::arg("yaw"))
         .def("set_turbine_omega", &ActuatorFarm::setTurbineOmega, py::arg("turbine"), py::arg("omega"))
 
-        .def("set_all_blade_coords", [](ActuatorFarm& al, arr coordsX, arr coordsY, arr coordsZ)
-        { 
-            al.setAllBladeCoords(static_cast<float *>(coordsX.request().ptr), static_cast<float *>(coordsY.request().ptr), static_cast<float *>(coordsZ.request().ptr)); 
+        .def("set_all_blade_coords", [](ActuatorFarm& al, arr coordsX, arr coordsY, arr coordsZ){ 
+            al.setAllBladeCoords(np_to_arr(coordsX), np_to_arr(coordsY), np_to_arr(coordsZ)); 
         }, py::arg("blade_coords_x"), py::arg("blade_coords_y"), py::arg("blade_coords_z") )
-        .def("set_all_blade_velocities", [](ActuatorFarm& al, arr velocitiesX, arr velocitiesY, arr velocitiesZ)
-        { 
-            al.setAllBladeVelocities(static_cast<float *>(velocitiesX.request().ptr), static_cast<float *>(velocitiesY.request().ptr), static_cast<float *>(velocitiesZ.request().ptr)); 
+        .def("set_all_blade_velocities", [](ActuatorFarm& al, arr velocitiesX, arr velocitiesY, arr velocitiesZ){ 
+            al.setAllBladeVelocities(np_to_arr(velocitiesX), np_to_arr(velocitiesY), np_to_arr(velocitiesZ)); 
         }, py::arg("blade_velocities_x"), py::arg("blade_velocities_y"), py::arg("blade_velocities_z") )
-        .def("set_all_blade_forces", [](ActuatorFarm& al, arr forcesX, arr forcesY, arr forcesZ)
-        { 
-            al.setAllBladeForces(static_cast<float *>(forcesX.request().ptr), static_cast<float *>(forcesY.request().ptr), static_cast<float *>(forcesZ.request().ptr));
+        .def("set_all_blade_forces", [](ActuatorFarm& al, arr forcesX, arr forcesY, arr forcesZ){ 
+            al.setAllBladeForces(np_to_arr(forcesX), np_to_arr(forcesY), np_to_arr(forcesZ));
         }, py::arg("blade_forces_x"), py::arg("blade_forces_y"), py::arg("blade_forces_z") )     
-        .def("set_turbine_blade_coords", [](ActuatorFarm& al, uint turbine, arr coordsX, arr coordsY, arr coordsZ)
-        { 
-            al.setTurbineBladeCoords(turbine, static_cast<float *>(coordsX.request().ptr), static_cast<float *>(coordsY.request().ptr), static_cast<float *>(coordsZ.request().ptr)); 
+        .def("set_turbine_blade_coords", [](ActuatorFarm& al, uint turbine, arr coordsX, arr coordsY, arr coordsZ){ 
+            al.setTurbineBladeCoords(turbine, np_to_arr(coordsX), np_to_arr(coordsY), np_to_arr(coordsZ)); 
         }, py::arg("turbine"), py::arg("blade_coords_x"), py::arg("blade_coords_y"), py::arg("blade_coords_z") )
-        .def("set_turbine_blade_velocities", [](ActuatorFarm& al, uint turbine, arr velocitiesX, arr velocitiesY, arr velocitiesZ)
-        {
-            al.setTurbineBladeVelocities(turbine, static_cast<float *>(velocitiesX.request().ptr), static_cast<float *>(velocitiesY.request().ptr), static_cast<float *>(velocitiesZ.request().ptr)); 
+        .def("set_turbine_blade_velocities", [](ActuatorFarm& al, uint turbine, arr velocitiesX, arr velocitiesY, arr velocitiesZ){
+            al.setTurbineBladeVelocities(turbine, np_to_arr(velocitiesX), np_to_arr(velocitiesY), np_to_arr(velocitiesZ)); 
         }, py::arg("turbine"), py::arg("blade_velocities_x"), py::arg("blade_velocities_y"), py::arg("blade_velocities_z") )
-        .def("set_turbine_blade_forces", [](ActuatorFarm& al, uint turbine, arr forcesX, arr forcesY, arr forcesZ)
-        { 
-            al.setTurbineBladeForces(turbine, static_cast<float *>(forcesX.request().ptr), static_cast<float *>(forcesY.request().ptr), static_cast<float *>(forcesZ.request().ptr)); 
+        .def("set_turbine_blade_forces", [](ActuatorFarm& al, uint turbine, arr forcesX, arr forcesY, arr forcesZ){ 
+            al.setTurbineBladeForces(turbine, np_to_arr(forcesX), np_to_arr(forcesY), np_to_arr(forcesZ)); 
         }, py::arg("turbine"), py::arg("blade_forces_x"), py::arg("blade_forces_y"), py::arg("blade_forces_z") )
         .def("calc_blade_forces", &ActuatorFarm::calcBladeForces);
     }
diff --git a/pythonbindings/src/gpu/submodules/grid_generator.cpp b/pythonbindings/src/gpu/submodules/grid_generator.cpp
index 59d0bd5708b11f246664d1e8c7ee198f986d80c1..f4c2b733e7b099309b3fdc238ee71c22d940cced 100644
--- a/pythonbindings/src/gpu/submodules/grid_generator.cpp
+++ b/pythonbindings/src/gpu/submodules/grid_generator.cpp
@@ -42,6 +42,10 @@
 #include "gpu/GridGenerator/grid/GridBuilder/GridBuilder.h"
 #include "gpu/GridGenerator/grid/GridBuilder/LevelGridBuilder.h"
 #include "gpu/GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
+#include "basics/constants/NumericConstants.h"
+
+using namespace vf::basics::constant;
+
 
 namespace grid_generator
 {
@@ -91,16 +95,16 @@ namespace grid_generator
         .def("set_pressure_boundary_condition", &LevelGridBuilder::setPressureBoundaryCondition, py::arg("side_type"), py::arg("rho"))
         .def("set_periodic_boundary_condition", &LevelGridBuilder::setPeriodicBoundaryCondition, py::arg("periodic_x"), py::arg("periodic_y"), py::arg("periodic_z"))
         .def("set_no_slip_boundary_condition", &LevelGridBuilder::setNoSlipBoundaryCondition, py::arg("side_type"))
-        .def("set_precursor_boundary_condition", &LevelGridBuilder::setPrecursorBoundaryCondition, py::arg("side_type"), py::arg("file_collection"), py::arg("n_t_read"), py::arg("velocity_x")=0.0f, py::arg("velocity_y")=0.0f, py::arg("velocity_z")=0.0f, py::arg("file_level_to_grid_level_map")=std::vector<uint>())
+        .def("set_precursor_boundary_condition", &LevelGridBuilder::setPrecursorBoundaryCondition, py::arg("side_type"), py::arg("file_collection"), py::arg("n_t_read"), py::arg("velocity_x")=c0o1, py::arg("velocity_y")=c0o1, py::arg("velocity_z")=c0o1, py::arg("file_level_to_grid_level_map")=std::vector<uint>())
         .def("set_stress_boundary_condition", &LevelGridBuilder::setStressBoundaryCondition, py::arg("side_type"), py::arg("normal_x"), py::arg("normal_y"), py::arg("normal_z"), py::arg("sampling_offset"), py::arg("z0"), py::arg("dx"));
 
         py::class_<MultipleGridBuilder, LevelGridBuilder, std::shared_ptr<MultipleGridBuilder>>(gridGeneratorModule, "MultipleGridBuilder")
         .def_static("make_shared", &MultipleGridBuilder::makeShared, py::return_value_policy::reference, py::arg("grid_factory"))
         .def("add_coarse_grid", &MultipleGridBuilder::addCoarseGrid, py::arg("start_x"), py::arg("start_y"), py::arg("start_z"), py::arg("end_x"), py::arg("end_y"), py::arg("end_z"), py::arg("delta"))
-        .def("add_grid", py::overload_cast<Object*>(&MultipleGridBuilder::addGrid), py::arg("grid_shape"))
-        .def("add_grid", py::overload_cast<Object*, uint>(&MultipleGridBuilder::addGrid), py::arg("grid_shape"), py::arg("level_fine"))
-        .def("add_geometry", py::overload_cast<Object*>(&MultipleGridBuilder::addGeometry), py::arg("solid_object"))
-        .def("add_geometry", py::overload_cast<Object*, uint>(&MultipleGridBuilder::addGeometry), py::arg("solid_object"), py::arg("level"))
+        .def("add_grid", py::overload_cast<SPtr<Object>>(&MultipleGridBuilder::addGrid), py::arg("grid_shape"))
+        .def("add_grid", py::overload_cast<SPtr<Object>, uint>(&MultipleGridBuilder::addGrid), py::arg("grid_shape"), py::arg("level_fine"))
+        .def("add_geometry", py::overload_cast<SPtr<Object>>(&MultipleGridBuilder::addGeometry), py::arg("solid_object"))
+        .def("add_geometry", py::overload_cast<SPtr<Object>, uint>(&MultipleGridBuilder::addGeometry), py::arg("solid_object"), py::arg("level"))
         .def("get_number_of_levels", &MultipleGridBuilder::getNumberOfLevels)
         .def("build_grids", &MultipleGridBuilder::buildGrids, py::arg("enable_thin_walls"))
         .def("set_subdomain_box", &MultipleGridBuilder::setSubDomainBox, py::arg("bounding_box"))
diff --git a/pythonbindings/src/gpu/submodules/probes.cpp b/pythonbindings/src/gpu/submodules/probes.cpp
index 7c26958df81a60f00c9909a91f5576a5931652d4..9c3fc8ab15234013a093dbe00f6654ea3257d4b0 100644
--- a/pythonbindings/src/gpu/submodules/probes.cpp
+++ b/pythonbindings/src/gpu/submodules/probes.cpp
@@ -72,13 +72,16 @@ namespace probes
                         uint,
                         uint, 
                         uint,
-                        uint>(), 
+                        uint,
+                        bool>(), 
                         py::arg("probe_name"),
                         py::arg("output_path"),
                         py::arg("t_start_avg"),
                         py::arg("t_avg"),
                         py::arg("t_start_out"),
-                        py::arg("t_out"))
+                        py::arg("t_out"),
+                        py::arg("output_timeseries"))
+        .def("add_probe_point", &PointProbe::addProbePoint, py::arg("point_coord_x"), py::arg("point_coord_y"), py::arg("point_coord_z"))
         .def("add_probe_points_from_list", &PointProbe::addProbePointsFromList, py::arg("point_coords_x"), py::arg("point_coords_y"), py::arg("point_coords_z"))
         .def("add_probe_points_from_x_normal_plane", &PointProbe::addProbePointsFromXNormalPlane, py::arg("pos_x"), py::arg("pos0_y"), py::arg("pos0_z"), py::arg("pos1_y"), py::arg("pos1_z"), py::arg("n_y"), py::arg("n_z"));
 
diff --git a/pythonbindings/src/lbm/lbm.cpp b/pythonbindings/src/lbm.cpp
similarity index 93%
rename from pythonbindings/src/lbm/lbm.cpp
rename to pythonbindings/src/lbm.cpp
index 90fd4a71b0101469666936c89974de316e0e2b18..622cc9742fdaa98f2ff6d974e495e6b8b490a2c2 100644
--- a/pythonbindings/src/lbm/lbm.cpp
+++ b/pythonbindings/src/lbm.cpp
@@ -32,14 +32,11 @@
 //=======================================================================================
 #include <pybind11/pybind11.h>
 
-namespace lbm
+namespace lbm_bindings
 {
     namespace py = pybind11;
 
-    py::module makeModule(py::module_ &parentModule)
+    PYBIND11_MODULE(lbm, m)
     {
-        py::module lbmModule = parentModule.def_submodule("lbm");
-
-        return lbmModule;
     }
 }
\ No newline at end of file
diff --git a/pythonbindings/src/logger/logger.cpp b/pythonbindings/src/logger.cpp
similarity index 73%
rename from pythonbindings/src/logger/logger.cpp
rename to pythonbindings/src/logger.cpp
index c4c99c0a5077303b398e0726eaba0420ddb0dceb..367ae693475eca064c128de47c88e56fca91a58e 100644
--- a/pythonbindings/src/logger/logger.cpp
+++ b/pythonbindings/src/logger.cpp
@@ -33,25 +33,23 @@
 #include <pybind11/pybind11.h>
 #include <logger/Logger.h>
 
-namespace logging
+namespace logger_bindings
 {
+
     namespace py = pybind11;
 
-    py::module makeModule(py::module_ &parentModule)
+    PYBIND11_MODULE(logger, m)
     {
-        py::module loggerModule = parentModule.def_submodule("logger");
-
-        py::class_<vf::logging::Logger>(loggerModule, "Logger")
+        py::class_<vf::logging::Logger>(m, "Logger")
         .def_static("initialize_logger", &vf::logging::Logger::initializeLogger)
         .def_static("change_log_path", &vf::logging::Logger::changeLogPath, py::arg("path"));
 
         // use f-strings (f"text {float}") in python for compounded messages
-        loggerModule.def("vf_log_trace", [](std::string message){ VF_LOG_TRACE(message); }, py::arg("message"));        
-        loggerModule.def("vf_log_debug", [](std::string message){ VF_LOG_DEBUG(message); }, py::arg("message"));        
-        loggerModule.def("vf_log_info", [](std::string message){ VF_LOG_INFO(message); }, py::arg("message"));        
-        loggerModule.def("vf_log_warning", [](std::string message){ VF_LOG_WARNING(message); }, py::arg("message"));        
-        loggerModule.def("vf_log_critical", [](std::string message){ VF_LOG_CRITICAL(message); }, py::arg("message"));        
-
-        return loggerModule;
+        m.def("vf_log_trace", [](std::string message){ VF_LOG_TRACE(message); }, py::arg("message"));        
+        m.def("vf_log_debug", [](std::string message){ VF_LOG_DEBUG(message); }, py::arg("message"));        
+        m.def("vf_log_info", [](std::string message){ VF_LOG_INFO(message); }, py::arg("message"));        
+        m.def("vf_log_warning", [](std::string message){ VF_LOG_WARNING(message); }, py::arg("message"));        
+        m.def("vf_log_critical", [](std::string message){ VF_LOG_CRITICAL(message); }, py::arg("message"));       
     }
-} // namespace logging
+}
+
diff --git a/regression-tests/flow_around_cylinder_test.sh b/regression-tests/flow_around_cylinder_test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..63f90886b79002dcffe6beb24e626922ca95fe78
--- /dev/null
+++ b/regression-tests/flow_around_cylinder_test.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+source ./regression-tests/__regression_test_executer.sh
+
+
+# 1. set reference data directory (must match the folder structure in https://github.com/irmb/test_data)
+REFERENCE_DATA_DIR=regression_tests/cpu/FlowAroundCylinder_2023_04
+
+# 2. set cmake flags for the build of VirtualFluids
+CMAKE_FLAGS="--preset=make_cpu -DCMAKE_BUILD_TYPE=Release"
+
+# 3. define the application to be executed
+APPLICATION="./build/bin/FlowAroundCylinder ./apps/cpu/FlowAroundCylinder/cylinder.cfg"
+
+# 4. set the path to the produced data
+RESULT_DATA_DIR=output/FlowAroundCylinder
+
+
+run_regression_test "$REFERENCE_DATA_DIR" "$CMAKE_FLAGS" "$APPLICATION" "$RESULT_DATA_DIR"
diff --git a/regression-tests/multigpu_test/rocket4GPU.yml b/regression-tests/multigpu_test/rocket4GPU.yml
index 33b7178372f0ce869565e8eee567a75ac8759ee4..a7ece055707c26a7a27e9c12be3447dc1b77855f 100755
--- a/regression-tests/multigpu_test/rocket4GPU.yml
+++ b/regression-tests/multigpu_test/rocket4GPU.yml
@@ -37,7 +37,7 @@ copy:
 
 collect:
   - from: multigpu_test/output/4GPU/
-    to: output/4GPU
+    to: output/4GPU/
     overwrite: true
 
   - from: multigpu_test/slurm4GPU.out
@@ -45,8 +45,7 @@ collect:
     overwrite: true
 
 clean:
-  - multigpu_test/output/*
-  - multigpu_test/src/*
+  - multigpu_test/*
 
 sbatch: multigpu_test/slurm4GPU.job
 continue_if_job_fails: true
diff --git a/regression-tests/multigpu_test/rocket8GPU.yml b/regression-tests/multigpu_test/rocket8GPU.yml
index 9c59b4ce52984ad552bb3d32233a4d694589721f..4b434fc8a2433dab513649800dbe3f160d986edd 100755
--- a/regression-tests/multigpu_test/rocket8GPU.yml
+++ b/regression-tests/multigpu_test/rocket8GPU.yml
@@ -37,7 +37,7 @@ copy:
 
 collect:
   - from: multigpu_test/output/8GPU/
-    to: output/8GPU
+    to: output/8GPU/
     overwrite: true
 
   - from: multigpu_test/slurm8GPU.out
@@ -45,8 +45,7 @@ collect:
     overwrite: true
 
 clean:
-  - multigpu_test/output/*
-  - multigpu_test/src/*
+  - multigpu_test/*
 
 sbatch: multigpu_test/slurm8GPU.job
 continue_if_job_fails: true
diff --git a/regression-tests/multigpu_test/slurm4GPU.job b/regression-tests/multigpu_test/slurm4GPU.job
index 70b33f07f4a4a7be7f5b50990098f3322238af4a..0be42c51bac9a341b56eb705f9bdb518883f507d 100755
--- a/regression-tests/multigpu_test/slurm4GPU.job
+++ b/regression-tests/multigpu_test/slurm4GPU.job
@@ -2,14 +2,19 @@
 
 #SBATCH --partition=gpu01_queue
 #SBATCH --nodes=1
-#SBATCH --time=10:00:00
+#SBATCH --time=03:00:00
 #SBATCH --job-name=Regr4GPU
 #SBATCH --ntasks-per-node=4
 #SBATCH --gres=gpu:4
 #SBATCH --output=multigpu_test/slurm4GPU.out
 ##SBATCH --exclusive
 
-module purge 
+echo "SLURM_JOBID="$SLURM_JOBID
+echo "SLURM_JOB_NODELIST"=$SLURM_JOB_NODELIST
+echo "SLURM_NNODES"=$SLURM_NNODES
+echo "SLURM_TASKS_PER_NODE"=$SLURM_TASKS_PER_NODE
+
+module purge
 module load comp/gcc/10.2.0
 module load mpi/openmpi/4.0.5_gcc_9.3/openmpi
 module load cuda/11.3
@@ -19,7 +24,7 @@ PATH=/home/irmb/tools/cmake-3.20.3-linux-x86_64/bin:$PATH
 module list
 
 cd multigpu_test
-rm -r build && mkdir -p build
+rm -rf build && mkdir -p build
 cd build
 cmake .. -DBUILD_VF_GPU=ON -DCMAKE_CUDA_ARCHITECTURES=60 -DUSER_APPS=apps/gpu/LBM/DrivenCavityMultiGPU\;apps/gpu/LBM/SphereScaling
 make -j 16
diff --git a/regression-tests/multigpu_test/slurm8GPU.job b/regression-tests/multigpu_test/slurm8GPU.job
index b91d7d473d935d4d0fbe8deba344dbaa58cf5080..bb7bf55c70eb6b178eff3f52e18c35d7cafd6938 100755
--- a/regression-tests/multigpu_test/slurm8GPU.job
+++ b/regression-tests/multigpu_test/slurm8GPU.job
@@ -2,14 +2,19 @@
 
 #SBATCH --partition=gpu01_queue
 #SBATCH --nodes=2
-#SBATCH --time=10:00:00
+#SBATCH --time=03:00:00
 #SBATCH --job-name=Regr8GPU
 #SBATCH --ntasks-per-node=4
 #SBATCH --gres=gpu:4
 #SBATCH --output=multigpu_test/slurm8GPU.out
 ##SBATCH --exclusive
 
-module purge 
+echo "SLURM_JOBID="$SLURM_JOBID
+echo "SLURM_JOB_NODELIST"=$SLURM_JOB_NODELIST
+echo "SLURM_NNODES"=$SLURM_NNODES
+echo "SLURM_TASKS_PER_NODE"=$SLURM_TASKS_PER_NODE
+
+module purge
 module load comp/gcc/10.2.0
 module load mpi/openmpi/4.0.5_gcc_9.3/openmpi
 module load cuda/11.3
@@ -19,7 +24,7 @@ PATH=/home/irmb/tools/cmake-3.20.3-linux-x86_64/bin:$PATH
 module list
 
 cd multigpu_test
-rm -r build && mkdir -p build
+rm -rf build && mkdir -p build
 cd build
 cmake .. -DBUILD_VF_GPU=ON -DCMAKE_CUDA_ARCHITECTURES=60 -DUSER_APPS=apps/gpu/LBM/DrivenCavityMultiGPU\;apps/gpu/LBM/SphereScaling
 make -j 16
diff --git a/regression-tests/multigpu_test/utilities/parsejobid.py b/regression-tests/multigpu_test/utilities/parsejobid.py
new file mode 100644
index 0000000000000000000000000000000000000000..f209f6d3d0ac20243a94d16f89d2aaddeeae24f7
--- /dev/null
+++ b/regression-tests/multigpu_test/utilities/parsejobid.py
@@ -0,0 +1,20 @@
+from pathlib import Path
+import sys
+
+LAUNCH_MESSAGE = "Launched job"
+
+
+def parsejobid(file: str) -> str:
+    file_path = Path(file)
+    if not file_path.exists():
+        raise FileNotFoundError(file)
+
+    text_content = file_path.read_text().strip()
+    launch_line = next(
+        filter(lambda line: LAUNCH_MESSAGE in line, text_content.splitlines())
+    )
+    return launch_line.split()[-1].strip()
+
+
+if __name__ == "__main__":
+    print(parsejobid(sys.argv[1]))
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 5894f9dec06953c3eeb909af96db9cb19d202d65..0000000000000000000000000000000000000000
--- a/setup.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-[metadata]
-name = pyfluids
-description = Python binding for VirtualFluids
-long_description = file: README.md
-long_description_content_type = text/markdown
-platforms = any
-url = https://git.rz.tu-bs.de/irmb/virtualfluids
-version = 0.1.0
-
-[options]
-python_requires = >=3.6
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 530431b3775970b5222bc87d32bfb407363f95d6..0000000000000000000000000000000000000000
--- a/setup.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import sys
-from pathlib import Path
-from typing import List
-
-import skbuild
-
-"""
-Install python wrapper of Virtual Fluids
-install via python:
-    python setup.py install
-    set CMAKE Flags via -DBUILD_VF_GPU:BOOL=ON
-    CMAKE flags have to be separated by -- 
-    example: python setup.py install -- -DBUILD_VF_CPU:BOOL=ON
-or install via pip:
-    pip install .
-    for pip>21:
-        set CMAKE Flags via --config-settings "-DBUILD_VF_GPU=ON"
-        example: pip install . --config-settings="-DBUILD_VF_GPU=ON"
-        each option has to be passed in individually i.e --config-settings="-DOPT1=ON" --config-settings="-DOPT2=OFF"
-    for pip <21:
-        set CMAKE Flags via --global-option ="-DBUILD_VF_GPU=ON"
-        example: pip install . --global-option="-DBUILD_VF_GPU=ON"
-"""
-
-package_name = "pyfluids"
-target = "python_bindings"
-src_dir = "pythonbindings"
-stub_package = package_name+"-stubs"
-
-stub_dir = Path(src_dir)/stub_package
-
-
-def add_subfiles(dir_path: Path, suffix: str, root_dir: Path) -> List[str]:
-    files = []
-    for f in dir_path.iterdir():
-        if f.is_dir():
-            files.extend(add_subfiles(f, suffix, root_dir))
-        if f.is_file():
-            if f.suffix != suffix:
-                continue
-            files.append(str(f.relative_to(root_dir)))
-    return files
-
-def add_directory(dir_path: Path, suffix: str):
-    return add_subfiles(dir_path, suffix, dir_path)
-
-stub_files = add_directory(stub_dir, ".pyi")
-
-# hack to get config-args for installation with pip>21
-cmake_args = []
-if "config_args" in locals():
-    cmake_args.extend([f"{k}={v}" for k, v in locals()["config_args"].items()])
-
-cmake_args += [
-        f"-DPython3_ROOT_DIR={Path(sys.prefix)}",
-        "-DBUILD_VF_PYTHON_BINDINGS=ON",
-        "-DBUILD_SHARED_LIBS=OFF",
-        "-DBUILD_VF_DOUBLE_ACCURACY=OFF",
-        "-DBUILD_VF_UNIT_TESTS:BOOL=OFF",
-        "-DBUILD_WARNINGS_AS_ERRORS=OFF",
-    ]
-
-skbuild.setup(
-    name=package_name,
-    packages=[package_name, "pymuparser", "pyfluids-stubs"],
-    package_dir={"": src_dir},
-    cmake_args=cmake_args,
-    cmake_install_target=target,
-    package_data={  "pyfluids": ["py.typed"],
-                    "pyfluids-stubs": stub_files},
-    include_package_data=True,
-)
diff --git a/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolationProcessor.cpp b/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolator.cpp
similarity index 94%
rename from src/cpu/NonNewtonianFluids/LBM/RheologyInterpolationProcessor.cpp
rename to src/cpu/NonNewtonianFluids/LBM/RheologyInterpolator.cpp
index 0a9c380dece3ba90f7d2d3d5d2a84ceadfcf4850..8da8886a42b0a9f9c784eca708618217f06c883a 100644
--- a/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolationProcessor.cpp
+++ b/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolator.cpp
@@ -26,51 +26,46 @@
 //  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 RheologyInterpolationProcessor.cpp
+//! \file RheologyInterpolator.cpp
 //! \ingroup LBM
 //! \author Konstantin Kutscher
 //=======================================================================================
 
-#include "RheologyInterpolationProcessor.h"
+#include "RheologyInterpolator.h"
 #include "D3Q27System.h"
 #include "Rheology.h"
 
 
-RheologyInterpolationProcessor::RheologyInterpolationProcessor()
+RheologyInterpolator::RheologyInterpolator()
    : omegaC(0.0), omegaF(0.0), omegaMin(0.0)
 {
 
 }
 //////////////////////////////////////////////////////////////////////////
-RheologyInterpolationProcessor::RheologyInterpolationProcessor(real omegaC, real omegaF, real omegaMin)
+RheologyInterpolator::RheologyInterpolator(real omegaC, real omegaF, real omegaMin)
    : omegaC(omegaC), omegaF(omegaF), omegaMin(omegaMin)
 {
 
 }
 //////////////////////////////////////////////////////////////////////////
-RheologyInterpolationProcessor::~RheologyInterpolationProcessor()
+InterpolationProcessorPtr RheologyInterpolator::clone()
 {
-
-}
-//////////////////////////////////////////////////////////////////////////
-InterpolationProcessorPtr RheologyInterpolationProcessor::clone()
-{
-   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new RheologyInterpolationProcessor(this->omegaC, this->omegaF, this->omegaMin));
+   InterpolationProcessorPtr iproc = std::make_shared<RheologyInterpolator>(this->omegaC, this->omegaF, this->omegaMin);
    return iproc;
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::setOmegas( real omegaC, real omegaF )
+void RheologyInterpolator::setOmegas( real omegaC, real omegaF )
 {
    this->omegaC = omegaC;
    this->omegaF = omegaF;
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::setOmegaMin( real omegaMin )
+void RheologyInterpolator::setOmegaMin( real omegaMin )
 {
    this->omegaMin = omegaMin;
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::setOffsets(real xoff, real yoff, real zoff)
+void RheologyInterpolator::setOffsets(real xoff, real yoff, real zoff)
 {
    this->xoff = xoff;
    this->yoff = yoff;
@@ -80,7 +75,7 @@ void RheologyInterpolationProcessor::setOffsets(real xoff, real yoff, real zoff)
    this->zoff_sq = zoff * zoff;
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
+void RheologyInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
 {
     setOffsets(xoff, yoff, zoff);
     calcInterpolatedCoefficiets_intern(icellC, omegaC, 0.5, 0.25, -0.25, -0.25, -1, -1, -1);
@@ -101,14 +96,14 @@ void RheologyInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC,
     calcInterpolatedNode(icellF.TNE, /*omegaF,*/  0.25,  0.25,  0.25, calcPressTNE(),  1,  1,  1);
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
+void RheologyInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
 {
    setOffsets(xoff, yoff, zoff);
     calcInterpolatedCoefficiets_intern(icellF, omegaF, 2.0, 0, 0, 0, 0, 0, 0);
    calcInterpolatedNodeFC(icellC, omegaC);
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::calcMoments(const real* const f, real omegaInf, real& press, real& vx1, real& vx2, real& vx3, real& kxy, real& kyz, real& kxz, real& kxxMyy, real& kxxMzz)
+void RheologyInterpolator::calcMoments(const real* const f, real omegaInf, real& press, real& vx1, real& vx2, real& vx3, real& kxy, real& kyz, real& kxz, real& kxxMyy, real& kxxMzz)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -129,7 +124,7 @@ void RheologyInterpolationProcessor::calcMoments(const real* const f, real omega
    kxxMzz = -3./2.*omega*((((f[DIR_MP0]+f[DIR_PM0])-(f[DIR_0MM]+f[DIR_0PP]))+((f[DIR_MM0]+f[DIR_PP0])-(f[DIR_0MP]+f[DIR_0PM])))+((f[DIR_M00]+f[DIR_P00])-(f[DIR_00M]+f[DIR_00P]))-(vx1*vx1-vx3*vx3));
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::calcInterpolatedCoefficiets_intern(const D3Q27ICell& icell,
+void RheologyInterpolator::calcInterpolatedCoefficiets_intern(const D3Q27ICell& icell,
                                                                           real omega,
                                                                           real eps_new,
                                                                           real x,
@@ -432,7 +427,7 @@ void RheologyInterpolationProcessor::calcInterpolatedCoefficiets_intern(const D3
    yz_TNW =   0.0625*eps_new *((                bxyz +     cxyz)/(72.*o));
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::calcInterpolatedNode(real* f, /*real omega,*/ real x, real y, real z, real press, real xs, real ys, real zs)
+void RheologyInterpolator::calcInterpolatedNode(real* f, /*real omega,*/ real x, real y, real z, real press, real xs, real ys, real zs)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -475,7 +470,7 @@ void RheologyInterpolationProcessor::calcInterpolatedNode(real* f, /*real omega,
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SWB -0.25, -0.25, -0.25
-real RheologyInterpolationProcessor::calcPressBSW()
+real RheologyInterpolator::calcPressBSW()
 {
    return   press_SWT * (0.140625 + 0.1875 * xoff + 0.1875 * yoff - 0.5625 * zoff) +
       press_NWT * (0.046875 + 0.0625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
@@ -488,7 +483,7 @@ real RheologyInterpolationProcessor::calcPressBSW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SWT -0.25, -0.25, 0.25
-real RheologyInterpolationProcessor::calcPressTSW()
+real RheologyInterpolator::calcPressTSW()
 {
    return   press_SWT * (0.421875 + 0.5625 * xoff + 0.5625 * yoff - 0.5625 * zoff) +
       press_NWT * (0.140625 + 0.1875 * xoff - 0.5625 * yoff - 0.1875 * zoff) +
@@ -501,7 +496,7 @@ real RheologyInterpolationProcessor::calcPressTSW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SET 0.25, -0.25, 0.25
-real RheologyInterpolationProcessor::calcPressTSE()
+real RheologyInterpolator::calcPressTSE()
 {
    return   press_SET * (0.421875 - 0.5625 * xoff + 0.5625 * yoff - 0.5625 * zoff) +
       press_NET * (0.140625 - 0.1875 * xoff - 0.5625 * yoff - 0.1875 * zoff) +
@@ -514,7 +509,7 @@ real RheologyInterpolationProcessor::calcPressTSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SEB 0.25, -0.25, -0.25
-real RheologyInterpolationProcessor::calcPressBSE()
+real RheologyInterpolator::calcPressBSE()
 {
    return   press_SET * (0.140625 - 0.1875 * xoff + 0.1875 * yoff - 0.5625 * zoff) +
       press_NET * (0.046875 - 0.0625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
@@ -527,7 +522,7 @@ real RheologyInterpolationProcessor::calcPressBSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWB -0.25, 0.25, -0.25
-real RheologyInterpolationProcessor::calcPressBNW()
+real RheologyInterpolator::calcPressBNW()
 {
    return   press_NWT * (0.140625 + 0.1875 * xoff - 0.1875 * yoff - 0.5625 * zoff) +
       press_NET * (0.046875 - 0.1875 * xoff - 0.0625 * yoff - 0.1875 * zoff) +
@@ -540,7 +535,7 @@ real RheologyInterpolationProcessor::calcPressBNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWT -0.25, 0.25, 0.25
-real RheologyInterpolationProcessor::calcPressTNW()
+real RheologyInterpolator::calcPressTNW()
 {
    return   press_NWT * (0.421875 + 0.5625 * xoff - 0.5625 * yoff - 0.5625 * zoff) +
       press_NET * (0.140625 - 0.5625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
@@ -553,7 +548,7 @@ real RheologyInterpolationProcessor::calcPressTNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NET 0.25, 0.25, 0.25
-real RheologyInterpolationProcessor::calcPressTNE()
+real RheologyInterpolator::calcPressTNE()
 {
    return   press_NET * (0.421875 - 0.5625 * xoff - 0.5625 * yoff - 0.5625 * zoff) +
       press_NWT * (0.140625 + 0.5625 * xoff - 0.1875 * yoff - 0.1875 * zoff) +
@@ -566,7 +561,7 @@ real RheologyInterpolationProcessor::calcPressTNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NEB 0.25, 0.25, -0.25
-real RheologyInterpolationProcessor::calcPressBNE()
+real RheologyInterpolator::calcPressBNE()
 {
    return   press_NET * (0.140625 - 0.1875 * xoff - 0.1875 * yoff - 0.5625 * zoff) +
       press_NWT * (0.046875 + 0.1875 * xoff - 0.0625 * yoff - 0.1875 * zoff) +
@@ -579,7 +574,7 @@ real RheologyInterpolationProcessor::calcPressBNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position C 0.0, 0.0, 0.0
-void RheologyInterpolationProcessor::calcInterpolatedNodeFC(real* f, real omega)
+void RheologyInterpolator::calcInterpolatedNodeFC(real* f, real omega)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -664,14 +659,14 @@ void RheologyInterpolationProcessor::calcInterpolatedNodeFC(real* f, real omega)
    f[DIR_000] = f_ZERO + feq[DIR_000];
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
+void RheologyInterpolator::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
 {
 	vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z+axyz*x*y*z;
 	vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z+bxyz*x*y*z;
 	vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z+cxyz*x*y*z;
 }
 //////////////////////////////////////////////////////////////////////////
-void RheologyInterpolationProcessor::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
+void RheologyInterpolator::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
 {
 	tauxx=ax+2*axx*x+axy*y+axz*z+axyz*y*z;
 	tauyy=by+2*byy*y+bxy*x+byz*z+bxyz*x*z;
diff --git a/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolationProcessor.h b/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolator.h
similarity index 89%
rename from src/cpu/NonNewtonianFluids/LBM/RheologyInterpolationProcessor.h
rename to src/cpu/NonNewtonianFluids/LBM/RheologyInterpolator.h
index 178932204307606b9fc48d2745ebf1353547e3e8..4b9391df278dc3e69a08df8a1400e3871ca7f067 100644
--- a/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolationProcessor.h
+++ b/src/cpu/NonNewtonianFluids/LBM/RheologyInterpolator.h
@@ -26,24 +26,23 @@
 //  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 RheologyInterpolationProcessor.h
+//! \file RheologyInterpolator.h
 //! \ingroup LBM
 //! \author Konstantin Kutscher
 //=======================================================================================
-#ifndef RheologyInterpolationProcessor_H_
-#define RheologyInterpolationProcessor_H_
+#ifndef RheologyInterpolator_H_
+#define RheologyInterpolator_H_
 
-#include "InterpolationProcessor.h"
+#include "Interpolation/Interpolator.h"
 #include "D3Q27System.h"
 
 //! \brief A class implements an interpolation function of grid refinement for thixotropic fluid.
 
-class RheologyInterpolationProcessor : public InterpolationProcessor
+class RheologyInterpolator : public Interpolator
 {
 public:
-   RheologyInterpolationProcessor();
-   RheologyInterpolationProcessor(real omegaC, real omegaF, real omegaMin);
-   virtual ~RheologyInterpolationProcessor();
+   RheologyInterpolator();
+   RheologyInterpolator(real omegaC, real omegaF, real omegaMin);
    InterpolationProcessorPtr clone();
    void setOmegas(real omegaC, real omegaF);
    void setOmegaMin(real omegaMin);
@@ -94,12 +93,12 @@ private:
 };
 
 //////////////////////////////////////////////////////////////////////////
-inline void RheologyInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
+inline void RheologyInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
 {
    this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
 }
 //////////////////////////////////////////////////////////////////////////
-inline void RheologyInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
+inline void RheologyInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
 {
    this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
 }
diff --git a/src/cpu/NonNewtonianFluids/LBM/RheologyK17LBMKernel.cpp b/src/cpu/NonNewtonianFluids/LBM/RheologyK17LBMKernel.cpp
index a9c7a05da6eefb4f44834d1c91f5e5b43d4f5eb4..2981156c4a5f6acc0df336d9d66cc9a9e97d8c1a 100644
--- a/src/cpu/NonNewtonianFluids/LBM/RheologyK17LBMKernel.cpp
+++ b/src/cpu/NonNewtonianFluids/LBM/RheologyK17LBMKernel.cpp
@@ -33,7 +33,7 @@
 
 #include "RheologyK17LBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <math.h>
 #include "DataSet3D.h"
diff --git a/src/cpu/NonNewtonianFluids/LBM/ThixotropyExpLBMKernel.cpp b/src/cpu/NonNewtonianFluids/LBM/ThixotropyExpLBMKernel.cpp
index cbfa924405109fa03dfef6532c538fb2917d2d43..a55ee9a28740843a4bf3c8587b3afb5f348c2759 100644
--- a/src/cpu/NonNewtonianFluids/LBM/ThixotropyExpLBMKernel.cpp
+++ b/src/cpu/NonNewtonianFluids/LBM/ThixotropyExpLBMKernel.cpp
@@ -1,6 +1,6 @@
 #include "ThixotropyExpLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <math.h>
 #include "DataSet3D.h"
diff --git a/src/cpu/NonNewtonianFluids/LBM/ThixotropyLBMKernel.cpp b/src/cpu/NonNewtonianFluids/LBM/ThixotropyLBMKernel.cpp
index 368436088dc72bb10677f046aa9e954f9120be42..f764af6f5cd75b67ce51f8644d9f1839894fcdc3 100644
--- a/src/cpu/NonNewtonianFluids/LBM/ThixotropyLBMKernel.cpp
+++ b/src/cpu/NonNewtonianFluids/LBM/ThixotropyLBMKernel.cpp
@@ -1,6 +1,6 @@
 #include "ThixotropyLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <math.h>
 #include "DataSet3D.h"
diff --git a/src/cpu/NonNewtonianFluids/NonNewtonianFluids.h b/src/cpu/NonNewtonianFluids/NonNewtonianFluids.h
index 169082259b203b195b7fc636d84cdd4029ce6ccf..16492a081134ac81b691f0e79160874075b6c10d 100644
--- a/src/cpu/NonNewtonianFluids/NonNewtonianFluids.h
+++ b/src/cpu/NonNewtonianFluids/NonNewtonianFluids.h
@@ -18,7 +18,7 @@
 #include "NonNewtonianFluids/LBM/ThixotropyExpLBMKernel.h"
 #include "NonNewtonianFluids/LBM/RheologyBinghamModelLBMKernel.h"
 #include "NonNewtonianFluids/LBM/RheologyHerschelBulkleyModelLBMKernel.h"
-#include "NonNewtonianFluids/LBM/RheologyInterpolationProcessor.h"
+#include "NonNewtonianFluids/LBM/RheologyInterpolator.h"
 #include "NonNewtonianFluids/LBM/Rheology.h"
 #include "NonNewtonianFluids/LBM/RheologyK17LBMKernel.h"
 #include "NonNewtonianFluids/LBM/RheologyPowellEyringModelLBMKernel.h"
diff --git a/src/cpu/VirtualFluids.h b/src/cpu/VirtualFluids.h
index 6fa9b30bfc0e650f289d00a2970bdff545c71359..d8f79867c20ff1df40a15a6e437012246a4e5b00 100644
--- a/src/cpu/VirtualFluids.h
+++ b/src/cpu/VirtualFluids.h
@@ -208,14 +208,11 @@
 #include <TimeDependentBCSimulationObserver.h>
 
 #include <IntegrateValuesHelper.h>
-//#include <LBM/D3Q27CompactInterpolationProcessor.h>
-#include <LBM/CompressibleOffsetInterpolationProcessor.h>
-#include <LBM/CompressibleOffsetMomentsInterpolationProcessor.h>
-#include <LBM/CompressibleOffsetSquarePressureInterpolationProcessor.h>
-#include <LBM/IncompressibleOffsetInterpolationProcessor.h>
-#include <LBM/InterpolationHelper.h>
-#include <LBM/InterpolationProcessor.h>
-//#include <LBM/D3Q27OffsetInterpolationProcessor.h>
+#include <LBM/Interpolation/CompressibleOffsetInterpolator.h>
+#include <LBM/Interpolation/CompressibleOffsetMomentsInterpolator.h>
+#include <LBM/Interpolation/CompressibleOffsetSquarePressureInterpolator.h>
+#include <LBM/Interpolation/IncompressibleOffsetInterpolator.h>
+#include <LBM/Interpolation/Interpolator.h>
 #include <IncompressibleCumulantWithSpongeLayerLBMKernel.h>
 #include <LBM/CompressibleCumulant4thOrderViscosityLBMKernel.h>
 #include <LBM/CompressibleCumulantLBMKernel.h>
@@ -223,7 +220,6 @@
 #include <LBM/ICell.h>
 #include <LBM/IncompressibleCumulantLBMKernel.h>
 #include <LBM/InitDensityLBMKernel.h>
-#include <LBM/InterpolationProcessor.h>
 #include <LBM/LBMKernel.h>
 #include <LBM/LBMKernelETD3Q27BGK.h>
 #include <LBM/LBMSystem.h>
diff --git a/src/cpu/VirtualFluidsCore/CMakeLists.txt b/src/cpu/VirtualFluidsCore/CMakeLists.txt
index 9f3cd96e889097a32ce737e56e3f1fa31dddaee0..aae663e80011c117a83d5a52d0ac0cbe0c59a5a8 100644
--- a/src/cpu/VirtualFluidsCore/CMakeLists.txt
+++ b/src/cpu/VirtualFluidsCore/CMakeLists.txt
@@ -31,6 +31,7 @@ target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Co
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Data)
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Interactors)
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/LBM)
+target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/LBM/Interpolation)
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Parallel)
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Simulation)
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Visitors)
diff --git a/src/cpu/VirtualFluidsCore/Connectors/CoarseToFineVectorConnector.h b/src/cpu/VirtualFluidsCore/Connectors/CoarseToFineVectorConnector.h
index d7f9f72c4f86f5d849fa4f2c0cd703333007091a..3c63750440bf5b8da2b81eec0fc32cde88e6515a 100644
--- a/src/cpu/VirtualFluidsCore/Connectors/CoarseToFineVectorConnector.h
+++ b/src/cpu/VirtualFluidsCore/Connectors/CoarseToFineVectorConnector.h
@@ -40,7 +40,7 @@
 #include "Block3DConnector.h"
 #include "D3Q27System.h"
 #include "Grid3D.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "LBMKernel.h"
 #include "MathUtil.hpp"
 #include "basics/container/CbVector.h"
diff --git a/src/cpu/VirtualFluidsCore/Connectors/FineToCoarseVectorConnector.h b/src/cpu/VirtualFluidsCore/Connectors/FineToCoarseVectorConnector.h
index ffab5008241e7f8f4457c7385c83872a296ee748..f9ce668e9b370513c42fb54a4dcff2c8ddfff898 100644
--- a/src/cpu/VirtualFluidsCore/Connectors/FineToCoarseVectorConnector.h
+++ b/src/cpu/VirtualFluidsCore/Connectors/FineToCoarseVectorConnector.h
@@ -40,7 +40,7 @@
 #include "Block3DConnector.h"
 #include "D3Q27System.h"
 #include "Grid3D.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "LBMKernel.h"
 #include "MathUtil.hpp"
 #include "basics/transmitter/TbTransmitter.h"
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulant4thOrderViscosityLBMKernel.cpp b/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulant4thOrderViscosityLBMKernel.cpp
index 421f81a1ac3301d982178a06b4b8c6378f626e57..c6349de8f1d281d31d0be4e684c54da457d3029f 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulant4thOrderViscosityLBMKernel.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulant4thOrderViscosityLBMKernel.cpp
@@ -1,6 +1,6 @@
 #include "CompressibleCumulant4thOrderViscosityLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <cmath>
 #include "DataSet3D.h"
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulantLBMKernel.cpp b/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulantLBMKernel.cpp
index 3c0795c21ed41c1f22dc06268e5fc1fa7922c845..ded8dff43910db33bd591cd4546f1dc73cc1110b 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulantLBMKernel.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/CompressibleCumulantLBMKernel.cpp
@@ -1,6 +1,6 @@
 #include "CompressibleCumulantLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include "DataSet3D.h"
 #include "Block3D.h"
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetMomentsInterpolationProcessor.cpp b/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetMomentsInterpolationProcessor.cpp
deleted file mode 100644
index 74527c0c39d5255a4ca3e647a288fffa027373ac..0000000000000000000000000000000000000000
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetMomentsInterpolationProcessor.cpp
+++ /dev/null
@@ -1,1292 +0,0 @@
-#include "CompressibleOffsetMomentsInterpolationProcessor.h"
-#include "D3Q27System.h"
-
-//using namespace UbMath;
-using namespace vf::basics::constant;
-
-CompressibleOffsetMomentsInterpolationProcessor::CompressibleOffsetMomentsInterpolationProcessor()
-    
-{
-   this->bulkViscosity = c0o1;
-   this->shearViscosity = c0o1;
-   this->OxxPyyPzzC = c1o1;
-   this->OxxPyyPzzF = c1o1;
-}
-//////////////////////////////////////////////////////////////////////////
-CompressibleOffsetMomentsInterpolationProcessor::CompressibleOffsetMomentsInterpolationProcessor(real omegaC, real omegaF)
-   : omegaC(omegaC), omegaF(omegaF)
-{
-   this->bulkViscosity = c0o1;
-   this->shearViscosity = c0o1;
-   this->OxxPyyPzzC = c1o1;
-   this->OxxPyyPzzF = c1o1;
-}
-//////////////////////////////////////////////////////////////////////////
-CompressibleOffsetMomentsInterpolationProcessor::~CompressibleOffsetMomentsInterpolationProcessor()
-= default;
-//////////////////////////////////////////////////////////////////////////
-InterpolationProcessorPtr CompressibleOffsetMomentsInterpolationProcessor::clone()
-{
-   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new CompressibleOffsetMomentsInterpolationProcessor(this->omegaC, this->omegaF));
-
-   dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iproc)->OxxPyyPzzC = this->OxxPyyPzzC;
-   dynamicPointerCast<CompressibleOffsetMomentsInterpolationProcessor>(iproc)->OxxPyyPzzF = this->OxxPyyPzzF;
-
-   return iproc;
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::setOmegas( real omegaC, real omegaF )
-{
-   this->omegaC = omegaC;
-   this->omegaF = omegaF;
-
-   real dtC = (c3o1 *shearViscosity)/((c1o1/omegaC)-c1o2);
-   real dtF = (c3o1 *shearViscosity)/((c1o1/omegaF)-c1o2);
-
-   if (bulkViscosity != 0)
-   {
-      this->OxxPyyPzzC = LBMSystem::calcOmega2(bulkViscosity, dtC);
-      this->OxxPyyPzzF = LBMSystem::calcOmega2(bulkViscosity, dtF);
-   }
-   else
-   {
-      this->OxxPyyPzzC = c1o1;
-      this->OxxPyyPzzF = c1o1;
-   }
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::setOffsets(real xoff, real yoff, real zoff)
-{
-   this->xoff = xoff;
-   this->yoff = yoff;
-   this->zoff = zoff;     
-   this->xoff_sq = xoff * xoff;
-   this->yoff_sq = yoff * yoff;
-   this->zoff_sq = zoff * zoff;
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
-{
-   setOffsets(xoff, yoff, zoff);
-   calcInterpolatedCoefficiets(icellC, omegaC, c1o2);
-   calcInterpolatedNodeCF(icellF.BSW, omegaF, -c1o4, -c1o4, -c1o4, calcPressBSW(), -c1o1, -c1o1, -c1o1);
-   calcInterpolatedNodeCF(icellF.BNE, omegaF,  c1o4,  c1o4, -c1o4, calcPressBNE(),  c1o1,  c1o1, -c1o1);
-   calcInterpolatedNodeCF(icellF.TNW, omegaF, -c1o4,  c1o4,  c1o4, calcPressTNW(), -c1o1,  c1o1,  c1o1);
-   calcInterpolatedNodeCF(icellF.TSE, omegaF,  c1o4, -c1o4,  c1o4, calcPressTSE(),  c1o1, -c1o1,  c1o1);
-   calcInterpolatedNodeCF(icellF.BNW, omegaF, -c1o4,  c1o4, -c1o4, calcPressBNW(), -c1o1,  c1o1, -c1o1);
-   calcInterpolatedNodeCF(icellF.BSE, omegaF,  c1o4, -c1o4, -c1o4, calcPressBSE(),  c1o1, -c1o1, -c1o1);
-   calcInterpolatedNodeCF(icellF.TSW, omegaF, -c1o4, -c1o4,  c1o4, calcPressTSW(), -c1o1, -c1o1,  c1o1);
-   calcInterpolatedNodeCF(icellF.TNE, omegaF,  c1o4,  c1o4,  c1o4, calcPressTNE(),  c1o1,  c1o1,  c1o1);
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
-{
-   setOffsets(xoff, yoff, zoff);
-   calcInterpolatedCoefficiets(icellF, omegaF, c2o1);
-   calcInterpolatedNodeFC(icellC, omegaC);
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::calcMoments(const real* const f, real omega, real& press, real& vx1, real& vx2, real& vx3, 
-                                                    real& kxy, real& kyz, real& kxz, real& kxxMyy, real& kxxMzz)
-{
-   using namespace D3Q27System;
-   using namespace vf::lbm::dir;
-
-   real drho = c0o1;
-   D3Q27System::calcCompMacroscopicValues(f,drho,vx1,vx2,vx3);
-   
-   press = drho; //interpolate rho!
-
-   kxy   = -c3o1*omega*((((f[DIR_MMP]+f[DIR_PPM])-(f[DIR_MPP]+f[DIR_PMM]))+((f[DIR_MMM]+f[DIR_PPP])-(f[DIR_MPM]+f[DIR_PMP])))+((f[DIR_MM0]+f[DIR_PP0])-(f[DIR_MP0]+f[DIR_PM0]))/(c1o1 + drho)-(vx1*vx2));// might not be optimal MG 25.2.13
-   kyz   = -c3o1*omega*((((f[DIR_MMM]+f[DIR_PPP])-(f[DIR_PMP]+f[DIR_MPM]))+((f[DIR_PMM]+f[DIR_MPP])-(f[DIR_MMP]+f[DIR_PPM])))+((f[DIR_0MM]+f[DIR_0PP])-(f[DIR_0MP]+f[DIR_0PM]))/(c1o1 + drho)-(vx2*vx3));
-   kxz   = -c3o1*omega*((((f[DIR_MPM]+f[DIR_PMP])-(f[DIR_MMP]+f[DIR_PPM]))+((f[DIR_MMM]+f[DIR_PPP])-(f[DIR_PMM]+f[DIR_MPP])))+((f[DIR_M0M]+f[DIR_P0P])-(f[DIR_M0P]+f[DIR_P0M]))/(c1o1 + drho)-(vx1*vx3));
-   kxxMyy = -c3o1/c2o1*omega*((((f[DIR_M0M]+f[DIR_P0P])-(f[DIR_0MM]+f[DIR_0PP]))+((f[DIR_M0P]+f[DIR_P0M])-(f[DIR_0MP]+f[DIR_0PM])))+((f[DIR_M00]+f[DIR_P00])-(f[DIR_0M0]+f[DIR_0P0]))/(c1o1 + drho)-(vx1*vx1-vx2*vx2));
-   kxxMzz = -c3o1/c2o1*omega*((((f[DIR_MP0]+f[DIR_PM0])-(f[DIR_0MM]+f[DIR_0PP]))+((f[DIR_MM0]+f[DIR_PP0])-(f[DIR_0MP]+f[DIR_0PM])))+((f[DIR_M00]+f[DIR_P00])-(f[DIR_00M]+f[DIR_00P]))/(c1o1 + drho)-(vx1*vx1-vx3*vx3));
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new)
-{
-   real        vx1_SWT,vx2_SWT,vx3_SWT;
-   real        vx1_NWT,vx2_NWT,vx3_NWT;
-   real        vx1_NET,vx2_NET,vx3_NET;
-   real        vx1_SET,vx2_SET,vx3_SET;
-   real        vx1_SWB,vx2_SWB,vx3_SWB;
-   real        vx1_NWB,vx2_NWB,vx3_NWB;
-   real        vx1_NEB,vx2_NEB,vx3_NEB;
-   real        vx1_SEB,vx2_SEB,vx3_SEB;
-
-   real        kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT;
-   real        kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT;
-   real        kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET;
-   real        kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET;
-   real        kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB;
-   real        kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB;
-   real        kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB;
-   real        kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB;
-
-   calcMoments(icell.TSW,omega,press_SWT,vx1_SWT,vx2_SWT,vx3_SWT, kxyFromfcNEQ_SWT, kyzFromfcNEQ_SWT, kxzFromfcNEQ_SWT, kxxMyyFromfcNEQ_SWT, kxxMzzFromfcNEQ_SWT);
-   calcMoments(icell.TNW,omega,press_NWT,vx1_NWT,vx2_NWT,vx3_NWT, kxyFromfcNEQ_NWT, kyzFromfcNEQ_NWT, kxzFromfcNEQ_NWT, kxxMyyFromfcNEQ_NWT, kxxMzzFromfcNEQ_NWT);
-   calcMoments(icell.TNE,omega,press_NET,vx1_NET,vx2_NET,vx3_NET, kxyFromfcNEQ_NET, kyzFromfcNEQ_NET, kxzFromfcNEQ_NET, kxxMyyFromfcNEQ_NET, kxxMzzFromfcNEQ_NET);
-   calcMoments(icell.TSE,omega,press_SET,vx1_SET,vx2_SET,vx3_SET, kxyFromfcNEQ_SET, kyzFromfcNEQ_SET, kxzFromfcNEQ_SET, kxxMyyFromfcNEQ_SET, kxxMzzFromfcNEQ_SET);
-   calcMoments(icell.BSW,omega,press_SWB,vx1_SWB,vx2_SWB,vx3_SWB, kxyFromfcNEQ_SWB, kyzFromfcNEQ_SWB, kxzFromfcNEQ_SWB, kxxMyyFromfcNEQ_SWB, kxxMzzFromfcNEQ_SWB);
-   calcMoments(icell.BNW,omega,press_NWB,vx1_NWB,vx2_NWB,vx3_NWB, kxyFromfcNEQ_NWB, kyzFromfcNEQ_NWB, kxzFromfcNEQ_NWB, kxxMyyFromfcNEQ_NWB, kxxMzzFromfcNEQ_NWB);
-   calcMoments(icell.BNE,omega,press_NEB,vx1_NEB,vx2_NEB,vx3_NEB, kxyFromfcNEQ_NEB, kyzFromfcNEQ_NEB, kxzFromfcNEQ_NEB, kxxMyyFromfcNEQ_NEB, kxxMzzFromfcNEQ_NEB);
-   calcMoments(icell.BSE,omega,press_SEB,vx1_SEB,vx2_SEB,vx3_SEB, kxyFromfcNEQ_SEB, kyzFromfcNEQ_SEB, kxzFromfcNEQ_SEB, kxxMyyFromfcNEQ_SEB, kxxMzzFromfcNEQ_SEB);
-
-   //LBMReal dxRho=c1o4*((press_NET-press_SWB)+(press_SET-press_NWB)+(press_NEB-press_SWT)+(press_SEB-press_NWT));
-   //LBMReal dyRho=c1o4*((press_NET-press_SWB)-(press_SET-press_NWB)+(press_NEB-press_SWT)-(press_SEB-press_NWT));
-   //LBMReal dzRho=c1o4*((press_NET-press_SWB)+(press_SET-press_NWB)-(press_NEB-press_SWT)-(press_SEB-press_NWT));
-
-   //   kxyFromfcNEQ_SWT+=vx1_SWT*dyRho+vx2_SWT*dxRho;
-   //   kxyFromfcNEQ_NWT+=vx1_NWT*dyRho+vx2_NWT*dxRho;
-   //   kxyFromfcNEQ_NET+=vx1_NET*dyRho+vx2_NET*dxRho;
-   //   kxyFromfcNEQ_SET+=vx1_SET*dyRho+vx2_SET*dxRho;
-   //   kxyFromfcNEQ_SWB+=vx1_SWB*dyRho+vx2_SWB*dxRho;
-   //   kxyFromfcNEQ_NWB+=vx1_NWB*dyRho+vx2_NWB*dxRho;
-   //   kxyFromfcNEQ_NEB+=vx1_NEB*dyRho+vx2_NEB*dxRho;
-   //   kxyFromfcNEQ_SEB+=vx1_SEB*dyRho+vx2_SEB*dxRho;
-
-   //   kyzFromfcNEQ_SWT+=vx3_SWT*dyRho+vx2_SWT*dzRho;
-   //   kyzFromfcNEQ_NWT+=vx3_NWT*dyRho+vx2_NWT*dzRho;
-   //   kyzFromfcNEQ_NET+=vx3_NET*dyRho+vx2_NET*dzRho;
-   //   kyzFromfcNEQ_SET+=vx3_SET*dyRho+vx2_SET*dzRho;
-   //   kyzFromfcNEQ_SWB+=vx3_SWB*dyRho+vx2_SWB*dzRho;
-   //   kyzFromfcNEQ_NWB+=vx3_NWB*dyRho+vx2_NWB*dzRho;
-   //   kyzFromfcNEQ_NEB+=vx3_NEB*dyRho+vx2_NEB*dzRho;
-   //   kyzFromfcNEQ_SEB+=vx3_SEB*dyRho+vx2_SEB*dzRho;
-
-   //   kxzFromfcNEQ_SWT+=vx1_SWT*dzRho+vx3_SWT*dxRho;
-   //   kxzFromfcNEQ_NWT+=vx1_NWT*dzRho+vx3_NWT*dxRho;
-   //   kxzFromfcNEQ_NET+=vx1_NET*dzRho+vx3_NET*dxRho;
-   //   kxzFromfcNEQ_SET+=vx1_SET*dzRho+vx3_SET*dxRho;
-   //   kxzFromfcNEQ_SWB+=vx1_SWB*dzRho+vx3_SWB*dxRho;
-   //   kxzFromfcNEQ_NWB+=vx1_NWB*dzRho+vx3_NWB*dxRho;
-   //   kxzFromfcNEQ_NEB+=vx1_NEB*dzRho+vx3_NEB*dxRho;
-   //   kxzFromfcNEQ_SEB+=vx1_SEB*dzRho+vx3_SEB*dxRho;
-
-   //   kxxMyyFromfcNEQ_SWT+=vx1_SWT*dxRho-vx2_SWT*dyRho;
-   //   kxxMyyFromfcNEQ_NWT+=vx1_NWT*dxRho-vx2_NWT*dyRho;
-   //   kxxMyyFromfcNEQ_NET+=vx1_NET*dxRho-vx2_NET*dyRho;
-   //   kxxMyyFromfcNEQ_SET+=vx1_SET*dxRho-vx2_SET*dyRho;
-   //   kxxMyyFromfcNEQ_SWB+=vx1_SWB*dxRho-vx2_SWB*dyRho;
-   //   kxxMyyFromfcNEQ_NWB+=vx1_NWB*dxRho-vx2_NWB*dyRho;
-   //   kxxMyyFromfcNEQ_NEB+=vx1_NEB*dxRho-vx2_NEB*dyRho;
-   //   kxxMyyFromfcNEQ_SEB+=vx1_SEB*dxRho-vx2_SEB*dyRho;
-
-   //   kxxMzzFromfcNEQ_SWT+=vx1_SWT*dxRho-vx3_SWT*dzRho;
-   //   kxxMzzFromfcNEQ_NWT+=vx1_NWT*dxRho-vx3_NWT*dzRho;
-   //   kxxMzzFromfcNEQ_NET+=vx1_NET*dxRho-vx3_NET*dzRho;
-   //   kxxMzzFromfcNEQ_SET+=vx1_SET*dxRho-vx3_SET*dzRho;
-   //   kxxMzzFromfcNEQ_SWB+=vx1_SWB*dxRho-vx3_SWB*dzRho;
-   //   kxxMzzFromfcNEQ_NWB+=vx1_NWB*dxRho-vx3_NWB*dzRho;
-   //   kxxMzzFromfcNEQ_NEB+=vx1_NEB*dxRho-vx3_NEB*dzRho;
-   //   kxxMzzFromfcNEQ_SEB+=vx1_SEB*dxRho-vx3_SEB*dzRho;
-
-
-      //kxxMzzFromfcNEQ_SWT=0.0;
-      //kxxMzzFromfcNEQ_NWT=0.0;
-      //kxxMzzFromfcNEQ_NET=0.0;
-      //kxxMzzFromfcNEQ_SET=0.0;
-      //kxxMzzFromfcNEQ_SWB=0.0;
-      //kxxMzzFromfcNEQ_NWB=0.0;
-      //kxxMzzFromfcNEQ_NEB=0.0;
-      //kxxMzzFromfcNEQ_SEB=0.0;
-
-
-
-
-
-   a0 = (-kxxMyyFromfcNEQ_NEB - kxxMyyFromfcNEQ_NET + kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_NWT -
-      kxxMyyFromfcNEQ_SEB - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_SWT -
-      kxxMzzFromfcNEQ_NEB - kxxMzzFromfcNEQ_NET + kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_NWT -
-      kxxMzzFromfcNEQ_SEB - kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_SWT -
-      c2o1*kxyFromfcNEQ_NEB - c2o1*kxyFromfcNEQ_NET - c2o1*kxyFromfcNEQ_NWB - c2o1*kxyFromfcNEQ_NWT +
-      c2o1*kxyFromfcNEQ_SEB + c2o1*kxyFromfcNEQ_SET + c2o1*kxyFromfcNEQ_SWB + c2o1*kxyFromfcNEQ_SWT +
-      c2o1*kxzFromfcNEQ_NEB - c2o1*kxzFromfcNEQ_NET + c2o1*kxzFromfcNEQ_NWB - c2o1*kxzFromfcNEQ_NWT +
-      c2o1*kxzFromfcNEQ_SEB - c2o1*kxzFromfcNEQ_SET + c2o1*kxzFromfcNEQ_SWB - c2o1*kxzFromfcNEQ_SWT +
-      c8o1*vx1_NEB + c8o1*vx1_NET + c8o1*vx1_NWB + c8o1*vx1_NWT + c8o1*vx1_SEB +
-      c8o1*vx1_SET + c8o1*vx1_SWB + c8o1*vx1_SWT + c2o1*vx2_NEB + c2o1*vx2_NET -
-      c2o1*vx2_NWB - c2o1*vx2_NWT - c2o1*vx2_SEB - c2o1*vx2_SET + c2o1*vx2_SWB +
-      c2o1*vx2_SWT - c2o1*vx3_NEB + c2o1*vx3_NET + c2o1*vx3_NWB - c2o1*vx3_NWT -
-      c2o1*vx3_SEB + c2o1*vx3_SET + c2o1*vx3_SWB - c2o1*vx3_SWT)/c64o1;
-   b0 = (c2o1*kxxMyyFromfcNEQ_NEB + c2o1*kxxMyyFromfcNEQ_NET + c2o1*kxxMyyFromfcNEQ_NWB + c2o1*kxxMyyFromfcNEQ_NWT -
-      c2o1*kxxMyyFromfcNEQ_SEB - c2o1*kxxMyyFromfcNEQ_SET - c2o1*kxxMyyFromfcNEQ_SWB - c2o1*kxxMyyFromfcNEQ_SWT -
-      kxxMzzFromfcNEQ_NEB - kxxMzzFromfcNEQ_NET - kxxMzzFromfcNEQ_NWB - kxxMzzFromfcNEQ_NWT +
-      kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_SET + kxxMzzFromfcNEQ_SWB + kxxMzzFromfcNEQ_SWT -
-      c2o1*kxyFromfcNEQ_NEB - c2o1*kxyFromfcNEQ_NET + c2o1*kxyFromfcNEQ_NWB + c2o1*kxyFromfcNEQ_NWT -
-      c2o1*kxyFromfcNEQ_SEB - c2o1*kxyFromfcNEQ_SET + c2o1*kxyFromfcNEQ_SWB + c2o1*kxyFromfcNEQ_SWT +
-      c2o1*kyzFromfcNEQ_NEB - c2o1*kyzFromfcNEQ_NET + c2o1*kyzFromfcNEQ_NWB - c2o1*kyzFromfcNEQ_NWT +
-      c2o1*kyzFromfcNEQ_SEB - c2o1*kyzFromfcNEQ_SET + c2o1*kyzFromfcNEQ_SWB - c2o1*kyzFromfcNEQ_SWT +
-      c2o1*vx1_NEB + c2o1*vx1_NET - c2o1*vx1_NWB - c2o1*vx1_NWT -
-      c2o1*vx1_SEB - c2o1*vx1_SET + c2o1*vx1_SWB + c2o1*vx1_SWT +
-      c8o1*vx2_NEB + c8o1*vx2_NET + c8o1*vx2_NWB + c8o1*vx2_NWT +
-      c8o1*vx2_SEB + c8o1*vx2_SET + c8o1*vx2_SWB + c8o1*vx2_SWT -
-      c2o1*vx3_NEB + c2o1*vx3_NET - c2o1*vx3_NWB + c2o1*vx3_NWT +
-      c2o1*vx3_SEB - c2o1*vx3_SET + c2o1*vx3_SWB - c2o1*vx3_SWT)/c64o1;
-   c0 = (kxxMyyFromfcNEQ_NEB - kxxMyyFromfcNEQ_NET + kxxMyyFromfcNEQ_NWB - kxxMyyFromfcNEQ_NWT +
-      kxxMyyFromfcNEQ_SEB - kxxMyyFromfcNEQ_SET + kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_SWT -
-      c2o1*kxxMzzFromfcNEQ_NEB + c2o1*kxxMzzFromfcNEQ_NET - c2o1*kxxMzzFromfcNEQ_NWB + c2o1*kxxMzzFromfcNEQ_NWT -
-      c2o1*kxxMzzFromfcNEQ_SEB + c2o1*kxxMzzFromfcNEQ_SET - c2o1*kxxMzzFromfcNEQ_SWB + c2o1*kxxMzzFromfcNEQ_SWT -
-      c2o1*kxzFromfcNEQ_NEB - c2o1*kxzFromfcNEQ_NET + c2o1*kxzFromfcNEQ_NWB + c2o1*kxzFromfcNEQ_NWT -
-      c2o1*kxzFromfcNEQ_SEB - c2o1*kxzFromfcNEQ_SET + c2o1*kxzFromfcNEQ_SWB + c2o1*kxzFromfcNEQ_SWT -
-      c2o1*kyzFromfcNEQ_NEB - c2o1*kyzFromfcNEQ_NET - c2o1*kyzFromfcNEQ_NWB - c2o1*kyzFromfcNEQ_NWT +
-      c2o1*kyzFromfcNEQ_SEB + c2o1*kyzFromfcNEQ_SET + c2o1*kyzFromfcNEQ_SWB + c2o1*kyzFromfcNEQ_SWT -
-      c2o1*vx1_NEB + c2o1*vx1_NET + c2o1*vx1_NWB - c2o1*vx1_NWT -
-      c2o1*vx1_SEB + c2o1*vx1_SET + c2o1*vx1_SWB - c2o1*vx1_SWT -
-      c2o1*vx2_NEB + c2o1*vx2_NET - c2o1*vx2_NWB + c2o1*vx2_NWT +
-      c2o1*vx2_SEB - c2o1*vx2_SET + c2o1*vx2_SWB - c2o1*vx2_SWT +
-      c8o1*vx3_NEB + c8o1*vx3_NET + c8o1*vx3_NWB + c8o1*vx3_NWT +
-      c8o1*vx3_SEB + c8o1*vx3_SET + c8o1*vx3_SWB + c8o1*vx3_SWT)/c64o1;
-   ax = (vx1_NEB + vx1_NET - vx1_NWB - vx1_NWT + vx1_SEB + vx1_SET - vx1_SWB - vx1_SWT)/c4o1;
-   bx = (vx2_NEB + vx2_NET - vx2_NWB - vx2_NWT + vx2_SEB + vx2_SET - vx2_SWB - vx2_SWT)/c4o1;
-   cx = (vx3_NEB + vx3_NET - vx3_NWB - vx3_NWT + vx3_SEB + vx3_SET - vx3_SWB - vx3_SWT)/c4o1;
-   axx= (kxxMyyFromfcNEQ_NEB + kxxMyyFromfcNEQ_NET - kxxMyyFromfcNEQ_NWB - kxxMyyFromfcNEQ_NWT +
-      kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_SWB - kxxMyyFromfcNEQ_SWT +
-      kxxMzzFromfcNEQ_NEB + kxxMzzFromfcNEQ_NET - kxxMzzFromfcNEQ_NWB - kxxMzzFromfcNEQ_NWT +
-      kxxMzzFromfcNEQ_SEB + kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_SWT +
-      c2o1*vx2_NEB + c2o1*vx2_NET - c2o1*vx2_NWB - c2o1*vx2_NWT -
-      c2o1*vx2_SEB - c2o1*vx2_SET + c2o1*vx2_SWB + c2o1*vx2_SWT -
-      c2o1*vx3_NEB + c2o1*vx3_NET + c2o1*vx3_NWB - c2o1*vx3_NWT -
-      c2o1*vx3_SEB + c2o1*vx3_SET + c2o1*vx3_SWB - c2o1*vx3_SWT)/c16o1;
-   bxx= (kxyFromfcNEQ_NEB + kxyFromfcNEQ_NET - kxyFromfcNEQ_NWB - kxyFromfcNEQ_NWT +
-      kxyFromfcNEQ_SEB + kxyFromfcNEQ_SET - kxyFromfcNEQ_SWB - kxyFromfcNEQ_SWT -
-      c2o1*vx1_NEB - c2o1*vx1_NET + c2o1*vx1_NWB + c2o1*vx1_NWT +
-      c2o1*vx1_SEB + c2o1*vx1_SET - c2o1*vx1_SWB - c2o1*vx1_SWT)/c8o1;
-   cxx= (kxzFromfcNEQ_NEB + kxzFromfcNEQ_NET - kxzFromfcNEQ_NWB - kxzFromfcNEQ_NWT +
-      kxzFromfcNEQ_SEB + kxzFromfcNEQ_SET - kxzFromfcNEQ_SWB - kxzFromfcNEQ_SWT +
-      c2o1*vx1_NEB - c2o1*vx1_NET - c2o1*vx1_NWB + c2o1*vx1_NWT +
-      c2o1*vx1_SEB - c2o1*vx1_SET - c2o1*vx1_SWB + c2o1*vx1_SWT)/c8o1;
-   ay = (vx1_NEB + vx1_NET + vx1_NWB + vx1_NWT - vx1_SEB - vx1_SET - vx1_SWB - vx1_SWT)/c4o1;
-   by = (vx2_NEB + vx2_NET + vx2_NWB + vx2_NWT - vx2_SEB - vx2_SET - vx2_SWB - vx2_SWT)/c4o1;
-   cy = (vx3_NEB + vx3_NET + vx3_NWB + vx3_NWT - vx3_SEB - vx3_SET - vx3_SWB - vx3_SWT)/c4o1;
-   ayy= (kxyFromfcNEQ_NEB + kxyFromfcNEQ_NET + kxyFromfcNEQ_NWB + kxyFromfcNEQ_NWT -
-      kxyFromfcNEQ_SEB - kxyFromfcNEQ_SET - kxyFromfcNEQ_SWB - kxyFromfcNEQ_SWT -
-      c2o1*vx2_NEB - c2o1*vx2_NET + c2o1*vx2_NWB + c2o1*vx2_NWT +
-      c2o1*vx2_SEB + c2o1*vx2_SET - c2o1*vx2_SWB - c2o1*vx2_SWT)/c8o1;
-   byy= (-c2o1*kxxMyyFromfcNEQ_NEB - c2o1*kxxMyyFromfcNEQ_NET - c2o1*kxxMyyFromfcNEQ_NWB - c2o1*kxxMyyFromfcNEQ_NWT +
-      c2o1*kxxMyyFromfcNEQ_SEB + c2o1*kxxMyyFromfcNEQ_SET + c2o1*kxxMyyFromfcNEQ_SWB + c2o1*kxxMyyFromfcNEQ_SWT +
-      kxxMzzFromfcNEQ_NEB + kxxMzzFromfcNEQ_NET + kxxMzzFromfcNEQ_NWB + kxxMzzFromfcNEQ_NWT -
-      kxxMzzFromfcNEQ_SEB - kxxMzzFromfcNEQ_SET - kxxMzzFromfcNEQ_SWB - kxxMzzFromfcNEQ_SWT +
-      c2o1*vx1_NEB + c2o1*vx1_NET - c2o1*vx1_NWB - c2o1*vx1_NWT -
-      c2o1*vx1_SEB - c2o1*vx1_SET + c2o1*vx1_SWB + c2o1*vx1_SWT -
-      c2o1*vx3_NEB + c2o1*vx3_NET - c2o1*vx3_NWB + c2o1*vx3_NWT +
-      c2o1*vx3_SEB - c2o1*vx3_SET + c2o1*vx3_SWB - c2o1*vx3_SWT)/c16o1;
-   cyy= (kyzFromfcNEQ_NEB + kyzFromfcNEQ_NET + kyzFromfcNEQ_NWB + kyzFromfcNEQ_NWT -
-      kyzFromfcNEQ_SEB - kyzFromfcNEQ_SET - kyzFromfcNEQ_SWB - kyzFromfcNEQ_SWT +
-      c2o1*vx2_NEB - c2o1*vx2_NET + c2o1*vx2_NWB - c2o1*vx2_NWT -
-      c2o1*vx2_SEB + c2o1*vx2_SET - c2o1*vx2_SWB + c2o1*vx2_SWT)/c8o1;
-   az = (-vx1_NEB + vx1_NET - vx1_NWB + vx1_NWT - vx1_SEB + vx1_SET - vx1_SWB + vx1_SWT)/c4o1;
-   bz = (-vx2_NEB + vx2_NET - vx2_NWB + vx2_NWT - vx2_SEB + vx2_SET - vx2_SWB + vx2_SWT)/c4o1;
-   cz = (-vx3_NEB + vx3_NET - vx3_NWB + vx3_NWT - vx3_SEB + vx3_SET - vx3_SWB + vx3_SWT)/c4o1;
-   azz= (-kxzFromfcNEQ_NEB + kxzFromfcNEQ_NET - kxzFromfcNEQ_NWB + kxzFromfcNEQ_NWT -
-      kxzFromfcNEQ_SEB + kxzFromfcNEQ_SET - kxzFromfcNEQ_SWB + kxzFromfcNEQ_SWT +
-      c2o1*vx3_NEB - c2o1*vx3_NET - c2o1*vx3_NWB + c2o1*vx3_NWT +
-      c2o1*vx3_SEB - c2o1*vx3_SET - c2o1*vx3_SWB + c2o1*vx3_SWT)/c8o1;
-   bzz= (-kyzFromfcNEQ_NEB + kyzFromfcNEQ_NET - kyzFromfcNEQ_NWB + kyzFromfcNEQ_NWT -
-      kyzFromfcNEQ_SEB + kyzFromfcNEQ_SET - kyzFromfcNEQ_SWB + kyzFromfcNEQ_SWT +
-      c2o1*vx3_NEB - c2o1*vx3_NET + c2o1*vx3_NWB - c2o1*vx3_NWT -
-      c2o1*vx3_SEB + c2o1*vx3_SET - c2o1*vx3_SWB + c2o1*vx3_SWT)/c8o1;
-   czz= (-kxxMyyFromfcNEQ_NEB + kxxMyyFromfcNEQ_NET - kxxMyyFromfcNEQ_NWB + kxxMyyFromfcNEQ_NWT -
-      kxxMyyFromfcNEQ_SEB + kxxMyyFromfcNEQ_SET - kxxMyyFromfcNEQ_SWB + kxxMyyFromfcNEQ_SWT +
-      c2o1*kxxMzzFromfcNEQ_NEB - c2o1*kxxMzzFromfcNEQ_NET + c2o1*kxxMzzFromfcNEQ_NWB - c2o1*kxxMzzFromfcNEQ_NWT +
-      c2o1*kxxMzzFromfcNEQ_SEB - c2o1*kxxMzzFromfcNEQ_SET + c2o1*kxxMzzFromfcNEQ_SWB - c2o1*kxxMzzFromfcNEQ_SWT -
-      c2o1*vx1_NEB + c2o1*vx1_NET + c2o1*vx1_NWB - c2o1*vx1_NWT -
-      c2o1*vx1_SEB + c2o1*vx1_SET + c2o1*vx1_SWB - c2o1*vx1_SWT -
-      c2o1*vx2_NEB + c2o1*vx2_NET - c2o1*vx2_NWB + c2o1*vx2_NWT +
-      c2o1*vx2_SEB - c2o1*vx2_SET + c2o1*vx2_SWB - c2o1*vx2_SWT)/c16o1;
-   axy= (vx1_NEB + vx1_NET - vx1_NWB - vx1_NWT - vx1_SEB - vx1_SET + vx1_SWB + vx1_SWT)/c2o1;
-   bxy= (vx2_NEB + vx2_NET - vx2_NWB - vx2_NWT - vx2_SEB - vx2_SET + vx2_SWB + vx2_SWT)/c2o1;
-   cxy= (vx3_NEB + vx3_NET - vx3_NWB - vx3_NWT - vx3_SEB - vx3_SET + vx3_SWB + vx3_SWT)/c2o1;
-   axz= (-vx1_NEB + vx1_NET + vx1_NWB - vx1_NWT - vx1_SEB + vx1_SET + vx1_SWB - vx1_SWT)/c2o1;
-   bxz= (-vx2_NEB + vx2_NET + vx2_NWB - vx2_NWT - vx2_SEB + vx2_SET + vx2_SWB - vx2_SWT)/c2o1;
-   cxz= (-vx3_NEB + vx3_NET + vx3_NWB - vx3_NWT - vx3_SEB + vx3_SET + vx3_SWB - vx3_SWT)/c2o1;
-   ayz= (-vx1_NEB + vx1_NET - vx1_NWB + vx1_NWT + vx1_SEB - vx1_SET + vx1_SWB - vx1_SWT)/c2o1;
-   byz= (-vx2_NEB + vx2_NET - vx2_NWB + vx2_NWT + vx2_SEB - vx2_SET + vx2_SWB - vx2_SWT)/c2o1;
-   cyz= (-vx3_NEB + vx3_NET - vx3_NWB + vx3_NWT + vx3_SEB - vx3_SET + vx3_SWB - vx3_SWT)/c2o1;
-   axyz=-vx1_NEB + vx1_NET + vx1_NWB - vx1_NWT + vx1_SEB - vx1_SET - vx1_SWB + vx1_SWT;
-   bxyz=-vx2_NEB + vx2_NET + vx2_NWB - vx2_NWT + vx2_SEB - vx2_SET - vx2_SWB + vx2_SWT;
-   cxyz=-vx3_NEB + vx3_NET + vx3_NWB - vx3_NWT + vx3_SEB - vx3_SET - vx3_SWB + vx3_SWT;
-
-
-   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-   kxyAverage       = c0o1;//(kxyFromfcNEQ_SWB+
-                       //kxyFromfcNEQ_SWT+
-                       //kxyFromfcNEQ_SET+
-                       //kxyFromfcNEQ_SEB+
-                       //kxyFromfcNEQ_NWB+
-                       //kxyFromfcNEQ_NWT+
-                       //kxyFromfcNEQ_NET+
-                       //kxyFromfcNEQ_NEB)*c1o8-(ay+bx);
-   kyzAverage       = c0o1;//(kyzFromfcNEQ_SWB+
-                       //kyzFromfcNEQ_SWT+
-                       //kyzFromfcNEQ_SET+
-                       //kyzFromfcNEQ_SEB+
-                       //kyzFromfcNEQ_NWB+
-                       //kyzFromfcNEQ_NWT+
-                       //kyzFromfcNEQ_NET+
-                       //kyzFromfcNEQ_NEB)*c1o8-(bz+cy);
-   kxzAverage       = c0o1;//(kxzFromfcNEQ_SWB+
-                       //kxzFromfcNEQ_SWT+
-                       //kxzFromfcNEQ_SET+
-                       //kxzFromfcNEQ_SEB+
-                       //kxzFromfcNEQ_NWB+
-                       //kxzFromfcNEQ_NWT+
-                       //kxzFromfcNEQ_NET+
-                       //kxzFromfcNEQ_NEB)*c1o8-(az+cx);
-   kxxMyyAverage    = c0o1;//(kxxMyyFromfcNEQ_SWB+
-                       //kxxMyyFromfcNEQ_SWT+
-                       //kxxMyyFromfcNEQ_SET+
-                       //kxxMyyFromfcNEQ_SEB+
-                       //kxxMyyFromfcNEQ_NWB+
-                       //kxxMyyFromfcNEQ_NWT+
-                       //kxxMyyFromfcNEQ_NET+
-                       //kxxMyyFromfcNEQ_NEB)*c1o8-(ax-by);
-   kxxMzzAverage    = c0o1;//(kxxMzzFromfcNEQ_SWB+
-                       //kxxMzzFromfcNEQ_SWT+
-                       //kxxMzzFromfcNEQ_SET+
-                       //kxxMzzFromfcNEQ_SEB+
-                       //kxxMzzFromfcNEQ_NWB+
-                       //kxxMzzFromfcNEQ_NWT+
-                       //kxxMzzFromfcNEQ_NET+
-                       //kxxMzzFromfcNEQ_NEB)*c1o8-(ax-cz);
-   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-   //
-   // Bernd das Brot
-   //
-   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-   a0 = a0 + xoff * ax + yoff * ay + zoff * az + xoff_sq * axx + yoff_sq * ayy + zoff_sq * azz + xoff*yoff*axy + xoff*zoff*axz + yoff*zoff*ayz + xoff*yoff*zoff*axyz ;
-   ax = ax + c2o1 * xoff * axx + yoff * axy + zoff * axz + yoff*zoff*axyz;
-   ay = ay + c2o1 * yoff * ayy + xoff * axy + zoff * ayz + xoff*zoff*axyz;
-   az = az + c2o1 * zoff * azz + xoff * axz + yoff * ayz + xoff*yoff*axyz;
-   b0 = b0 + xoff * bx + yoff * by + zoff * bz + xoff_sq * bxx + yoff_sq * byy + zoff_sq * bzz + xoff*yoff*bxy + xoff*zoff*bxz + yoff*zoff*byz + xoff*yoff*zoff*bxyz;
-   bx = bx + c2o1 * xoff * bxx + yoff * bxy + zoff * bxz + yoff*zoff*bxyz;
-   by = by + c2o1 * yoff * byy + xoff * bxy + zoff * byz + xoff*zoff*bxyz;
-   bz = bz + c2o1 * zoff * bzz + xoff * bxz + yoff * byz + xoff*yoff*bxyz;
-   c0 = c0 + xoff * cx + yoff * cy + zoff * cz + xoff_sq * cxx + yoff_sq * cyy + zoff_sq * czz + xoff*yoff*cxy + xoff*zoff*cxz + yoff*zoff*cyz + xoff*yoff*zoff*cxyz;
-   cx = cx + c2o1 * xoff * cxx + yoff * cxy + zoff * cxz + yoff*zoff*cxyz;
-   cy = cy + c2o1 * yoff * cyy + xoff * cxy + zoff * cyz + xoff*zoff*cxyz;
-   cz = cz + c2o1 * zoff * czz + xoff * cxz + yoff * cyz + xoff*yoff*cxyz;
-   axy= axy + zoff*axyz;
-   axz= axz + yoff*axyz;
-   ayz= ayz + xoff*axyz;
-   bxy= bxy + zoff*bxyz;
-   bxz= bxz + yoff*bxyz;
-   byz= byz + xoff*bxyz;
-   cxy= cxy + zoff*cxyz;
-   cxz= cxz + yoff*cxyz;
-   cyz= cyz + xoff*cxyz;
-   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-   const real o = omega;
-
-   f_E = eps_new*((c2o1*(-c2o1*ax + by + cz-kxxMzzAverage-kxxMyyAverage))/(c27o1*o));
-   f_N = eps_new*((c2o1*(ax - c2o1*by + cz+c2o1*kxxMyyAverage-kxxMzzAverage))/(c27o1*o));
-   f_T = eps_new*((c2o1*(ax + by - c2o1*cz-kxxMyyAverage+c2o1*kxxMzzAverage))/(c27o1*o));
-   f_NE = eps_new*(-(ax + c3o1*ay + c3o1*bx + by - c2o1*cz+c2o1*kxxMyyAverage-kxxMyyAverage+c3o1*kxyAverage)/(c54o1*o));
-   f_SE = eps_new*(-(ax - c3o1*ay - c3o1*bx + by - c2o1*cz+c2o1*kxxMyyAverage-kxxMyyAverage-c3o1*kxyAverage)/(c54o1*o));
-   f_TE = eps_new*(-(ax + c3o1*az - c2o1*by + c3o1*cx + cz+c2o1*kxxMyyAverage-kxxMzzAverage+c3o1*kxzAverage)/(c54o1*o));
-   f_BE = eps_new*(-(ax - c3o1*az - c2o1*by - c3o1*cx + cz+c2o1*kxxMyyAverage-kxxMzzAverage-c3o1*kxzAverage)/(c54o1*o));
-   f_TN = eps_new*(-(-c2o1*ax + by + c3o1*bz + c3o1*cy + cz-kxxMyyAverage-kxxMzzAverage+c3o1*kyzAverage)/(c54o1*o));
-   f_BN = eps_new*(-(-c2o1*ax + by - c3o1*bz - c3o1*cy + cz-kxxMyyAverage-kxxMzzAverage-c3o1*kyzAverage)/(c54o1*o));
-   f_ZERO = 0.;
-   f_TNE = eps_new*(-(ay + az + bx + bz + cx + cy+kxyAverage+kxzAverage+kyzAverage)/(c72o1*o));
-   f_TSW = eps_new*((-ay + az - bx + bz + cx + cy-kxyAverage+kxzAverage+kyzAverage)/(c72o1*o));
-   f_TSE = eps_new*((ay - az + bx + bz - cx + cy+kxyAverage-kxzAverage+kyzAverage)/(c72o1*o));
-   f_TNW = eps_new*((ay + az + bx - bz + cx - cy+kxyAverage+kxzAverage-kyzAverage)/(c72o1*o));
-
-   x_E = c1o4*eps_new*((c2o1*(-c4o1*axx + bxy + cxz))/(c27o1*o));
-   x_N = c1o4*eps_new*((c2o1*(c2o1*axx - c2o1*bxy + cxz))/(c27o1*o));
-   x_T = c1o4*eps_new*((c2o1*(c2o1*axx + bxy - c2o1*cxz))/(c27o1*o));
-   x_NE = c1o4*eps_new*(-((c2o1*axx + c3o1*axy + c6o1*bxx + bxy - c2o1*cxz))/(c54o1*o));
-   x_SE = c1o4*eps_new*(-((c2o1*axx - c3o1*axy - c6o1*bxx + bxy - c2o1*cxz))/(c54o1*o));
-   x_TE = c1o4*eps_new*(-((c2o1*axx + c3o1*axz - c2o1*bxy + c6o1*cxx + cxz))/(c54o1*o));
-   x_BE = c1o4*eps_new*(-((c2o1*axx - c3o1*axz - c2o1*bxy - c6o1*cxx + cxz))/(c54o1*o));
-   x_TN = c1o4*eps_new*(-((-c4o1*axx + bxy + c3o1*bxz + c3o1*cxy + cxz))/(c54o1*o));
-   x_BN = c1o4*eps_new*(-((-c4o1*axx + bxy - c3o1*bxz - c3o1*cxy + cxz))/(c54o1*o));
-   x_ZERO = c0o1;
-   x_TNE = c1o4*eps_new*(-((axy + axz + c2o1*bxx + bxz + c2o1*cxx + cxy))/(c72o1*o));
-   x_TSW = c1o4*eps_new*(((-axy + axz - c2o1*bxx + bxz + c2o1*cxx + cxy))/(c72o1*o));
-   x_TSE = c1o4*eps_new*(((axy - axz + c2o1*bxx + bxz - c2o1*cxx + cxy))/(c72o1*o));
-   x_TNW = c1o4*eps_new*(((axy + axz + c2o1*bxx - bxz + c2o1*cxx - cxy))/(c72o1*o));
-
-   y_E = c1o4*eps_new*(c2o1*(-c2o1*axy + c2o1*byy + cyz))/(c27o1*o);
-   y_N = c1o4*eps_new*(c2o1*(axy - c4o1*byy + cyz))/(c27o1*o);
-   y_T = c1o4*eps_new*(c2o1*(axy + c2o1*byy - c2o1*cyz))/(c27o1*o);
-   y_NE = c1o4*eps_new*(-((axy + c6o1*ayy + c3o1*bxy + c2o1*byy - c2o1*cyz))/(c54o1*o));
-   y_SE = c1o4*eps_new*(-((axy - c6o1*ayy - c3o1*bxy + c2o1*byy - c2o1*cyz))/(c54o1*o));
-   y_TE = c1o4*eps_new*(-((axy + c3o1*ayz - c4o1*byy + c3o1*cxy + cyz))/(c54o1*o));
-   y_BE = c1o4*eps_new*(-((axy - c3o1*ayz - c4o1*byy - c3o1*cxy + cyz))/(c54o1*o));
-   y_TN = c1o4*eps_new*(-((-c2o1*axy + c2o1*byy + c3o1*byz + c6o1*cyy + cyz))/(c54o1*o));
-   y_BN = c1o4*eps_new*(-((-c2o1*axy + c2o1*byy - c3o1*byz - c6o1*cyy + cyz))/(c54o1*o));
-   y_ZERO = c0o1;
-   y_TNE = c1o4*eps_new*(-((c2o1*ayy + ayz + bxy + byz + cxy + c2o1*cyy))/(c72o1*o));
-   y_TSW = c1o4*eps_new*(((-c2o1*ayy + ayz - bxy + byz + cxy + c2o1*cyy))/(c72o1*o));
-   y_TSE = c1o4*eps_new*(((c2o1*ayy - ayz + bxy + byz - cxy + c2o1*cyy))/(c72o1*o));
-   y_TNW = c1o4*eps_new*(((c2o1*ayy + ayz + bxy - byz + cxy - c2o1*cyy))/(c72o1*o));
-
-   z_E = c1o4*eps_new*((c2o1*(-c2o1*axz + byz + c2o1*czz))/(c27o1*o));
-   z_N = c1o4*eps_new*((c2o1*(axz - c2o1*byz + c2o1*czz))/(c27o1*o));
-   z_T = c1o4*eps_new*((c2o1*(axz + byz - c4o1*czz))/(c27o1*o));
-   z_NE = c1o4*eps_new*(-((axz + c3o1*ayz + c3o1*bxz + byz - c4o1*czz))/(c54o1*o));
-   z_SE = c1o4*eps_new*(-((axz - c3o1*ayz - c3o1*bxz + byz - c4o1*czz))/(c54o1*o));
-   z_TE = c1o4*eps_new*(-((axz + c6o1*azz - c2o1*byz + c3o1*cxz + c2o1*czz))/(c54o1*o));
-   z_BE = c1o4*eps_new*(-((axz - c6o1*azz - c2o1*byz - c3o1*cxz + c2o1*czz))/(c54o1*o));
-   z_TN = c1o4*eps_new*(-((-c2o1*axz + byz + c6o1*bzz + c3o1*cyz + c2o1*czz))/(c54o1*o));
-   z_BN = c1o4*eps_new*(-((-c2o1*axz + byz - c6o1*bzz - c3o1*cyz + c2o1*czz))/(c54o1*o));
-   z_ZERO = c0o1;
-   z_TNE = c1o4*eps_new*(-((ayz + c2o1*azz + bxz + c2o1*bzz + cxz + cyz))/(c72o1*o));
-   z_TSW = c1o4*eps_new*(((-ayz + c2o1*azz - bxz + c2o1*bzz + cxz + cyz))/(c72o1*o));
-   z_TSE = c1o4*eps_new*(((ayz - c2o1*azz + bxz + c2o1*bzz - cxz + cyz))/(c72o1*o));
-   z_TNW = c1o4*eps_new*(((ayz + c2o1*azz + bxz - c2o1*bzz + cxz - cyz))/(c72o1*o));
-
-   xy_E   =   c1o16*eps_new *((                       c2o1*cxyz)/(c27o1*o));
-   xy_N   =   c1o16*eps_new *((                       c2o1*cxyz)/(c27o1*o));
-   xy_T   = -(c1o16*eps_new *((                       c4o1*cxyz)/(c27o1*o)));
-   xy_NE  =   c1o16*eps_new *(                            cxyz /(c27o1*o));
-   xy_SE  =   c1o16*eps_new *(                            cxyz /(c27o1*o));
-   xy_TE  = -(c1o16*eps_new *(( c3o1*axyz            +     cxyz)/(c54o1*o)));
-   xy_BE  = -(c1o16*eps_new *((-c3o1*axyz            +     cxyz)/(c54o1*o)));
-   xy_TN  = -(c1o16*eps_new *((            c3o1*bxyz +     cxyz)/(c54o1*o)));
-   xy_BN  = -(c1o16*eps_new *((          - c3o1*bxyz +     cxyz)/(c54o1*o)));
-   //xy_ZERO=   c1o16*eps_new;
-   xy_TNE = -(c1o16*eps_new *((     axyz +     bxyz           )/(c72o1*o)));
-   xy_TSW =   c1o16*eps_new *((     axyz +     bxyz           )/(c72o1*o));
-   xy_TSE =   c1o16*eps_new *((-    axyz +     bxyz           )/(c72o1*o));
-   xy_TNW =   c1o16*eps_new *((     axyz -     bxyz           )/(c72o1*o));
-
-   xz_E   =   c1o16*eps_new *((            c2o1*bxyz           )/(c27o1*o));
-   xz_N   = -(c1o16*eps_new *((            c4o1*bxyz           )/(c27o1*o)));
-   xz_T   =   c1o16*eps_new *((            c2o1*bxyz           )/(c27o1*o));
-   xz_NE  = -(c1o16*eps_new *(( c3o1*axyz +     bxyz           )/(c54o1*o)));
-   xz_SE  = -(c1o16*eps_new *((-c3o1*axyz +     bxyz           )/(c54o1*o)));
-   xz_TE  =   c1o16*eps_new *((                bxyz           )/(c27o1*o));
-   xz_BE  =   c1o16*eps_new *((                bxyz           )/(c27o1*o));
-   xz_TN  = -(c1o16*eps_new *((                bxyz + c3o1*cxyz)/(c54o1*o)));
-   xz_BN  = -(c1o16*eps_new *((                bxyz - c3o1*cxyz)/(c54o1*o)));
-   //xz_ZERO=   c1o16*eps_new;
-   xz_TNE = -(c1o16*eps_new *((     axyz            +     cxyz)/(c72o1*o)));
-   xz_TSW =   c1o16*eps_new *((-    axyz            +     cxyz)/(c72o1*o));
-   xz_TSE =   c1o16*eps_new *((     axyz            +     cxyz)/(c72o1*o));
-   xz_TNW =   c1o16*eps_new *((     axyz            -     cxyz)/(c72o1*o));
-
-   yz_E   = -(c1o16*eps_new *(( c4o1*axyz                      )/(c27o1*o)));
-   yz_N   =   c1o16*eps_new *(( c2o1*axyz                      )/(c27o1*o));
-   yz_T   =   c1o16*eps_new *(( c2o1*axyz                      )/(c27o1*o));
-   yz_NE  = -(c1o16*eps_new *((     axyz + c3o1*bxyz           )/(c54o1*o)));
-   yz_SE  = -(c1o16*eps_new *((     axyz - c3o1*bxyz           )/(c54o1*o)));
-   yz_TE  = -(c1o16*eps_new *((     axyz            + c3o1*cxyz)/(c54o1*o)));
-   yz_BE  = -(c1o16*eps_new *((     axyz            - c3o1*cxyz)/(c54o1*o)));
-   yz_TN  =   c1o16*eps_new *((     axyz                      )/(c27o1*o));
-   yz_BN  =   c1o16*eps_new *((     axyz                      )/(c27o1*o));
-   //yz_ZERO=   c1o16*eps_new;
-   yz_TNE = -(c1o16*eps_new *((                bxyz +     cxyz)/(c72o1*o)));
-   yz_TSW =   c1o16*eps_new *((          -     bxyz +     cxyz)/(c72o1*o));
-   yz_TSE =   c1o16*eps_new *((                bxyz -     cxyz)/(c72o1*o));
-   yz_TNW =   c1o16*eps_new *((                bxyz +     cxyz)/(c72o1*o));
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::calcInterpolatedNodeCF(real* f, real omega, real x, real y, real z, real press, real xs, real ys, real zs)
-{
-   using namespace D3Q27System;
-   using namespace vf::lbm::dir;
-   using namespace vf::basics::constant;
-
-   real eps_new = c1o2;
-   real o = omega;
-   //bulk viscosity
-   real oP = OxxPyyPzzF;
-
-//   LBMReal rho  = press ;//+ (c2o1*axx*x+axy*y+axz*z+axyz*y*z+ax + c2o1*byy*y+bxy*x+byz*z+bxyz*x*z+by + c2o1*czz*z+cxz*x+cyz*y+cxyz*x*y+cz)/c3o1;
-   real vx1  = a0 + c1o4*( xs*ax + ys*ay + zs*az) + c1o16*(axx + xs*ys*axy + xs*zs*axz + ayy + ys*zs*ayz + azz) + c1o64*(xs*ys*zs*axyz);
-   real vx2  = b0 + c1o4*( xs*bx + ys*by + zs*bz) + c1o16*(bxx + xs*ys*bxy + xs*zs*bxz + byy + ys*zs*byz + bzz) + c1o64*(xs*ys*zs*bxyz);
-   real vx3  = c0 + c1o4*( xs*cx + ys*cy + zs*cz) + c1o16*(cxx + xs*ys*cxy + xs*zs*cxz + cyy + ys*zs*cyz + czz) + c1o64*(xs*ys*zs*cxyz);
-
-   real mfcbb = c0o1;
-   real mfabb = c0o1;
-   real mfbcb = c0o1;
-   real mfbab = c0o1;
-   real mfbbc = c0o1;
-   real mfbba = c0o1;
-   real mfccb = c0o1;
-   real mfaab = c0o1;
-   real mfcab = c0o1;
-   real mfacb = c0o1;
-   real mfcbc = c0o1;
-   real mfaba = c0o1;
-   real mfcba = c0o1;
-   real mfabc = c0o1;
-   real mfbcc = c0o1;
-   real mfbaa = c0o1;
-   real mfbca = c0o1;
-   real mfbac = c0o1;
-   real mfbbb = c0o1;
-   real mfccc = c0o1;
-   real mfaac = c0o1;
-   real mfcac = c0o1;
-   real mfacc = c0o1;
-   real mfcca = c0o1;
-   real mfaaa = c0o1;
-   real mfcaa = c0o1;
-   real mfaca = c0o1;
-
-   mfaaa = press; // if drho is interpolated directly
-
-   real vx1Sq = vx1*vx1;
-   real vx2Sq = vx2*vx2;
-   real vx3Sq = vx3*vx3;
-   real oMdrho = c1o1;
-
-   //c2o1f
-
-   // linear combinations
-   real mxxPyyPzz = mfaaa - c2o3*(ax + by + c2o1 *axx*x + bxy*x + axy*y + c2o1 *byy*y + axz*z + byz*z + bxyz*x*z + axyz*y*z + cz - cxz*x + cyz*y + cxyz*x*y + c2o1 *czz*z)*eps_new / oP* (c1o1 + press);
-   real mxxMyy    = -c2o3*(ax - by + kxxMyyAverage + c2o1 *axx*x - bxy*x + axy*y - c2o1 *byy*y + axz*z - byz*z - bxyz*x*z + axyz*y*z)*eps_new/o * (c1o1 + press);
-   real mxxMzz    = -c2o3*(ax - cz + kxxMzzAverage + c2o1 *axx*x - cxz*x + axy*y - cyz*y - cxyz*x*y + axz*z - c2o1 *czz*z + axyz*y*z)*eps_new/o * (c1o1 + press);
-
-   mfabb     = -c1o3 * (bz + cy + kyzAverage + bxz*x + cxy*x + byz*y + c2o1 *cyy*y + bxyz*x*y + c2o1 *bzz*z + cyz*z + cxyz*x*z)*eps_new/o * (c1o1 + press);
-   mfbab     = -c1o3 * (az + cx + kxzAverage + axz*x + c2o1 *cxx*x + ayz*y + cxy*y + axyz*x*y + c2o1 *azz*z + cxz*z + cxyz*y*z)*eps_new/o * (c1o1 + press);
-   mfbba     = -c1o3 * (ay + bx + kxyAverage + axy*x + c2o1 *bxx*x + c2o1 *ayy*y + bxy*y + ayz*z + bxz*z + axyz*x*z + bxyz*y*z)*eps_new/o * (c1o1 + press);
-
-   // linear combinations back
-   mfcaa = c1o3 * (mxxMyy +       mxxMzz + mxxPyyPzz) ;
-   mfaca = c1o3 * (-c2o1 * mxxMyy +       mxxMzz + mxxPyyPzz) ;
-   mfaac = c1o3 * (mxxMyy - c2o1 * mxxMzz + mxxPyyPzz) ;
-
-   //three
-   mfbbb = c0o1;
-   real mxxyPyzz = c0o1;
-   real mxxyMyzz = c0o1;
-   real mxxzPyyz = c0o1;
-   real mxxzMyyz = c0o1;
-   real mxyyPxzz = c0o1;
-   real mxyyMxzz = c0o1;
-
-   // linear combinations back
-   mfcba = (mxxyMyzz + mxxyPyzz) * c1o2;
-   mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
-   mfcab = (mxxzMyyz + mxxzPyyz) * c1o2;
-   mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
-   mfbca = (mxyyMxzz + mxyyPxzz) * c1o2;
-   mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
-
-   //4.f
-   mfacc = mfaaa*c1o9;
-   mfcac = mfacc;
-   mfcca = mfacc;
-
-   //5.
-
-   //6.
-
-   mfccc = mfaaa*c1o27;
-   ////////////////////////////////////////////////////////////////////////////////////
-   //back
-   ////////////////////////////////////////////////////////////////////////////////////
-   //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
-   ////////////////////////////////////////////////////////////////////////////////////
-   // Z - Dir
-   real m0 =  mfaac * c1o2 +      mfaab * (vx3 - c1o2) + (mfaaa + c1o1 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   real m1 = -mfaac        - c2o1 * mfaab *  vx3         +  mfaaa                * (c1o1 - vx3Sq)              - c1o1 * oMdrho * vx3Sq;
-   real m2 =  mfaac * c1o2 +      mfaab * (vx3 + c1o2) + (mfaaa + c1o1 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfaaa = m0;
-   mfaab = m1;
-   mfaac = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfabc * c1o2 +      mfabb * (vx3 - c1o2) + mfaba * (vx3Sq - vx3) * c1o2;
-   m1 = -mfabc        - c2o1 * mfabb *  vx3         + mfaba * (c1o1 - vx3Sq);
-   m2 =  mfabc * c1o2 +      mfabb * (vx3 + c1o2) + mfaba * (vx3Sq + vx3) * c1o2;
-   mfaba = m0;
-   mfabb = m1;
-   mfabc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfacc * c1o2 +      mfacb * (vx3 - c1o2) + (mfaca + c1o3 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   m1 = -mfacc        - c2o1 * mfacb *  vx3         +  mfaca                  * (c1o1 - vx3Sq)              - c1o3 * oMdrho * vx3Sq;
-   m2 =  mfacc * c1o2 +      mfacb * (vx3 + c1o2) + (mfaca + c1o3 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfaca = m0;
-   mfacb = m1;
-   mfacc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfbac * c1o2 +      mfbab * (vx3 - c1o2) + mfbaa * (vx3Sq - vx3) * c1o2;
-   m1 = -mfbac        - c2o1 * mfbab *  vx3         + mfbaa * (c1o1 - vx3Sq);
-   m2 =  mfbac * c1o2 +      mfbab * (vx3 + c1o2) + mfbaa * (vx3Sq + vx3) * c1o2;
-   mfbaa = m0;
-   mfbab = m1;
-   mfbac = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbbc * c1o2 +      mfbbb * (vx3 - c1o2) + mfbba * (vx3Sq - vx3) * c1o2;
-   m1 = -mfbbc        - c2o1 * mfbbb *  vx3         + mfbba * (c1o1 - vx3Sq);
-   m2 =  mfbbc * c1o2 +      mfbbb * (vx3 + c1o2) + mfbba * (vx3Sq + vx3) * c1o2;
-   mfbba = m0;
-   mfbbb = m1;
-   mfbbc = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbcc * c1o2 +      mfbcb * (vx3 - c1o2) + mfbca * (vx3Sq - vx3) * c1o2;
-   m1 = -mfbcc        - c2o1 * mfbcb *  vx3         + mfbca * (c1o1 - vx3Sq);
-   m2 =  mfbcc * c1o2 +      mfbcb * (vx3 + c1o2) + mfbca * (vx3Sq + vx3) * c1o2;
-   mfbca = m0;
-   mfbcb = m1;
-   mfbcc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcac * c1o2 +      mfcab * (vx3 - c1o2) + (mfcaa + c1o3 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   m1 = -mfcac        - c2o1 * mfcab *  vx3         +  mfcaa                  * (c1o1 - vx3Sq)              - c1o3 * oMdrho * vx3Sq;
-   m2 =  mfcac * c1o2 +      mfcab * (vx3 + c1o2) + (mfcaa + c1o3 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfcaa = m0;
-   mfcab = m1;
-   mfcac = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfcbc * c1o2 +      mfcbb * (vx3 - c1o2) + mfcba * (vx3Sq - vx3) * c1o2;
-   m1 = -mfcbc        - c2o1 * mfcbb *  vx3         + mfcba * (c1o1 - vx3Sq);
-   m2 =  mfcbc * c1o2 +      mfcbb * (vx3 + c1o2) + mfcba * (vx3Sq + vx3) * c1o2;
-   mfcba = m0;
-   mfcbb = m1;
-   mfcbc = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfccc * c1o2 +      mfccb * (vx3 - c1o2) + (mfcca + c1o9 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   m1 = -mfccc        - c2o1 * mfccb *  vx3         +  mfcca                  * (c1o1 - vx3Sq)              - c1o9 * oMdrho * vx3Sq;
-   m2 =  mfccc * c1o2 +      mfccb * (vx3 + c1o2) + (mfcca + c1o9 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfcca = m0;
-   mfccb = m1;
-   mfccc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
-   ////////////////////////////////////////////////////////////////////////////////////
-   // Y - Dir
-   m0 =  mfaca * c1o2 +      mfaba * (vx2 - c1o2) + (mfaaa + c1o6 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfaca        - c2o1 * mfaba *  vx2         +  mfaaa                  * (c1o1 - vx2Sq)              - c1o6 * oMdrho * vx2Sq;
-   m2 =  mfaca * c1o2 +      mfaba * (vx2 + c1o2) + (mfaaa + c1o6 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfaaa = m0;
-   mfaba = m1;
-   mfaca = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfacb * c1o2 +      mfabb * (vx2 - c1o2) + (mfaab + c2o3 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfacb        - c2o1 * mfabb *  vx2         +  mfaab                  * (c1o1 - vx2Sq)              - c2o3 * oMdrho * vx2Sq;
-   m2 =  mfacb * c1o2 +      mfabb * (vx2 + c1o2) + (mfaab + c2o3 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfaab = m0;
-   mfabb = m1;
-   mfacb = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfacc * c1o2 +      mfabc * (vx2 - c1o2) + (mfaac + c1o6 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfacc        - c2o1 * mfabc *  vx2         +  mfaac                  * (c1o1 - vx2Sq)              - c1o6 * oMdrho * vx2Sq;
-   m2 =  mfacc * c1o2 +      mfabc * (vx2 + c1o2) + (mfaac + c1o6 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfaac = m0;
-   mfabc = m1;
-   mfacc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfbca * c1o2 +      mfbba * (vx2 - c1o2) + mfbaa * (vx2Sq - vx2) * c1o2;
-   m1 = -mfbca        - c2o1 * mfbba *  vx2         + mfbaa * (c1o1 - vx2Sq);
-   m2 =  mfbca * c1o2 +      mfbba * (vx2 + c1o2) + mfbaa * (vx2Sq + vx2) * c1o2;
-   mfbaa = m0;
-   mfbba = m1;
-   mfbca = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbcb * c1o2 +      mfbbb * (vx2 - c1o2) + mfbab * (vx2Sq - vx2) * c1o2;
-   m1 = -mfbcb        - c2o1 * mfbbb *  vx2         + mfbab * (c1o1 - vx2Sq);
-   m2 =  mfbcb * c1o2 +      mfbbb * (vx2 + c1o2) + mfbab * (vx2Sq + vx2) * c1o2;
-   mfbab = m0;
-   mfbbb = m1;
-   mfbcb = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbcc * c1o2 +      mfbbc * (vx2 - c1o2) + mfbac * (vx2Sq - vx2) * c1o2;
-   m1 = -mfbcc        - c2o1 * mfbbc *  vx2         + mfbac * (c1o1 - vx2Sq);
-   m2 =  mfbcc * c1o2 +      mfbbc * (vx2 + c1o2) + mfbac * (vx2Sq + vx2) * c1o2;
-   mfbac = m0;
-   mfbbc = m1;
-   mfbcc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcca * c1o2 +      mfcba * (vx2 - c1o2) + (mfcaa + c1o18 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfcca        - c2o1 * mfcba *  vx2         +  mfcaa                   * (c1o1 - vx2Sq)              - c1o18 * oMdrho * vx2Sq;
-   m2 =  mfcca * c1o2 +      mfcba * (vx2 + c1o2) + (mfcaa + c1o18 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfcaa = m0;
-   mfcba = m1;
-   mfcca = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfccb * c1o2 +      mfcbb * (vx2 - c1o2) + (mfcab + c2o9 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfccb        - c2o1 * mfcbb *  vx2         +  mfcab                  * (c1o1 - vx2Sq)              - c2o9 * oMdrho * vx2Sq;
-   m2 =  mfccb * c1o2 +      mfcbb * (vx2 + c1o2) + (mfcab + c2o9 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfcab = m0;
-   mfcbb = m1;
-   mfccb = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfccc * c1o2 +      mfcbc * (vx2 - c1o2) + (mfcac + c1o18 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfccc        - c2o1 * mfcbc *  vx2         +  mfcac                   * (c1o1 - vx2Sq)              - c1o18 * oMdrho * vx2Sq;
-   m2 =  mfccc * c1o2 +      mfcbc * (vx2 + c1o2) + (mfcac + c1o18 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfcac = m0;
-   mfcbc = m1;
-   mfccc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
-   ////////////////////////////////////////////////////////////////////////////////////
-   // X - Dir
-   m0 =  mfcaa * c1o2 +      mfbaa * (vx1 - c1o2) + (mfaaa + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcaa        - c2o1 * mfbaa *  vx1         +  mfaaa                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfcaa * c1o2 +      mfbaa * (vx1 + c1o2) + (mfaaa + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaaa = m0;
-   mfbaa = m1;
-   mfcaa = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcba * c1o2 +      mfbba * (vx1 - c1o2) + (mfaba + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcba        - c2o1 * mfbba *  vx1         +  mfaba                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfcba * c1o2 +      mfbba * (vx1 + c1o2) + (mfaba + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaba = m0;
-   mfbba = m1;
-   mfcba = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcca * c1o2 +      mfbca * (vx1 - c1o2) + (mfaca + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcca        - c2o1 * mfbca *  vx1         +  mfaca                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfcca * c1o2 +      mfbca * (vx1 + c1o2) + (mfaca + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaca = m0;
-   mfbca = m1;
-   mfcca = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcab * c1o2 +      mfbab * (vx1 - c1o2) + (mfaab + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcab        - c2o1 * mfbab *  vx1         +  mfaab                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfcab * c1o2 +      mfbab * (vx1 + c1o2) + (mfaab + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaab = m0;
-   mfbab = m1;
-   mfcab = m2;
-   ///////////b////////////////////////////////////////////////////////////////////////
-   m0 =  mfcbb * c1o2 +      mfbbb * (vx1 - c1o2) + (mfabb + c4o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcbb        - c2o1 * mfbbb *  vx1         +  mfabb                  * (c1o1 - vx1Sq)              - c4o9 * oMdrho * vx1Sq;
-   m2 =  mfcbb * c1o2 +      mfbbb * (vx1 + c1o2) + (mfabb + c4o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfabb = m0;
-   mfbbb = m1;
-   mfcbb = m2;
-   ///////////b////////////////////////////////////////////////////////////////////////
-   m0 =  mfccb * c1o2 +      mfbcb * (vx1 - c1o2) + (mfacb + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfccb        - c2o1 * mfbcb *  vx1         +  mfacb                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfccb * c1o2 +      mfbcb * (vx1 + c1o2) + (mfacb + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfacb = m0;
-   mfbcb = m1;
-   mfccb = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcac * c1o2 +      mfbac * (vx1 - c1o2) + (mfaac + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcac        - c2o1 * mfbac *  vx1         +  mfaac                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfcac * c1o2 +      mfbac * (vx1 + c1o2) + (mfaac + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaac = m0;
-   mfbac = m1;
-   mfcac = m2;
-   ///////////c////////////////////////////////////////////////////////////////////////
-   m0 =  mfcbc * c1o2 +      mfbbc * (vx1 - c1o2) + (mfabc + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcbc        - c2o1 * mfbbc *  vx1         +  mfabc                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfcbc * c1o2 +      mfbbc * (vx1 + c1o2) + (mfabc + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfabc = m0;
-   mfbbc = m1;
-   mfcbc = m2;
-   ///////////c////////////////////////////////////////////////////////////////////////
-   m0 =  mfccc * c1o2 +      mfbcc * (vx1 - c1o2) + (mfacc + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfccc        - c2o1 * mfbcc *  vx1         +  mfacc                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfccc * c1o2 +      mfbcc * (vx1 + c1o2) + (mfacc + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfacc = m0;
-   mfbcc = m1;
-   mfccc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-
-   f[DIR_P00] = mfcbb;
-   f[DIR_M00] = mfabb;
-   f[DIR_0P0] = mfbcb;
-   f[DIR_0M0] = mfbab;
-   f[DIR_00P] = mfbbc;
-   f[DIR_00M] = mfbba;
-   f[DIR_PP0] = mfccb;
-   f[DIR_MM0] = mfaab;
-   f[DIR_PM0] = mfcab;
-   f[DIR_MP0] = mfacb;
-   f[DIR_P0P] = mfcbc;
-   f[DIR_M0M] = mfaba;
-   f[DIR_P0M] = mfcba;
-   f[DIR_M0P] = mfabc;
-   f[DIR_0PP] = mfbcc;
-   f[DIR_0MM] = mfbaa;
-   f[DIR_0PM] = mfbca;
-   f[DIR_0MP] = mfbac;
-   f[DIR_000] = mfbbb;
-   f[DIR_PPP] = mfccc;
-   f[DIR_PMP] = mfcac;
-   f[DIR_PPM] = mfcca;
-   f[DIR_PMM] = mfcaa;
-   f[DIR_MPP] = mfacc;
-   f[DIR_MMP] = mfaac;
-   f[DIR_MPM] = mfaca;
-   f[DIR_MMM] = mfaaa;
-}
-//////////////////////////////////////////////////////////////////////////
-//Position SWB -0.25, -0.25, -0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressBSW()
-{
-   return   press_SWT * (c9o64 + c3o16 * xoff + c3o16 * yoff - c9o16 * zoff) +
-      press_NWT * (c3o64 + c1o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
-      press_SET * (c3o64 - c3o16 * xoff + c1o16 * yoff - c3o16 * zoff) +
-      press_NET * (c1o64 - c1o16 * xoff - c1o16 * yoff - c1o16 * zoff) +
-      press_NEB * (c3o64 - c3o16 * xoff - c3o16 * yoff + c1o16 * zoff) +
-      press_NWB * (c9o64 + c3o16 * xoff - c9o16 * yoff + c3o16 * zoff) +
-      press_SEB * (c9o64 - c9o16 * xoff + c3o16 * yoff + c3o16 * zoff) +
-      press_SWB * (c27o64 + c9o16 * xoff + c9o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position SWT -0.25, -0.25, 0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressTSW()
-{
-   return   press_SWT * (c27o64 + c9o16 * xoff + c9o16 * yoff - c9o16 * zoff) +
-      press_NWT * (c9o64 + c3o16 * xoff - c9o16 * yoff - c3o16 * zoff) +
-      press_SET * (c9o64 - c9o16 * xoff + c3o16 * yoff - c3o16 * zoff) +
-      press_NET * (c3o64 - c3o16 * xoff - c3o16 * yoff - c1o16 * zoff) +
-      press_NEB * (c1o64 - c1o16 * xoff - c1o16 * yoff + c1o16 * zoff) +
-      press_NWB * (c3o64 + c1o16 * xoff - c3o16 * yoff + c3o16 * zoff) +
-      press_SEB * (c3o64 - c3o16 * xoff + c1o16 * yoff + c3o16 * zoff) +
-      press_SWB * (c9o64 + c3o16 * xoff + c3o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position SET 0.25, -0.25, 0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressTSE()
-{
-   return   press_SET * (c27o64 - c9o16 * xoff + c9o16 * yoff - c9o16 * zoff) +
-      press_NET * (c9o64 - c3o16 * xoff - c9o16 * yoff - c3o16 * zoff) +
-      press_SWT * (c9o64 + c9o16 * xoff + c3o16 * yoff - c3o16 * zoff) +
-      press_NWT * (c3o64 + c3o16 * xoff - c3o16 * yoff - c1o16 * zoff) +
-      press_NWB * (c1o64 + c1o16 * xoff - c1o16 * yoff + c1o16 * zoff) +
-      press_NEB * (c3o64 - c1o16 * xoff - c3o16 * yoff + c3o16 * zoff) +
-      press_SWB * (c3o64 + c3o16 * xoff + c1o16 * yoff + c3o16 * zoff) +
-      press_SEB * (c9o64 - c3o16 * xoff + c3o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position SEB 0.25, -0.25, -0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressBSE()
-{
-   return   press_SET * (c9o64 - c3o16 * xoff + c3o16 * yoff - c9o16 * zoff) +
-      press_NET * (c3o64 - c1o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
-      press_SWT * (c3o64 + c3o16 * xoff + c1o16 * yoff - c3o16 * zoff) +
-      press_NWT * (c1o64 + c1o16 * xoff - c1o16 * yoff - c1o16 * zoff) +
-      press_NWB * (c3o64 + c3o16 * xoff - c3o16 * yoff + c1o16 * zoff) +
-      press_NEB * (c9o64 - c3o16 * xoff - c9o16 * yoff + c3o16 * zoff) +
-      press_SWB * (c9o64 + c9o16 * xoff + c3o16 * yoff + c3o16 * zoff) +
-      press_SEB * (c27o64 - c9o16 * xoff + c9o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position NWB -0.25, 0.25, -0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressBNW()
-{
-   return   press_NWT * (c9o64 + c3o16 * xoff - c3o16 * yoff - c9o16 * zoff) +
-      press_NET * (c3o64 - c3o16 * xoff - c1o16 * yoff - c3o16 * zoff) +
-      press_SWT * (c3o64 + c1o16 * xoff + c3o16 * yoff - c3o16 * zoff) +
-      press_SET * (c1o64 - c1o16 * xoff + c1o16 * yoff - c1o16 * zoff) +
-      press_SEB * (c3o64 - c3o16 * xoff + c3o16 * yoff + c1o16 * zoff) +
-      press_NEB * (c9o64 - c9o16 * xoff - c3o16 * yoff + c3o16 * zoff) +
-      press_SWB * (c9o64 + c3o16 * xoff + c9o16 * yoff + c3o16 * zoff) +
-      press_NWB * (c27o64 + c9o16 * xoff - c9o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position NWT -0.25, 0.25, 0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressTNW()
-{
-   return   press_NWT * (c27o64 + c9o16 * xoff - c9o16 * yoff - c9o16 * zoff) +
-      press_NET * (c9o64 - c9o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
-      press_SWT * (c9o64 + c3o16 * xoff + c9o16 * yoff - c3o16 * zoff) +
-      press_SET * (c3o64 - c3o16 * xoff + c3o16 * yoff - c1o16 * zoff) +
-      press_SEB * (c1o64 - c1o16 * xoff + c1o16 * yoff + c1o16 * zoff) +
-      press_NEB * (c3o64 - c3o16 * xoff - c1o16 * yoff + c3o16 * zoff) +
-      press_SWB * (c3o64 + c1o16 * xoff + c3o16 * yoff + c3o16 * zoff) +
-      press_NWB * (c9o64 + c3o16 * xoff - c3o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position NET 0.25, 0.25, 0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressTNE()
-{
-   return   press_NET * (c27o64 - c9o16 * xoff - c9o16 * yoff - c9o16 * zoff) +
-      press_NWT * (c9o64 + c9o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
-      press_SET * (c9o64 - c3o16 * xoff + c9o16 * yoff - c3o16 * zoff) +
-      press_SWT * (c3o64 + c3o16 * xoff + c3o16 * yoff - c1o16 * zoff) +
-      press_SWB * (c1o64 + c1o16 * xoff + c1o16 * yoff + c1o16 * zoff) +
-      press_NWB * (c3o64 + c3o16 * xoff - c1o16 * yoff + c3o16 * zoff) +
-      press_SEB * (c3o64 - c1o16 * xoff + c3o16 * yoff + c3o16 * zoff) +
-      press_NEB * (c9o64 - c3o16 * xoff - c3o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position NEB 0.25, 0.25, -0.25
-real CompressibleOffsetMomentsInterpolationProcessor::calcPressBNE()
-{
-   return   press_NET * (c9o64 - c3o16 * xoff - c3o16 * yoff - c9o16 * zoff) +
-      press_NWT * (c3o64 + c3o16 * xoff - c1o16 * yoff - c3o16 * zoff) +
-      press_SET * (c3o64 - c1o16 * xoff + c3o16 * yoff - c3o16 * zoff) +
-      press_SWT * (c1o64 + c1o16 * xoff + c1o16 * yoff - c1o16 * zoff) +
-      press_SWB * (c3o64 + c3o16 * xoff + c3o16 * yoff + c1o16 * zoff) +
-      press_NWB * (c9o64 + c9o16 * xoff - c3o16 * yoff + c3o16 * zoff) +
-      press_SEB * (c9o64 - c3o16 * xoff + c9o16 * yoff + c3o16 * zoff) +
-      press_NEB * (c27o64 - c9o16 * xoff - c9o16 * yoff + c9o16 * zoff);
-}
-//////////////////////////////////////////////////////////////////////////
-//Position C 0.0, 0.0, 0.0
-void CompressibleOffsetMomentsInterpolationProcessor::calcInterpolatedNodeFC(real* f, real omega)
-{
-   using namespace D3Q27System;
-   using namespace vf::lbm::dir;
-
-   real press  =  press_NET * (c4o32 - c1o4 * xoff - c1o4 * yoff - c1o4 * zoff) +
-      press_NWT * (c4o32 + c1o4 * xoff - c1o4 * yoff - c1o4 * zoff) +
-      press_SET * (c4o32 - c1o4 * xoff + c1o4 * yoff - c1o4 * zoff) +
-      press_SWT * (c4o32 + c1o4 * xoff + c1o4 * yoff - c1o4 * zoff) +
-      press_NEB * (c4o32 - c1o4 * xoff - c1o4 * yoff + c1o4 * zoff) +
-      press_NWB * (c4o32 + c1o4 * xoff - c1o4 * yoff + c1o4 * zoff) +
-      press_SEB * (c4o32 - c1o4 * xoff + c1o4 * yoff + c1o4 * zoff) +
-      press_SWB * (c4o32 + c1o4 * xoff + c1o4 * yoff + c1o4 * zoff);
-   real vx1  = a0;
-   real vx2  = b0;
-   real vx3  = c0;
-
-//   LBMReal rho = press ;//+ (ax+by+cz)/c3o1;
-
-   real eps_new = c2o1;
-   real o  = omega;
-   //bulk viscosity
-   real oP = OxxPyyPzzC;
-
-   real mfcbb = c0o1;
-   real mfabb = c0o1;
-   real mfbcb = c0o1;
-   real mfbab = c0o1;
-   real mfbbc = c0o1;
-   real mfbba = c0o1;
-   real mfccb = c0o1;
-   real mfaab = c0o1;
-   real mfcab = c0o1;
-   real mfacb = c0o1;
-   real mfcbc = c0o1;
-   real mfaba = c0o1;
-   real mfcba = c0o1;
-   real mfabc = c0o1;
-   real mfbcc = c0o1;
-   real mfbaa = c0o1;
-   real mfbca = c0o1;
-   real mfbac = c0o1;
-   real mfbbb = c0o1;
-   real mfccc = c0o1;
-   real mfaac = c0o1;
-   real mfcac = c0o1;
-   real mfacc = c0o1;
-   real mfcca = c0o1;
-   real mfaaa = c0o1;
-   real mfcaa = c0o1;
-   real mfaca = c0o1;
-
-   mfaaa = press; // if drho is interpolated directly
-
-   real vx1Sq = vx1*vx1;
-   real vx2Sq = vx2*vx2;
-   real vx3Sq = vx3*vx3;
-   real oMdrho = c1o1;
-   //oMdrho = one - mfaaa;
-
-   //2.f
-   // linear combinations
-
-/////////////////////////
-   real mxxPyyPzz = mfaaa    -c2o3*(ax+by+cz)*eps_new/oP*(c1o1 +press);
-
-   real mxxMyy    = -c2o3*((ax - by)+kxxMyyAverage)*eps_new/o * (c1o1 + press);
-   real mxxMzz    = -c2o3*((ax - cz)+kxxMzzAverage)*eps_new/o * (c1o1 + press);
-
-   mfabb     = -c1o3 * ((bz + cy)+kyzAverage)*eps_new/o * (c1o1 + press);
-   mfbab     = -c1o3 * ((az + cx)+kxzAverage)*eps_new/o * (c1o1 + press);
-   mfbba     = -c1o3 * ((ay + bx)+kxyAverage)*eps_new/o * (c1o1 + press);
-
-   ////////////////////////
-   // linear combinations back
-   mfcaa = c1o3 * (mxxMyy +       mxxMzz + mxxPyyPzz);
-   mfaca = c1o3 * (-c2o1 * mxxMyy +       mxxMzz + mxxPyyPzz);
-   mfaac = c1o3 * (mxxMyy - c2o1 * mxxMzz + mxxPyyPzz);
-
-   //three
-   mfbbb = c0o1;
-
-   real mxxyPyzz = c0o1;
-   real mxxyMyzz = c0o1;
-   real mxxzPyyz = c0o1;
-   real mxxzMyyz = c0o1;
-   real mxyyPxzz = c0o1;
-   real mxyyMxzz = c0o1;
-
-   // linear combinations back
-   mfcba = (mxxyMyzz + mxxyPyzz) * c1o2;
-   mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
-   mfcab = (mxxzMyyz + mxxzPyyz) * c1o2;
-   mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
-   mfbca = (mxyyMxzz + mxyyPxzz) * c1o2;
-   mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
-
-   //4.f
-   mfacc = mfaaa*c1o9;
-   mfcac = mfacc;
-   mfcca = mfacc;
-   //5.
-
-   //6.
-   mfccc = mfaaa*c1o27;
-   ////////////////////////////////////////////////////////////////////////////////////
-   //back
-   ////////////////////////////////////////////////////////////////////////////////////
-   //mit 1, 0, 1/3, 0, 0, 0, 1/3, 0, 1/9   Konditionieren
-   ////////////////////////////////////////////////////////////////////////////////////
-   // Z - Dir
-   real m0 =  mfaac * c1o2 +      mfaab * (vx3 - c1o2) + (mfaaa + c1o1 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   real m1 = -mfaac        - c2o1 * mfaab *  vx3         +  mfaaa                * (c1o1 - vx3Sq)              - c1o1 * oMdrho * vx3Sq;
-   real m2 =  mfaac * c1o2 +      mfaab * (vx3 + c1o2) + (mfaaa + c1o1 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfaaa = m0;
-   mfaab = m1;
-   mfaac = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfabc * c1o2 +      mfabb * (vx3 - c1o2) + mfaba * (vx3Sq - vx3) * c1o2;
-   m1 = -mfabc        - c2o1 * mfabb *  vx3         + mfaba * (c1o1 - vx3Sq);
-   m2 =  mfabc * c1o2 +      mfabb * (vx3 + c1o2) + mfaba * (vx3Sq + vx3) * c1o2;
-   mfaba = m0;
-   mfabb = m1;
-   mfabc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfacc * c1o2 +      mfacb * (vx3 - c1o2) + (mfaca + c1o3 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   m1 = -mfacc        - c2o1 * mfacb *  vx3         +  mfaca                  * (c1o1 - vx3Sq)              - c1o3 * oMdrho * vx3Sq;
-   m2 =  mfacc * c1o2 +      mfacb * (vx3 + c1o2) + (mfaca + c1o3 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfaca = m0;
-   mfacb = m1;
-   mfacc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfbac * c1o2 +      mfbab * (vx3 - c1o2) + mfbaa * (vx3Sq - vx3) * c1o2;
-   m1 = -mfbac        - c2o1 * mfbab *  vx3         + mfbaa * (c1o1 - vx3Sq);
-   m2 =  mfbac * c1o2 +      mfbab * (vx3 + c1o2) + mfbaa * (vx3Sq + vx3) * c1o2;
-   mfbaa = m0;
-   mfbab = m1;
-   mfbac = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbbc * c1o2 +      mfbbb * (vx3 - c1o2) + mfbba * (vx3Sq - vx3) * c1o2;
-   m1 = -mfbbc        - c2o1 * mfbbb *  vx3         + mfbba * (c1o1 - vx3Sq);
-   m2 =  mfbbc * c1o2 +      mfbbb * (vx3 + c1o2) + mfbba * (vx3Sq + vx3) * c1o2;
-   mfbba = m0;
-   mfbbb = m1;
-   mfbbc = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbcc * c1o2 +      mfbcb * (vx3 - c1o2) + mfbca * (vx3Sq - vx3) * c1o2;
-   m1 = -mfbcc        - c2o1 * mfbcb *  vx3         + mfbca * (c1o1 - vx3Sq);
-   m2 =  mfbcc * c1o2 +      mfbcb * (vx3 + c1o2) + mfbca * (vx3Sq + vx3) * c1o2;
-   mfbca = m0;
-   mfbcb = m1;
-   mfbcc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcac * c1o2 +      mfcab * (vx3 - c1o2) + (mfcaa + c1o3 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   m1 = -mfcac        - c2o1 * mfcab *  vx3         +  mfcaa                  * (c1o1 - vx3Sq)              - c1o3 * oMdrho * vx3Sq;
-   m2 =  mfcac * c1o2 +      mfcab * (vx3 + c1o2) + (mfcaa + c1o3 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfcaa = m0;
-   mfcab = m1;
-   mfcac = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfcbc * c1o2 +      mfcbb * (vx3 - c1o2) + mfcba * (vx3Sq - vx3) * c1o2;
-   m1 = -mfcbc        - c2o1 * mfcbb *  vx3         + mfcba * (c1o1 - vx3Sq);
-   m2 =  mfcbc * c1o2 +      mfcbb * (vx3 + c1o2) + mfcba * (vx3Sq + vx3) * c1o2;
-   mfcba = m0;
-   mfcbb = m1;
-   mfcbc = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfccc * c1o2 +      mfccb * (vx3 - c1o2) + (mfcca + c1o9 * oMdrho) * (vx3Sq - vx3) * c1o2;
-   m1 = -mfccc        - c2o1 * mfccb *  vx3         +  mfcca                  * (c1o1 - vx3Sq)              - c1o9 * oMdrho * vx3Sq;
-   m2 =  mfccc * c1o2 +      mfccb * (vx3 + c1o2) + (mfcca + c1o9 * oMdrho) * (vx3Sq + vx3) * c1o2;
-   mfcca = m0;
-   mfccb = m1;
-   mfccc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   //mit 1/6, 2/3, 1/6, 0, 0, 0, 1/18, 2/9, 1/18   Konditionieren
-   ////////////////////////////////////////////////////////////////////////////////////
-   // Y - Dir
-   m0 =  mfaca * c1o2 +      mfaba * (vx2 - c1o2) + (mfaaa + c1o6 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfaca        - c2o1 * mfaba *  vx2         +  mfaaa                  * (c1o1 - vx2Sq)              - c1o6 * oMdrho * vx2Sq;
-   m2 =  mfaca * c1o2 +      mfaba * (vx2 + c1o2) + (mfaaa + c1o6 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfaaa = m0;
-   mfaba = m1;
-   mfaca = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfacb * c1o2 +      mfabb * (vx2 - c1o2) + (mfaab + c2o3 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfacb        - c2o1 * mfabb *  vx2         +  mfaab                  * (c1o1 - vx2Sq)              - c2o3 * oMdrho * vx2Sq;
-   m2 =  mfacb * c1o2 +      mfabb * (vx2 + c1o2) + (mfaab + c2o3 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfaab = m0;
-   mfabb = m1;
-   mfacb = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfacc * c1o2 +      mfabc * (vx2 - c1o2) + (mfaac + c1o6 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfacc        - c2o1 * mfabc *  vx2         +  mfaac                  * (c1o1 - vx2Sq)              - c1o6 * oMdrho * vx2Sq;
-   m2 =  mfacc * c1o2 +      mfabc * (vx2 + c1o2) + (mfaac + c1o6 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfaac = m0;
-   mfabc = m1;
-   mfacc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfbca * c1o2 +      mfbba * (vx2 - c1o2) + mfbaa * (vx2Sq - vx2) * c1o2;
-   m1 = -mfbca        - c2o1 * mfbba *  vx2         + mfbaa * (c1o1 - vx2Sq);
-   m2 =  mfbca * c1o2 +      mfbba * (vx2 + c1o2) + mfbaa * (vx2Sq + vx2) * c1o2;
-   mfbaa = m0;
-   mfbba = m1;
-   mfbca = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbcb * c1o2 +      mfbbb * (vx2 - c1o2) + mfbab * (vx2Sq - vx2) * c1o2;
-   m1 = -mfbcb        - c2o1 * mfbbb *  vx2         + mfbab * (c1o1 - vx2Sq);
-   m2 =  mfbcb * c1o2 +      mfbbb * (vx2 + c1o2) + mfbab * (vx2Sq + vx2) * c1o2;
-   mfbab = m0;
-   mfbbb = m1;
-   mfbcb = m2;
-   /////////b//////////////////////////////////////////////////////////////////////////
-   m0 =  mfbcc * c1o2 +      mfbbc * (vx2 - c1o2) + mfbac * (vx2Sq - vx2) * c1o2;
-   m1 = -mfbcc        - c2o1 * mfbbc *  vx2         + mfbac * (c1o1 - vx2Sq);
-   m2 =  mfbcc * c1o2 +      mfbbc * (vx2 + c1o2) + mfbac * (vx2Sq + vx2) * c1o2;
-   mfbac = m0;
-   mfbbc = m1;
-   mfbcc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcca * c1o2 +      mfcba * (vx2 - c1o2) + (mfcaa + c1o18 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfcca        - c2o1 * mfcba *  vx2         +  mfcaa                   * (c1o1 - vx2Sq)              - c1o18 * oMdrho * vx2Sq;
-   m2 =  mfcca * c1o2 +      mfcba * (vx2 + c1o2) + (mfcaa + c1o18 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfcaa = m0;
-   mfcba = m1;
-   mfcca = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfccb * c1o2 +      mfcbb * (vx2 - c1o2) + (mfcab + c2o9 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfccb        - c2o1 * mfcbb *  vx2         +  mfcab                  * (c1o1 - vx2Sq)              - c2o9 * oMdrho * vx2Sq;
-   m2 =  mfccb * c1o2 +      mfcbb * (vx2 + c1o2) + (mfcab + c2o9 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfcab = m0;
-   mfcbb = m1;
-   mfccb = m2;
-   /////////c//////////////////////////////////////////////////////////////////////////
-   m0 =  mfccc * c1o2 +      mfcbc * (vx2 - c1o2) + (mfcac + c1o18 * oMdrho) * (vx2Sq - vx2) * c1o2;
-   m1 = -mfccc        - c2o1 * mfcbc *  vx2         +  mfcac                   * (c1o1 - vx2Sq)              - c1o18 * oMdrho * vx2Sq;
-   m2 =  mfccc * c1o2 +      mfcbc * (vx2 + c1o2) + (mfcac + c1o18 * oMdrho) * (vx2Sq + vx2) * c1o2;
-   mfcac = m0;
-   mfcbc = m1;
-   mfccc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   //mit 1/36, 1/9, 1/36, 1/9, 4/9, 1/9, 1/36, 1/9, 1/36 Konditionieren
-   ////////////////////////////////////////////////////////////////////////////////////
-   // X - Dir
-   m0 =  mfcaa * c1o2 +      mfbaa * (vx1 - c1o2) + (mfaaa + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcaa        - c2o1 * mfbaa *  vx1         +  mfaaa                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfcaa * c1o2 +      mfbaa * (vx1 + c1o2) + (mfaaa + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaaa = m0;
-   mfbaa = m1;
-   mfcaa = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcba * c1o2 +      mfbba * (vx1 - c1o2) + (mfaba + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcba        - c2o1 * mfbba *  vx1         +  mfaba                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfcba * c1o2 +      mfbba * (vx1 + c1o2) + (mfaba + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaba = m0;
-   mfbba = m1;
-   mfcba = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcca * c1o2 +      mfbca * (vx1 - c1o2) + (mfaca + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcca        - c2o1 * mfbca *  vx1         +  mfaca                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfcca * c1o2 +      mfbca * (vx1 + c1o2) + (mfaca + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaca = m0;
-   mfbca = m1;
-   mfcca = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcab * c1o2 +      mfbab * (vx1 - c1o2) + (mfaab + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcab        - c2o1 * mfbab *  vx1         +  mfaab                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfcab * c1o2 +      mfbab * (vx1 + c1o2) + (mfaab + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaab = m0;
-   mfbab = m1;
-   mfcab = m2;
-   ///////////b////////////////////////////////////////////////////////////////////////
-   m0 =  mfcbb * c1o2 +      mfbbb * (vx1 - c1o2) + (mfabb + c4o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcbb        - c2o1 * mfbbb *  vx1         +  mfabb                  * (c1o1 - vx1Sq)              - c4o9 * oMdrho * vx1Sq;
-   m2 =  mfcbb * c1o2 +      mfbbb * (vx1 + c1o2) + (mfabb + c4o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfabb = m0;
-   mfbbb = m1;
-   mfcbb = m2;
-   ///////////b////////////////////////////////////////////////////////////////////////
-   m0 =  mfccb * c1o2 +      mfbcb * (vx1 - c1o2) + (mfacb + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfccb        - c2o1 * mfbcb *  vx1         +  mfacb                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfccb * c1o2 +      mfbcb * (vx1 + c1o2) + (mfacb + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfacb = m0;
-   mfbcb = m1;
-   mfccb = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-   ////////////////////////////////////////////////////////////////////////////////////
-   m0 =  mfcac * c1o2 +      mfbac * (vx1 - c1o2) + (mfaac + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcac        - c2o1 * mfbac *  vx1         +  mfaac                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfcac * c1o2 +      mfbac * (vx1 + c1o2) + (mfaac + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfaac = m0;
-   mfbac = m1;
-   mfcac = m2;
-   ///////////c////////////////////////////////////////////////////////////////////////
-   m0 =  mfcbc * c1o2 +      mfbbc * (vx1 - c1o2) + (mfabc + c1o9 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfcbc        - c2o1 * mfbbc *  vx1         +  mfabc                  * (c1o1 - vx1Sq)              - c1o9 * oMdrho * vx1Sq;
-   m2 =  mfcbc * c1o2 +      mfbbc * (vx1 + c1o2) + (mfabc + c1o9 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfabc = m0;
-   mfbbc = m1;
-   mfcbc = m2;
-   ///////////c////////////////////////////////////////////////////////////////////////
-   m0 =  mfccc * c1o2 +      mfbcc * (vx1 - c1o2) + (mfacc + c1o36 * oMdrho) * (vx1Sq - vx1) * c1o2;
-   m1 = -mfccc        - c2o1 * mfbcc *  vx1         +  mfacc                   * (c1o1 - vx1Sq)              - c1o36 * oMdrho * vx1Sq;
-   m2 =  mfccc * c1o2 +      mfbcc * (vx1 + c1o2) + (mfacc + c1o36 * oMdrho) * (vx1Sq + vx1) * c1o2;
-   mfacc = m0;
-   mfbcc = m1;
-   mfccc = m2;
-   ////////////////////////////////////////////////////////////////////////////////////
-
-   f[DIR_P00] = mfcbb;
-   f[DIR_M00] = mfabb;
-   f[DIR_0P0] = mfbcb;
-   f[DIR_0M0] = mfbab;
-   f[DIR_00P] = mfbbc;
-   f[DIR_00M] = mfbba;
-   f[DIR_PP0] = mfccb;
-   f[DIR_MM0] = mfaab;
-   f[DIR_PM0] = mfcab;
-   f[DIR_MP0] = mfacb;
-   f[DIR_P0P] = mfcbc;
-   f[DIR_M0M] = mfaba;
-   f[DIR_P0M] = mfcba;
-   f[DIR_M0P] = mfabc;
-   f[DIR_0PP] = mfbcc;
-   f[DIR_0MM] = mfbaa;
-   f[DIR_0PM] = mfbca;
-   f[DIR_0MP] = mfbac;
-   f[DIR_000] = mfbbb;
-   f[DIR_PPP] = mfccc;
-   f[DIR_PMP] = mfcac;
-   f[DIR_PPM] = mfcca;
-   f[DIR_PMM] = mfcaa;
-   f[DIR_MPP] = mfacc;
-   f[DIR_MMP] = mfaac;
-   f[DIR_MPM] = mfaca;
-   f[DIR_MMM] = mfaaa;
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
-{
-	vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z+axyz*x*y*z;
-	vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z+bxyz*x*y*z;
-	vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z+cxyz*x*y*z;
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
-{
-	tauxx=ax+c2o1*axx*x+axy*y+axz*z+axyz*y*z;
-	tauyy=by+c2o1*byy*y+bxy*x+byz*z+bxyz*x*z;
-	tauzz=cz+c2o1*czz*z+cxz*x+cyz*y+cxyz*x*y;
-	tauxy= c1o2*((ay+c2o1*ayy*y+axy*x+ayz*z+axyz*x*z)+(bx+c2o1*bxx*x+bxy*y+bxz*z+bxyz*y*z));
-	tauxz= c1o2*((az+c2o1*azz*z+axz*x+ayz*y+axyz*x*y)+(cx+c2o1*cxx*x+cxy*y+cxz*z+cxyz*y*z));
-	tauyz= c1o2*((bz+c2o1*bzz*z+bxz*x+byz*y+bxyz*x*y)+(cy+c2o1*cyy*y+cxy*x+cyz*z+cxyz*x*z));
-}
-//////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetMomentsInterpolationProcessor::setBulkViscosity(real shearViscosity, real bulkViscosity)
-{
-   this->shearViscosity = shearViscosity;
-   this->bulkViscosity  = bulkViscosity;
-}
-
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetMomentsInterpolationProcessor.h b/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetMomentsInterpolationProcessor.h
deleted file mode 100644
index 32ab8cedf89e2e644f2f939f49ed4b0101eb0e32..0000000000000000000000000000000000000000
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetMomentsInterpolationProcessor.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef CompressibleOffsetMomentsInterpolationProcessor_H_
-#define CompressibleOffsetMomentsInterpolationProcessor_H_
-
-#include "InterpolationProcessor.h"
-#include "D3Q27System.h"
-
-//////////////////////////////////////////////////////////////////////////
-//it works only for cascaded LBM
-//super compact interpolation method by Martin Geier
-//////////////////////////////////////////////////////////////////////////
-
-class CompressibleOffsetMomentsInterpolationProcessor;
-
-class CompressibleOffsetMomentsInterpolationProcessor : public InterpolationProcessor
-{
-public:
-   CompressibleOffsetMomentsInterpolationProcessor();
-   CompressibleOffsetMomentsInterpolationProcessor(real omegaC, real omegaF);
-   ~CompressibleOffsetMomentsInterpolationProcessor() override;
-   InterpolationProcessorPtr clone() override;
-   void setOmegas(real omegaC, real omegaF) override;
-   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF) override;
-   void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff) override;
-   void interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC) override; 
-   void interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff) override; 
-   void setBulkViscosity(real shearViscosity, real bulkViscosity);
-protected:   
-private:
-   real omegaC{0.0}, omegaF{0.0};
-   real a0, ax, ay, az, axx, ayy, azz, axy, axz, ayz, b0, bx, by, bz, bxx, byy, bzz, bxy, bxz, byz, c0, cx, cy, cz, cxx, cyy, czz, cxy, cxz, cyz, axyz, bxyz, cxyz;
-   real xoff,    yoff,    zoff;
-   real xoff_sq, yoff_sq, zoff_sq;
-   real press_SWT, press_NWT, press_NET, press_SET, press_SWB, press_NWB, press_NEB, press_SEB;
-
-   real  f_E,  f_N,  f_T,  f_NE,  f_SE,  f_BE,  f_TE,  f_TN,  f_BN,  f_TNE,  f_TNW,  f_TSE,  f_TSW,  f_ZERO;
-   real  x_E,  x_N,  x_T,  x_NE,  x_SE,  x_BE,  x_TE,  x_TN,  x_BN,  x_TNE,  x_TNW,  x_TSE,  x_TSW,  x_ZERO;
-   real  y_E,  y_N,  y_T,  y_NE,  y_SE,  y_BE,  y_TE,  y_TN,  y_BN,  y_TNE,  y_TNW,  y_TSE,  y_TSW,  y_ZERO;
-   real  z_E,  z_N,  z_T,  z_NE,  z_SE,  z_BE,  z_TE,  z_TN,  z_BN,  z_TNE,  z_TNW,  z_TSE,  z_TSW,  z_ZERO;
-   real xy_E, xy_N, xy_T, xy_NE, xy_SE, xy_BE, xy_TE, xy_TN, xy_BN, xy_TNE, xy_TNW, xy_TSE, xy_TSW/*, xy_ZERO*/;
-   real xz_E, xz_N, xz_T, xz_NE, xz_SE, xz_BE, xz_TE, xz_TN, xz_BN, xz_TNE, xz_TNW, xz_TSE, xz_TSW/*, xz_ZERO*/;
-   real yz_E, yz_N, yz_T, yz_NE, yz_SE, yz_BE, yz_TE, yz_TN, yz_BN, yz_TNE, yz_TNW, yz_TSE, yz_TSW/*, yz_ZERO*/;
-
-   real kxyAverage, kyzAverage, kxzAverage, kxxMyyAverage, kxxMzzAverage; 
-
-//   real a,b,c;
-
-   // bulk viscosity
-   real shearViscosity;
-   real bulkViscosity;
-   real OxxPyyPzzC;
-   real OxxPyyPzzF;
-
-   void setOffsets(real xoff, real yoff, real zoff) override;
-   void calcMoments(const real* const f, real omega, real& rho, real& vx1, real& vx2, real& vx3, 
-      real& kxy, real& kyz, real& kxz, real& kxxMyy, real& kxxMzz);
-   void calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new) override;
-   void calcInterpolatedNodeCF(real* f, real omega, real x, real y, real z, real press, real xs, real ys, real zs);
-   real calcPressBSW();
-   real calcPressTSW();
-   real calcPressTSE();
-   real calcPressBSE();
-   real calcPressBNW();
-   real calcPressTNW();
-   real calcPressTNE();
-   real calcPressBNE();
-   void calcInterpolatedNodeFC(real* f, real omega) override;
-   void calcInterpolatedVelocity(real x, real y, real z,real& vx1, real& vx2, real& vx3) override;
-   void calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz) override;
-};
-
-//////////////////////////////////////////////////////////////////////////
-inline void CompressibleOffsetMomentsInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
-{
-   this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
-}
-//////////////////////////////////////////////////////////////////////////
-inline void CompressibleOffsetMomentsInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
-{
-   this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
-}
-
-#endif
diff --git a/src/cpu/VirtualFluidsCore/LBM/CumulantLBMKernel.cpp b/src/cpu/VirtualFluidsCore/LBM/CumulantLBMKernel.cpp
index 548339f940d45ab2239ce6cb1cebbfa9bf0082b5..1b8d5a230ddf7a2d9b58c9e7ca8231f5c9d3500f 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CumulantLBMKernel.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/CumulantLBMKernel.cpp
@@ -1,6 +1,6 @@
 #include "CumulantLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include <math.h>
 #include "DataSet3D.h"
diff --git a/src/cpu/VirtualFluidsCore/LBM/IncompressibleCumulantLBMKernel.cpp b/src/cpu/VirtualFluidsCore/LBM/IncompressibleCumulantLBMKernel.cpp
index 990bb8f89f4b6abb1a0e77b550af4d751ad49a40..39d6fd268a56f4824babaccea3449ea097c85bf2 100644
--- a/src/cpu/VirtualFluidsCore/LBM/IncompressibleCumulantLBMKernel.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/IncompressibleCumulantLBMKernel.cpp
@@ -1,6 +1,6 @@
 #include "IncompressibleCumulantLBMKernel.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27EsoTwist3DSplittedVector.h"
 #include "DataSet3D.h"
 #include <cmath>
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetInterpolationProcessor.cpp b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetInterpolator.cpp
similarity index 95%
rename from src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetInterpolationProcessor.cpp
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetInterpolator.cpp
index 5cf501e20012804b7e84090243dad466e06ad06c..509115d26edfaa398877739bf1f25919595e9aa6 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetInterpolationProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetInterpolator.cpp
@@ -1,32 +1,32 @@
-#include "CompressibleOffsetInterpolationProcessor.h"
+#include "CompressibleOffsetInterpolator.h"
 #include "D3Q27System.h"
 
 //using namespace UbMath;
 using namespace vf::basics::constant;
 
 //////////////////////////////////////////////////////////////////////////
-CompressibleOffsetInterpolationProcessor::CompressibleOffsetInterpolationProcessor(real omegaC, real omegaF)
+CompressibleOffsetInterpolator::CompressibleOffsetInterpolator(real omegaC, real omegaF)
    : omegaC(omegaC), omegaF(omegaF)
 {
 
 }
 
 //////////////////////////////////////////////////////////////////////////
-InterpolationProcessorPtr CompressibleOffsetInterpolationProcessor::clone()
+InterpolationProcessorPtr CompressibleOffsetInterpolator::clone()
 {
-   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new CompressibleOffsetInterpolationProcessor(this->omegaC, this->omegaF));
+   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new CompressibleOffsetInterpolator(this->omegaC, this->omegaF));
    //dynamicPointerCast<D3Q27IncompressibleOffsetInterpolationProcessor>(iproc)->forcingC = forcingC;
    //dynamicPointerCast<D3Q27IncompressibleOffsetInterpolationProcessor>(iproc)->forcingF = forcingF;
    return iproc;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::setOmegas( real omegaC, real omegaF )
+void CompressibleOffsetInterpolator::setOmegas( real omegaC, real omegaF )
 {
    this->omegaC = omegaC;
    this->omegaF = omegaF;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::setOffsets(real xoff, real yoff, real zoff)
+void CompressibleOffsetInterpolator::setOffsets(real xoff, real yoff, real zoff)
 {
    this->xoff = xoff;
    this->yoff = yoff;
@@ -36,7 +36,7 @@ void CompressibleOffsetInterpolationProcessor::setOffsets(real xoff, real yoff,
    this->zoff_sq = zoff * zoff;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
+void CompressibleOffsetInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
 {
    setOffsets(xoff, yoff, zoff);
    calcInterpolatedCoefficiets(icellC, omegaC, c1o2);
@@ -50,14 +50,14 @@ void CompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICel
    calcInterpolatedNodeCF(icellF.TNE, omegaF,  c1o4,  c1o4,  c1o4, calcPressTNE(),  c1o1,  c1o1,  c1o1);
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
+void CompressibleOffsetInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
 {
    setOffsets(xoff, yoff, zoff);
    calcInterpolatedCoefficiets(icellF, omegaF, c2o1);
    calcInterpolatedNodeFC(icellC, omegaC);
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::calcMoments(const real* const f, real omega, real& press, real& vx1, real& vx2, real& vx3, 
+void CompressibleOffsetInterpolator::calcMoments(const real* const f, real omega, real& press, real& vx1, real& vx2, real& vx3, 
                                                     real& kxy, real& kyz, real& kxz, real& kxxMyy, real& kxxMzz)
 {
    using namespace D3Q27System;
@@ -76,7 +76,7 @@ void CompressibleOffsetInterpolationProcessor::calcMoments(const real* const f,
    kxxMzz = -c3o1/c2o1*omega*((((f[DIR_MP0]+f[DIR_PM0])-(f[DIR_0MM]+f[DIR_0PP]))+((f[DIR_MM0]+f[DIR_PP0])-(f[DIR_0MP]+f[DIR_0PM])))+((f[DIR_M00]+f[DIR_P00])-(f[DIR_00M]+f[DIR_00P]))/(c1o1 + drho)-(vx1*vx1-vx3*vx3));
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new)
+void CompressibleOffsetInterpolator::calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new)
 {
    real        vx1_SWT,vx2_SWT,vx3_SWT;
    real        vx1_NWT,vx2_NWT,vx3_NWT;
@@ -457,7 +457,7 @@ void CompressibleOffsetInterpolationProcessor::calcInterpolatedCoefficiets(const
    yz_TNW =   c1o16*eps_new *((                bxyz +     cxyz)/(c72o1*o));
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::calcInterpolatedNodeCF(real* f, real  /*omega*/, real  /*x*/, real  /*y*/, real  /*z*/, real press, real xs, real ys, real zs)
+void CompressibleOffsetInterpolator::calcInterpolatedNodeCF(real* f, real  /*omega*/, real  /*x*/, real  /*y*/, real  /*z*/, real press, real xs, real ys, real zs)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -504,8 +504,8 @@ void CompressibleOffsetInterpolationProcessor::calcInterpolatedNodeCF(real* f, r
    f[DIR_000] = f_ZERO + xs*x_ZERO + ys*y_ZERO + zs*z_ZERO                                                 + feq[DIR_000];
 }
 //////////////////////////////////////////////////////////////////////////
-//Position SWB -c1o4, -c1o4, -c1o4
-real CompressibleOffsetInterpolationProcessor::calcPressBSW()
+//Position SWB -0.25, -0.25, -0.25
+real CompressibleOffsetInterpolator::calcPressBSW()
 {
    return   press_SWT * (c9o64 + c3o16 * xoff + c3o16 * yoff - c9o16 * zoff) +
       press_NWT * (c3o64 + c1o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -517,8 +517,8 @@ real CompressibleOffsetInterpolationProcessor::calcPressBSW()
       press_SWB * (c27o64 + c9o16 * xoff + c9o16 * yoff + c9o16 * zoff);
 }
 //////////////////////////////////////////////////////////////////////////
-//Position SWT -c1o4, -c1o4, c1o4
-real CompressibleOffsetInterpolationProcessor::calcPressTSW()
+//Position SWT -0.25, -0.25, 0.25
+real CompressibleOffsetInterpolator::calcPressTSW()
 {
    return   press_SWT * (c27o64 + c9o16 * xoff + c9o16 * yoff - c9o16 * zoff) +
       press_NWT * (c9o64 + c3o16 * xoff - c9o16 * yoff - c3o16 * zoff) +
@@ -531,7 +531,7 @@ real CompressibleOffsetInterpolationProcessor::calcPressTSW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SET 0.25, -0.25, 0.25
-real CompressibleOffsetInterpolationProcessor::calcPressTSE()
+real CompressibleOffsetInterpolator::calcPressTSE()
 {
    return   press_SET * (c27o64 - c9o16 * xoff + c9o16 * yoff - c9o16 * zoff) +
       press_NET * (c9o64 - c3o16 * xoff - c9o16 * yoff - c3o16 * zoff) +
@@ -544,7 +544,7 @@ real CompressibleOffsetInterpolationProcessor::calcPressTSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SEB 0.25, -0.25, -0.25
-real CompressibleOffsetInterpolationProcessor::calcPressBSE()
+real CompressibleOffsetInterpolator::calcPressBSE()
 {
    return   press_SET * (c9o64 - c3o16 * xoff + c3o16 * yoff - c9o16 * zoff) +
       press_NET * (c3o64 - c1o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -557,7 +557,7 @@ real CompressibleOffsetInterpolationProcessor::calcPressBSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWB -0.25, 0.25, -0.25
-real CompressibleOffsetInterpolationProcessor::calcPressBNW()
+real CompressibleOffsetInterpolator::calcPressBNW()
 {
    return   press_NWT * (c9o64 + c3o16 * xoff - c3o16 * yoff - c9o16 * zoff) +
       press_NET * (c3o64 - c3o16 * xoff - c1o16 * yoff - c3o16 * zoff) +
@@ -570,7 +570,7 @@ real CompressibleOffsetInterpolationProcessor::calcPressBNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWT -0.25, 0.25, 0.25
-real CompressibleOffsetInterpolationProcessor::calcPressTNW()
+real CompressibleOffsetInterpolator::calcPressTNW()
 {
    return   press_NWT * (c27o64 + c9o16 * xoff - c9o16 * yoff - c9o16 * zoff) +
       press_NET * (c9o64 - c9o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -583,7 +583,7 @@ real CompressibleOffsetInterpolationProcessor::calcPressTNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NET 0.25, 0.25, 0.25
-real CompressibleOffsetInterpolationProcessor::calcPressTNE()
+real CompressibleOffsetInterpolator::calcPressTNE()
 {
    return   press_NET * (c27o64 - c9o16 * xoff - c9o16 * yoff - c9o16 * zoff) +
       press_NWT * (c9o64 + c9o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -596,7 +596,7 @@ real CompressibleOffsetInterpolationProcessor::calcPressTNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NEB 0.25, 0.25, -0.25
-real CompressibleOffsetInterpolationProcessor::calcPressBNE()
+real CompressibleOffsetInterpolator::calcPressBNE()
 {
    return   press_NET * (c9o64 - c3o16 * xoff - c3o16 * yoff - c9o16 * zoff) +
       press_NWT * (c3o64 + c3o16 * xoff - c1o16 * yoff - c3o16 * zoff) +
@@ -609,7 +609,7 @@ real CompressibleOffsetInterpolationProcessor::calcPressBNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position C 0.0, 0.0, 0.0
-void CompressibleOffsetInterpolationProcessor::calcInterpolatedNodeFC(real* f, real omega)
+void CompressibleOffsetInterpolator::calcInterpolatedNodeFC(real* f, real omega)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -699,14 +699,14 @@ void CompressibleOffsetInterpolationProcessor::calcInterpolatedNodeFC(real* f, r
    f[DIR_000] = f_ZERO + feq[DIR_000];
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
+void CompressibleOffsetInterpolator::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
 {
 	vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z+axyz*x*y*z;
 	vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z+bxyz*x*y*z;
 	vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z+cxyz*x*y*z;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetInterpolationProcessor::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
+void CompressibleOffsetInterpolator::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
 {
 	tauxx=ax+c2o1*axx*x+axy*y+axz*z+axyz*y*z;
 	tauyy=by+c2o1*byy*y+bxy*x+byz*z+bxyz*x*z;
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetInterpolationProcessor.h b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetInterpolator.h
similarity index 85%
rename from src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetInterpolationProcessor.h
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetInterpolator.h
index fefd6ed1566fe0a4c3c414748a522edbfede48a1..8b295977773ad95c00b36a9ef775d45140fe34df 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetInterpolationProcessor.h
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetInterpolator.h
@@ -1,7 +1,7 @@
 #ifndef CompressibleOffsetInterpolationProcessor_H_
 #define CompressibleOffsetInterpolationProcessor_H_
 
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27System.h"
 
 //////////////////////////////////////////////////////////////////////////
@@ -9,14 +9,14 @@
 //super compact interpolation method by Martin Geier
 //////////////////////////////////////////////////////////////////////////
 
-class CompressibleOffsetInterpolationProcessor;
+class CompressibleOffsetInterpolator;
 
-class CompressibleOffsetInterpolationProcessor : public InterpolationProcessor
+class CompressibleOffsetInterpolator : public Interpolator
 {
 public:
-   CompressibleOffsetInterpolationProcessor() = default;
-   CompressibleOffsetInterpolationProcessor(real omegaC, real omegaF);
-   ~CompressibleOffsetInterpolationProcessor() override = default;
+   CompressibleOffsetInterpolator() = default;
+   CompressibleOffsetInterpolator(real omegaC, real omegaF);
+   ~CompressibleOffsetInterpolator() override = default;
 
    InterpolationProcessorPtr clone() override;
    void setOmegas(real omegaC, real omegaF) override;
@@ -64,12 +64,12 @@ private:
 };
 
 //////////////////////////////////////////////////////////////////////////
-inline void CompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
+inline void CompressibleOffsetInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
 {
    this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
 }
 //////////////////////////////////////////////////////////////////////////
-inline void CompressibleOffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
+inline void CompressibleOffsetInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
 {
    this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
 }
diff --git a/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetMomentsInterpolator.cpp b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetMomentsInterpolator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e7d891df037a05fed023fff3aaaa0db19f0cfa43
--- /dev/null
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetMomentsInterpolator.cpp
@@ -0,0 +1,65 @@
+#include "CompressibleOffsetMomentsInterpolator.h"
+
+#include <algorithm>
+
+#include <basics/constants/NumericConstants.h>
+
+#include <lbm/refinement/InterpolationCF.h>
+#include <lbm/refinement/InterpolationFC.h>
+#include <lbm/refinement/Coefficients.h>
+
+
+void calculateCoefficients(vf::lbm::Coefficients& coefficients, const D3Q27ICell& icell, real omega, real xoff, real yoff, real zoff)
+{
+    vf::lbm::MomentsOnSourceNodeSet momentsSet;
+
+    momentsSet.calculateMMM(icell.BSW, omega);
+    momentsSet.calculateMMP(icell.TSW, omega);
+    momentsSet.calculateMPP(icell.TNW, omega);
+    momentsSet.calculateMPM(icell.BNW, omega);
+    momentsSet.calculatePMM(icell.BSE, omega);
+    momentsSet.calculatePPP(icell.TNE, omega);
+    momentsSet.calculatePMP(icell.TSE, omega);
+    momentsSet.calculatePPM(icell.BNE, omega);
+
+    momentsSet.calculateCoefficients(coefficients, xoff, yoff, zoff);
+}
+
+CompressibleOffsetMomentsInterpolator::CompressibleOffsetMomentsInterpolator(real omegaC, real omegaF)
+   : omegaC(omegaC), omegaF(omegaF)
+{
+}
+
+InterpolationProcessorPtr CompressibleOffsetMomentsInterpolator::clone()
+{
+   return InterpolationProcessorPtr (new CompressibleOffsetMomentsInterpolator(this->omegaC, this->omegaF));
+}
+
+void CompressibleOffsetMomentsInterpolator::setOmegas(real omegaC, real omegaF)
+{
+   this->omegaC = omegaC;
+   this->omegaF = omegaF;
+}
+
+void CompressibleOffsetMomentsInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
+{
+    vf::lbm::Coefficients coefficients;
+    calculateCoefficients(coefficients, icellC, omegaC, xoff, yoff, zoff);
+
+     vf::lbm::interpolateCF(icellF.BSW, omegaF, vf::basics::constant::c1o2, coefficients, -0.25, -0.25, -0.25);
+     vf::lbm::interpolateCF(icellF.BNE, omegaF, vf::basics::constant::c1o2, coefficients,  0.25,  0.25, -0.25);
+     vf::lbm::interpolateCF(icellF.TNW, omegaF, vf::basics::constant::c1o2, coefficients, -0.25,  0.25,  0.25);
+     vf::lbm::interpolateCF(icellF.TSE, omegaF, vf::basics::constant::c1o2, coefficients,  0.25, -0.25,  0.25);
+     vf::lbm::interpolateCF(icellF.BNW, omegaF, vf::basics::constant::c1o2, coefficients, -0.25,  0.25, -0.25);
+     vf::lbm::interpolateCF(icellF.BSE, omegaF, vf::basics::constant::c1o2, coefficients,  0.25, -0.25, -0.25);
+     vf::lbm::interpolateCF(icellF.TSW, omegaF, vf::basics::constant::c1o2, coefficients, -0.25, -0.25,  0.25);
+     vf::lbm::interpolateCF(icellF.TNE, omegaF, vf::basics::constant::c1o2, coefficients,  0.25,  0.25,  0.25);
+}
+
+void CompressibleOffsetMomentsInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
+{
+    vf::lbm::Coefficients coefficients;
+    calculateCoefficients(coefficients, icellF, omegaF, xoff, yoff, zoff);
+
+    vf::lbm::interpolateFC(icellC, vf::basics::constant::c2o1, omegaC, coefficients);
+}
diff --git a/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetMomentsInterpolator.h b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetMomentsInterpolator.h
new file mode 100644
index 0000000000000000000000000000000000000000..444170d565fc80cf735cd134f0b46ac54fc38902
--- /dev/null
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetMomentsInterpolator.h
@@ -0,0 +1,41 @@
+#ifndef CompressibleOffsetMomentsInterpolationProcessor_H_
+#define CompressibleOffsetMomentsInterpolationProcessor_H_
+
+#include "Interpolator.h"
+#include "D3Q27System.h"
+
+//////////////////////////////////////////////////////////////////////////
+//it works only for cascaded LBM
+//super compact interpolation method by Martin Geier
+//////////////////////////////////////////////////////////////////////////
+
+class CompressibleOffsetMomentsInterpolator : public Interpolator
+{
+public:
+    CompressibleOffsetMomentsInterpolator() = default;
+    CompressibleOffsetMomentsInterpolator(real omegaC, real omegaF);
+    InterpolationProcessorPtr clone() override;
+
+    void setOmegas(real omegaC, real omegaF) override;
+
+    void interpolateCoarseToFine(D3Q27ICell &icellC, D3Q27ICell &icellF) override;
+    void interpolateCoarseToFine(D3Q27ICell &icellC, D3Q27ICell &icellF, real xoff, real yoff, real zoff) override;
+    void interpolateFineToCoarse(D3Q27ICell &icellF, real *icellC) override;
+    void interpolateFineToCoarse(D3Q27ICell &icellF, real *icellC, real xoff, real yoff, real zoff) override;
+
+private:
+    real omegaC{ 0.0 }, omegaF{ 0.0 };
+};
+
+//////////////////////////////////////////////////////////////////////////
+inline void CompressibleOffsetMomentsInterpolator::interpolateCoarseToFine(D3Q27ICell &icellC, D3Q27ICell &icellF)
+{
+    this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
+}
+//////////////////////////////////////////////////////////////////////////
+inline void CompressibleOffsetMomentsInterpolator::interpolateFineToCoarse(D3Q27ICell &icellF, real *icellC)
+{
+    this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
+}
+
+#endif
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetSquarePressureInterpolationProcessor.cpp b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetSquarePressureInterpolator.cpp
similarity index 96%
rename from src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetSquarePressureInterpolationProcessor.cpp
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetSquarePressureInterpolator.cpp
index dee6d12a5812e29d91aa1c12c25d61ade0759ef8..3b5d7386ae4e615a6f89d6ed07eb78d02b295799 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetSquarePressureInterpolationProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetSquarePressureInterpolator.cpp
@@ -1,10 +1,10 @@
-#include "CompressibleOffsetSquarePressureInterpolationProcessor.h"
+#include "CompressibleOffsetSquarePressureInterpolator.h"
 #include "D3Q27System.h"
 
 //using namespace UbMath;
 using namespace vf::basics::constant;
 
-CompressibleOffsetSquarePressureInterpolationProcessor::CompressibleOffsetSquarePressureInterpolationProcessor()
+CompressibleOffsetSquarePressureInterpolator::CompressibleOffsetSquarePressureInterpolator()
     
 {
    this->bulkOmegaToOmega = false;
@@ -12,7 +12,7 @@ CompressibleOffsetSquarePressureInterpolationProcessor::CompressibleOffsetSquare
    this->OxxPyyPzzF = c1o1;
 }
 //////////////////////////////////////////////////////////////////////////
-CompressibleOffsetSquarePressureInterpolationProcessor::CompressibleOffsetSquarePressureInterpolationProcessor(real omegaC, real omegaF)
+CompressibleOffsetSquarePressureInterpolator::CompressibleOffsetSquarePressureInterpolator(real omegaC, real omegaF)
    : omegaC(omegaC), omegaF(omegaF)
 {
    this->bulkOmegaToOmega = false;
@@ -20,32 +20,32 @@ CompressibleOffsetSquarePressureInterpolationProcessor::CompressibleOffsetSquare
    this->OxxPyyPzzF = c1o1;
 }
 //////////////////////////////////////////////////////////////////////////
-CompressibleOffsetSquarePressureInterpolationProcessor::~CompressibleOffsetSquarePressureInterpolationProcessor()
+CompressibleOffsetSquarePressureInterpolator::~CompressibleOffsetSquarePressureInterpolator()
 = default;
 //////////////////////////////////////////////////////////////////////////
-InterpolationProcessorPtr CompressibleOffsetSquarePressureInterpolationProcessor::clone()
+InterpolationProcessorPtr CompressibleOffsetSquarePressureInterpolator::clone()
 {
-   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new CompressibleOffsetSquarePressureInterpolationProcessor(this->omegaC, this->omegaF));
+   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new CompressibleOffsetSquarePressureInterpolator(this->omegaC, this->omegaF));
    if (bulkOmegaToOmega)
    {
-      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolationProcessor>(iproc)->OxxPyyPzzC = omegaC;
-      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolationProcessor>(iproc)->OxxPyyPzzF = omegaF;
+      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolator>(iproc)->OxxPyyPzzC = omegaC;
+      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolator>(iproc)->OxxPyyPzzF = omegaF;
    }
    else
    {
-      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolationProcessor>(iproc)->OxxPyyPzzC = c1o1;
-      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolationProcessor>(iproc)->OxxPyyPzzF = c1o1;
+      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolator>(iproc)->OxxPyyPzzC = c1o1;
+      dynamicPointerCast<CompressibleOffsetSquarePressureInterpolator>(iproc)->OxxPyyPzzF = c1o1;
    }
    return iproc;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::setOmegas( real omegaC, real omegaF )
+void CompressibleOffsetSquarePressureInterpolator::setOmegas( real omegaC, real omegaF )
 {
    this->omegaC = omegaC;
    this->omegaF = omegaF;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::setOffsets(real xoff, real yoff, real zoff)
+void CompressibleOffsetSquarePressureInterpolator::setOffsets(real xoff, real yoff, real zoff)
 {
    this->xoff = xoff;
    this->yoff = yoff;
@@ -55,7 +55,7 @@ void CompressibleOffsetSquarePressureInterpolationProcessor::setOffsets(real xof
    this->zoff_sq = zoff * zoff;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
+void CompressibleOffsetSquarePressureInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
 {
    setOffsets(xoff, yoff, zoff);
    calcInterpolatedCoefficiets(icellC, omegaC, c1o2);
@@ -69,14 +69,14 @@ void CompressibleOffsetSquarePressureInterpolationProcessor::interpolateCoarseTo
    calcInterpolatedNodeCF(icellF.TNE, omegaF,  c1o4,  c1o4,  c1o4, calcPressTNE(),  c1o1,  c1o1,  c1o1);
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
+void CompressibleOffsetSquarePressureInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
 {
    setOffsets(xoff, yoff, zoff);
    calcInterpolatedCoefficiets(icellF, omegaF, c2o1);
    calcInterpolatedNodeFC(icellC, omegaC);
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::calcMoments(const real* const f, real omega, real& press, real& vx1, real& vx2, real& vx3, 
+void CompressibleOffsetSquarePressureInterpolator::calcMoments(const real* const f, real omega, real& press, real& vx1, real& vx2, real& vx3, 
                                                     real& kxy, real& kyz, real& kxz, real& kxxMyy, real& kxxMzz)
 {
    using namespace D3Q27System;
@@ -94,7 +94,7 @@ void CompressibleOffsetSquarePressureInterpolationProcessor::calcMoments(const r
    kxxMzz = -c3o1/c2o1*omega*((((f[DIR_MP0]+f[DIR_PM0])-(f[DIR_0MM]+f[DIR_0PP]))+((f[DIR_MM0]+f[DIR_PP0])-(f[DIR_0MP]+f[DIR_0PM])))+((f[DIR_M00]+f[DIR_P00])-(f[DIR_00M]+f[DIR_00P]))/(c1o1 + drho)-(vx1*vx1-vx3*vx3));
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new)
+void CompressibleOffsetSquarePressureInterpolator::calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new)
 {
    real        vx1_SWT,vx2_SWT,vx3_SWT;
    real        vx1_NWT,vx2_NWT,vx3_NWT;
@@ -475,7 +475,7 @@ void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedCoe
    yz_TNW =   c1o16*eps_new *((                bxyz +     cxyz)/(c72o1*o));
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedNodeCF(real* f, real omega, real x, real y, real z, real press, real xs, real ys, real zs)
+void CompressibleOffsetSquarePressureInterpolator::calcInterpolatedNodeCF(real* f, real omega, real x, real y, real z, real press, real xs, real ys, real zs)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -812,8 +812,8 @@ void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedNod
    f[DIR_MMM]  = mfaaa;
 }
 //////////////////////////////////////////////////////////////////////////
-//Position SWB -c1o4, -c1o4, -c1o4
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBSW()
+//Position SWB -0.25, -0.25, -0.25
+real CompressibleOffsetSquarePressureInterpolator::calcPressBSW()
 {
    return   press_SWT * (c9o64 + c3o16 * xoff + c3o16 * yoff - c9o16 * zoff) +
       press_NWT * (c3o64 + c1o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -826,7 +826,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBSW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SWT -0.25, -0.25, 0.25
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTSW()
+real CompressibleOffsetSquarePressureInterpolator::calcPressTSW()
 {
    return   press_SWT * (c27o64 + c9o16 * xoff + c9o16 * yoff - c9o16 * zoff) +
       press_NWT * (c9o64 + c3o16 * xoff - c9o16 * yoff - c3o16 * zoff) +
@@ -839,7 +839,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTSW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SET 0.25, -0.25, 0.25
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTSE()
+real CompressibleOffsetSquarePressureInterpolator::calcPressTSE()
 {
    return   press_SET * (c27o64 - c9o16 * xoff + c9o16 * yoff - c9o16 * zoff) +
       press_NET * (c9o64 - c3o16 * xoff - c9o16 * yoff - c3o16 * zoff) +
@@ -852,7 +852,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SEB 0.25, -0.25, -0.25
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBSE()
+real CompressibleOffsetSquarePressureInterpolator::calcPressBSE()
 {
    return   press_SET * (c9o64 - c3o16 * xoff + c3o16 * yoff - c9o16 * zoff) +
       press_NET * (c3o64 - c1o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -865,7 +865,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWB -0.25, 0.25, -0.25
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBNW()
+real CompressibleOffsetSquarePressureInterpolator::calcPressBNW()
 {
    return   press_NWT * (c9o64 + c3o16 * xoff - c3o16 * yoff - c9o16 * zoff) +
       press_NET * (c3o64 - c3o16 * xoff - c1o16 * yoff - c3o16 * zoff) +
@@ -878,7 +878,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWT -0.25, 0.25, 0.25
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTNW()
+real CompressibleOffsetSquarePressureInterpolator::calcPressTNW()
 {
    return   press_NWT * (c27o64 + c9o16 * xoff - c9o16 * yoff - c9o16 * zoff) +
       press_NET * (c9o64 - c9o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -891,7 +891,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NET 0.25, 0.25, 0.25
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTNE()
+real CompressibleOffsetSquarePressureInterpolator::calcPressTNE()
 {
    return   press_NET * (c27o64 - c9o16 * xoff - c9o16 * yoff - c9o16 * zoff) +
       press_NWT * (c9o64 + c9o16 * xoff - c3o16 * yoff - c3o16 * zoff) +
@@ -904,7 +904,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressTNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NEB 0.25, 0.25, -0.25
-real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBNE()
+real CompressibleOffsetSquarePressureInterpolator::calcPressBNE()
 {
    return   press_NET * (c9o64 - c3o16 * xoff - c3o16 * yoff - c9o16 * zoff) +
       press_NWT * (c3o64 + c3o16 * xoff - c1o16 * yoff - c3o16 * zoff) +
@@ -917,7 +917,7 @@ real CompressibleOffsetSquarePressureInterpolationProcessor::calcPressBNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position C 0.0, 0.0, 0.0
-void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedNodeFC(real* f, real omega)
+void CompressibleOffsetSquarePressureInterpolator::calcInterpolatedNodeFC(real* f, real omega)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -1266,14 +1266,14 @@ void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedNod
    f[DIR_MMM]  = mfaaa;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
+void CompressibleOffsetSquarePressureInterpolator::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
 {
 	vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z+axyz*x*y*z;
 	vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z+bxyz*x*y*z;
 	vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z+cxyz*x*y*z;
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
+void CompressibleOffsetSquarePressureInterpolator::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
 {
 	tauxx=ax+c2o1*axx*x+axy*y+axz*z+axyz*y*z;
 	tauyy=by+c2o1*byy*y+bxy*x+byz*z+bxyz*x*z;
@@ -1283,7 +1283,7 @@ void CompressibleOffsetSquarePressureInterpolationProcessor::calcInterpolatedShe
 	tauyz=c1o2*((bz+c2o1*bzz*z+bxz*x+byz*y+bxyz*x*y)+(cy+c2o1*cyy*y+cxy*x+cyz*z+cxyz*x*z));
 }
 //////////////////////////////////////////////////////////////////////////
-void CompressibleOffsetSquarePressureInterpolationProcessor::setBulkOmegaToOmega(bool value)
+void CompressibleOffsetSquarePressureInterpolator::setBulkOmegaToOmega(bool value)
 {
    bulkOmegaToOmega = value;
 }
diff --git a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetSquarePressureInterpolationProcessor.h b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetSquarePressureInterpolator.h
similarity index 84%
rename from src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetSquarePressureInterpolationProcessor.h
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetSquarePressureInterpolator.h
index d9285289f63e7dfca694342df092b6e5f4ecb4d5..8a6308f947f79305079b1fa45edff0fb9c703a55 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CompressibleOffsetSquarePressureInterpolationProcessor.h
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/CompressibleOffsetSquarePressureInterpolator.h
@@ -1,7 +1,7 @@
 #ifndef CompressibleOffsetSquarePressureInterpolationProcessor_H_
 #define CompressibleOffsetSquarePressureInterpolationProcessor_H_
 
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27System.h"
 
 //////////////////////////////////////////////////////////////////////////
@@ -9,14 +9,14 @@
 //super compact interpolation method by Martin Geier
 //////////////////////////////////////////////////////////////////////////
 
-class CompressibleOffsetSquarePressureInterpolationProcessor;
+class CompressibleOffsetSquarePressureInterpolator;
 
-class CompressibleOffsetSquarePressureInterpolationProcessor : public InterpolationProcessor
+class CompressibleOffsetSquarePressureInterpolator : public Interpolator
 {
 public:
-   CompressibleOffsetSquarePressureInterpolationProcessor();
-   CompressibleOffsetSquarePressureInterpolationProcessor(real omegaC, real omegaF);
-   ~CompressibleOffsetSquarePressureInterpolationProcessor() override;
+   CompressibleOffsetSquarePressureInterpolator();
+   CompressibleOffsetSquarePressureInterpolator(real omegaC, real omegaF);
+   ~CompressibleOffsetSquarePressureInterpolator() override;
    InterpolationProcessorPtr clone() override;
    void setOmegas(real omegaC, real omegaF) override;
    void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF) override;
@@ -68,12 +68,12 @@ private:
 };
 
 //////////////////////////////////////////////////////////////////////////
-inline void CompressibleOffsetSquarePressureInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
+inline void CompressibleOffsetSquarePressureInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
 {
    this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
 }
 //////////////////////////////////////////////////////////////////////////
-inline void CompressibleOffsetSquarePressureInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
+inline void CompressibleOffsetSquarePressureInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
 {
    this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
 }
diff --git a/src/cpu/VirtualFluidsCore/LBM/IncompressibleOffsetInterpolationProcessor.cpp b/src/cpu/VirtualFluidsCore/LBM/Interpolation/IncompressibleOffsetInterpolator.cpp
similarity index 95%
rename from src/cpu/VirtualFluidsCore/LBM/IncompressibleOffsetInterpolationProcessor.cpp
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/IncompressibleOffsetInterpolator.cpp
index 26635dbac5d4b2844e6f0205f30a063c5533d612..0cd44125559e1ccf2ed0704f1a7214888a27739d 100644
--- a/src/cpu/VirtualFluidsCore/LBM/IncompressibleOffsetInterpolationProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/IncompressibleOffsetInterpolator.cpp
@@ -1,31 +1,31 @@
-#include "IncompressibleOffsetInterpolationProcessor.h"
+#include "IncompressibleOffsetInterpolator.h"
 #include "D3Q27System.h"
 
 
 
 //////////////////////////////////////////////////////////////////////////
-IncompressibleOffsetInterpolationProcessor::IncompressibleOffsetInterpolationProcessor(real omegaC, real omegaF)
+IncompressibleOffsetInterpolator::IncompressibleOffsetInterpolator(real omegaC, real omegaF)
    : omegaC(omegaC), omegaF(omegaF)
 {
 
 }
 
 //////////////////////////////////////////////////////////////////////////
-InterpolationProcessorPtr IncompressibleOffsetInterpolationProcessor::clone()
+InterpolationProcessorPtr IncompressibleOffsetInterpolator::clone()
 {
-   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new IncompressibleOffsetInterpolationProcessor(this->omegaC, this->omegaF));
+   InterpolationProcessorPtr iproc = InterpolationProcessorPtr (new IncompressibleOffsetInterpolator(this->omegaC, this->omegaF));
    //dynamicPointerCast<D3Q27IncompressibleOffsetInterpolationProcessor>(iproc)->forcingC = forcingC;
    //dynamicPointerCast<D3Q27IncompressibleOffsetInterpolationProcessor>(iproc)->forcingF = forcingF;
    return iproc;
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::setOmegas( real omegaC, real omegaF )
+void IncompressibleOffsetInterpolator::setOmegas( real omegaC, real omegaF )
 {
    this->omegaC = omegaC;
    this->omegaF = omegaF;
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::setOffsets(real xoff, real yoff, real zoff)
+void IncompressibleOffsetInterpolator::setOffsets(real xoff, real yoff, real zoff)
 {
    this->xoff = xoff;
    this->yoff = yoff;
@@ -35,7 +35,7 @@ void IncompressibleOffsetInterpolationProcessor::setOffsets(real xoff, real yoff
    this->zoff_sq = zoff * zoff;
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
+void IncompressibleOffsetInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF, real xoff, real yoff, real zoff)
 {
     using namespace vf::basics::constant;
 
@@ -51,14 +51,14 @@ void IncompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27IC
    calcInterpolatedNode(icellF.TNE, omegaF,  c1o4,  c1o4,  c1o4, calcPressTNE(),  c1o1,  c1o1,  c1o1);
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
+void IncompressibleOffsetInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff)
 {
    setOffsets(xoff, yoff, zoff);
    calcInterpolatedCoefficiets(icellF, omegaF, vf::basics::constant::c2o1);
    calcInterpolatedNodeFC(icellC, omegaC);
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::calcMoments(const real* const f, real omega, real& press, real& vx1, real& vx2, real& vx3, 
+void IncompressibleOffsetInterpolator::calcMoments(const real* const f, real omega, real& press, real& vx1, real& vx2, real& vx3, 
                                                     real& kxy, real& kyz, real& kxz, real& kxxMyy, real& kxxMzz)
 {
    using namespace D3Q27System;
@@ -104,7 +104,7 @@ void IncompressibleOffsetInterpolationProcessor::calcMoments(const real* const f
    //UBLOG(logINFO,"f[TN]  = " << f[TN] << " TN  = " << TN);
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new)
+void IncompressibleOffsetInterpolator::calcInterpolatedCoefficiets(const D3Q27ICell& icell, real omega, real eps_new)
 {
     using namespace vf::basics::constant;
 
@@ -532,7 +532,7 @@ void IncompressibleOffsetInterpolationProcessor::calcInterpolatedCoefficiets(con
    yz_TNW =   c1o16*eps_new *((                bxyz +     cxyz)/(c72o1*o));
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::calcInterpolatedNode(real* f, real  /*omega*/, real  /*x*/, real  /*y*/, real  /*z*/, real press, real xs, real ys, real zs)
+void IncompressibleOffsetInterpolator::calcInterpolatedNode(real* f, real  /*omega*/, real  /*x*/, real  /*y*/, real  /*z*/, real press, real xs, real ys, real zs)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -581,7 +581,7 @@ void IncompressibleOffsetInterpolationProcessor::calcInterpolatedNode(real* f, r
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SWB -0.25, -0.25, -0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressBSW()
+real IncompressibleOffsetInterpolator::calcPressBSW()
 {
     using namespace vf::basics::constant;
 
@@ -596,7 +596,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressBSW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SWT -0.25, -0.25, 0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressTSW()
+real IncompressibleOffsetInterpolator::calcPressTSW()
 {
     using namespace vf::basics::constant;
 
@@ -611,7 +611,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressTSW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SET 0.25, -0.25, 0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressTSE()
+real IncompressibleOffsetInterpolator::calcPressTSE()
 {
     using namespace vf::basics::constant;
 
@@ -626,7 +626,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressTSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position SEB 0.25, -0.25, -0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressBSE()
+real IncompressibleOffsetInterpolator::calcPressBSE()
 {
     using namespace vf::basics::constant;
 
@@ -641,7 +641,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressBSE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWB -0.25, 0.25, -0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressBNW()
+real IncompressibleOffsetInterpolator::calcPressBNW()
 {
     using namespace vf::basics::constant;
 
@@ -656,7 +656,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressBNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NWT -0.25, 0.25, 0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressTNW()
+real IncompressibleOffsetInterpolator::calcPressTNW()
 {
     using namespace vf::basics::constant;
 
@@ -671,7 +671,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressTNW()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NET 0.25, 0.25, 0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressTNE()
+real IncompressibleOffsetInterpolator::calcPressTNE()
 {
     using namespace vf::basics::constant;
 
@@ -686,7 +686,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressTNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position NEB 0.25, 0.25, -0.25
-real IncompressibleOffsetInterpolationProcessor::calcPressBNE()
+real IncompressibleOffsetInterpolator::calcPressBNE()
 {
     using namespace vf::basics::constant;
 
@@ -701,7 +701,7 @@ real IncompressibleOffsetInterpolationProcessor::calcPressBNE()
 }
 //////////////////////////////////////////////////////////////////////////
 //Position C 0.0, 0.0, 0.0
-void IncompressibleOffsetInterpolationProcessor::calcInterpolatedNodeFC(real* f, real omega)
+void IncompressibleOffsetInterpolator::calcInterpolatedNodeFC(real* f, real omega)
 {
    using namespace D3Q27System;
    using namespace vf::lbm::dir;
@@ -792,14 +792,14 @@ void IncompressibleOffsetInterpolationProcessor::calcInterpolatedNodeFC(real* f,
    f[DIR_000] = f_ZERO + feq[DIR_000];
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
+void IncompressibleOffsetInterpolator::calcInterpolatedVelocity(real x, real y, real z, real& vx1, real& vx2, real& vx3)
 {
 	vx1  = a0 + ax*x + ay*y + az*z + axx*x*x + ayy*y*y + azz*z*z + axy*x*y + axz*x*z + ayz*y*z+axyz*x*y*z;
 	vx2  = b0 + bx*x + by*y + bz*z + bxx*x*x + byy*y*y + bzz*z*z + bxy*x*y + bxz*x*z + byz*y*z+bxyz*x*y*z;
 	vx3  = c0 + cx*x + cy*y + cz*z + cxx*x*x + cyy*y*y + czz*z*z + cxy*x*y + cxz*x*z + cyz*y*z+cxyz*x*y*z;
 }
 //////////////////////////////////////////////////////////////////////////
-void IncompressibleOffsetInterpolationProcessor::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
+void IncompressibleOffsetInterpolator::calcInterpolatedShearStress(real x, real y, real z,real& tauxx, real& tauyy, real& tauzz,real& tauxy, real& tauxz, real& tauyz)
 {
     using namespace vf::basics::constant;
 
diff --git a/src/cpu/VirtualFluidsCore/LBM/IncompressibleOffsetInterpolationProcessor.h b/src/cpu/VirtualFluidsCore/LBM/Interpolation/IncompressibleOffsetInterpolator.h
similarity index 83%
rename from src/cpu/VirtualFluidsCore/LBM/IncompressibleOffsetInterpolationProcessor.h
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/IncompressibleOffsetInterpolator.h
index 866c0f6933e67d66b3b36d65a0f484ba2d8cbf86..2fee5d62c30162e0f2af514e3551c8aa93ca9dab 100644
--- a/src/cpu/VirtualFluidsCore/LBM/IncompressibleOffsetInterpolationProcessor.h
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/IncompressibleOffsetInterpolator.h
@@ -1,7 +1,7 @@
 #ifndef IncompressibleOffsetInterpolationProcessor_H_
 #define IncompressibleOffsetInterpolationProcessor_H_
 
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "D3Q27System.h"
 
 //////////////////////////////////////////////////////////////////////////
@@ -9,15 +9,15 @@
 //super compact interpolation method by Martin Geier
 //////////////////////////////////////////////////////////////////////////
 
-class IncompressibleOffsetInterpolationProcessor;
-using D3Q27IncompressibleOffsetInterpolationProcessorPtr = SPtr<IncompressibleOffsetInterpolationProcessor>;
+class IncompressibleOffsetInterpolator;
+using D3Q27IncompressibleOffsetInterpolationProcessorPtr = SPtr<IncompressibleOffsetInterpolator>;
 
-class IncompressibleOffsetInterpolationProcessor : public InterpolationProcessor
+class IncompressibleOffsetInterpolator : public Interpolator
 {
 public:
-   IncompressibleOffsetInterpolationProcessor() = default;
-   IncompressibleOffsetInterpolationProcessor(real omegaC, real omegaF);
-   ~IncompressibleOffsetInterpolationProcessor() override = default;
+   IncompressibleOffsetInterpolator() = default;
+   IncompressibleOffsetInterpolator(real omegaC, real omegaF);
+   ~IncompressibleOffsetInterpolator() override = default;
    InterpolationProcessorPtr clone() override;
    void setOmegas(real omegaC, real omegaF) override;
    void interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF) override;
@@ -25,7 +25,7 @@ public:
    void interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC) override; 
    void interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC, real xoff, real yoff, real zoff) override; 
    //real forcingC, forcingF;
-protected:   
+protected:
 private:
    real omegaC{0.0}, omegaF{0.0};
    real a0, ax, ay, az, axx, ayy, azz, axy, axz, ayz, b0, bx, by, bz, bxx, byy, bzz, bxy, bxz, byz, c0, cx, cy, cz, cxx, cyy, czz, cxy, cxz, cyz, axyz, bxyz, cxyz;
@@ -64,12 +64,12 @@ private:
 };
 
 //////////////////////////////////////////////////////////////////////////
-inline void IncompressibleOffsetInterpolationProcessor::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
+inline void IncompressibleOffsetInterpolator::interpolateCoarseToFine(D3Q27ICell& icellC, D3Q27ICell& icellF)
 {
    this->interpolateCoarseToFine(icellC, icellF, 0.0, 0.0, 0.0);
 }
 //////////////////////////////////////////////////////////////////////////
-inline void IncompressibleOffsetInterpolationProcessor::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
+inline void IncompressibleOffsetInterpolator::interpolateFineToCoarse(D3Q27ICell& icellF, real* icellC)
 {
    this->interpolateFineToCoarse(icellF, icellC, 0.0, 0.0, 0.0);
 }
diff --git a/src/cpu/VirtualFluidsCore/LBM/InterpolationProcessor.cpp b/src/cpu/VirtualFluidsCore/LBM/Interpolation/Interpolator.cpp
similarity index 73%
rename from src/cpu/VirtualFluidsCore/LBM/InterpolationProcessor.cpp
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/Interpolator.cpp
index a82f397c9f89d7605d8409b8f32f8d87a8f8a402..f28b1efed4836ca71b09a390078dd2aaf5463710 100644
--- a/src/cpu/VirtualFluidsCore/LBM/InterpolationProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/Interpolator.cpp
@@ -1,11 +1,22 @@
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
+
+
+struct Range
+{
+    Range(int maxX1, int maxX2, int maxX3) : m_maxX1(maxX1), m_maxX2(maxX2), m_maxX3(maxX3) {}
+    inline bool operator()(int x1, int x2, int x3)
+    {
+        return x1 >= 0 && x1 < m_maxX1 && x2 >= 0 && x2 < m_maxX2 && x3 >= 0 && x3 < m_maxX3;
+    }
+
+    int m_maxX1;
+    int m_maxX2;
+    int m_maxX3;
+};
+
 
 //////////////////////////////////////////////////////////////////////////
-InterpolationProcessor::InterpolationProcessor() = default;
-//////////////////////////////////////////////////////////////////////////
-InterpolationProcessor::~InterpolationProcessor() = default;
-//////////////////////////////////////////////////////////////////////////
-void InterpolationProcessor::readICell(SPtr<DistributionArray3D> f, D3Q27ICell &icell, int x1, int x2, int x3)
+void Interpolator::readICell(SPtr<DistributionArray3D> f, D3Q27ICell &icell, int x1, int x2, int x3)
 {
     f->getDistribution(icell.BSW, x1, x2, x3);
     f->getDistribution(icell.BSE, x1 + 1, x2, x3);
@@ -17,7 +28,7 @@ void InterpolationProcessor::readICell(SPtr<DistributionArray3D> f, D3Q27ICell &
     f->getDistribution(icell.TNE, x1 + 1, x2 + 1, x3 + 1);
 }
 //////////////////////////////////////////////////////////////////////////
-void InterpolationProcessor::writeICell(SPtr<DistributionArray3D> f, const D3Q27ICell &icell, int x1, int x2, int x3)
+void Interpolator::writeICell(SPtr<DistributionArray3D> f, const D3Q27ICell &icell, int x1, int x2, int x3)
 {
     f->setDistribution(icell.BSW, x1, x2, x3);
     f->setDistribution(icell.BSE, x1 + 1, x2, x3);
@@ -29,7 +40,7 @@ void InterpolationProcessor::writeICell(SPtr<DistributionArray3D> f, const D3Q27
     f->setDistribution(icell.TNE, x1 + 1, x2 + 1, x3 + 1);
 }
 //////////////////////////////////////////////////////////////////////////
-void InterpolationProcessor::writeICellInv(SPtr<DistributionArray3D> f, const D3Q27ICell &icell, int x1, int x2, int x3)
+void Interpolator::writeICellInv(SPtr<DistributionArray3D> f, const D3Q27ICell &icell, int x1, int x2, int x3)
 {
     f->setDistributionInv(icell.BSW, x1, x2, x3);
     f->setDistributionInv(icell.BSE, x1 + 1, x2, x3);
@@ -41,18 +52,18 @@ void InterpolationProcessor::writeICellInv(SPtr<DistributionArray3D> f, const D3
     f->setDistributionInv(icell.TNE, x1 + 1, x2 + 1, x3 + 1);
 }
 //////////////////////////////////////////////////////////////////////////
-void InterpolationProcessor::writeINode(SPtr<DistributionArray3D> f, const real *const inode, int x1, int x2, int x3)
+void Interpolator::writeINode(SPtr<DistributionArray3D> f, const real *const inode, int x1, int x2, int x3)
 {
     f->setDistribution(inode, x1, x2, x3);
 }
 //////////////////////////////////////////////////////////////////////////
-void InterpolationProcessor::writeINodeInv(SPtr<DistributionArray3D> f, const real *const inode, int x1, int x2,
+void Interpolator::writeINodeInv(SPtr<DistributionArray3D> f, const real *const inode, int x1, int x2,
                                            int x3)
 {
     f->setDistributionInv(inode, x1, x2, x3);
 }
 //////////////////////////////////////////////////////////////////////////
-bool InterpolationProcessor::iCellHasSolid(const SPtr<BCArray3D> bcArray, int x1, int x2, int x3)
+bool Interpolator::iCellHasSolid(const SPtr<BCArray3D> bcArray, int x1, int x2, int x3)
 {
     for (int ix3 = x3; ix3 <= x3 + 1; ix3++)
         for (int ix2 = x2; ix2 <= x2 + 1; ix2++)
@@ -63,13 +74,12 @@ bool InterpolationProcessor::iCellHasSolid(const SPtr<BCArray3D> bcArray, int x1
     return false;
 }
 //////////////////////////////////////////////////////////////////////////
-bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SPtr<DistributionArray3D> f,
+bool Interpolator::findNeighborICell(const SPtr<BCArray3D> bcArray, SPtr<DistributionArray3D> f,
                                                D3Q27ICell &icell, int maxX1, int maxX2, int maxX3, int x1, int x2,
                                                int x3, real &xoff, real &yoff, real &zoff)
 {
-    m_maxX1 = maxX1;
-    m_maxX2 = maxX2;
-    m_maxX3 = maxX3;
+
+    Range inRange(maxX1, maxX2, maxX3);
 
     // GoWest
     if (inRange(x1 - 1, x2, x3) && !iCellHasSolid(bcArray, x1 - 1, x2, x3)) {
@@ -80,7 +90,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     }
     // GoEast
     else if (inRange(x1 + 2, x2, x3) &&
-             !iCellHasSolid(bcArray, x1 + 1, x2, x3)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+             !iCellHasSolid(bcArray, x1 + 1, x2, x3)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2, x3);
         xoff = -1;
@@ -96,7 +106,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     }
     // GoNorth
     else if (inRange(x1, x2 + 2, x3) &&
-             !iCellHasSolid(bcArray, x1, x2 + 1, x3)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+             !iCellHasSolid(bcArray, x1, x2 + 1, x3)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1, x2 + 1, x3);
         xoff = 0;
@@ -112,7 +122,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     }
     // GoTop
     else if (inRange(x1, x2, x3 + 2) &&
-             !iCellHasSolid(bcArray, x1, x2, x3 + 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+             !iCellHasSolid(bcArray, x1, x2, x3 + 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1, x2, x3 + 1);
         xoff = 0;
@@ -122,7 +132,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoNW
     else if (inRange(x1 - 1, x2 + 2, x3) &&
              !iCellHasSolid(bcArray, x1 - 1, x2 + 1,
-                            x3)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 - 1, x2 + 1, x3);
         xoff = 1;
@@ -132,7 +142,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoNE
     else if (inRange(x1 + 2, x2 + 2, x3) &&
              !iCellHasSolid(bcArray, x1 + 1, x2 + 1,
-                            x3)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2 + 1, x3);
         xoff = -1;
@@ -142,7 +152,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoSW
     else if (inRange(x1 - 1, x2 - 1, x3) &&
              !iCellHasSolid(bcArray, x1 - 1, x2 - 1,
-                            x3)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 - 1, x2 - 1, x3);
         xoff = 1;
@@ -152,7 +162,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoSE
     else if (inRange(x1 + 2, x2 - 1, x3) &&
              !iCellHasSolid(bcArray, x1 + 1, x2 - 1,
-                            x3)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2 - 1, x3);
         xoff = -1;
@@ -169,7 +179,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoBE
     else if (inRange(x1 + 2, x2, x3 - 1) &&
              !iCellHasSolid(bcArray, x1 + 1, x2,
-                            x3 - 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 - 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2, x3 - 1);
         xoff = -1;
@@ -186,7 +196,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoBN
     else if (inRange(x1, x2 + 2, x3 - 1) &&
              !iCellHasSolid(bcArray, x1, x2 + 1,
-                            x3 - 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 - 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1, x2 + 1, x3 - 1);
         xoff = 0;
@@ -203,7 +213,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoTE
     else if (inRange(x1 + 2, x2, x3 + 2) &&
              !iCellHasSolid(bcArray, x1 + 1, x2,
-                            x3 + 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 + 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2, x3 + 1);
         xoff = -1;
@@ -220,7 +230,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoTN
     else if (inRange(x1, x2 + 2, x3 + 2) &&
              !iCellHasSolid(bcArray, x1, x2 + 1,
-                            x3 + 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 + 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1, x2 + 1, x3 + 1);
         xoff = 0;
@@ -230,7 +240,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoTNW
     else if (inRange(x1 - 1, x2 + 2, x3 + 2) &&
              !iCellHasSolid(bcArray, x1 - 1, x2 + 1,
-                            x3 + 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 + 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 - 1, x2 + 1, x3 + 1);
         xoff = 1;
@@ -240,7 +250,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoTNE
     else if (inRange(x1 + 2, x2 + 2, x3 + 2) &&
              !iCellHasSolid(bcArray, x1 + 1, x2 + 1,
-                            x3 + 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 + 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2 + 1, x3 + 1);
         xoff = -1;
@@ -250,7 +260,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoTSE
     else if (inRange(x1 + 2, x2 - 1, x3 + 2) &&
              !iCellHasSolid(bcArray, x1 + 1, x2 - 1,
-                            x3 + 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 + 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2 - 1, x3 + 1);
         xoff = -1;
@@ -260,7 +270,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoTSW
     else if (inRange(x1 - 1, x2 - 1, x3 + 2) &&
              !iCellHasSolid(bcArray, x1 - 1, x2 - 1,
-                            x3 + 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 + 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 - 1, x2 - 1, x3 + 1);
         xoff = 1;
@@ -270,7 +280,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoBNW
     else if (inRange(x1 - 1, x2 + 2, x3 - 1) &&
              !iCellHasSolid(bcArray, x1 - 1, x2 + 1,
-                            x3 - 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 - 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 - 1, x2 + 1, x3 - 1);
         xoff = 1;
@@ -280,7 +290,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoBNE
     else if (inRange(x1 + 2, x2 + 2, x3 - 1) &&
              !iCellHasSolid(bcArray, x1 + 1, x2 + 1,
-                            x3 - 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 - 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2 + 1, x3 - 1);
         xoff = -1;
@@ -290,7 +300,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoBSE
     else if (inRange(x1 + 2, x2 - 1, x3 - 1) &&
              !iCellHasSolid(bcArray, x1 + 1, x2 - 1,
-                            x3 - 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 - 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 + 1, x2 - 1, x3 - 1);
         xoff = -1;
@@ -300,7 +310,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     // GoBSW
     else if (inRange(x1 - 1, x2 - 1, x3 - 1) &&
              !iCellHasSolid(bcArray, x1 - 1, x2 - 1,
-                            x3 - 1)) // ist �bern�chster Knoten auch im Gebiet (Grundknoten bei 0,0,0
+                            x3 - 1)) // is next but one node in area (base node at 0,0,0)
     {
         readICell(f, icell, x1 - 1, x2 - 1, x3 - 1);
         xoff = 1;
@@ -320,7 +330,7 @@ bool InterpolationProcessor::findNeighborICell(const SPtr<BCArray3D> bcArray, SP
     return true;
 }
 //////////////////////////////////////////////////////////////////////////
-int InterpolationProcessor::iCellHowManySolids(const SPtr<BCArray3D> bcArray, int x1, int x2, int x3)
+int Interpolator::iCellHowManySolids(const SPtr<BCArray3D> bcArray, int x1, int x2, int x3)
 {
     int count = 0;
     for (int ix3 = x3; ix3 <= x3 + 1; ix3++)
diff --git a/src/cpu/VirtualFluidsCore/LBM/InterpolationProcessor.h b/src/cpu/VirtualFluidsCore/LBM/Interpolation/Interpolator.h
similarity index 75%
rename from src/cpu/VirtualFluidsCore/LBM/InterpolationProcessor.h
rename to src/cpu/VirtualFluidsCore/LBM/Interpolation/Interpolator.h
index f298a531b61ca4c4d9ddffc6e2dfeab535be0aa1..81a0d7a363b73a01f079c412b2fd97765841d939 100644
--- a/src/cpu/VirtualFluidsCore/LBM/InterpolationProcessor.h
+++ b/src/cpu/VirtualFluidsCore/LBM/Interpolation/Interpolator.h
@@ -1,5 +1,7 @@
-#ifndef INTERPOLATIONPROCESSOR_H
-#define INTERPOLATIONPROCESSOR_H
+#ifndef CPU_INTERPOLATER_H
+#define CPU_INTERPOLATER_H
+
+#include <memory>
 
 #include "BCArray3D.h"
 #include "BoundaryConditions.h"
@@ -17,17 +19,16 @@ struct D3Q27ICell {
     real BSE[27];
 };
 
-class InterpolationProcessor;
-using InterpolationProcessorPtr = SPtr<InterpolationProcessor>;
+class Interpolator;
+using InterpolationProcessorPtr = std::shared_ptr<Interpolator>;
 
-#include "InterpolationHelper.h"
 
-class InterpolationProcessor
+class Interpolator
 {
 public:
-    InterpolationProcessor();
-    virtual ~InterpolationProcessor();
-    virtual InterpolationProcessorPtr clone()                                    = 0;
+    virtual ~Interpolator() = default;
+    virtual InterpolationProcessorPtr clone() = 0;
+
     virtual void setOmegas(real omegaC, real omegaF)                       = 0;
     virtual void interpolateCoarseToFine(D3Q27ICell &icellC, D3Q27ICell &icellF) = 0;
     virtual void interpolateCoarseToFine(D3Q27ICell &icellC, D3Q27ICell &icellF, real xoff, real yoff,
@@ -52,21 +53,9 @@ protected:
     virtual void calcInterpolatedNodeFC(real *f, real omega) {}
     virtual void calcInterpolatedVelocity(real x, real y, real z, real &vx1, real &vx2, real &vx3) {}
     virtual void calcInterpolatedShearStress(real x, real y, real z, real &tauxx, real &tauyy,
-                                             real &tauzz, real &tauxy, real &tauxz, real &tauyz)
-    {
-    }
+                                             real &tauzz, real &tauxy, real &tauxz, real &tauyz) {}
     virtual void setOffsets(real xoff, real yoff, real zoff) {}
-    friend class InterpolationHelper;
 
-private:
-    bool inRange(int x1, int x2, int x3);
-    int m_maxX1, m_maxX2, m_maxX3;
 };
 
-//////////////////////////////////////////////////////////////////////////
-inline bool InterpolationProcessor::inRange(int x1, int x2, int x3)
-{
-    return x1 >= 0 && x1 < m_maxX1 && x2 >= 0 && x2 < m_maxX2 && x3 >= 0 && x3 < m_maxX3;
-}
-
 #endif
diff --git a/src/cpu/VirtualFluidsCore/LBM/InterpolationHelper.cpp b/src/cpu/VirtualFluidsCore/LBM/InterpolationHelper.cpp
deleted file mode 100644
index f4b54988b4c3c20928f93359b22d74cf671c03e6..0000000000000000000000000000000000000000
--- a/src/cpu/VirtualFluidsCore/LBM/InterpolationHelper.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "InterpolationHelper.h"
-
-InterpolationHelper::InterpolationHelper(InterpolationProcessorPtr iProcessor) : iProcessor(iProcessor) {}
-//////////////////////////////////////////////////////////////////////////
-InterpolationHelper::~InterpolationHelper() = default;
-//////////////////////////////////////////////////////////////////////////
-void InterpolationHelper::interpolate8to1(D3Q27ICell &icellF, real *icellC, real /*x1*/, real /*x2*/,
-                                          real /*x3*/, real omega)
-{
-    iProcessor->calcInterpolatedCoefficiets(icellF, omega, vf::basics::constant::c1o1);
-    iProcessor->calcInterpolatedNodeFC(icellC, omega);
-}
-//////////////////////////////////////////////////////////////////////////
-void InterpolationHelper::interpolate8to1WithVelocity(D3Q27ICell &icellF, real x1, real x2, real x3,
-                                                      real omega, real &vx1, real &vx2, real &vx3)
-{
-    iProcessor->setOffsets(vf::basics::constant::c0o1, vf::basics::constant::c0o1, vf::basics::constant::c0o1);
-    iProcessor->calcInterpolatedCoefficiets(icellF, omega, vf::basics::constant::c0o1);
-    iProcessor->calcInterpolatedVelocity(x1, x2, x3, vx1, vx2, vx3);
-}
-//////////////////////////////////////////////////////////////////////////
-void InterpolationHelper::interpolate8to1WithVelocityWithShearStress(D3Q27ICell &icellF, real x1, real x2,
-                                                                     real x3, real omega, real &vx1,
-                                                                     real &vx2, real &vx3, real &tauxx,
-                                                                     real &tauyy, real &tauzz, real &tauxy,
-                                                                     real &tauxz, real &tauyz)
-{
-    iProcessor->setOffsets(vf::basics::constant::c0o1, vf::basics::constant::c0o1, vf::basics::constant::c0o1);
-    iProcessor->calcInterpolatedCoefficiets(icellF, omega, vf::basics::constant::c0o1);
-    iProcessor->calcInterpolatedVelocity(x1, x2, x3, vx1, vx2, vx3);
-    iProcessor->calcInterpolatedShearStress(x1, x2, x3, tauxx, tauyy, tauzz, tauxy, tauxz, tauyz);
-}
-
-//////////////////////////////////////////////////////////////////////////
diff --git a/src/cpu/VirtualFluidsCore/LBM/InterpolationHelper.h b/src/cpu/VirtualFluidsCore/LBM/InterpolationHelper.h
deleted file mode 100644
index b67e8d18ac5c54c775c098aad484d4b5657a917b..0000000000000000000000000000000000000000
--- a/src/cpu/VirtualFluidsCore/LBM/InterpolationHelper.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef D3Q27InterpolationHelper_H_
-#define D3Q27InterpolationHelper_H_
-
-#include "InterpolationProcessor.h"
-
-class InterpolationHelper;
-using InterpolationHelperPtr = SPtr<InterpolationHelper>;
-
-class InterpolationHelper
-{
-public:
-    InterpolationHelper(InterpolationProcessorPtr iProcessor);
-    ~InterpolationHelper();
-    void interpolate8to1(D3Q27ICell &icellF, real *icellC, real x1, real x2, real x3, real omega);
-    void interpolate8to1WithVelocity(D3Q27ICell &icellF, real x1, real x2, real x3, real omega, real &vx1,
-                                     real &vx2, real &vx3);
-    void interpolate8to1WithVelocityWithShearStress(D3Q27ICell &icellF, real x1, real x2, real x3, real omega,
-                                                    real &vx1, real &vx2, real &vx3, real &tauxx,
-                                                    real &tauyy, real &tauzz, real &tauxy, real &tauxz,
-                                                    real &tauyz);
-
-protected:
-private:
-    InterpolationProcessorPtr iProcessor;
-};
-
-#endif
diff --git a/src/cpu/VirtualFluidsCore/SimulationObservers/ShearStressSimulationObserver.cpp b/src/cpu/VirtualFluidsCore/SimulationObservers/ShearStressSimulationObserver.cpp
index 92c8f5f60344019cff472851104b86e5838302a8..2d7863292e8fc0eb153d78c2b4edfdf8a7cb4235 100644
--- a/src/cpu/VirtualFluidsCore/SimulationObservers/ShearStressSimulationObserver.cpp
+++ b/src/cpu/VirtualFluidsCore/SimulationObservers/ShearStressSimulationObserver.cpp
@@ -8,7 +8,7 @@
 #include "D3Q27Interactor.h"
 #include "DataSet3D.h"
 #include "Grid3D.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "LBMKernel.h"
 #include "UbScheduler.h"
 
@@ -421,139 +421,139 @@ void ShearStressSimulationObserver::findPlane(int ix1, int ix2, int ix3, SPtr<Gr
     bcPtr                                   = bcArray->getBC(ix1, ix2, ix3);
     int x, y, z;
 
-    if (InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2, ix3)) {
+    if (Interpolator::iCellHasSolid(bcArray, ix1, ix2, ix3)) {
         x = ix1;
         y = ix2;
         z = ix3;
-    } else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2 - 1, ix3)) {
+    } else if (Interpolator::iCellHasSolid(bcArray, ix1, ix2 - 1, ix3)) {
         x = ix1 + 0;
         y = ix2 - 1;
         z = ix3 + 0;
     } // S
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1, ix2, ix3 - 1)) {
         x = ix1 + 0;
         y = ix2 + 0;
         z = ix3 - 1;
     } // B
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2, ix3)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2, ix3)) {
         x = ix1 - 1;
         y = ix2 + 0;
         z = ix3 + 0;
     } // w
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2 - 1, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1, ix2 - 1, ix3 - 1)) {
         x = ix1 + 0;
         y = ix2 - 1;
         z = ix3 - 1;
     } // BS
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2, ix3 - 1)) {
         x = ix1 - 1;
         y = ix2 + 0;
         z = ix3 - 1;
     } // BW
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2 - 1, ix3)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2 - 1, ix3)) {
         x = ix1 - 1;
         y = ix2 - 1;
         z = ix3 + 0;
     } // SW
 
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2 - 1, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2 - 1, ix3 - 1)) {
         x = ix1 - 1;
         y = ix2 - 1;
         z = ix3 - 1;
     } // BSW
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2, ix3)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2, ix3)) {
         x = ix1 + 1;
         y = ix2 + 0;
         z = ix3 + 0;
     } // E
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2 + 1, ix3)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1, ix2 + 1, ix3)) {
         x = ix1 + 0;
         y = ix2 + 1;
         z = ix3 + 0;
     } // N
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1, ix2, ix3 + 1)) {
         x = ix1 + 0;
         y = ix2 + 0;
         z = ix3 + 1;
     } // T
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2 + 1, ix3)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2 + 1, ix3)) {
         x = ix1 + 1;
         y = ix2 + 1;
         z = ix3 + 0;
     } // NE
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2, ix3 + 1)) {
         x = ix1 + 1;
         y = ix2 + 0;
         z = ix3 + 1;
     } // TE
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1, ix2 + 1, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1, ix2 + 1, ix3 + 1)) {
         x = ix1 + 0;
         y = ix2 + 1;
         z = ix3 + 1;
     } // TN
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2 + 1, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2 + 1, ix3 + 1)) {
         x = ix1 + 1;
         y = ix2 + 1;
         z = ix3 + 1;
     } // TNE
 
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2 - 1, ix3)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2 - 1, ix3)) {
         x = ix1 + 1;
         y = ix2 - 1;
         z = ix3 + 0;
     } // SE
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2 + 1, ix3)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2 + 1, ix3)) {
         x = ix1 - 1;
         y = ix2 + 1;
         z = ix3 + 0;
     } // NW
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2, ix3 - 1)) {
         x = ix1 + 1;
         y = ix2 + 0;
         z = ix3 - 1;
     } // BE
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2, ix3 + 1)) {
         x = ix1 - 1;
         y = ix2 + 0;
         z = ix3 + 1;
     } // TW
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 0, ix2 + 1, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 0, ix2 + 1, ix3 - 1)) {
         x = ix1 + 0;
         y = ix2 + 1;
         z = ix3 - 1;
     } // BN
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 0, ix2 - 1, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 0, ix2 - 1, ix3 + 1)) {
         x = ix1 + 0;
         y = ix2 - 1;
         z = ix3 + 1;
     } // TS
 
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2 + 1, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2 + 1, ix3 + 1)) {
         x = ix1 - 1;
         y = ix2 + 1;
         z = ix3 + 1;
     } // TNW
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2 - 1, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2 - 1, ix3 + 1)) {
         x = ix1 + 1;
         y = ix2 - 1;
         z = ix3 + 1;
     } // TSE
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2 - 1, ix3 + 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2 - 1, ix3 + 1)) {
         x = ix1 - 1;
         y = ix2 - 1;
         z = ix3 + 1;
     } // TSW
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2 + 1, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2 + 1, ix3 - 1)) {
         x = ix1 + 1;
         y = ix2 + 1;
         z = ix3 - 1;
     } // BNE
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 - 1, ix2 + 1, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 - 1, ix2 + 1, ix3 - 1)) {
         x = ix1 - 1;
         y = ix2 + 1;
         z = ix3 - 1;
     } // BNW
-    else if (InterpolationProcessor::iCellHasSolid(bcArray, ix1 + 1, ix2 - 1, ix3 - 1)) {
+    else if (Interpolator::iCellHasSolid(bcArray, ix1 + 1, ix2 - 1, ix3 - 1)) {
         x = ix1 + 1;
         y = ix2 - 1;
         z = ix3 - 1;
@@ -594,7 +594,7 @@ void ShearStressSimulationObserver::findPlane(int ix1, int ix2, int ix3, SPtr<Gr
         }
     }
 
-    if (InterpolationProcessor::iCellHasSolid(bcArray, x, y, z)) {
+    if (Interpolator::iCellHasSolid(bcArray, x, y, z)) {
         for (int i = x; i <= x + 1; i++) {
             for (int j = y; j <= y + 1; j++) {
                 for (int k = z; k <= z + 1; k++) {
diff --git a/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.cpp b/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.cpp
index 660363e22e7c315a40df596aa95137f5589fff72..67202b66ae6a7ad158d29dd1b55bf658404e2ee8 100644
--- a/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.cpp
+++ b/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.cpp
@@ -8,7 +8,7 @@
 #include "DataSet3D.h"
 #include "Grid3D.h"
 #include "D3Q27System.h"
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 #include "LBMKernel.h"
 #include <CbArray2D.h>
 #include <basics/utilities/UbFileInputASCII.h>
diff --git a/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.h b/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.h
index a143ab6b0b40a8b35023a4916ffcbd20ae4b726c..eab801e448b4c797c7260274af66ea50a4677def 100644
--- a/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.h
+++ b/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsWithInterpolationGridVisitor.h
@@ -8,12 +8,12 @@
 
 class Grid3D;
 class Block3D;
-class InterpolationProcessor;
+class Interpolator;
 
 class InitDistributionsWithInterpolationGridVisitor : public Grid3DVisitor
 {
 public:
-    InitDistributionsWithInterpolationGridVisitor(SPtr<Grid3D> oldGrid, SPtr<InterpolationProcessor> iProcessor,
+    InitDistributionsWithInterpolationGridVisitor(SPtr<Grid3D> oldGrid, SPtr<Interpolator> iProcessor,
                                                   real nu);
     ~InitDistributionsWithInterpolationGridVisitor() override;
     void visit(SPtr<Grid3D> grid) override;
@@ -30,7 +30,7 @@ private:
     SPtr<Grid3D> oldGrid;
     real nu;
 
-    SPtr<InterpolationProcessor> iProcessor;
+    SPtr<Interpolator> iProcessor;
 };
 
 #endif // InitDistributionsWithVelocityProfileBlockVisitor_h__
diff --git a/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.cpp b/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.cpp
index 7ff7d20b9fcd85b6939f3184fcde86c6fdaae77d..362e8c92751e1275bfdaa7d7daf1567f117ecdf4 100644
--- a/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.cpp
+++ b/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.cpp
@@ -40,9 +40,9 @@
 #include <basics/transmitter/TbTransmitterLocal.h>
 
 #include <mpi/Communicator.h>
-#include "InterpolationProcessor.h"
+#include "Interpolator.h"
 
-SetInterpolationConnectorsBlockVisitor::SetInterpolationConnectorsBlockVisitor(std::shared_ptr<vf::mpi::Communicator> comm, real nue, SPtr<InterpolationProcessor> iProcessor) :
+SetInterpolationConnectorsBlockVisitor::SetInterpolationConnectorsBlockVisitor(std::shared_ptr<vf::mpi::Communicator> comm, real nue, SPtr<Interpolator> iProcessor) :
 Block3DVisitor(0, D3Q27System::MAXLEVEL), 
 	comm(comm),
 	nue(nue),
diff --git a/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.h b/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.h
index c30d87ecaa042a30d931e29ba185fdd5230e2a68..b1f6f99e1c4eff543f87dfcd70e7b45bf27701d5 100644
--- a/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.h
+++ b/src/cpu/VirtualFluidsCore/Visitors/SetInterpolationConnectorsBlockVisitor.h
@@ -44,13 +44,13 @@
 class Grid3D;
 class Block3D;
 namespace vf::mpi {class Communicator;}
-class InterpolationProcessor;
+class Interpolator;
 
 //! \brief  A class sets connectors between blocks.
 class SetInterpolationConnectorsBlockVisitor : public Block3DVisitor
 {
 public:
-    SetInterpolationConnectorsBlockVisitor(std::shared_ptr<vf::mpi::Communicator> comm, real nue, SPtr<InterpolationProcessor> iProcessor);
+    SetInterpolationConnectorsBlockVisitor(std::shared_ptr<vf::mpi::Communicator> comm, real nue, SPtr<Interpolator> iProcessor);
     ~SetInterpolationConnectorsBlockVisitor() override;
     void visit(SPtr<Grid3D> grid, SPtr<Block3D> block) override;
     //////////////////////////////////////////////////////////////////////////
@@ -66,7 +66,7 @@ protected:
     std::shared_ptr<vf::mpi::Communicator> comm;
     int gridRank;
     real nue;
-    SPtr<InterpolationProcessor> iProcessor;
+    SPtr<Interpolator> iProcessor;
 };
 
 #endif // SetInterpolationConnectorsBlockVisitor_H
diff --git a/src/cpu/simulationconfig/Simulation.cpp b/src/cpu/simulationconfig/Simulation.cpp
index ec8773515ce49bdb8c0680152924605203ba9405..67c4e469d41ea24f1029f09e1beb78a597974e4c 100644
--- a/src/cpu/simulationconfig/Simulation.cpp
+++ b/src/cpu/simulationconfig/Simulation.cpp
@@ -26,7 +26,7 @@
 #include <Simulation/Simulation.h>
 #include <Simulation/Grid3D.h>
 #include <Interactors/InteractorsHelper.h>
-#include <LBM/CompressibleOffsetMomentsInterpolationProcessor.h>
+#include <LBM/Interpolation/CompressibleOffsetMomentsInterpolator.h>
 #include <LBM/LBMKernel.h>
 #include <LBM/LBMUnitConverter.h>
 #include <mpi/MPICommunicator.h>
diff --git a/src/cuda/DeviceInfo.cpp b/src/cuda/DeviceInfo.cpp
index 20ea2c4f6ba098b17e444f55625a6791e46141e5..81fea1cf21418ef98217293985f8c1101f8635be 100644
--- a/src/cuda/DeviceInfo.cpp
+++ b/src/cuda/DeviceInfo.cpp
@@ -15,7 +15,7 @@ void verifyNumberOfDevices(int deviceId)
     int device_count = 0;
     cudaError_t errorId = cudaGetDeviceCount(&device_count);
     if(errorId != cudaSuccess) {
-        VF_LOG_CRITICAL("Error while accessing the device count: {}", cudaGetErrorString(errorId));
+        VF_LOG_CRITICAL("Device {}: Error while accessing the device count: {}", deviceId, cudaGetErrorString(errorId));
     }
     if (deviceId > device_count) {
         throw std::runtime_error("chosen gpudevice >=  device_count ... exiting\n");
@@ -28,13 +28,13 @@ void verifyComputeCapability(int deviceId)
     cudaError_t errorId = cudaGetDeviceProperties(&deviceProp, deviceId);
 
     if(errorId != cudaSuccess){
-        VF_LOG_CRITICAL("Error while accessing the device properties occurs: {}", cudaGetErrorString(errorId));
+        VF_LOG_CRITICAL("Device {}: Error while accessing the device properties occurs: {}", deviceId, cudaGetErrorString(errorId));
     }
 
     VF_LOG_INFO("[compute capability] = [{}.{}]\n", deviceProp.major, deviceProp.minor);
 
     if (deviceProp.major > 999) {
-        throw std::runtime_error("warning, CUDA Device Emulation (CPU) detected, exiting\n");
+        throw std::runtime_error("Warning, CUDA Device Emulation (CPU) detected, exiting\n");
     }
 }
 
@@ -43,13 +43,13 @@ void setCudaDevice(int deviceId)
     // choose a cuda device for kernel execution
     cudaError_t errorId = cudaSetDevice(deviceId);
     if (errorId != cudaSuccess) {
-        VF_LOG_CRITICAL("Error while setting the device to {}: {}", deviceId, cudaGetErrorString(errorId));
+        VF_LOG_CRITICAL("Device {}: Error while setting the device to: {}", deviceId, cudaGetErrorString(errorId));
     } else {
         int device;
         // double check that device was properly selected
         errorId = cudaGetDevice(&device);
         if(errorId != cudaSuccess) {
-            VF_LOG_CRITICAL("Error while getting the device: {}", cudaGetErrorString(errorId));
+            VF_LOG_CRITICAL("Device {}: Error while getting the device: {}", deviceId, cudaGetErrorString(errorId));
         }
     }
 }
@@ -70,7 +70,7 @@ void printCudaInformation(int deviceId)
     cudaError_t errorId = cudaGetDeviceProperties(&prop, deviceId);
 
     if(errorId != cudaSuccess){
-        VF_LOG_CRITICAL("Error while accessing the device properties occurs: {}", cudaGetErrorString(errorId));
+        VF_LOG_CRITICAL("Device {}: Error while accessing the device properties occurs: {}", deviceId, cudaGetErrorString(errorId));
     }
 
     printf(" --- General Information for device %d ---\n", deviceId);
diff --git a/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.cpp b/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.cpp
index 571796d503a1a73b3eccf631a347884c7522b533..15efa9d3204cc37d4c4ccd8778ea13769ef655b8 100644
--- a/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.cpp
+++ b/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.cpp
@@ -49,16 +49,16 @@ std::vector<T> readStringToVector(std::string s)
 
 std::string readElement(std::string line)
 {
-    size_t elemStart = line.find("<")+1;
+    const size_t elemStart = line.find('<')+1;
     // size_t elemEnd = line.find("/>", elemStart);
-    size_t nameLen = line.find(" ", elemStart)-elemStart;
+    const size_t nameLen = line.find(' ', elemStart)-elemStart;
     return line.substr(elemStart, nameLen);
 }
 
 std::string readAttribute(std::string line, std::string attributeName)
 {
-    size_t attributeStart = line.find(attributeName)+attributeName.size() + 2; // add 2 for '="'
-    size_t attributeLen = line.find("\"", attributeStart)-attributeStart;
+    const size_t attributeStart = line.find(attributeName)+attributeName.size() + 2; // add 2 for '="'
+    const size_t attributeLen = line.find("\"", attributeStart)-attributeStart;
     return line.substr(attributeStart, attributeLen);
 }
 
@@ -94,7 +94,7 @@ void VTKFile::readHeader()
     getline(file, line); // </ImageData
     getline(file, line); // AppendedData
 
-    int offset = int(file.tellg())+sizeof(char)+4; // skip underscore and bytesPerVal
+    const int offset = int(file.tellg())+sizeof(char)+4; // skip underscore and bytesPerVal
 
     for(auto& quantity: this->quantities)
     {
@@ -118,7 +118,7 @@ void VTKFile::readHeader()
 
 }
 
-bool VTKFile::markNANs(std::vector<uint> readIndices)
+bool VTKFile::markNANs(const std::vector<uint>& readIndices) const
 {
     std::ifstream buf(fileName.c_str(), std::ios::in | std::ios::binary);
 
@@ -126,7 +126,7 @@ bool VTKFile::markNANs(std::vector<uint> readIndices)
     tmp.reserve(readIndices.size());
     buf.seekg(this->quantities[0].offset);
     buf.read((char*) tmp.data(), sizeof(double)*readIndices.size());
-    auto firstNAN = std::find_if(tmp.begin(), tmp.end(), [](auto it){ return isnan(it); });
+    const auto firstNAN = std::find_if(tmp.begin(), tmp.end(), [](auto it){ return isnan(it); });
     
     return firstNAN != tmp.end();
 }
@@ -161,7 +161,7 @@ void VTKFile::getData(real *data, uint numberOfNodes, const std::vector<uint> &r
 {
     if(!this->loaded) loadFile();
 
-    size_t nPoints = writeIndices.size();
+    const size_t nPoints = writeIndices.size();
 
     for(size_t j=0; j<this->quantities.size(); j++)
     {
@@ -177,7 +177,7 @@ void VTKFile::printFileInfo()
 {
     printf("file %s with \n nx %i ny %i nz %i \n origin %f %f %f \n spacing %f %f %f \n", 
             fileName.c_str(), nx, ny, nz, minX, minY, minZ, deltaX, deltaY, deltaZ);
-    for(auto quantity: this->quantities)
+    for(const auto& quantity: this->quantities)
     {
         printf("\t quantity %s offset %i \n", quantity.name.c_str(), quantity.offset);
     }
@@ -199,8 +199,8 @@ void VTKFileCollection::findFiles()
             std::vector<VTKFile> filesWithThisId;
             while (!foundLastPart)
             {
-                std::string fname = makeFileName((int)files.size(), (int)filesOnThisLevel.size(), (int)filesWithThisId.size());
-                std::ifstream f(fname);
+                const std::string fname = makeFileName((int)files.size(), (int)filesOnThisLevel.size(), (int)filesWithThisId.size());
+                const std::ifstream f(fname);
                 if(f.good())
                     filesWithThisId.emplace_back(fname);
                 else
@@ -223,7 +223,7 @@ void VTKFileCollection::findFiles()
     }
 
     if(files.empty())
-        VF_LOG_CRITICAL("VTKFileCollection found no files!"); 
+        throw std::runtime_error("VTKFileCollection found no files!");
 }
     
 void TransientBCInputFileReader::getNeighbors(uint* neighbor0PP, uint* neighbor0PM, uint* neighbor0MP, uint* neighbor0MM)
@@ -260,8 +260,8 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
 {
     this->nPoints = (uint)coordsY.size();
     this->initializeIndexVectors();
-    real max_diff = 1e-4; // maximum distance between point on grid and precursor plane to count as exact match
-    real eps = 1e-7; // small number to avoid division by zero
+    const real max_diff = 1e-4; // maximum distance between point on grid and precursor plane to count as exact match
+    const real eps = 1e-7; // small number to avoid division by zero
     bool perfect_match = true;
 
     this->weights0PP.reserve(this->nPoints);
@@ -277,11 +277,11 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
     for(uint i=0; i<nPoints; i++)
     {
 
-        real posY = coordsY[i];
-        real posZ = coordsZ[i];
+        const real posY = coordsY[i];
+        const real posZ = coordsZ[i];
         bool found0PP = false, found0PM = false, found0MP = false, found0MM = false, foundAll = false;
 
-        uint level = this->readLevel;
+        const uint level = this->readLevel;
 
         for(int fileId=0; fileId<(int)this->fileCollection->files[level].size(); fileId++)
         {
@@ -290,7 +290,7 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
 
             // y in simulation is x in precursor/file, z in simulation is y in precursor/file 
             // simulation -> file: N -> E, S -> W, T -> N, B -> S
-            int idx = file.findNeighborMMM(posY, posZ, 0.f);                            //!> index of nearest WSB neighbor on precursor file
+            const int idx = file.findNeighborMMM(posY, posZ, 0.f);                            //!> index of nearest WSB neighbor on precursor file
             
             if(idx!=-1)
             {
@@ -301,7 +301,7 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
                     this->weights0PM.emplace_back(0.f);
                     this->weights0MP.emplace_back(0.f);
                     this->weights0MM.emplace_back(0.f);
-                    uint writeIdx = this->getWriteIndex(level, fileId, idx);            //!> writeIdx: index on host/device array where precursor value will be written to after loading from file
+                    const uint writeIdx = this->getWriteIndex(level, fileId, idx);            //!> writeIdx: index on host/device array where precursor value will be written to after loading from file
                     this->planeNeighbor0PP.push_back(writeIdx);                          //!> neighbor lists mapping where BC kernel should read from on host/device array
                     this->planeNeighbor0PM.push_back(writeIdx);
                     this->planeNeighbor0MP.push_back(writeIdx);
@@ -319,8 +319,8 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
                 if(!found0MM)
                 {
                     found0MM = true;
-                    real dy = file.getX(idx)-posY;
-                    real dz = file.getY(idx)-posZ;
+                    const real dy = file.getX(idx)-posY;
+                    const real dz = file.getY(idx)-posZ;
                     this->weights0MM.emplace_back(1.f/(dy*dy+dz*dz+eps));
                     this->planeNeighbor0MM.emplace_back(getWriteIndex(level, fileId, idx));
                 }
@@ -329,12 +329,12 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
             
             if(!found0PP) //NT in simulation is EN in precursor
             {
-                int index = file.findNeighborPPM(posY, posZ, 0.f);
+                const int index = file.findNeighborPPM(posY, posZ, 0.f);
                 if(index!=-1)
                 {
                     found0PP = true;
-                    real dy = file.getX(index)-posY;
-                    real dz = file.getY(index)-posZ;
+                    const real dy = file.getX(index)-posY;
+                    const real dz = file.getY(index)-posZ;
                     this->weights0PP.emplace_back(1.f/(dy*dy+dz*dz+eps));
                     this->planeNeighbor0PP.emplace_back(getWriteIndex(level, fileId, index));
                 }
@@ -342,12 +342,12 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
 
             if(!found0PM) //NB in simulation is ES in precursor
             {
-                int index = file.findNeighborPMM(posY, posZ, 0.f);
+                const int index = file.findNeighborPMM(posY, posZ, 0.f);
                 if(index!=-1)
                 {
                     found0PM = true;
-                    real dy = file.getX(index)-posY;
-                    real dz = file.getY(index)-posZ;
+                    const real dy = file.getX(index)-posY;
+                    const real dz = file.getY(index)-posZ;
                     this->weights0PM.emplace_back(1.f/(dy*dy+dz*dz+eps));
                     this->planeNeighbor0PP.emplace_back(getWriteIndex(level, fileId, index));
                 }
@@ -355,12 +355,12 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
 
             if(!found0MP) //ST in simulation is WN in precursor
             {
-                int index = file.findNeighborMPM(posY, posZ, 0.f);
+                const int index = file.findNeighborMPM(posY, posZ, 0.f);
                 if(index!=-1)
                 {
                     found0MP = true;
-                    real dy = file.getX(index)-posY;
-                    real dz = file.getY(index)-posZ;
+                    const real dy = file.getX(index)-posY;
+                    const real dz = file.getY(index)-posZ;
                     this->weights0MP.emplace_back(1.f/(dy*dy+dz*dz+eps));
                     this->planeNeighbor0MP.emplace_back(getWriteIndex(level, fileId, index));
                 }
@@ -391,8 +391,8 @@ void VTKReader::fillArrays(std::vector<real>& coordsY, std::vector<real>& coords
 
 uint VTKReader::getWriteIndex(int level, int id, int linearIndex)
 {
-    auto it = std::find(this->writeIndices[level][id].begin(), this->writeIndices[level][id].end(), linearIndex);
-    uint idx = it-this->writeIndices[level][id].begin();
+    const auto it = std::find(this->writeIndices[level][id].begin(), this->writeIndices[level][id].end(), linearIndex);
+    const uint idx = it-this->writeIndices[level][id].begin();
     if(it==this->writeIndices[level][id].end())                         
     {
         this->writeIndices[level][id].push_back(this->nPointsRead);     //!> index on host/device array where value from file will be written to
@@ -407,17 +407,16 @@ void VTKReader::getNextData(real* data, uint numberOfNodes, real time)
 {
     // for(size_t level=0; level<this->fileCollection->files.size(); level++)
     // {
-        uint level = this->readLevel;
+        const uint level = this->readLevel;
         for(size_t id=0; id<this->fileCollection->files[level].size(); id++)
         {
             size_t numberOfFiles = this->nFile[level][id];
 
-
             if(!this->fileCollection->files[level][id][numberOfFiles].inZBounds(time))
             {
                 numberOfFiles++;
 
-                VF_LOG_INFO("PrecursorBC on level {}: switching to file no. {}\n", level, numberOfFiles);
+                VF_LOG_INFO("PrecursorBC on level {}: switching to file no. {}", level, numberOfFiles);
                 if(numberOfFiles == this->fileCollection->files[level][id].size())
                     throw std::runtime_error("Not enough Precursor Files to read");
 
@@ -433,10 +432,9 @@ void VTKReader::getNextData(real* data, uint numberOfNodes, real time)
                 }
             }
         
-
             VTKFile* file = &this->fileCollection->files[level][id][numberOfFiles];
 
-            int off = file->getClosestIdxZ(time)*file->getNumberOfPointsInXYPlane();
+            const int off = file->getClosestIdxZ(time)*file->getNumberOfPointsInXYPlane();
             file->getData(data, numberOfNodes, this->readIndices[level][id], this->writeIndices[level][id], off, this->writingOffset);
             this->nFile[level][id] = numberOfFiles;
         }
diff --git a/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.h b/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.h
index bdf29745a0a60473d0454c33dcb10a193ca10780..5b9ea91a831da4d9bf189418e0e3eaaf8abd7357 100644
--- a/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.h
+++ b/src/gpu/GridGenerator/TransientBCSetter/TransientBCSetter.h
@@ -41,7 +41,7 @@ public:
     };
 
     void getData(real* data, uint numberOfNodes, const std::vector<uint>& readIndices, const std::vector<uint>& writeIndices, uint offsetRead, uint offsetWrite);
-    bool markNANs(std::vector<uint> readIndices);
+    bool markNANs(const std::vector<uint>& readIndices) const;
     bool inBoundingBox(real posX, real posY, real posZ){return  inXBounds(posX) && inYBounds(posY) && inZBounds(posZ); };
     bool inXBounds(real posX){ return posX<=maxX && posX>=minX; };
     bool inYBounds(real posY){ return posY<=maxY && posY>=minY; };
@@ -183,7 +183,7 @@ public:
     void getNextData(real* data, uint numberOfNodes, real time) override;
     void fillArrays(std::vector<real>& coordsY, std::vector<real>& coordsZ) override;
 private:  
-    uint getWriteIndex(int level, int id, int linearIdx);
+    uint getWriteIndex(int level, int id, int linearIndex);
     void initializeIndexVectors();
 
 private:
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.cpp
index e7a9e5bb6b5a5b0fa24d7ff7da5e3318891ea48d..9b2d1c4f5fa742b46ecd9ad3a9f8e86b499909fb 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.cpp
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.cpp
@@ -35,7 +35,7 @@ void GridProvider::setNumberOfTaggedFluidNodes(uint numberOfNodes, CollisionTemp
     para->getParD(level)->numberOfTaggedFluidNodes[tag] = numberOfNodes;
 }
 
-void GridProvider::setInitalNodeValues(uint numberOfNodes, int level) const
+void GridProvider::setInitialNodeValues(uint numberOfNodes, int level) const
 {
     for (uint pos = 1; pos <= numberOfNodes; pos++)
     {
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.h b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.h
index 079843371208891cc2ef6ae206f53a6f57678a1a..ee6c93a5f718a2e6907e178bf7b751fbaed824dd 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.h
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridProvider.h
@@ -48,7 +48,7 @@ public:
 protected:
     void setNumberOfNodes(uint numberOfNodes, int level) const;
     void setNumberOfTaggedFluidNodes(uint numberOfNodes, CollisionTemplate tag, int level) const;
-    virtual void setInitalNodeValues(uint numberOfNodes, int level) const;
+    virtual void setInitialNodeValues(uint numberOfNodes, int level) const;
 
     void setPressSizePerLevel(int level, int sizePerLevel) const;
     void setVelocitySizePerLevel(int level, int sizePerLevel) const;
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderFiles/GridReader.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderFiles/GridReader.cpp
index c126b2f79e02272a0bd86bfe0f76fe5efe09a5a7..000e97e9a14e51d140dfa30cb325d2a04cd83f50 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderFiles/GridReader.cpp
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderFiles/GridReader.cpp
@@ -94,7 +94,7 @@ void GridReader::allocArrays_CoordNeighborGeo()
         neighWSB->initalNeighbors(para->getParH(level)->neighborInverse, level);
         geoV.initalNeighbors(     para->getParH(level)->typeOfGridNode,          level);
         rearrangeGeometry(para.get(), level);
-		setInitalNodeValues(numberOfNodesPerLevel, level);
+		setInitialNodeValues(numberOfNodesPerLevel, level);
 
         cudaMemoryManager->cudaCopyNeighborWSB(level);
         cudaMemoryManager->cudaCopySP(level);
diff --git a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.cpp b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.cpp
index 8984c15ebcc44598a30a3864945198ab0c5fde07..e3c86317c3bf7e4ece5720ac8117e5f418b22fa4 100644
--- a/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.cpp
+++ b/src/gpu/VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.cpp
@@ -4,6 +4,7 @@
 #include "Parameter/Parameter.h"
 #include "GridGenerator/grid/GridBuilder/GridBuilder.h"
 #include "GPU/CudaMemoryManager.h"
+#include "Parameter/CudaStreamManager.h"
 #include "IndexRearrangementForStreams.h"
 #include "InterpolationCellGrouper.h"
 
@@ -92,7 +93,7 @@ void GridGenerator::allocArrays_CoordNeighborGeo()
             para->getParH(level)->typeOfGridNode,
             level);
 
-        setInitalNodeValues(numberOfNodesPerLevel, level);
+        setInitialNodeValues(numberOfNodesPerLevel, level);
 
         cudaMemoryManager->cudaCopyNeighborWSB(level);
         cudaMemoryManager->cudaCopySP(level);
@@ -364,6 +365,8 @@ void GridGenerator::allocArrays_BoundaryValues()
 
             cudaMemoryManager->cudaCopyPrecursorBC(level);
             cudaMemoryManager->cudaAllocPrecursorData(level);
+            para->getParD(level)->precursorBC.streamIndex = para->getStreamManager()->registerAndLaunchStream(CudaStreamIndex::Precursor);
+            
 
             // read first timestep of precursor into next and copy to next on device
             for(auto reader : para->getParH(level)->transientBCInputFileReader)
diff --git a/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp b/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp
index 14e090ff3f02eaec87a9f709fc0e0ac8df711189..64943d19ff54bfaa174d0728a96c517f6605d565 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp
+++ b/src/gpu/VirtualFluids_GPU/GPU/CudaMemoryManager.cpp
@@ -1740,11 +1740,11 @@ void CudaMemoryManager::cudaCopyPrecursorBC(int lev)
 }
 void CudaMemoryManager::cudaCopyPrecursorData(int lev)
 {
-    auto prec = &parameter->getParH(lev)->precursorBC;
-    auto precStream = parameter->getStreamManager()->getStream(CudaStreamIndex::Precursor);
-    size_t memSize = prec->numberOfPrecursorNodes*sizeof(real)*prec->numberOfQuantities;
-    checkCudaErrors( cudaStreamSynchronize(precStream) );
-    checkCudaErrors( cudaMemcpyAsync(parameter->getParD(lev)->precursorBC.next, prec->next, memSize, cudaMemcpyHostToDevice, precStream) );
+    auto precurser = &parameter->getParH(lev)->precursorBC;
+    auto precurserStream = parameter->getStreamManager()->getStream(CudaStreamIndex::Precursor, precurser->streamIndex);
+    size_t memSize = precurser->numberOfPrecursorNodes*sizeof(real)*precurser->numberOfQuantities;
+    checkCudaErrors( cudaStreamSynchronize(precurserStream) );
+    checkCudaErrors( cudaMemcpyAsync(parameter->getParD(lev)->precursorBC.next, precurser->next, memSize, cudaMemcpyHostToDevice, precurserStream) );
 }
 
 
@@ -3399,14 +3399,17 @@ void CudaMemoryManager::cudaAllocProbeIndices(Probe* probe, int level)
     checkCudaErrors( cudaMalloc    ((void**) &probe->getProbeStruct(level)->pointIndicesD, tmp) );
     setMemsizeGPU(1.f*tmp, false);
 }
+
 void CudaMemoryManager::cudaCopyProbeIndicesHtoD(Probe* probe, int level)
 {
     checkCudaErrors( cudaMemcpy(probe->getProbeStruct(level)->pointIndicesD, probe->getProbeStruct(level)->pointIndicesH, sizeof(int)*probe->getProbeStruct(level)->nIndices, cudaMemcpyHostToDevice) );
 }
+
 void CudaMemoryManager::cudaCopyProbeIndicesDtoH(Probe* probe, int level)
 {
     checkCudaErrors( cudaMemcpy(probe->getProbeStruct(level)->pointIndicesH, probe->getProbeStruct(level)->pointIndicesD, sizeof(int)*probe->getProbeStruct(level)->nIndices, cudaMemcpyDeviceToHost) );
 }
+
 void CudaMemoryManager::cudaFreeProbeIndices(Probe* probe, int level)
 {
     checkCudaErrors( cudaFreeHost(probe->getProbeStruct(level)->pointIndicesH) );
@@ -3415,25 +3418,28 @@ void CudaMemoryManager::cudaFreeProbeIndices(Probe* probe, int level)
 
 void CudaMemoryManager::cudaAllocProbeQuantityArray(Probe* probe, int level)
 {
-    size_t tmp = sizeof(real)*probe->getProbeStruct(level)->nArrays*probe->getProbeStruct(level)->nPoints;
+    auto probeStruct = probe->getProbeStruct(level);
+    size_t tmp = sizeof(real)*probeStruct->nArrays*probeStruct->nPoints*probeStruct->nTimesteps;
 
-    checkCudaErrors( cudaMallocHost((void**) &probe->getProbeStruct(level)->quantitiesArrayH, tmp) );
+    checkCudaErrors( cudaMallocHost((void**) &probeStruct->quantitiesArrayH, tmp) );
     if(probe->getHasDeviceQuantityArray())
     {
-        checkCudaErrors( cudaMalloc    ((void**) &probe->getProbeStruct(level)->quantitiesArrayD, tmp) );
+        checkCudaErrors( cudaMalloc    ((void**) &probeStruct->quantitiesArrayD, tmp) );
         setMemsizeGPU(1.f*tmp, false);
     }
 }
 
 void CudaMemoryManager::cudaCopyProbeQuantityArrayHtoD(Probe* probe, int level)
 {
-    checkCudaErrors( cudaMemcpy(probe->getProbeStruct(level)->quantitiesArrayD, probe->getProbeStruct(level)->quantitiesArrayH, probe->getProbeStruct(level)->nArrays*sizeof(real)*probe->getProbeStruct(level)->nPoints, cudaMemcpyHostToDevice) );
+    auto probeStruct = probe->getProbeStruct(level);
+    size_t tmp = sizeof(real)*probeStruct->nArrays*probeStruct->nPoints*probeStruct->nTimesteps;
+    checkCudaErrors( cudaMemcpy(probeStruct->quantitiesArrayD, probeStruct->quantitiesArrayH, tmp, cudaMemcpyHostToDevice) );
 }
 void CudaMemoryManager::cudaCopyProbeQuantityArrayDtoH(Probe* probe, int level)
 {
     auto probeStruct = probe->getProbeStruct(level);
-
-    checkCudaErrors( cudaMemcpy(probeStruct->quantitiesArrayH, probeStruct->quantitiesArrayD, probeStruct->nArrays*sizeof(real)*probeStruct->nPoints, cudaMemcpyDeviceToHost) );
+    size_t tmp = sizeof(real)*probeStruct->nArrays*probeStruct->nPoints*probeStruct->nTimesteps;
+    checkCudaErrors( cudaMemcpy(probeStruct->quantitiesArrayH, probeStruct->quantitiesArrayD, tmp, cudaMemcpyDeviceToHost) );
 }
 
 void CudaMemoryManager::cudaFreeProbeQuantityArray(Probe* probe, int level)
diff --git a/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleCF_compressible.cu b/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleCF_compressible.cu
index ec1c8207bdd38666f4222270be81b91960142e62..528bbfc7a9584b2c5dedb17098324cbeab9ee1f6 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleCF_compressible.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleCF_compressible.cu
@@ -36,862 +36,27 @@
 #include "LBM/GPUHelperFunctions/ChimeraTransformation.h"
 #include "LBM/GPUHelperFunctions/ScalingUtilities.h"
 
-using namespace vf::basics::constant;
-using namespace vf::lbm::dir;
-using namespace vf::gpu;
+#include <lbm/refinement/InterpolationCF.h>
+#include <lbm/refinement/Coefficients.h>
 
-//////////////////////////////////////////////////////////////////////////
-//! \brief Calculate the interpolated distributions on the fine destination nodes
-//! \details Used in scaling from coarse to fine
-//! The function is executed in the following steps:
-//!
-__device__ __inline__ void interpolateDistributions(
-    const real& x, const real& y, const real& z,
-    real& m_000, 
-    real& m_100, real& m_010, real& m_001,
-    real& m_011, real& m_101, real& m_110, real& m_200, real& m_020, real& m_002,
-    real& m_111, real& m_210, real& m_012, real& m_201, real& m_021, real& m_120, real& m_102,
-    real& m_022, real& m_202, real& m_220, real& m_211, real& m_121, real& m_112,
-    real& m_122, real& m_212, real& m_221,
-    real& m_222,
-    const real& a_000, const real& a_100, const real& a_010, const real& a_001, const real& a_200, const real& a_020, const real& a_002, const real& a_110, const real&  a_101, const real& a_011, const real& a_111,
-    const real& b_000, const real& b_100, const real& b_010, const real& b_001, const real& b_200, const real& b_020, const real& b_002, const real& b_110, const real&  b_101, const real& b_011, const real& b_111,
-    const real& c_000, const real& c_100, const real& c_010, const real& c_001, const real& c_200, const real& c_020, const real& c_002, const real& c_110, const real&  c_101, const real& c_011, const real& c_111,
-    const real& d_000, const real& d_100, const real& d_010, const real& d_001, const real& d_110, const real& d_101, const real& d_011, const real& d_111,
-    const real& LaplaceRho, const real& eps_new, const real& omegaF, 
-    const real& kxxMyyAverage, const real& kxxMzzAverage, const real& kyzAverage, const real& kxzAverage, const real& kxyAverage
-)
-{
-    real useNEQ = c1o1;//zero;//one;   //.... one = on ..... zero = off 
-
-    //////////////////////////////////////////////////////////////////////////
-    // - Reset all moments to zero
-    //
-    m_111 = c0o1;
-    m_211 = c0o1;
-    m_011 = c0o1;
-    m_121 = c0o1;
-    m_101 = c0o1;
-    m_112 = c0o1;
-    m_110 = c0o1;
-    m_221 = c0o1;
-    m_001 = c0o1;
-    m_201 = c0o1;
-    m_021 = c0o1;
-    m_212 = c0o1;
-    m_010 = c0o1;
-    m_210 = c0o1;
-    m_012 = c0o1;
-    m_122 = c0o1;
-    m_100 = c0o1;
-    m_120 = c0o1;
-    m_102 = c0o1;
-    m_222 = c0o1;
-    m_022 = c0o1;
-    m_202 = c0o1;
-    m_002 = c0o1;
-    m_220 = c0o1;
-    m_020 = c0o1;
-    m_200 = c0o1;
-    m_000 = c0o1;
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Set macroscopic values on destination node (zeroth and first order moments)
-    //!
-    real press = d_000 + x * d_100 + y * d_010 + z * d_001 +
-                 x * y * d_110 + x * z * d_101 + y * z * d_011 + x * y * z * d_111 + c3o1 * x * x * LaplaceRho;
-    real vvx   = a_000 + x * a_100 + y * a_010 + z * a_001 +
-                 x * x * a_200 + y * y * a_020 + z * z * a_002 +
-                 x * y * a_110 + x * z * a_101 + y * z * a_011 + x * y * z * a_111;
-    real vvy   = b_000 + x * b_100 + y * b_010 + z * b_001 +
-                 x * x * b_200 + y * y * b_020 + z * z * b_002 +
-                 x * y * b_110 + x * z * b_101 + y * z * b_011 + x * y * z * b_111;
-    real vvz   = c_000 + x * c_100 + y * c_010 + z * c_001 +
-                 x * x * c_200 + y * y * c_020 + z * z * c_002 +
-                 x * y * c_110 + x * z * c_101 + y * z * c_011 + x * y * z * c_111;
-
-    m_000 = press; // m_000 is press, if drho is interpolated directly
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Set moments (second to sixth order) on destination node
-    //!
-    // linear combinations for second order moments
-    real mxxPyyPzz = m_000;
-
-    real mxxMyy = -c2o3 * (a_100 - b_010 + kxxMyyAverage + c2o1 * a_200 * x - b_110 * x + a_110 * y
-                  -c2o1 * b_020 * y + a_101 * z - b_011 * z - b_111 * x * z + a_111 * y * z) * eps_new/ omegaF * (c1o1 + press);
-    real mxxMzz = -c2o3 * (a_100 - c_001 + kxxMzzAverage + c2o1 * a_200 * x - c_101 * x + a_110 * y
-                  -c_011 * y - c_111 * x * y + a_101 * z - c2o1 * c_002 * z + a_111 * y * z) * eps_new/ omegaF * (c1o1 + press);
-
-    m_011 = -c1o3 * (b_001 + c_010 + kyzAverage + b_101 * x + c_110 * x + b_011 * y + c2o1 * c_020 * y
-            + b_111 * x * y + c2o1 * b_002 * z + c_011 * z + c_111 * x * z) * eps_new / omegaF * (c1o1 + press);
-    m_101 = -c1o3 * (a_001 + c_100 + kxzAverage + a_101 * x + c2o1 * c_200 * x + a_011 * y + c_110 * y
-            + a_111 * x * y + c2o1 * a_002 * z + c_101 * z + c_111 * y * z) * eps_new / omegaF * (c1o1 + press);
-    m_110 = -c1o3 * (a_010 + b_100 + kxyAverage + a_110 * x + c2o1 * b_200 * x + c2o1 * a_020 * y
-            + b_110 * y + a_011 * z + b_101 * z + a_111 * x * z + b_111 * y * z) * eps_new / omegaF * (c1o1 + press);
-
-    m_200 = c1o3 * (        mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
-    m_020 = c1o3 * (-c2o1 * mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
-    m_002 = c1o3 * (        mxxMyy - c2o1 * mxxMzz + mxxPyyPzz) * useNEQ;
-
-    // linear combinations for third order moments
-    m_111 = c0o1;
-
-    real mxxyPyzz = c0o1;
-    real mxxyMyzz = c0o1;
-    real mxxzPyyz = c0o1;
-    real mxxzMyyz = c0o1;
-    real mxyyPxzz = c0o1;
-    real mxyyMxzz = c0o1;
-
-    m_210 = ( mxxyMyzz + mxxyPyzz) * c1o2;
-    m_012 = (-mxxyMyzz + mxxyPyzz) * c1o2;
-    m_201 = ( mxxzMyyz + mxxzPyyz) * c1o2;
-    m_021 = (-mxxzMyyz + mxxzPyyz) * c1o2;
-    m_120 = ( mxyyMxzz + mxyyPxzz) * c1o2;
-    m_102 = (-mxyyMxzz + mxyyPxzz) * c1o2;
-
-    // fourth order moments
-    m_022 = m_000 * c1o9;
-    m_202 = m_022;
-    m_220 = m_022;
-
-    // fifth order moments
-
-    // sixth order moment
-    m_222 = m_000 * c1o27;
-
-    real vx_sq = vvx * vvx;
-    real vy_sq = vvy * vvy;
-    real vz_sq = vvz * vvz;
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Chimera transform from central moments to well conditioned distributions as defined in Appendix J in
-    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-    //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (88)-(96) in <a
-    //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040
-    //! ]</b></a>
-    //!
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    // X - Dir
-    backwardInverseChimeraWithK(m_000, m_100, m_200, vvx, vx_sq, c1o1, c1o1);
-    backwardChimera(            m_010, m_110, m_210, vvx, vx_sq);
-    backwardInverseChimeraWithK(m_020, m_120, m_220, vvx, vx_sq, c3o1, c1o3);
-    backwardChimera(            m_001, m_101, m_201, vvx, vx_sq);
-    backwardChimera(            m_011, m_111, m_211, vvx, vx_sq);
-    backwardChimera(            m_021, m_121, m_221, vvx, vx_sq);
-    backwardInverseChimeraWithK(m_002, m_102, m_202, vvx, vx_sq, c3o1, c1o3);
-    backwardChimera(            m_012, m_112, m_212, vvx, vx_sq);
-    backwardInverseChimeraWithK(m_022, m_122, m_222, vvx, vx_sq, c9o1, c1o9);
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    // Y - Dir
-    backwardInverseChimeraWithK(m_000, m_010, m_020, vvy, vy_sq, c6o1, c1o6);
-    backwardChimera(            m_001, m_011, m_021, vvy, vy_sq);
-    backwardInverseChimeraWithK(m_002, m_012, m_022, vvy, vy_sq, c18o1, c1o18);
-    backwardInverseChimeraWithK(m_100, m_110, m_120, vvy, vy_sq, c3o2, c2o3);
-    backwardChimera(            m_101, m_111, m_121, vvy, vy_sq);
-    backwardInverseChimeraWithK(m_102, m_112, m_122, vvy, vy_sq, c9o2, c2o9);
-    backwardInverseChimeraWithK(m_200, m_210, m_220, vvy, vy_sq, c6o1, c1o6);
-    backwardChimera(            m_201, m_211, m_221, vvy, vy_sq);
-    backwardInverseChimeraWithK(m_202, m_212, m_222, vvy, vy_sq, c18o1, c1o18);
 
-    ////////////////////////////////////////////////////////////////////////////////////
-    // Z - Dir
-    backwardInverseChimeraWithK(m_000, m_001, m_002, vvz, vz_sq, c36o1, c1o36);
-    backwardInverseChimeraWithK(m_010, m_011, m_012, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_020, m_021, m_022, vvz, vz_sq, c36o1, c1o36);
-    backwardInverseChimeraWithK(m_100, m_101, m_102, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_110, m_111, m_112, vvz, vz_sq, c9o4,  c4o9);
-    backwardInverseChimeraWithK(m_120, m_121, m_122, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_200, m_201, m_202, vvz, vz_sq, c36o1, c1o36);
-    backwardInverseChimeraWithK(m_210, m_211, m_212, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_220, m_221, m_222, vvz, vz_sq, c36o1, c1o36);
-}
-
-//////////////////////////////////////////////////////////////////////////
-//! \brief Interpolate from coarse to fine nodes
-//! \details This scaling function is designed for the Cumulant K17 Kernel chimera collision kernel.
-//!
-//! The function is executed in the following steps:
-//!
 
-// based on scaleCF_RhoSq_comp_27
-template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
-    real* distributionsCoarse, 
+template <bool hasTurbulentViscosity> __device__ void interpolate(
+    vf::lbm::Coefficients& coefficients,
+    const unsigned int nodeIndex,
     real* distributionsFine, 
-    unsigned int* neighborXcoarse,
-    unsigned int* neighborYcoarse,
-    unsigned int* neighborZcoarse,
     unsigned int* neighborXfine,
     unsigned int* neighborYfine,
     unsigned int* neighborZfine,
-    unsigned long long numberOfLBnodesCoarse, 
-    unsigned long long numberOfLBnodesFine, 
-    bool isEvenTimestep,
-    unsigned int* indicesCoarseMMM, 
-    unsigned int* indicesFineMMM, 
-    unsigned int numberOfInterfaceNodes, 
-    real omegaCoarse, 
-    real omegaFine, 
-    real* turbulentViscosityCoarse,
-    real* turbulentViscosityFine,
-    ICellNeigh neighborCoarseToFine)
+    unsigned long long numberOfLBnodesFine,
+    unsigned int* indicesFineMMM,
+    real omegaFine,
+    real* turbulentViscosityFine)
 {
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Get the node index coordinates from threadId_100, blockId_100, blockDim and gridDim.
-    //!
-    const unsigned nodeIndex = getNodeIndex();
-
-    //////////////////////////////////////////////////////////////////////////
-    //! - Return for non-interface node
-    if (nodeIndex >= numberOfInterfaceNodes)
-        return;
-
-    //////////////////////////////////////////////////////////////////////////
-    //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on
-    //! timestep is based on the esoteric twist algorithm \ref <a
-    //! href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
-    //! DOI:10.3390/computation5020019 ]</b></a>
-    //!
-    Distributions27 distFine, distCoarse;
-    getPointersToDistributions(distFine, distributionsFine, numberOfLBnodesFine, true);
-    getPointersToDistributions(distCoarse, distributionsCoarse, numberOfLBnodesCoarse, isEvenTimestep);
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - declare local variables for source nodes
-    //!
-    real eps_new = c1o2; // ratio of grid resolutions
-    real omegaC  = omegaCoarse;
-    real omegaF  = omegaFine;
-
-    // zeroth and first order moments at the source nodes
-    real drho_PPP, vx1_PPP, vx2_PPP, vx3_PPP;
-    real drho_MPP, vx1_MPP, vx2_MPP, vx3_MPP;
-    real drho_PMP, vx1_PMP, vx2_PMP, vx3_PMP;
-    real drho_MMP, vx1_MMP, vx2_MMP, vx3_MMP;
-    real drho_PPM, vx1_PPM, vx2_PPM, vx3_PPM;
-    real drho_MPM, vx1_MPM, vx2_MPM, vx3_MPM;
-    real drho_PMM, vx1_PMM, vx2_PMM, vx3_PMM;
-    real drho_MMM, vx1_MMM, vx2_MMM, vx3_MMM;
-
-    // second order moments at the source nodes
-    real kxyFromfcNEQ_PPP, kyzFromfcNEQ_PPP, kxzFromfcNEQ_PPP, kxxMyyFromfcNEQ_PPP, kxxMzzFromfcNEQ_PPP;
-    real kxyFromfcNEQ_MPP, kyzFromfcNEQ_MPP, kxzFromfcNEQ_MPP, kxxMyyFromfcNEQ_MPP, kxxMzzFromfcNEQ_MPP;
-    real kxyFromfcNEQ_PMP, kyzFromfcNEQ_PMP, kxzFromfcNEQ_PMP, kxxMyyFromfcNEQ_PMP, kxxMzzFromfcNEQ_PMP;
-    real kxyFromfcNEQ_MMP, kyzFromfcNEQ_MMP, kxzFromfcNEQ_MMP, kxxMyyFromfcNEQ_MMP, kxxMzzFromfcNEQ_MMP;
-    real kxyFromfcNEQ_PPM, kyzFromfcNEQ_PPM, kxzFromfcNEQ_PPM, kxxMyyFromfcNEQ_PPM, kxxMzzFromfcNEQ_PPM;
-    real kxyFromfcNEQ_MPM, kyzFromfcNEQ_MPM, kxzFromfcNEQ_MPM, kxxMyyFromfcNEQ_MPM, kxxMzzFromfcNEQ_MPM;
-    real kxyFromfcNEQ_PMM, kyzFromfcNEQ_PMM, kxzFromfcNEQ_PMM, kxxMyyFromfcNEQ_PMM, kxxMzzFromfcNEQ_PMM;
-    real kxyFromfcNEQ_MMM, kyzFromfcNEQ_MMM, kxzFromfcNEQ_MMM, kxxMyyFromfcNEQ_MMM, kxxMzzFromfcNEQ_MMM;
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Calculate moments for each source node 
-    //!
-    ////////////////////////////////////////////////////////////////////////////////
-    // source node BSW = MMM
-    ////////////////////////////////////////////////////////////////////////////////
-    // index of the base node and its neighbors
-    unsigned int k_base_000 = indicesCoarseMMM[nodeIndex];
-    unsigned int k_base_M00 = neighborXcoarse [k_base_000];
-    unsigned int k_base_0M0 = neighborYcoarse [k_base_000];
-    unsigned int k_base_00M = neighborZcoarse [k_base_000];
-    unsigned int k_base_MM0 = neighborYcoarse [k_base_M00];
-    unsigned int k_base_M0M = neighborZcoarse [k_base_M00];
-    unsigned int k_base_0MM = neighborZcoarse [k_base_0M0];
-    unsigned int k_base_MMM = neighborZcoarse [k_base_MM0];
-    ////////////////////////////////////////////////////////////////////////////////
-    // Set neighbor indices
-    unsigned int k_000 = k_base_000;
-    unsigned int k_M00 = k_base_M00;
-    unsigned int k_0M0 = k_base_0M0;
-    unsigned int k_00M = k_base_00M;
-    unsigned int k_MM0 = k_base_MM0;
-    unsigned int k_M0M = k_base_M0M;
-    unsigned int k_0MM = k_base_0MM;
-    unsigned int k_MMM = k_base_MMM;
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MMM, vx1_MMM, vx2_MMM, vx3_MMM,
-        kxyFromfcNEQ_MMM, kyzFromfcNEQ_MMM, kxzFromfcNEQ_MMM, kxxMyyFromfcNEQ_MMM, kxxMzzFromfcNEQ_MMM);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TSW = MMP
-    //////////////////////////////////////////////////////////////////////////
-    // Set neighbor indices - has to be recalculated for the new source node
-    k_000 = k_00M;
-    k_M00 = k_M0M;
-    k_0M0 = k_0MM;
-    k_00M = neighborZcoarse[k_00M];
-    k_MM0 = k_MMM;
-    k_M0M = neighborZcoarse[k_M0M];
-    k_0MM = neighborZcoarse[k_0MM];
-    k_MMM = neighborZcoarse[k_MMM];
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MMP, vx1_MMP, vx2_MMP, vx3_MMP,
-        kxyFromfcNEQ_MMP, kyzFromfcNEQ_MMP, kxzFromfcNEQ_MMP, kxxMyyFromfcNEQ_MMP, kxxMzzFromfcNEQ_MMP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TSE = PMP
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_000 = k_M00;
-    k_M00 = neighborXcoarse[k_M00];
-    k_0M0 = k_MM0;
-    k_00M = k_M0M;
-    k_MM0 = neighborXcoarse[k_MM0];
-    k_M0M = neighborXcoarse[k_M0M];
-    k_0MM = k_MMM;
-    k_MMM = neighborXcoarse[k_MMM];
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PMP, vx1_PMP, vx2_PMP, vx3_PMP,
-        kxyFromfcNEQ_PMP, kyzFromfcNEQ_PMP, kxzFromfcNEQ_PMP, kxxMyyFromfcNEQ_PMP, kxxMzzFromfcNEQ_PMP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node BSE = PMM 
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_00M = k_000;
-    k_M0M = k_M00;
-    k_0MM = k_0M0;
-    k_MMM = k_MM0;
-    k_000 = k_base_M00;
-    k_M00 = neighborXcoarse[k_base_M00];
-    k_0M0 = k_base_MM0;
-    k_MM0 = neighborXcoarse[k_base_MM0];
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PMM, vx1_PMM, vx2_PMM, vx3_PMM,
-        kxyFromfcNEQ_PMM, kyzFromfcNEQ_PMM, kxzFromfcNEQ_PMM, kxxMyyFromfcNEQ_PMM, kxxMzzFromfcNEQ_PMM);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node BNW = MPM
-    //////////////////////////////////////////////////////////////////////////
-    // index of the base node and its neighbors --> indices of all source nodes
-    k_base_000 = k_base_0M0;
-    k_base_M00 = k_base_MM0;
-    k_base_0M0 = neighborYcoarse[k_base_0M0];
-    k_base_00M = k_base_0MM;
-    k_base_MM0 = neighborYcoarse[k_base_MM0];
-    k_base_M0M = k_base_MMM;
-    k_base_0MM = neighborYcoarse[k_base_0MM];
-    k_base_MMM = neighborYcoarse[k_base_MMM];
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_000 = k_base_000;
-    k_M00 = k_base_M00;
-    k_0M0 = k_base_0M0;
-    k_00M = k_base_00M;
-    k_MM0 = k_base_MM0;
-    k_M0M = k_base_M0M;
-    k_0MM = k_base_0MM;
-    k_MMM = k_base_MMM;
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MPM, vx1_MPM, vx2_MPM, vx3_MPM,
-        kxyFromfcNEQ_MPM, kyzFromfcNEQ_MPM, kxzFromfcNEQ_MPM, kxxMyyFromfcNEQ_MPM, kxxMzzFromfcNEQ_MPM);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TNW = MPP
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_000 = k_00M;
-    k_M00 = k_M0M;
-    k_0M0 = k_0MM;
-    k_00M = neighborZcoarse[k_00M];
-    k_MM0 = k_MMM;
-    k_M0M = neighborZcoarse[k_M0M];
-    k_0MM = neighborZcoarse[k_0MM];
-    k_MMM = neighborZcoarse[k_MMM];
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-    
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MPP, vx1_MPP, vx2_MPP, vx3_MPP,
-        kxyFromfcNEQ_MPP, kyzFromfcNEQ_MPP, kxzFromfcNEQ_MPP, kxxMyyFromfcNEQ_MPP, kxxMzzFromfcNEQ_MPP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TNE = PPP
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    // index
-    k_000 = k_M00;
-    k_M00 = neighborXcoarse[k_M00];
-    k_0M0 = k_MM0;
-    k_00M = k_M0M;
-    k_MM0 = neighborXcoarse[k_MM0];
-    k_M0M = neighborXcoarse[k_M0M];
-    k_0MM = k_MMM;
-    k_MMM = neighborXcoarse[k_MMM];
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PPP, vx1_PPP, vx2_PPP, vx3_PPP,
-        kxyFromfcNEQ_PPP, kyzFromfcNEQ_PPP, kxzFromfcNEQ_PPP, kxxMyyFromfcNEQ_PPP, kxxMzzFromfcNEQ_PPP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node BNE = PPM
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_00M = k_000;
-    k_M0M = k_M00;
-    k_0MM = k_0M0;
-    k_MMM = k_MM0;
-    k_000 = k_base_M00;
-    k_M00 = neighborXcoarse[k_base_M00];
-    k_0M0 = k_base_MM0;
-    k_MM0 = neighborXcoarse[k_base_MM0];
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-    
-    calculateMomentsOnSourceNodes( distCoarse, omegaC,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PPM, vx1_PPM, vx2_PPM, vx3_PPM,
-        kxyFromfcNEQ_PPM, kyzFromfcNEQ_PPM, kxzFromfcNEQ_PPM, kxxMyyFromfcNEQ_PPM, kxxMzzFromfcNEQ_PPM);
-
-    //////////////////////////////////////////////////////////////////////////
-    //! - Calculate coefficients for polynomial interpolation
-    //!
-    // example: a_110: derivation in x and y direction
-    real a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110, a_101, a_011, a_111;
-    real b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110, b_101, b_011, b_111;
-    real c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110, c_101, c_011, c_111;
-    real d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111;
-
-    // a_000 = (-kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_PPP + kxxMyyFromfcNEQ_MPM + kxxMyyFromfcNEQ_MPP -
-    //         kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_PMP + kxxMyyFromfcNEQ_MMM + kxxMyyFromfcNEQ_MMP -
-    //         kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_PPP + kxxMzzFromfcNEQ_MPM + kxxMzzFromfcNEQ_MPP -
-    //         kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_PMP + kxxMzzFromfcNEQ_MMM + kxxMzzFromfcNEQ_MMP -
-    //         c2o1 * kxyFromfcNEQ_PPM - c2o1 * kxyFromfcNEQ_PPP - c2o1 * kxyFromfcNEQ_MPM - c2o1 * kxyFromfcNEQ_MPP +
-    //         c2o1 * kxyFromfcNEQ_PMM + c2o1 * kxyFromfcNEQ_PMP + c2o1 * kxyFromfcNEQ_MMM + c2o1 * kxyFromfcNEQ_MMP +
-    //         c2o1 * kxzFromfcNEQ_PPM - c2o1 * kxzFromfcNEQ_PPP + c2o1 * kxzFromfcNEQ_MPM - c2o1 * kxzFromfcNEQ_MPP +
-    //         c2o1 * kxzFromfcNEQ_PMM - c2o1 * kxzFromfcNEQ_PMP + c2o1 * kxzFromfcNEQ_MMM - c2o1 * kxzFromfcNEQ_MMP +
-    //         c8o1 * vx1_PPM + c8o1 * vx1_PPP + c8o1 * vx1_MPM + c8o1 * vx1_MPP + c8o1 * vx1_PMM + c8o1 * vx1_PMP +
-    //         c8o1 * vx1_MMM + c8o1 * vx1_MMP + c2o1 * vx2_PPM + c2o1 * vx2_PPP - c2o1 * vx2_MPM - c2o1 * vx2_MPP -
-    //         c2o1 * vx2_PMM - c2o1 * vx2_PMP + c2o1 * vx2_MMM + c2o1 * vx2_MMP - c2o1 * vx3_PPM + c2o1 * vx3_PPP +
-    //         c2o1 * vx3_MPM - c2o1 * vx3_MPP - c2o1 * vx3_PMM + c2o1 * vx3_PMP + c2o1 * vx3_MMM - c2o1 * vx3_MMP) /
-    //         c64o1;
-    a_000 =
-        c1o64 * (c2o1 * (((kxyFromfcNEQ_MMM - kxyFromfcNEQ_PPP) + (kxyFromfcNEQ_MMP - kxyFromfcNEQ_PPM)) +
-                         ((kxyFromfcNEQ_PMM - kxyFromfcNEQ_MPP) + (kxyFromfcNEQ_PMP - kxyFromfcNEQ_MPM)) +
-                         ((kxzFromfcNEQ_MMM - kxzFromfcNEQ_PPP) + (kxzFromfcNEQ_PPM - kxzFromfcNEQ_MMP)) +
-                         ((kxzFromfcNEQ_PMM - kxzFromfcNEQ_MPP) + (kxzFromfcNEQ_MPM - kxzFromfcNEQ_PMP)) +
-                         ((vx2_PPP + vx2_MMM) + (vx2_PPM + vx2_MMP)) - ((vx2_MPP + vx2_PMM) + (vx2_MPM + vx2_PMP)) +
-                         ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MMP)) + ((vx3_PMP + vx3_MPM) - (vx3_MPP + vx3_PMM))) +
-                 c8o1 * (((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) + ((vx1_MPP + vx1_PMM) + (vx1_PMP + vx1_MPM))) +
-                 ((kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_PPP) + (kxxMyyFromfcNEQ_MMP - kxxMyyFromfcNEQ_PPM)) +
-                 ((kxxMyyFromfcNEQ_MPP - kxxMyyFromfcNEQ_PMM) + (kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_PMP)) +
-                 ((kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_PPP) + (kxxMzzFromfcNEQ_MMP - kxxMzzFromfcNEQ_PPM)) +
-                 ((kxxMzzFromfcNEQ_MPP - kxxMzzFromfcNEQ_PMM) + (kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_PMP)));
-
-    // b_000 = (c2o1 * kxxMyyFromfcNEQ_PPM + c2o1 * kxxMyyFromfcNEQ_PPP + c2o1 * kxxMyyFromfcNEQ_MPM +
-    //         c2o1 * kxxMyyFromfcNEQ_MPP - c2o1 * kxxMyyFromfcNEQ_PMM - c2o1 * kxxMyyFromfcNEQ_PMP -
-    //         c2o1 * kxxMyyFromfcNEQ_MMM - c2o1 * kxxMyyFromfcNEQ_MMP - kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_PPP -
-    //         kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_MPP + kxxMzzFromfcNEQ_PMM + kxxMzzFromfcNEQ_PMP +
-    //         kxxMzzFromfcNEQ_MMM + kxxMzzFromfcNEQ_MMP - c2o1 * kxyFromfcNEQ_PPM - c2o1 * kxyFromfcNEQ_PPP +
-    //         c2o1 * kxyFromfcNEQ_MPM + c2o1 * kxyFromfcNEQ_MPP - c2o1 * kxyFromfcNEQ_PMM - c2o1 * kxyFromfcNEQ_PMP +
-    //         c2o1 * kxyFromfcNEQ_MMM + c2o1 * kxyFromfcNEQ_MMP + c2o1 * kyzFromfcNEQ_PPM - c2o1 * kyzFromfcNEQ_PPP +
-    //         c2o1 * kyzFromfcNEQ_MPM - c2o1 * kyzFromfcNEQ_MPP + c2o1 * kyzFromfcNEQ_PMM - c2o1 * kyzFromfcNEQ_PMP +
-    //         c2o1 * kyzFromfcNEQ_MMM - c2o1 * kyzFromfcNEQ_MMP + c2o1 * vx1_PPM + c2o1 * vx1_PPP - c2o1 * vx1_MPM -
-    //         c2o1 * vx1_MPP - c2o1 * vx1_PMM - c2o1 * vx1_PMP + c2o1 * vx1_MMM + c2o1 * vx1_MMP + c8o1 * vx2_PPM +
-    //         c8o1 * vx2_PPP + c8o1 * vx2_MPM + c8o1 * vx2_MPP + c8o1 * vx2_PMM + c8o1 * vx2_PMP + c8o1 * vx2_MMM +
-    //         c8o1 * vx2_MMP - c2o1 * vx3_PPM + c2o1 * vx3_PPP - c2o1 * vx3_MPM + c2o1 * vx3_MPP + c2o1 * vx3_PMM -
-    //         c2o1 * vx3_PMP + c2o1 * vx3_MMM - c2o1 * vx3_MMP) /
-    //         c64o1;
-    b_000 =
-        c1o64 * (c2o1 * (((kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MMM) + (kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_MMP)) +
-                         ((kxxMyyFromfcNEQ_MPP - kxxMyyFromfcNEQ_PMM) + (kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_PMP)) +
-                         ((kxyFromfcNEQ_MMM - kxyFromfcNEQ_PPP) + (kxyFromfcNEQ_MMP - kxyFromfcNEQ_PPM)) +
-                         ((kxyFromfcNEQ_MPP - kxyFromfcNEQ_PMM) + (kxyFromfcNEQ_MPM - kxyFromfcNEQ_PMP)) +
-                         ((kyzFromfcNEQ_MMM - kyzFromfcNEQ_PPP) + (kyzFromfcNEQ_PPM - kyzFromfcNEQ_MMP)) +
-                         ((kyzFromfcNEQ_PMM - kyzFromfcNEQ_MPP) + (kyzFromfcNEQ_MPM - kyzFromfcNEQ_PMP)) +
-                         ((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) - ((vx1_MPM + vx1_MPP) + (vx1_PMM + vx1_PMP)) +
-                         ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MMP)) + ((vx3_MPP + vx3_PMM) - (vx3_MPM + vx3_PMP))) +
-                 c8o1 * (((vx2_PPP + vx2_MMM) + (vx2_PPM + vx2_MMP)) + ((vx2_MPP + vx2_PMM) + (vx2_MPM + vx2_PMP))) +
-                 ((kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_PPP) + (kxxMzzFromfcNEQ_MMP - kxxMzzFromfcNEQ_PPM)) +
-                 ((kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_MPP) + (kxxMzzFromfcNEQ_PMP - kxxMzzFromfcNEQ_MPM)));
-
-    // c_000 = (kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_PPP + kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_MPP +
-    //         kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_PMP + kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_MMP -
-    //         c2o1 * kxxMzzFromfcNEQ_PPM + c2o1 * kxxMzzFromfcNEQ_PPP - c2o1 * kxxMzzFromfcNEQ_MPM +
-    //         c2o1 * kxxMzzFromfcNEQ_MPP - c2o1 * kxxMzzFromfcNEQ_PMM + c2o1 * kxxMzzFromfcNEQ_PMP -
-    //         c2o1 * kxxMzzFromfcNEQ_MMM + c2o1 * kxxMzzFromfcNEQ_MMP - c2o1 * kxzFromfcNEQ_PPM -
-    //         c2o1 * kxzFromfcNEQ_PPP + c2o1 * kxzFromfcNEQ_MPM + c2o1 * kxzFromfcNEQ_MPP - c2o1 * kxzFromfcNEQ_PMM -
-    //         c2o1 * kxzFromfcNEQ_PMP + c2o1 * kxzFromfcNEQ_MMM + c2o1 * kxzFromfcNEQ_MMP - c2o1 * kyzFromfcNEQ_PPM -
-    //         c2o1 * kyzFromfcNEQ_PPP - c2o1 * kyzFromfcNEQ_MPM - c2o1 * kyzFromfcNEQ_MPP + c2o1 * kyzFromfcNEQ_PMM +
-    //         c2o1 * kyzFromfcNEQ_PMP + c2o1 * kyzFromfcNEQ_MMM + c2o1 * kyzFromfcNEQ_MMP - c2o1 * vx1_PPM +
-    //         c2o1 * vx1_PPP + c2o1 * vx1_MPM - c2o1 * vx1_MPP - c2o1 * vx1_PMM + c2o1 * vx1_PMP + c2o1 * vx1_MMM -
-    //         c2o1 * vx1_MMP - c2o1 * vx2_PPM + c2o1 * vx2_PPP - c2o1 * vx2_MPM + c2o1 * vx2_MPP + c2o1 * vx2_PMM -
-    //         c2o1 * vx2_PMP + c2o1 * vx2_MMM - c2o1 * vx2_MMP + c8o1 * vx3_PPM + c8o1 * vx3_PPP + c8o1 * vx3_MPM +
-    //         c8o1 * vx3_MPP + c8o1 * vx3_PMM + c8o1 * vx3_PMP + c8o1 * vx3_MMM + c8o1 * vx3_MMP) /
-    //         c64o1;
-    c_000 =
-        c1o64 * (c2o1 * (((kxxMzzFromfcNEQ_PPP - kxxMzzFromfcNEQ_MMM) + (kxxMzzFromfcNEQ_MMP - kxxMzzFromfcNEQ_PPM)) +
-                         ((kxxMzzFromfcNEQ_MPP - kxxMzzFromfcNEQ_PMM) + (kxxMzzFromfcNEQ_PMP - kxxMzzFromfcNEQ_MPM)) +
-                         ((kxzFromfcNEQ_MMM - kxzFromfcNEQ_PPP) + (kxzFromfcNEQ_MMP - kxzFromfcNEQ_PPM)) +
-                         ((kxzFromfcNEQ_MPP - kxzFromfcNEQ_PMM) + (kxzFromfcNEQ_MPM - kxzFromfcNEQ_PMP)) +
-                         ((kyzFromfcNEQ_MMM - kyzFromfcNEQ_PPP) + (kyzFromfcNEQ_MMP - kyzFromfcNEQ_PPM)) +
-                         ((kyzFromfcNEQ_PMM - kyzFromfcNEQ_MPP) + (kyzFromfcNEQ_PMP - kyzFromfcNEQ_MPM)) +
-                         ((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_MPM + vx1_PMP) - (vx1_MPP + vx1_PMM)) +
-                         ((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_MPP + vx2_PMM) - (vx2_MPM + vx2_PMP))) +
-                 c8o1 * (((vx3_PPP + vx3_MMM) + (vx3_PPM + vx3_MMP)) + ((vx3_PMM + vx3_MPP) + (vx3_PMP + vx3_MPM))) +
-                 ((kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_PPP) + (kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_MMP)) +
-                 ((kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_MPP) + (kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_PMP)));
-
-    // a_100  = (vx1_PPM + vx1_PPP - vx1_MPM - vx1_MPP + vx1_PMM + vx1_PMP - vx1_MMM - vx1_MMP) / c4o1;
-    a_100 = c1o4 * (((vx1_PPP - vx1_MMM) + (vx1_PPM - vx1_MMP)) + ((vx1_PMM - vx1_MPP) + (vx1_PMP - vx1_MPM)));
-
-    // b_100  = (vx2_PPM + vx2_PPP - vx2_MPM - vx2_MPP + vx2_PMM + vx2_PMP - vx2_MMM - vx2_MMP) / c4o1;
-    b_100 = c1o4 * (((vx2_PPP - vx2_MMM) + (vx2_PPM - vx2_MMP)) + ((vx2_PMM - vx2_MPP) + (vx2_PMP - vx2_MPM)));
-
-    // c_100  = (vx3_PPM + vx3_PPP - vx3_MPM - vx3_MPP + vx3_PMM + vx3_PMP - vx3_MMM - vx3_MMP) / c4o1;
-    c_100 = c1o4 * (((vx3_PPP - vx3_MMM) + (vx3_PPM - vx3_MMP)) + ((vx3_PMM - vx3_MPP) + (vx3_PMP - vx3_MPM)));
-
-    // a_200 = (kxxMyyFromfcNEQ_PPM + kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_MPP +
-    //         kxxMyyFromfcNEQ_PMM + kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_MMP +
-    //         kxxMzzFromfcNEQ_PPM + kxxMzzFromfcNEQ_PPP - kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_MPP +
-    //         kxxMzzFromfcNEQ_PMM + kxxMzzFromfcNEQ_PMP - kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_MMP + c2o1 * vx2_PPM +
-    //         c2o1 * vx2_PPP - c2o1 * vx2_MPM - c2o1 * vx2_MPP - c2o1 * vx2_PMM - c2o1 * vx2_PMP + c2o1 * vx2_MMM +
-    //         c2o1 * vx2_MMP - c2o1 * vx3_PPM + c2o1 * vx3_PPP + c2o1 * vx3_MPM - c2o1 * vx3_MPP - c2o1 * vx3_PMM +
-    //         c2o1 * vx3_PMP + c2o1 * vx3_MMM - c2o1 * vx3_MMP) /
-    //         c16o1;
-    a_200 =
-        c1o16 * (c2o1 * (((vx2_PPP + vx2_MMM) + (vx2_PPM - vx2_MPP)) + ((vx2_MMP - vx2_PMM) - (vx2_MPM + vx2_PMP)) +
-                         ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MPP)) + ((vx3_MPM + vx3_PMP) - (vx3_MMP + vx3_PMM))) +
-                 ((kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MMM) + (kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_MMP)) +
-                 ((kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_MPP) + (kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MPM)) +
-                 ((kxxMzzFromfcNEQ_PPP - kxxMzzFromfcNEQ_MMM) + (kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_MMP)) +
-                 ((kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_MPP) + (kxxMzzFromfcNEQ_PMP - kxxMzzFromfcNEQ_MPM)));
-
-    // b_200 = (kxyFromfcNEQ_PPM + kxyFromfcNEQ_PPP - kxyFromfcNEQ_MPM - kxyFromfcNEQ_MPP + kxyFromfcNEQ_PMM +
-    //         kxyFromfcNEQ_PMP - kxyFromfcNEQ_MMM - kxyFromfcNEQ_MMP - c2o1 * vx1_PPM - c2o1 * vx1_PPP +
-    //         c2o1 * vx1_MPM + c2o1 * vx1_MPP + c2o1 * vx1_PMM + c2o1 * vx1_PMP - c2o1 * vx1_MMM - c2o1 * vx1_MMP) /
-    //         c8o1;
-    b_200 =
-        c1o8 * (c2o1 * (-((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) + ((vx1_MPP + vx1_PMM) + (vx1_MPM + vx1_PMP))) +
-                ((kxyFromfcNEQ_PPP - kxyFromfcNEQ_MMM) + (kxyFromfcNEQ_PPM - kxyFromfcNEQ_MMP)) +
-                ((kxyFromfcNEQ_PMM - kxyFromfcNEQ_MPP) + (kxyFromfcNEQ_PMP - kxyFromfcNEQ_MPM)));
-
-    // c_200 = (kxzFromfcNEQ_PPM + kxzFromfcNEQ_PPP - kxzFromfcNEQ_MPM - kxzFromfcNEQ_MPP + kxzFromfcNEQ_PMM +
-    //          kxzFromfcNEQ_PMP - kxzFromfcNEQ_MMM - kxzFromfcNEQ_MMP + c2o1 * vx1_PPM - c2o1 * vx1_PPP - c2o1 *
-    //          vx1_MPM + c2o1 * vx1_MPP + c2o1 * vx1_PMM - c2o1 * vx1_PMP - c2o1 * vx1_MMM + c2o1 * vx1_MMP) /
-    //         c8o1;
-    c_200 = c1o8 * (c2o1 * (((vx1_PPM + vx1_MMP) - (vx1_PPP + vx1_MMM)) + ((vx1_MPP + vx1_PMM) - (vx1_MPM + vx1_PMP))) +
-                    ((kxzFromfcNEQ_PPP - kxzFromfcNEQ_MMM) + (kxzFromfcNEQ_PPM - kxzFromfcNEQ_MMP)) +
-                    ((kxzFromfcNEQ_PMM - kxzFromfcNEQ_MPP) + (kxzFromfcNEQ_PMP - kxzFromfcNEQ_MPM)));
-
-    // a_010 = (vx1_PPM + vx1_PPP + vx1_MPM + vx1_MPP - vx1_PMM - vx1_PMP - vx1_MMM - vx1_MMP) / c4o1;
-    a_010 = c1o4 * (((vx1_PPP - vx1_MMM) + (vx1_PPM - vx1_MMP)) + ((vx1_MPP - vx1_PMM) + (vx1_MPM - vx1_PMP)));
-
-    // b_010 = (vx2_PPM + vx2_PPP + vx2_MPM + vx2_MPP - vx2_PMM - vx2_PMP - vx2_MMM - vx2_MMP) / c4o1;
-    b_010 = c1o4 * (((vx2_PPP - vx2_MMM) + (vx2_PPM - vx2_MMP)) + ((vx2_MPP - vx2_PMM) + (vx2_MPM - vx2_PMP)));
-
-    // c_010 = (vx3_PPM + vx3_PPP + vx3_MPM + vx3_MPP - vx3_PMM - vx3_PMP - vx3_MMM - vx3_MMP) / c4o1;
-    c_010 = c1o4 * (((vx3_PPP - vx3_MMM) + (vx3_PPM - vx3_MMP)) + ((vx3_MPP - vx3_PMM) + (vx3_MPM - vx3_PMP)));
-
-    // a_020 = (kxyFromfcNEQ_PPM + kxyFromfcNEQ_PPP + kxyFromfcNEQ_MPM + kxyFromfcNEQ_MPP - kxyFromfcNEQ_PMM -
-    //         kxyFromfcNEQ_PMP - kxyFromfcNEQ_MMM - kxyFromfcNEQ_MMP - c2o1 * vx2_PPM - c2o1 * vx2_PPP +
-    //         c2o1 * vx2_MPM + c2o1 * vx2_MPP + c2o1 * vx2_PMM + c2o1 * vx2_PMP - c2o1 * vx2_MMM - c2o1 * vx2_MMP) /
-    //         c8o1;
-    a_020 =
-        c1o8 * (c2o1 * (-((vx2_PPP + vx2_MMM) + (vx2_MMP + vx2_PPM)) + ((vx2_MPP + vx2_PMM) + (vx2_MPM + vx2_PMP))) +
-                ((kxyFromfcNEQ_PPP - kxyFromfcNEQ_MMM) + (kxyFromfcNEQ_PPM - kxyFromfcNEQ_MMP)) +
-                ((kxyFromfcNEQ_MPP - kxyFromfcNEQ_PMM) + (kxyFromfcNEQ_MPM - kxyFromfcNEQ_PMP)));
-
-    // b_020 = (-c2o1 * kxxMyyFromfcNEQ_PPM - c2o1 * kxxMyyFromfcNEQ_PPP - c2o1 * kxxMyyFromfcNEQ_MPM -
-    //         c2o1 * kxxMyyFromfcNEQ_MPP + c2o1 * kxxMyyFromfcNEQ_PMM + c2o1 * kxxMyyFromfcNEQ_PMP +
-    //         c2o1 * kxxMyyFromfcNEQ_MMM + c2o1 * kxxMyyFromfcNEQ_MMP + kxxMzzFromfcNEQ_PPM + kxxMzzFromfcNEQ_PPP +
-    //         kxxMzzFromfcNEQ_MPM + kxxMzzFromfcNEQ_MPP - kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_PMP -
-    //         kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_MMP + c2o1 * vx1_PPM + c2o1 * vx1_PPP - c2o1 * vx1_MPM -
-    //         c2o1 * vx1_MPP - c2o1 * vx1_PMM - c2o1 * vx1_PMP + c2o1 * vx1_MMM + c2o1 * vx1_MMP - c2o1 * vx3_PPM +
-    //         c2o1 * vx3_PPP - c2o1 * vx3_MPM + c2o1 * vx3_MPP + c2o1 * vx3_PMM - c2o1 * vx3_PMP + c2o1 * vx3_MMM -
-    //         c2o1 * vx3_MMP) /
-    //         c16o1;
-    b_020 =
-        c1o16 * (c2o1 * (((kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_PPP) + (kxxMyyFromfcNEQ_MMP - kxxMyyFromfcNEQ_PPM)) +
-                         ((kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_MPP) + (kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MPM)) +
-                         ((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) - ((vx1_MPP + vx1_PMM) + (vx1_PMP + vx1_MPM)) +
-                         ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MMP)) + ((vx3_MPP + vx3_PMM) - (vx3_MPM + vx3_PMP))) +
-                 ((kxxMzzFromfcNEQ_PPP - kxxMzzFromfcNEQ_MMM) + (kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_MMP)) +
-                 ((kxxMzzFromfcNEQ_MPP - kxxMzzFromfcNEQ_PMM) + (kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_PMP)));
-
-    // c_020 = (kyzFromfcNEQ_PPM + kyzFromfcNEQ_PPP + kyzFromfcNEQ_MPM + kyzFromfcNEQ_MPP - kyzFromfcNEQ_PMM -
-    //          kyzFromfcNEQ_PMP - kyzFromfcNEQ_MMM - kyzFromfcNEQ_MMP + c2o1 * vx2_PPM - c2o1 * vx2_PPP + c2o1 *
-    //          vx2_MPM - c2o1 * vx2_MPP - c2o1 * vx2_PMM + c2o1 * vx2_PMP - c2o1 * vx2_MMM + c2o1 * vx2_MMP) /
-    //         c8o1;
-    c_020 = c1o8 * (c2o1 * (((vx2_MMP + vx2_PPM) - (vx2_PPP + vx2_MMM)) + ((vx2_PMP + vx2_MPM) - (vx2_MPP + vx2_PMM))) +
-                    ((kyzFromfcNEQ_PPP - kyzFromfcNEQ_MMM) + (kyzFromfcNEQ_PPM - kyzFromfcNEQ_MMP)) +
-                    ((kyzFromfcNEQ_MPP - kyzFromfcNEQ_PMM) + (kyzFromfcNEQ_MPM - kyzFromfcNEQ_PMP)));
-
-    // a_001  = (-vx1_PPM + vx1_PPP - vx1_MPM + vx1_MPP - vx1_PMM + vx1_PMP - vx1_MMM + vx1_MMP) / c4o1;
-    a_001 = c1o4 * (((vx1_PPP - vx1_MMM) + (vx1_MMP - vx1_PPM)) + ((vx1_MPP - vx1_PMM) + (vx1_PMP - vx1_MPM)));
-
-    // b_001  = (-vx2_PPM + vx2_PPP - vx2_MPM + vx2_MPP - vx2_PMM + vx2_PMP - vx2_MMM + vx2_MMP) / c4o1;
-    b_001 = c1o4 * (((vx2_PPP - vx2_MMM) + (vx2_MMP - vx2_PPM)) + ((vx2_MPP - vx2_PMM) + (vx2_PMP - vx2_MPM)));
-
-    // c_001  = (-vx3_PPM + vx3_PPP - vx3_MPM + vx3_MPP - vx3_PMM + vx3_PMP - vx3_MMM + vx3_MMP) / c4o1;
-    c_001 = c1o4 * (((vx3_PPP - vx3_MMM) + (vx3_MMP - vx3_PPM)) + ((vx3_MPP - vx3_PMM) + (vx3_PMP - vx3_MPM)));
-
-    // a_002 = (-kxzFromfcNEQ_PPM + kxzFromfcNEQ_PPP - kxzFromfcNEQ_MPM + kxzFromfcNEQ_MPP - kxzFromfcNEQ_PMM +
-    //         kxzFromfcNEQ_PMP - kxzFromfcNEQ_MMM + kxzFromfcNEQ_MMP + c2o1 * vx3_PPM - c2o1 * vx3_PPP -
-    //         c2o1 * vx3_MPM + c2o1 * vx3_MPP + c2o1 * vx3_PMM - c2o1 * vx3_PMP - c2o1 * vx3_MMM + c2o1 * vx3_MMP) /
-    //         c8o1;
-    a_002 = c1o8 * (c2o1 * (((vx3_PPM + vx3_MMP) - (vx3_PPP + vx3_MMM)) + ((vx3_MPP + vx3_PMM) - (vx3_PMP + vx3_MPM))) +
-                    ((kxzFromfcNEQ_PPP - kxzFromfcNEQ_MMM) + (kxzFromfcNEQ_MMP - kxzFromfcNEQ_PPM)) +
-                    ((kxzFromfcNEQ_PMP - kxzFromfcNEQ_MPM) + (kxzFromfcNEQ_MPP - kxzFromfcNEQ_PMM)));
-
-    // b_002 = (-kyzFromfcNEQ_PPM + kyzFromfcNEQ_PPP - kyzFromfcNEQ_MPM + kyzFromfcNEQ_MPP - kyzFromfcNEQ_PMM +
-    //          kyzFromfcNEQ_PMP - kyzFromfcNEQ_MMM + kyzFromfcNEQ_MMP + c2o1 * vx3_PPM - c2o1 * vx3_PPP + c2o1 *
-    //          vx3_MPM - c2o1 * vx3_MPP - c2o1 * vx3_PMM + c2o1 * vx3_PMP - c2o1 * vx3_MMM + c2o1 * vx3_MMP) /
-    //         c8o1;
-    b_002 = c1o8 * (c2o1 * (((vx3_PPM + vx3_MMP) - (vx3_PPP + vx3_MMM)) + ((vx3_MPM + vx3_PMP) - (vx3_PMM + vx3_MPP))) +
-                    ((kyzFromfcNEQ_PPP - kyzFromfcNEQ_MMM) + (kyzFromfcNEQ_MMP - kyzFromfcNEQ_PPM)) +
-                    ((kyzFromfcNEQ_PMP - kyzFromfcNEQ_MPM) + (kyzFromfcNEQ_MPP - kyzFromfcNEQ_PMM)));
-
-    // c_002 = (-kxxMyyFromfcNEQ_PPM + kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MPM + kxxMyyFromfcNEQ_MPP -
-    //         kxxMyyFromfcNEQ_PMM + kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MMM + kxxMyyFromfcNEQ_MMP +
-    //         c2o1 * kxxMzzFromfcNEQ_PPM - c2o1 * kxxMzzFromfcNEQ_PPP + c2o1 * kxxMzzFromfcNEQ_MPM -
-    //         c2o1 * kxxMzzFromfcNEQ_MPP + c2o1 * kxxMzzFromfcNEQ_PMM - c2o1 * kxxMzzFromfcNEQ_PMP +
-    //         c2o1 * kxxMzzFromfcNEQ_MMM - c2o1 * kxxMzzFromfcNEQ_MMP - c2o1 * vx1_PPM + c2o1 * vx1_PPP +
-    //         c2o1 * vx1_MPM - c2o1 * vx1_MPP - c2o1 * vx1_PMM + c2o1 * vx1_PMP + c2o1 * vx1_MMM - c2o1 * vx1_MMP -
-    //         c2o1 * vx2_PPM + c2o1 * vx2_PPP - c2o1 * vx2_MPM + c2o1 * vx2_MPP + c2o1 * vx2_PMM - c2o1 * vx2_PMP +
-    //         c2o1 * vx2_MMM - c2o1 * vx2_MMP) /
-    //         c16o1;
-    c_002 =
-        c1o16 * (c2o1 * (((kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_PPP) + (kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_MMP)) +
-                         ((kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_PMP) + (kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_MPP)) +
-                         ((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_MPM + vx1_PMP) - (vx1_PMM + vx1_MPP)) +
-                         ((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_PMM + vx2_MPP) - (vx2_MPM + vx2_PMP))) +
-                 ((kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MMM) + (kxxMyyFromfcNEQ_MMP - kxxMyyFromfcNEQ_PPM)) +
-                 ((kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MPM) + (kxxMyyFromfcNEQ_MPP - kxxMyyFromfcNEQ_PMM)));
-
-    // a_110 = (vx1_PPM + vx1_PPP - vx1_MPM - vx1_MPP - vx1_PMM - vx1_PMP + vx1_MMM + vx1_MMP) / c2o1;
-    // b_110 = (vx2_PPM + vx2_PPP - vx2_MPM - vx2_MPP - vx2_PMM - vx2_PMP + vx2_MMM + vx2_MMP) / c2o1;
-    // c_110 = (vx3_PPM + vx3_PPP - vx3_MPM - vx3_MPP - vx3_PMM - vx3_PMP + vx3_MMM + vx3_MMP) / c2o1;
-    a_110 = c1o2 * (((vx1_PPP + vx1_MMM) + (vx1_MMP + vx1_PPM)) - ((vx1_MPM + vx1_PMP) + (vx1_PMM + vx1_MPP)));
-    b_110 = c1o2 * (((vx2_PPP + vx2_MMM) + (vx2_MMP + vx2_PPM)) - ((vx2_MPM + vx2_PMP) + (vx2_PMM + vx2_MPP)));
-    c_110 = c1o2 * (((vx3_PPP + vx3_MMM) + (vx3_MMP + vx3_PPM)) - ((vx3_MPM + vx3_PMP) + (vx3_PMM + vx3_MPP)));
-
-    // a_101 = (-vx1_PPM + vx1_PPP + vx1_MPM - vx1_MPP - vx1_PMM + vx1_PMP + vx1_MMM - vx1_MMP) / c2o1;
-    // b_101 = (-vx2_PPM + vx2_PPP + vx2_MPM - vx2_MPP - vx2_PMM + vx2_PMP + vx2_MMM - vx2_MMP) / c2o1;
-    // c_101 = (-vx3_PPM + vx3_PPP + vx3_MPM - vx3_MPP - vx3_PMM + vx3_PMP + vx3_MMM - vx3_MMP) / c2o1;
-    a_101 = c1o2 * (((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_MPM + vx1_PMP) - (vx1_PMM + vx1_MPP)));
-    b_101 = c1o2 * (((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_MPM + vx2_PMP) - (vx2_PMM + vx2_MPP)));
-    c_101 = c1o2 * (((vx3_PPP + vx3_MMM) - (vx3_MMP + vx3_PPM)) + ((vx3_MPM + vx3_PMP) - (vx3_PMM + vx3_MPP)));
-
-    // a_011 = (-vx1_PPM + vx1_PPP - vx1_MPM + vx1_MPP + vx1_PMM - vx1_PMP + vx1_MMM - vx1_MMP) / c2o1;
-    // b_011 = (-vx2_PPM + vx2_PPP - vx2_MPM + vx2_MPP + vx2_PMM - vx2_PMP + vx2_MMM - vx2_MMP) / c2o1;
-    // c_011 = (-vx3_PPM + vx3_PPP - vx3_MPM + vx3_MPP + vx3_PMM - vx3_PMP + vx3_MMM - vx3_MMP) / c2o1;
-    a_011 = c1o2 * (((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_PMM + vx1_MPP) - (vx1_MPM + vx1_PMP)));
-    b_011 = c1o2 * (((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_PMM + vx2_MPP) - (vx2_MPM + vx2_PMP)));
-    c_011 = c1o2 * (((vx3_PPP + vx3_MMM) - (vx3_MMP + vx3_PPM)) + ((vx3_PMM + vx3_MPP) - (vx3_MPM + vx3_PMP)));
-
-    // a_111 = -vx1_PPM + vx1_PPP + vx1_MPM - vx1_MPP + vx1_PMM - vx1_PMP - vx1_MMM + vx1_MMP;
-    // b_111 = -vx2_PPM + vx2_PPP + vx2_MPM - vx2_MPP + vx2_PMM - vx2_PMP - vx2_MMM + vx2_MMP;
-    // c_111 = -vx3_PPM + vx3_PPP + vx3_MPM - vx3_MPP + vx3_PMM - vx3_PMP - vx3_MMM + vx3_MMP;
-    a_111 = ((vx1_PPP - vx1_MMM) + (vx1_MMP - vx1_PPM)) + ((vx1_MPM - vx1_PMP) + (vx1_PMM - vx1_MPP));
-    b_111 = ((vx2_PPP - vx2_MMM) + (vx2_MMP - vx2_PPM)) + ((vx2_MPM - vx2_PMP) + (vx2_PMM - vx2_MPP));
-    c_111 = ((vx3_PPP - vx3_MMM) + (vx3_MMP - vx3_PPM)) + ((vx3_MPM - vx3_PMP) + (vx3_PMM - vx3_MPP));
-
-    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-    real kxyAverage    = c0o1;
-    real kyzAverage    = c0o1;
-    real kxzAverage    = c0o1;
-    real kxxMyyAverage = c0o1;
-    real kxxMzzAverage = c0o1;
-
-    // real kxyAverage    = (kxyFromfcNEQ_MMM+
-    //                       kxyFromfcNEQ_MMP+
-    //                       kxyFromfcNEQ_PMP+
-    //                       kxyFromfcNEQ_PMM+
-    //                       kxyFromfcNEQ_MPM+
-    //                       kxyFromfcNEQ_MPP+
-    //                       kxyFromfcNEQ_PPP+
-    //                       kxyFromfcNEQ_PPM) * c1o8 - (a_010 + b_100);
-    // real kyzAverage    = (kyzFromfcNEQ_MMM+
-    //                       kyzFromfcNEQ_MMP+
-    //                       kyzFromfcNEQ_PMP+
-    //                       kyzFromfcNEQ_PMM+
-    //                       kyzFromfcNEQ_MPM+
-    //                       kyzFromfcNEQ_MPP+
-    //                       kyzFromfcNEQ_PPP+
-    //                       kyzFromfcNEQ_PPM) * c1o8 - (b_001 + c_010);
-    // real kxzAverage    = (kxzFromfcNEQ_MMM+
-    //                       kxzFromfcNEQ_MMP+
-    //                       kxzFromfcNEQ_PMP+
-    //                       kxzFromfcNEQ_PMM+
-    //                       kxzFromfcNEQ_MPM+
-    //                       kxzFromfcNEQ_MPP+
-    //                       kxzFromfcNEQ_PPP+
-    //                       kxzFromfcNEQ_PPM) * c1o8 - (a_001 + c_100);
-    // real kxxMyyAverage = (kxxMyyFromfcNEQ_MMM+
-    //                       kxxMyyFromfcNEQ_MMP+
-    //                       kxxMyyFromfcNEQ_PMP+
-    //                       kxxMyyFromfcNEQ_PMM+
-    //                       kxxMyyFromfcNEQ_MPM+
-    //                       kxxMyyFromfcNEQ_MPP+
-    //                       kxxMyyFromfcNEQ_PPP+
-    //                       kxxMyyFromfcNEQ_PPM) * c1o8 - (a_100 - b_010);
-    // real kxxMzzAverage = (kxxMzzFromfcNEQ_MMM+
-    //                       kxxMzzFromfcNEQ_MMP+
-    //                       kxxMzzFromfcNEQ_PMP+
-    //                       kxxMzzFromfcNEQ_PMM+
-    //                       kxxMzzFromfcNEQ_MPM+
-    //                       kxxMzzFromfcNEQ_MPP+
-    //                       kxxMzzFromfcNEQ_PPP+
-    //                       kxxMzzFromfcNEQ_PPM) * c1o8 - (a_100 - c_001);
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Set the relative position of the offset cell {-1, 0, 1}
-    //!
-    real xoff    = neighborCoarseToFine.x[nodeIndex];
-    real yoff    = neighborCoarseToFine.y[nodeIndex];
-    real zoff    = neighborCoarseToFine.z[nodeIndex];
-
-    real xoff_sq = xoff * xoff;
-    real yoff_sq = yoff * yoff;
-    real zoff_sq = zoff * zoff;
-
-    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    //drho
-    real LaplaceRho = 
-        ((xoff != c0o1) || (yoff != c0o1) || (zoff != c0o1))
-        ? c0o1
-        : -c3o1 * (a_100 * a_100 + b_010 * b_010 + c_001 * c_001) - c6o1 * (b_100 * a_010 + c_100 * a_001 + c_010 * b_001);
-    // d_000 = ( drho_PPM + drho_PPP + drho_MPM + drho_MPP + drho_PMM + drho_PMP + drho_MMM + drho_MMP) * c1o8;
-    d_000 = c1o8 * (((drho_PPP + drho_MMM) + (drho_PPM + drho_MMP)) + ((drho_PMM + drho_MPP) + (drho_PMP + drho_MPM)));
-
-    // d_100 = ( drho_PPM + drho_PPP - drho_MPM - drho_MPP + drho_PMM + drho_PMP - drho_MMM - drho_MMP) * c1o4;
-    d_100 = c1o4 * (((drho_PPP - drho_MMM) + (drho_PPM - drho_MMP)) + ((drho_PMM - drho_MPP) + (drho_PMP - drho_MPM)));
-
-    // d_010 = ( drho_PPM + drho_PPP + drho_MPM + drho_MPP - drho_PMM - drho_PMP - drho_MMM - drho_MMP) * c1o4;
-    d_010 = c1o4 * (((drho_PPP - drho_MMM) + (drho_PPM - drho_MMP)) + ((drho_MPP - drho_PMM) + (drho_MPM - drho_PMP)));
+    Distributions27 distFine;
+    vf::gpu::getPointersToDistributions(distFine, distributionsFine, numberOfLBnodesFine, true);
 
-    // d_001 = (-drho_PPM + drho_PPP - drho_MPM + drho_MPP - drho_PMM + drho_PMP - drho_MMM + drho_MMP) * c1o4;
-    d_001 = c1o4 * (((drho_PPP - drho_MMM) + (drho_MMP - drho_PPM)) + ((drho_MPP - drho_PMM) + (drho_PMP - drho_MPM)));
-
-    // d_110 = ( drho_PPM + drho_PPP - drho_MPM - drho_MPP - drho_PMM - drho_PMP + drho_MMM + drho_MMP) * c1o2;
-    d_110 = c1o2 * (((drho_PPP + drho_MMM) + (drho_PPM + drho_MMP)) - ((drho_PMM + drho_MPP) + (drho_PMP + drho_MPM)));
-
-    // d_101 = (-drho_PPM + drho_PPP + drho_MPM - drho_MPP - drho_PMM + drho_PMP + drho_MMM - drho_MMP) * c1o2;
-    d_101 = c1o2 * (((drho_PPP + drho_MMM) - (drho_PPM + drho_MMP)) + ((drho_PMP + drho_MPM) - (drho_PMM + drho_MPP)));
-
-    // d_011 = (-drho_PPM + drho_PPP - drho_MPM + drho_MPP + drho_PMM - drho_PMP + drho_MMM - drho_MMP) * c1o2;
-    d_011 = c1o2 * (((drho_PPP + drho_MMM) - (drho_PPM + drho_MMP)) + ((drho_PMM + drho_MPP) - (drho_PMP + drho_MPM)));
-
-    // d_111 =  -drho_PPM + drho_PPP + drho_MPM - drho_MPP + drho_PMM - drho_PMP - drho_MMM + drho_MMP;
-    d_111 = (((drho_PPP - drho_MMM) + (drho_MMP - drho_PPM)) + ((drho_PMM - drho_MPP) + (drho_MPM - drho_PMP)));
-
-    //////////////////////////////////////////////////////////////////////////
-    //! - Extrapolation for refinement in to the wall (polynomial coefficients)
-    //!
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    //
-    // X------X
-    // |      | x---x
-    // |   ---+-+-> |    ----> offset-vector
-    // |      | x---x 
-    // X------X
-    //
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    a_000 = a_000 + xoff * a_100 + yoff * a_010 + zoff * a_001 + xoff_sq * a_200 + yoff_sq * a_020 + zoff_sq * a_002 +
-            xoff * yoff * a_110 + xoff * zoff * a_101 + yoff * zoff * a_011;
-    a_100 = a_100 + c2o1 * xoff * a_200 + yoff * a_110 + zoff * a_101;
-    a_010 = a_010 + c2o1 * yoff * a_020 + xoff * a_110 + zoff * a_011;
-    a_001 = a_001 + c2o1 * zoff * a_002 + xoff * a_101 + yoff * a_011;
-    b_000 = b_000 + xoff * b_100 + yoff * b_010 + zoff * b_001 + xoff_sq * b_200 + yoff_sq * b_020 + zoff_sq * b_002 +
-            xoff * yoff * b_110 + xoff * zoff * b_101 + yoff * zoff * b_011;
-    b_100 = b_100 + c2o1 * xoff * b_200 + yoff * b_110 + zoff * b_101;
-    b_010 = b_010 + c2o1 * yoff * b_020 + xoff * b_110 + zoff * b_011;
-    b_001 = b_001 + c2o1 * zoff * b_002 + xoff * b_101 + yoff * b_011;
-    c_000 = c_000 + xoff * c_100 + yoff * c_010 + zoff * c_001 + xoff_sq * c_200 + yoff_sq * c_020 + zoff_sq * c_002 +
-            xoff * yoff * c_110 + xoff * zoff * c_101 + yoff * zoff * c_011;
-    c_100 = c_100 + c2o1 * xoff * c_200 + yoff * c_110 + zoff * c_101;
-    c_010 = c_010 + c2o1 * yoff * c_020 + xoff * c_110 + zoff * c_011;
-    c_001 = c_001 + c2o1 * zoff * c_002 + xoff * c_101 + yoff * c_011;
-    d_000 = d_000 + xoff * d_100 + yoff * d_010 + zoff * d_001 + 
-            xoff * yoff * d_110 + xoff * zoff * d_101 + yoff * zoff * d_011;
-    d_100 = d_100 + yoff * d_110 + zoff * d_101;
-    d_010 = d_010 + xoff * d_110 + zoff * d_011;
-    d_001 = d_001 + xoff * d_101 + yoff * d_011;
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Set all moments to zero
-    //!      
-    real m_111 = c0o1;
-    real m_211 = c0o1;
-    real m_011 = c0o1;
-    real m_121 = c0o1;
-    real m_101 = c0o1;
-    real m_112 = c0o1;
-    real m_110 = c0o1;
-    real m_221 = c0o1;
-    real m_001 = c0o1;
-    real m_201 = c0o1;
-    real m_021 = c0o1;
-    real m_212 = c0o1;
-    real m_010 = c0o1;
-    real m_210 = c0o1;
-    real m_012 = c0o1;
-    real m_122 = c0o1;
-    real m_100 = c0o1;
-    real m_120 = c0o1;
-    real m_102 = c0o1;
-    real m_222 = c0o1;
-    real m_022 = c0o1;
-    real m_202 = c0o1;
-    real m_002 = c0o1;
-    real m_220 = c0o1;
-    real m_020 = c0o1;
-    real m_200 = c0o1;
-    real m_000 = c0o1;
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Define aliases to use the same variable for the distributions (f's):
-    //!
-    real& f_000 = m_111;
-    real& f_P00 = m_211;
-    real& f_M00 = m_011;
-    real& f_0P0 = m_121;
-    real& f_0M0 = m_101;
-    real& f_00P = m_112;
-    real& f_00M = m_110;
-    real& f_PP0 = m_221;
-    real& f_MM0 = m_001;
-    real& f_PM0 = m_201;
-    real& f_MP0 = m_021;
-    real& f_P0P = m_212;
-    real& f_M0M = m_010;
-    real& f_P0M = m_210;
-    real& f_M0P = m_012;
-    real& f_0PP = m_122;
-    real& f_0MM = m_100;
-    real& f_0PM = m_120;
-    real& f_0MP = m_102;
-    real& f_PPP = m_222;
-    real& f_MPP = m_022;
-    real& f_PMP = m_202;
-    real& f_MMP = m_002;
-    real& f_PPM = m_220;
-    real& f_MPM = m_020;
-    real& f_PMM = m_200;
-    real& f_MMM = m_000;
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
     // Position BSW = MMM: -0.25, -0.25, -0.25
     //
@@ -901,81 +66,37 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
     real z = -c1o4;
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // index of the base node and its neighbors
-    k_base_000 = indicesFineMMM[nodeIndex];
-    k_base_M00 = neighborXfine [k_base_000];
-    k_base_0M0 = neighborYfine [k_base_000];
-    k_base_00M = neighborZfine [k_base_000];
-    k_base_MM0 = neighborYfine [k_base_M00];
-    k_base_M0M = neighborZfine [k_base_M00];
-    k_base_0MM = neighborZfine [k_base_0M0];
-    k_base_MMM = neighborZfine [k_base_MM0];
+    unsigned int k_base_000 = indicesFineMMM[nodeIndex];
+    unsigned int k_base_M00 = neighborXfine [k_base_000];
+    unsigned int k_base_0M0 = neighborYfine [k_base_000];
+    unsigned int k_base_00M = neighborZfine [k_base_000];
+    unsigned int k_base_MM0 = neighborYfine [k_base_M00];
+    unsigned int k_base_M0M = neighborZfine [k_base_M00];
+    unsigned int k_base_0MM = neighborZfine [k_base_0M0];
+    unsigned int k_base_MMM = neighborZfine [k_base_MM0];
     //////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_000 = k_base_000;
-    k_M00 = k_base_M00;
-    k_0M0 = k_base_0M0;
-    k_00M = k_base_00M;
-    k_MM0 = k_base_MM0;
-    k_M0M = k_base_M0M;
-    k_0MM = k_base_0MM;
-    k_MMM = k_base_MMM;
+    vf::gpu::ListIndices indices;
+    indices.k_000 = k_base_000;
+    indices.k_M00 = k_base_M00;
+    indices.k_0M0 = k_base_0M0;
+    indices.k_00M = k_base_00M;
+    indices.k_MM0 = k_base_MM0;
+    indices.k_M0M = k_base_M0M;
+    indices.k_0MM = k_base_0MM;
+    indices.k_MMM = k_base_MMM;
     ////////////////////////////////////////////////////////////////////////////////
     //! - Set moments (zeroth to sixth order) on destination node
     //!
+    real omegaF  = omegaFine;
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
+    const real epsilon_new = c1o2; // ratio of grid resolutions
+    real f[27];
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
+
+    write(distFine, indices, f);
 
-    //////////////////////////////////////////////////////////////////////////
-    //! - Write distributions: style of reading and writing the distributions from/to
-    //! stored arrays dependent on timestep is based on the esoteric twist algorithm
-    //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
-    //! DOI:10.3390/computation5020019 ]</b></a>
-    //!
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
-    //////////////////////////////////////////////////////////////////////////
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
@@ -987,66 +108,23 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
     z =  c1o4;
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_000 = k_00M;
-    k_M00 = k_M0M;
-    k_0M0 = k_0MM;
-    k_00M = neighborZfine[k_00M];
-    k_MM0 = k_MMM;
-    k_M0M = neighborZfine[k_M0M];
-    k_0MM = neighborZfine[k_0MM];
-    k_MMM = neighborZfine[k_MMM];
+    indices.k_000 = indices.k_00M;
+    indices.k_M00 = indices.k_M0M;
+    indices.k_0M0 = indices.k_0MM;
+    indices.k_00M = neighborZfine[indices.k_00M];
+    indices.k_MM0 = indices.k_MMM;
+    indices.k_M0M = neighborZfine[indices.k_M0M];
+    indices.k_0MM = neighborZfine[indices.k_0MM];
+    indices.k_MMM = neighborZfine[indices.k_MMM];
 
     ////////////////////////////////////////////////////////////////////////////////
     // Set moments (zeroth to sixth orders) on destination node
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
 
-    //////////////////////////////////////////////////////////////////////////
-    // Write distributions
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
+
+    write(distFine, indices, f);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
@@ -1058,66 +136,23 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
     z =  c1o4;
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_000 = k_M00;
-    k_M00 = neighborXfine[k_M00];
-    k_0M0 = k_MM0;
-    k_00M = k_M0M;
-    k_MM0 = neighborXfine[k_MM0];
-    k_M0M = neighborXfine[k_M0M];
-    k_0MM = k_MMM;
-    k_MMM = neighborXfine[k_MMM];
+    indices.k_000 = indices.k_M00;
+    indices.k_M00 = neighborXfine[indices.k_M00];
+    indices.k_0M0 = indices.k_MM0;
+    indices.k_00M = indices.k_M0M;
+    indices.k_MM0 = neighborXfine[indices.k_MM0];
+    indices.k_M0M = neighborXfine[indices.k_M0M];
+    indices.k_0MM = indices.k_MMM;
+    indices.k_MMM = neighborXfine[indices.k_MMM];
 
     ////////////////////////////////////////////////////////////////////////////////
     // Set moments (zeroth to sixth orders) on destination node
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
 
-    //////////////////////////////////////////////////////////////////////////
-    // Write distributions
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
+
+    write(distFine, indices, f);
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
@@ -1129,67 +164,23 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
     z = -c1o4;
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_00M = k_000;
-    k_M0M = k_M00;
-    k_0MM = k_0M0;
-    k_MMM = k_MM0;
-    k_000 = k_base_M00;
-    k_M00 = neighborXfine[k_base_M00];
-    k_0M0 = k_base_MM0;
-    k_MM0 = neighborXfine[k_base_MM0];
+    indices.k_00M = indices.k_000;
+    indices.k_M0M = indices.k_M00;
+    indices.k_0MM = indices.k_0M0;
+    indices.k_MMM = indices.k_MM0;
+    indices.k_000 = k_base_M00;
+    indices.k_M00 = neighborXfine[k_base_M00];
+    indices.k_0M0 = k_base_MM0;
+    indices.k_MM0 = neighborXfine[k_base_MM0];
 
     ////////////////////////////////////////////////////////////////////////////////
     // Set moments (zeroth to sixth orders) on destination node
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
 
-    //////////////////////////////////////////////////////////////////////////
-    // Write distributions
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
 
+    write(distFine, indices, f);
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
     // Position BNW = MPM: -0.25, 0.25, -0.25
@@ -1212,67 +203,23 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
 
     //////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_000 = k_base_000;
-    k_M00 = k_base_M00;
-    k_0M0 = k_base_0M0;
-    k_00M = k_base_00M;
-    k_MM0 = k_base_MM0;
-    k_M0M = k_base_M0M;
-    k_0MM = k_base_0MM;
-    k_MMM = k_base_MMM;
+    indices.k_000 = k_base_000;
+    indices.k_M00 = k_base_M00;
+    indices.k_0M0 = k_base_0M0;
+    indices.k_00M = k_base_00M;
+    indices.k_MM0 = k_base_MM0;
+    indices.k_M0M = k_base_M0M;
+    indices.k_0MM = k_base_0MM;
+    indices.k_MMM = k_base_MMM;
 
     ////////////////////////////////////////////////////////////////////////////////
     // Set moments (zeroth to sixth orders) on destination node
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
 
-    //////////////////////////////////////////////////////////////////////////
-    // Write distributions
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
 
+    write(distFine, indices, f);
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
     // Position TNW = MPP: -0.25, 0.25, 0.25
@@ -1283,67 +230,20 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
     z =  c1o4;
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_000 = k_00M;
-    k_M00 = k_M0M;
-    k_0M0 = k_0MM;
-    k_00M = neighborZfine[k_00M];
-    k_MM0 = k_MMM;
-    k_M0M = neighborZfine[k_M0M];
-    k_0MM = neighborZfine[k_0MM];
-    k_MMM = neighborZfine[k_MMM];
+    indices.k_000 = indices.k_00M;
+    indices.k_M00 = indices.k_M0M;
+    indices.k_0M0 = indices.k_0MM;
+    indices.k_00M = neighborZfine[indices.k_00M];
+    indices.k_MM0 = indices.k_MMM;
+    indices.k_M0M = neighborZfine[indices.k_M0M];
+    indices.k_0MM = neighborZfine[indices.k_0MM];
+    indices.k_MMM = neighborZfine[indices.k_MMM];
 
-    ////////////////////////////////////////////////////////////////////////////////
-    // Set moments (zeroth to sixth orders) on destination node
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
-
-    //////////////////////////////////////////////////////////////////////////
-    // Write distributions
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
 
+    write(distFine, indices, f);
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
     // Position TNE = PPP: 0.25, 0.25, 0.25
@@ -1354,67 +254,20 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
     z = c1o4;
     ////////////////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_000 = k_M00;
-    k_M00 = neighborXfine[k_M00];
-    k_0M0 = k_MM0;
-    k_00M = k_M0M;
-    k_MM0 = neighborXfine[k_MM0];
-    k_M0M = neighborXfine[k_M0M];
-    k_0MM = k_MMM;
-    k_MMM = neighborXfine[k_MMM];
+    indices.k_000 = indices.k_M00;
+    indices.k_M00 = neighborXfine[indices.k_M00];
+    indices.k_0M0 = indices.k_MM0;
+    indices.k_00M = indices.k_M0M;
+    indices.k_MM0 = neighborXfine[indices.k_MM0];
+    indices.k_M0M = neighborXfine[indices.k_M0M];
+    indices.k_0MM = indices.k_MMM;
+    indices.k_MMM = neighborXfine[indices.k_MMM];
 
-    ////////////////////////////////////////////////////////////////////////////////
-    // Set moments (zeroth to sixth orders) on destination node
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
-
-    //////////////////////////////////////////////////////////////////////////
-    // Write distributions
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
 
+    write(distFine, indices, f);
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     //
     //Position BNE = PPM: 0.25, 0.25, -0.25
@@ -1425,66 +278,252 @@ template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
     z = -c1o4;
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Set neighbor indices
-    k_00M = k_000;
-    k_M0M = k_M00;
-    k_0MM = k_0M0;
-    k_MMM = k_MM0;
-    k_000 = k_base_M00;
-    k_M00 = neighborXfine[k_base_M00];
-    k_0M0 = k_base_MM0;
-    k_MM0 = neighborXfine[k_base_MM0];
+    indices.k_00M = indices.k_000;
+    indices.k_M0M = indices.k_M00;
+    indices.k_0MM = indices.k_0M0;
+    indices.k_MMM = indices.k_MM0;
+    indices.k_000 = k_base_M00;
+    indices.k_M00 = neighborXfine[k_base_M00];
+    indices.k_0M0 = k_base_MM0;
+    indices.k_MM0 = neighborXfine[k_base_MM0];
+
+    omegaF = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaFine, turbulentViscosityFine[indices.k_000]) : omegaFine;
+
+    vf::lbm::interpolateCF(f, omegaF, epsilon_new, coefficients, x, y, z);
+
+    write(distFine, indices, f);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//! \brief Interpolate from coarse to fine nodes
+//! \details This scaling function is designed for the Cumulant K17 Kernel chimera collision kernel.
+//!
+//! The function is executed in the following steps:
+//!
+// based on scaleCF_RhoSq_comp_27
+template<bool hasTurbulentViscosity> __global__ void scaleCF_compressible(
+    real* distributionsCoarse, 
+    real* distributionsFine, 
+    unsigned int* neighborXcoarse,
+    unsigned int* neighborYcoarse,
+    unsigned int* neighborZcoarse,
+    unsigned int* neighborXfine,
+    unsigned int* neighborYfine,
+    unsigned int* neighborZfine,
+    unsigned long long numberOfLBnodesCoarse, 
+    unsigned long long numberOfLBnodesFine, 
+    bool isEvenTimestep,
+    unsigned int* indicesCoarseMMM, 
+    unsigned int* indicesFineMMM, 
+    unsigned int numberOfInterfaceNodes, 
+    real omegaCoarse, 
+    real omegaFine, 
+    real* turbulentViscosityCoarse,
+    real* turbulentViscosityFine,
+    ICellNeigh neighborCoarseToFine)
+{
+    const unsigned nodeIndex = vf::gpu::getNodeIndex();
+
+    if (nodeIndex >= numberOfInterfaceNodes)
+        return;
+
+    // 1.calculate moments
+    vf::lbm::MomentsOnSourceNodeSet momentsSet;
 
+    // - ###########################################
+    // TODO: The following part starting from here
+    //       should be exchanged by function call of calculate_moment_set<hasTurbulentViscosity>()
+    //       However, this leads to a very small deviation in the results (~10e-6).
+    real omegaC  = omegaCoarse;
+    Distributions27 distCoarse;
+    vf::gpu::getPointersToDistributions(distCoarse, distributionsCoarse, numberOfLBnodesCoarse, isEvenTimestep);
+
+    vf::gpu::ListIndices indices;
     ////////////////////////////////////////////////////////////////////////////////
-    // Set moments (zeroth to sixth orders) on destination node
+    //! - Calculate moments for each source node 
+    //!
+    ////////////////////////////////////////////////////////////////////////////////
+    // source node BSW = MMM
+    ////////////////////////////////////////////////////////////////////////////////
+    // index of the base node and its neighbors
+    unsigned int k_base_000 = indicesCoarseMMM[nodeIndex];
+    unsigned int k_base_M00 = neighborXcoarse [k_base_000];
+    unsigned int k_base_0M0 = neighborYcoarse [k_base_000];
+    unsigned int k_base_00M = neighborZcoarse [k_base_000];
+    unsigned int k_base_MM0 = neighborYcoarse [k_base_M00];
+    unsigned int k_base_M0M = neighborZcoarse [k_base_M00];
+    unsigned int k_base_0MM = neighborZcoarse [k_base_0M0];
+    unsigned int k_base_MMM = neighborZcoarse [k_base_MM0];
+    ////////////////////////////////////////////////////////////////////////////////
+    // Set neighbor indices
+    indices.k_000 = k_base_000;
+    indices.k_M00 = k_base_M00;
+    indices.k_0M0 = k_base_0M0;
+    indices.k_00M = k_base_00M;
+    indices.k_MM0 = k_base_MM0;
+    indices.k_M0M = k_base_M0M;
+    indices.k_0MM = k_base_0MM;
+    indices.k_MMM = k_base_MMM;
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+
+    real f_coarse[27];
+
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculateMMM(f_coarse, omegaC);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node TSW = MMP
+    //////////////////////////////////////////////////////////////////////////
+    // Set neighbor indices - has to be recalculated for the new source node
+    indices.k_000 = indices.k_00M;
+    indices.k_M00 = indices.k_M0M;
+    indices.k_0M0 = indices.k_0MM;
+    indices.k_00M = neighborZcoarse[indices.k_00M];
+    indices.k_MM0 = indices.k_MMM;
+    indices.k_M0M = neighborZcoarse[indices.k_M0M];
+    indices.k_0MM = neighborZcoarse[indices.k_0MM];
+    indices.k_MMM = neighborZcoarse[indices.k_MMM];
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculateMMP(f_coarse, omegaC);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node TSE = PMP
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = indices.k_M00;
+    indices.k_M00 = neighborXcoarse[indices.k_M00];
+    indices.k_0M0 = indices.k_MM0;
+    indices.k_00M = indices.k_M0M;
+    indices.k_MM0 = neighborXcoarse[indices.k_MM0];
+    indices.k_M0M = neighborXcoarse[indices.k_M0M];
+    indices.k_0MM = indices.k_MMM;
+    indices.k_MMM = neighborXcoarse[indices.k_MMM];
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculatePMP(f_coarse, omegaC);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node BSE = PMM 
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_00M = indices.k_000;
+    indices.k_M0M = indices.k_M00;
+    indices.k_0MM = indices.k_0M0;
+    indices.k_MMM = indices.k_MM0;
+    indices.k_000 = k_base_M00;
+    indices.k_M00 = neighborXcoarse[k_base_M00];
+    indices.k_0M0 = k_base_MM0;
+    indices.k_MM0 = neighborXcoarse[k_base_MM0];
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
 
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    interpolateDistributions(
-        x, y, z,
-        m_000, 
-        m_100, m_010, m_001,
-        m_011, m_101, m_110, m_200, m_020, m_002,
-        m_111, m_210, m_012, m_201, m_021, m_120, m_102,
-        m_022, m_202, m_220, m_211, m_121, m_112,
-        m_122, m_212, m_221,
-        m_222,
-        a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110,  a_101, a_011, a_111,
-        b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110,  b_101, b_011, b_111,
-        c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110,  c_101, c_011, c_111,
-        d_000, d_100, d_010, d_001, d_110, d_101, d_011, d_111,
-        LaplaceRho, eps_new, omegaF, 
-        kxxMyyAverage, kxxMzzAverage, kyzAverage, kxzAverage, kxyAverage
-    );
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculatePMM(f_coarse, omegaC);
 
     //////////////////////////////////////////////////////////////////////////
-    // Write distributions
-    (distFine.f[DIR_000])[k_000] = f_000;
-    (distFine.f[DIR_P00])[k_000] = f_P00;
-    (distFine.f[DIR_M00])[k_M00] = f_M00;
-    (distFine.f[DIR_0P0])[k_000] = f_0P0;
-    (distFine.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distFine.f[DIR_00P])[k_000] = f_00P;
-    (distFine.f[DIR_00M])[k_00M] = f_00M;
-    (distFine.f[DIR_PP0])[k_000] = f_PP0;
-    (distFine.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distFine.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distFine.f[DIR_MP0])[k_M00] = f_MP0;
-    (distFine.f[DIR_P0P])[k_000] = f_P0P;
-    (distFine.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distFine.f[DIR_P0M])[k_00M] = f_P0M;
-    (distFine.f[DIR_M0P])[k_M00] = f_M0P;
-    (distFine.f[DIR_0PP])[k_000] = f_0PP;
-    (distFine.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distFine.f[DIR_0PM])[k_00M] = f_0PM;
-    (distFine.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distFine.f[DIR_PPP])[k_000] = f_PPP;
-    (distFine.f[DIR_MPP])[k_M00] = f_MPP;
-    (distFine.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distFine.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distFine.f[DIR_PPM])[k_00M] = f_PPM;
-    (distFine.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distFine.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distFine.f[DIR_MMM])[k_MMM] = f_MMM;
+    // source node BNW = MPM
+    //////////////////////////////////////////////////////////////////////////
+    // index of the base node and its neighbors --> indices of all source nodes
+    k_base_000 = k_base_0M0;
+    k_base_M00 = k_base_MM0;
+    k_base_0M0 = neighborYcoarse[k_base_0M0];
+    k_base_00M = k_base_0MM;
+    k_base_MM0 = neighborYcoarse[k_base_MM0];
+    k_base_M0M = k_base_MMM;
+    k_base_0MM = neighborYcoarse[k_base_0MM];
+    k_base_MMM = neighborYcoarse[k_base_MMM];
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = k_base_000;
+    indices.k_M00 = k_base_M00;
+    indices.k_0M0 = k_base_0M0;
+    indices.k_00M = k_base_00M;
+    indices.k_MM0 = k_base_MM0;
+    indices.k_M0M = k_base_M0M;
+    indices.k_0MM = k_base_0MM;
+    indices.k_MMM = k_base_MMM;
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculateMPM(f_coarse, omegaC);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node TNW = MPP
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = indices.k_00M;
+    indices.k_M00 = indices.k_M0M;
+    indices.k_0M0 = indices.k_0MM;
+    indices.k_00M = neighborZcoarse[indices.k_00M];
+    indices.k_MM0 = indices.k_MMM;
+    indices.k_M0M = neighborZcoarse[indices.k_M0M];
+    indices.k_0MM = neighborZcoarse[indices.k_0MM];
+    indices.k_MMM = neighborZcoarse[indices.k_MMM];
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculateMPP(f_coarse, omegaC);
+    //////////////////////////////////////////////////////////////////////////
+    // source node TNE = PPP
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = indices.k_M00;
+    indices.k_M00 = neighborXcoarse[indices.k_M00];
+    indices.k_0M0 = indices.k_MM0;
+    indices.k_00M = indices.k_M0M;
+    indices.k_MM0 = neighborXcoarse[indices.k_MM0];
+    indices.k_M0M = neighborXcoarse[indices.k_M0M];
+    indices.k_0MM = indices.k_MMM;
+    indices.k_MMM = neighborXcoarse[indices.k_MMM];
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculatePPP(f_coarse, omegaC);
+    //////////////////////////////////////////////////////////////////////////
+    // source node BNE = PPM
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_00M = indices.k_000;
+    indices.k_M0M = indices.k_M00;
+    indices.k_0MM = indices.k_0M0;
+    indices.k_MMM = indices.k_MM0;
+    indices.k_000 = k_base_M00;
+    indices.k_M00 = neighborXcoarse[k_base_M00];
+    indices.k_0M0 = k_base_MM0;
+    indices.k_MM0 = neighborXcoarse[k_base_MM0];
+
+    omegaC = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+
+    read(f_coarse, distCoarse, indices);
+    momentsSet.calculatePPM(f_coarse, omegaC);
+    // should be extractel until this line
+    // - ###################################################################
+
+    // 2.calculate coefficients
+    vf::lbm::Coefficients coefficients;
+    momentsSet.calculateCoefficients(coefficients, neighborCoarseToFine.x[nodeIndex], neighborCoarseToFine.y[nodeIndex], neighborCoarseToFine.z[nodeIndex]);
+
+    // 3. interpolate coarse to fine
+    interpolate<hasTurbulentViscosity>(
+        coefficients,
+        nodeIndex,
+        distributionsFine, 
+        neighborXfine,
+        neighborYfine,
+        neighborZfine,
+        numberOfLBnodesFine,
+        indicesFineMMM,
+        omegaFine,
+        turbulentViscosityFine);
 }
 
 template __global__ void scaleCF_compressible<true>( real* distributionsCoarse, real* distributionsFine, unsigned int* neighborXcoarse, unsigned int* neighborYcoarse, unsigned int* neighborZcoarse, unsigned int* neighborXfine, unsigned int* neighborYfine, unsigned int* neighborZfine, unsigned long long numberOfLBnodesCoarse, unsigned long long numberOfLBnodesFine, bool isEvenTimestep, unsigned int* indicesCoarseMMM, unsigned int* indicesFineMMM, unsigned int numberOfInterfaceNodes, real omegaCoarse, real omegaFine, real* turbulentViscosityCoarse, real* turbulentViscosityFine, ICellNeigh offsetCF);
diff --git a/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleFC_compressible.cu b/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleFC_compressible.cu
index 5776ba476e3537360b32ee85f32514324946ff75..3276db0595329b4c948779d0b27857170d125f78 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleFC_compressible.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/GridScaling/scaleFC_compressible.cu
@@ -35,16 +35,44 @@
 #include "LBM/GPUHelperFunctions/KernelUtilities.h"
 #include "LBM/GPUHelperFunctions/ScalingUtilities.h"
 
-using namespace vf::basics::constant;
-using namespace vf::lbm::dir;
-using namespace vf::gpu;
+#include <lbm/KernelParameter.h>
+#include <lbm/refinement/InterpolationFC.h>
+#include <lbm/refinement/Coefficients.h>
+
+
+template <bool hasTurbulentViscosity> __device__ void interpolate(
+    vf::lbm::Coefficients& coefficients,
+    const unsigned int nodeIndex,
+    real* distributionsCoarse, 
+    unsigned int* neighborXcoarse,
+    unsigned int* neighborYcoarse,
+    unsigned int* neighborZcoarse,
+    unsigned long long numberOfLBnodesCoarse,
+    unsigned int* indicesCoarse000,
+    real omegaCoarse,
+    real* turbulentViscosityCoarse,
+    bool isEvenTimestep
+)
+{
+    // Position Coarse 0., 0., 0.
+    Distributions27 distCoarse;
+    vf::gpu::getPointersToDistributions(distCoarse, distributionsCoarse, numberOfLBnodesCoarse, isEvenTimestep);
+
+    vf::gpu::ListIndices indices(indicesCoarse000[nodeIndex], neighborXcoarse, neighborYcoarse, neighborZcoarse);
+
+    const real epsilonNew = c2o1; // ratio of grid resolutions
+    const real omegaCoarseNew = hasTurbulentViscosity ? vf::gpu::calculateOmega(omegaCoarse, turbulentViscosityCoarse[indices.k_000]) : omegaCoarse;
+    real fCoarse[27];
+    vf::lbm::interpolateFC(fCoarse, epsilonNew, omegaCoarseNew, coefficients);
+
+    vf::gpu::write(distCoarse, indices, fCoarse);
+}
+
+
 
 //////////////////////////////////////////////////////////////////////////
 //! \brief Interpolate from fine to coarse
 //! \details This scaling function is designed for the Cumulant K17 Kernel chimera collision kernel
-//! The function is executed in the following steps:
-//!
-
 // based on scaleFC_RhoSq_comp_27
 template<bool hasTurbulentViscosity> __global__ void scaleFC_compressible(
     real *distributionsCoarse,
@@ -61,653 +89,41 @@ template<bool hasTurbulentViscosity> __global__ void scaleFC_compressible(
     unsigned int *indicesCoarse000,
     unsigned int *indicesFineMMM,
     unsigned int numberOfInterfaceNodes,
-    real omegaCoarse,
-    real omegaFine,
+    const real omega_coarse,
+    const real omegaFine,
     real* turbulentViscosityCoarse,
     real* turbulentViscosityFine,
     ICellNeigh neighborFineToCoarse)
 {
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Get the node index coordinates from threadIdx, blockIdx, blockDim and gridDim.
-    //!
-    const unsigned nodeIndex = getNodeIndex();
+    const unsigned nodeIndex = vf::gpu::getNodeIndex();
 
-    //////////////////////////////////////////////////////////////////////////
-    //! - Return for non-interface node
     if (nodeIndex >= numberOfInterfaceNodes)
         return;
 
-    //////////////////////////////////////////////////////////////////////////
-    //! - Read distributions: style of reading and writing the distributions from/to stored arrays dependent on
-    //! timestep is based on the esoteric twist algorithm \ref <a
-    //! href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
-    //! DOI:10.3390/computation5020019 ]</b></a>
-    //!
-    Distributions27 distFine, distCoarse;
-    getPointersToDistributions(distFine, distributionsFine, numberOfLBnodesFine, true);
-    getPointersToDistributions(distCoarse, distributionsCoarse, numberOfLBnodesCoarse, isEvenTimestep);
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - declare local variables for source nodes
-    //!
-    real eps_new = c2o1; // ratio of grid resolutions
-    real omegaF  = omegaFine;
-    real omegaC  = omegaCoarse;
-
-    // zeroth and first order moments at the source nodes
-    real drho_PPP, vx1_PPP, vx2_PPP, vx3_PPP;
-    real drho_MPP, vx1_MPP, vx2_MPP, vx3_MPP;
-    real drho_PMP, vx1_PMP, vx2_PMP, vx3_PMP;
-    real drho_MMP, vx1_MMP, vx2_MMP, vx3_MMP;
-    real drho_PPM, vx1_PPM, vx2_PPM, vx3_PPM;
-    real drho_MPM, vx1_MPM, vx2_MPM, vx3_MPM;
-    real drho_PMM, vx1_PMM, vx2_PMM, vx3_PMM;
-    real drho_MMM, vx1_MMM, vx2_MMM, vx3_MMM;
-
-    // second order moments at the source nodes
-    real kxyFromfcNEQ_PPP, kyzFromfcNEQ_PPP, kxzFromfcNEQ_PPP, kxxMyyFromfcNEQ_PPP, kxxMzzFromfcNEQ_PPP;
-    real kxyFromfcNEQ_MPP, kyzFromfcNEQ_MPP, kxzFromfcNEQ_MPP, kxxMyyFromfcNEQ_MPP, kxxMzzFromfcNEQ_MPP;
-    real kxyFromfcNEQ_PMP, kyzFromfcNEQ_PMP, kxzFromfcNEQ_PMP, kxxMyyFromfcNEQ_PMP, kxxMzzFromfcNEQ_PMP;
-    real kxyFromfcNEQ_MMP, kyzFromfcNEQ_MMP, kxzFromfcNEQ_MMP, kxxMyyFromfcNEQ_MMP, kxxMzzFromfcNEQ_MMP;
-    real kxyFromfcNEQ_PPM, kyzFromfcNEQ_PPM, kxzFromfcNEQ_PPM, kxxMyyFromfcNEQ_PPM, kxxMzzFromfcNEQ_PPM;
-    real kxyFromfcNEQ_MPM, kyzFromfcNEQ_MPM, kxzFromfcNEQ_MPM, kxxMyyFromfcNEQ_MPM, kxxMzzFromfcNEQ_MPM;
-    real kxyFromfcNEQ_PMM, kyzFromfcNEQ_PMM, kxzFromfcNEQ_PMM, kxxMyyFromfcNEQ_PMM, kxxMzzFromfcNEQ_PMM;
-    real kxyFromfcNEQ_MMM, kyzFromfcNEQ_MMM, kxzFromfcNEQ_MMM, kxxMyyFromfcNEQ_MMM, kxxMzzFromfcNEQ_MMM;
-
-    //////////////////////////////////////////////////////////////////////////
-    //! - Calculate moments for each source node 
-    //!
-    //////////////////////////////////////////////////////////////////////////
-    // source node BSW = MMM
-    //////////////////////////////////////////////////////////////////////////
-    // index of the base node and its neighbors
-    unsigned int k_base_000 = indicesFineMMM[nodeIndex];
-    unsigned int k_base_M00 = neighborXfine [k_base_000];
-    unsigned int k_base_0M0 = neighborYfine [k_base_000];
-    unsigned int k_base_00M = neighborZfine [k_base_000];
-    unsigned int k_base_MM0 = neighborYfine [k_base_M00];
-    unsigned int k_base_M0M = neighborZfine [k_base_M00];
-    unsigned int k_base_0MM = neighborZfine [k_base_0M0];
-    unsigned int k_base_MMM = neighborZfine [k_base_MM0];
-    //////////////////////////////////////////////////////////////////////////
-    // Set neighbor indices
-    unsigned int k_000 = k_base_000;
-    unsigned int k_M00 = k_base_M00;
-    unsigned int k_0M0 = k_base_0M0;
-    unsigned int k_00M = k_base_00M;
-    unsigned int k_MM0 = k_base_MM0;
-    unsigned int k_M0M = k_base_M0M;
-    unsigned int k_0MM = k_base_0MM;
-    unsigned int k_MMM = k_base_MMM;
-
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MMM, vx1_MMM, vx2_MMM, vx3_MMM,
-        kxyFromfcNEQ_MMM, kyzFromfcNEQ_MMM, kxzFromfcNEQ_MMM, kxxMyyFromfcNEQ_MMM, kxxMzzFromfcNEQ_MMM);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TSW = MMP
-    //////////////////////////////////////////////////////////////////////////
-    // Set neighbor indices - has to be recalculated for the new source node
-    k_000 = k_00M;
-    k_M00 = k_M0M;
-    k_0M0 = k_0MM;
-    k_00M = neighborZfine[k_00M];
-    k_MM0 = k_MMM;
-    k_M0M = neighborZfine[k_M0M];
-    k_0MM = neighborZfine[k_0MM];
-    k_MMM = neighborZfine[k_MMM];
-
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MMP, vx1_MMP, vx2_MMP, vx3_MMP,
-        kxyFromfcNEQ_MMP, kyzFromfcNEQ_MMP, kxzFromfcNEQ_MMP, kxxMyyFromfcNEQ_MMP, kxxMzzFromfcNEQ_MMP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TSE = PMP
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_000 = k_M00;
-    k_M00 = neighborXfine[k_M00];
-    k_0M0 = k_MM0;
-    k_00M = k_M0M;
-    k_MM0 = neighborXfine[k_MM0];
-    k_M0M = neighborXfine[k_M0M];
-    k_0MM = k_MMM;
-    k_MMM = neighborXfine[k_MMM];
-
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PMP, vx1_PMP, vx2_PMP, vx3_PMP,
-        kxyFromfcNEQ_PMP, kyzFromfcNEQ_PMP, kxzFromfcNEQ_PMP, kxxMyyFromfcNEQ_PMP, kxxMzzFromfcNEQ_PMP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node BSE = PMM 
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_00M = k_000;
-    k_M0M = k_M00;
-    k_0MM = k_0M0;
-    k_MMM = k_MM0;
-    k_000 = k_base_M00;
-    k_M00 = neighborXfine[k_base_M00];
-    k_0M0 = k_base_MM0;
-    k_MM0 = neighborXfine[k_base_MM0];
-
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PMM, vx1_PMM, vx2_PMM, vx3_PMM,
-        kxyFromfcNEQ_PMM, kyzFromfcNEQ_PMM, kxzFromfcNEQ_PMM, kxxMyyFromfcNEQ_PMM, kxxMzzFromfcNEQ_PMM);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node BNW = MPM
-    //////////////////////////////////////////////////////////////////////////
-    // index of the base node and its neighbors --> indices of all source nodes
-    k_base_000 = k_base_0M0;
-    k_base_M00 = k_base_MM0;
-    k_base_0M0 = neighborYfine[k_base_0M0];
-    k_base_00M = k_base_0MM;
-    k_base_MM0 = neighborYfine[k_base_MM0];
-    k_base_M0M = k_base_MMM;
-    k_base_0MM = neighborYfine[k_base_0MM];
-    k_base_MMM = neighborYfine[k_base_MMM];
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_000 = k_base_000;
-    k_M00 = k_base_M00;
-    k_0M0 = k_base_0M0;
-    k_00M = k_base_00M;
-    k_MM0 = k_base_MM0;
-    k_M0M = k_base_M0M;
-    k_0MM = k_base_0MM;
-    k_MMM = k_base_MMM;
-
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MPM, vx1_MPM, vx2_MPM, vx3_MPM,
-        kxyFromfcNEQ_MPM, kyzFromfcNEQ_MPM, kxzFromfcNEQ_MPM, kxxMyyFromfcNEQ_MPM, kxxMzzFromfcNEQ_MPM);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TNW = MPP
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_000 = k_00M;
-    k_M00 = k_M0M;
-    k_0M0 = k_0MM;
-    k_00M = neighborZfine[k_00M];
-    k_MM0 = k_MMM;
-    k_M0M = neighborZfine[k_M0M];
-    k_0MM = neighborZfine[k_0MM];
-    k_MMM = neighborZfine[k_MMM];
-
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-    
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_MPP, vx1_MPP, vx2_MPP, vx3_MPP,
-        kxyFromfcNEQ_MPP, kyzFromfcNEQ_MPP, kxzFromfcNEQ_MPP, kxxMyyFromfcNEQ_MPP, kxxMzzFromfcNEQ_MPP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node TNE = PPP
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_000 = k_M00;
-    k_M00 = neighborXfine[k_M00];
-    k_0M0 = k_MM0;
-    k_00M = k_M0M;
-    k_MM0 = neighborXfine[k_MM0];
-    k_M0M = neighborXfine[k_M0M];
-    k_0MM = k_MMM;
-    k_MMM = neighborXfine[k_MMM];
-
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PPP, vx1_PPP, vx2_PPP, vx3_PPP,
-        kxyFromfcNEQ_PPP, kyzFromfcNEQ_PPP, kxzFromfcNEQ_PPP, kxxMyyFromfcNEQ_PPP, kxxMzzFromfcNEQ_PPP);
-
-    //////////////////////////////////////////////////////////////////////////
-    // source node BNE = PPM
-    //////////////////////////////////////////////////////////////////////////
-    // index
-    k_00M = k_000;
-    k_M0M = k_M00;
-    k_0MM = k_0M0;
-    k_MMM = k_MM0;
-    k_000 = k_base_M00;
-    k_M00 = neighborXfine[k_base_M00];
-    k_0M0 = k_base_MM0;
-    k_MM0 = neighborXfine[k_base_MM0];
-    
-    if(hasTurbulentViscosity) omegaF = omegaFine/ (c1o1 + c3o1*omegaFine*turbulentViscosityFine[k_000]);
-
-    calculateMomentsOnSourceNodes( distFine, omegaF,
-        k_000, k_M00, k_0M0, k_00M, k_MM0, k_M0M, k_0MM, k_MMM, drho_PPM, vx1_PPM, vx2_PPM, vx3_PPM,
-        kxyFromfcNEQ_PPM, kyzFromfcNEQ_PPM, kxzFromfcNEQ_PPM, kxxMyyFromfcNEQ_PPM, kxxMzzFromfcNEQ_PPM);
-
-    //////////////////////////////////////////////////////////////////////////
-    //! - Calculate coefficients for polynomial interpolation
-    //!
-    // example: a_110: derivation in x and y direction
-    real a_000, a_100, a_010, a_001, a_200, a_020, a_002, a_110, a_101, a_011;
-    real b_000, b_100, b_010, b_001, b_200, b_020, b_002, b_110, b_101, b_011;
-    real c_000, c_100, c_010, c_001, c_200, c_020, c_002, c_110, c_101, c_011;
-    real d_000, d_100, d_010, d_001, d_110, d_101, d_011;
-
-    a_000 = c1o64 * (
-            c2o1 * (
-            ((kxyFromfcNEQ_MMM - kxyFromfcNEQ_PPP) + (kxyFromfcNEQ_MMP - kxyFromfcNEQ_PPM)) + ((kxyFromfcNEQ_PMM - kxyFromfcNEQ_MPP) + (kxyFromfcNEQ_PMP - kxyFromfcNEQ_MPM)) + 
-            ((kxzFromfcNEQ_MMM - kxzFromfcNEQ_PPP) + (kxzFromfcNEQ_PPM - kxzFromfcNEQ_MMP)) + ((kxzFromfcNEQ_PMM - kxzFromfcNEQ_MPP) + (kxzFromfcNEQ_MPM - kxzFromfcNEQ_PMP)) + 
-            ((vx2_PPP + vx2_MMM) + (vx2_PPM + vx2_MMP)) - ((vx2_MPP + vx2_PMM) + (vx2_MPM + vx2_PMP)) + 
-            ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MMP)) + ((vx3_PMP + vx3_MPM) - (vx3_MPP + vx3_PMM))) + 
-            c8o1 * (((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) + ((vx1_MPP + vx1_PMM) + (vx1_PMP + vx1_MPM))) +
-            ((kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_PPP) + (kxxMyyFromfcNEQ_MMP - kxxMyyFromfcNEQ_PPM)) + 
-            ((kxxMyyFromfcNEQ_MPP - kxxMyyFromfcNEQ_PMM) + (kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_PMP)) +
-            ((kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_PPP) + (kxxMzzFromfcNEQ_MMP - kxxMzzFromfcNEQ_PPM)) + 
-            ((kxxMzzFromfcNEQ_MPP - kxxMzzFromfcNEQ_PMM) + (kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_PMP)));
-    b_000 = c1o64 * (
-            c2o1 * (
-            ((kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MMM) + (kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_MMP)) + 
-            ((kxxMyyFromfcNEQ_MPP - kxxMyyFromfcNEQ_PMM) + (kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_PMP)) + 
-            ((kxyFromfcNEQ_MMM - kxyFromfcNEQ_PPP) + (kxyFromfcNEQ_MMP - kxyFromfcNEQ_PPM)) + 
-            ((kxyFromfcNEQ_MPP - kxyFromfcNEQ_PMM) + (kxyFromfcNEQ_MPM - kxyFromfcNEQ_PMP)) + 
-            ((kyzFromfcNEQ_MMM - kyzFromfcNEQ_PPP) + (kyzFromfcNEQ_PPM - kyzFromfcNEQ_MMP)) + 
-            ((kyzFromfcNEQ_PMM - kyzFromfcNEQ_MPP) + (kyzFromfcNEQ_MPM - kyzFromfcNEQ_PMP)) + 
-            ((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) - ((vx1_MPM + vx1_MPP) + (vx1_PMM + vx1_PMP)) + 
-            ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MMP)) + ((vx3_MPP + vx3_PMM) - (vx3_MPM + vx3_PMP))) + 
-            c8o1 * (((vx2_PPP + vx2_MMM) + (vx2_PPM + vx2_MMP)) + ((vx2_MPP + vx2_PMM) + (vx2_MPM + vx2_PMP))) + 
-            ((kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_PPP) + (kxxMzzFromfcNEQ_MMP - kxxMzzFromfcNEQ_PPM)) +
-            ((kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_MPP) + (kxxMzzFromfcNEQ_PMP - kxxMzzFromfcNEQ_MPM)));
-    c_000 = c1o64 * ( 
-            c2o1 * (
-            ((kxxMzzFromfcNEQ_PPP - kxxMzzFromfcNEQ_MMM) + (kxxMzzFromfcNEQ_MMP - kxxMzzFromfcNEQ_PPM)) + 
-            ((kxxMzzFromfcNEQ_MPP - kxxMzzFromfcNEQ_PMM) + (kxxMzzFromfcNEQ_PMP - kxxMzzFromfcNEQ_MPM)) + 
-            ((kxzFromfcNEQ_MMM - kxzFromfcNEQ_PPP) + (kxzFromfcNEQ_MMP - kxzFromfcNEQ_PPM)) + 
-            ((kxzFromfcNEQ_MPP - kxzFromfcNEQ_PMM) + (kxzFromfcNEQ_MPM - kxzFromfcNEQ_PMP)) + 
-            ((kyzFromfcNEQ_MMM - kyzFromfcNEQ_PPP) + (kyzFromfcNEQ_MMP - kyzFromfcNEQ_PPM)) + 
-            ((kyzFromfcNEQ_PMM - kyzFromfcNEQ_MPP) + (kyzFromfcNEQ_PMP - kyzFromfcNEQ_MPM)) + 
-            ((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_MPM + vx1_PMP) - (vx1_MPP + vx1_PMM)) + 
-            ((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_MPP + vx2_PMM) - (vx2_MPM + vx2_PMP))) + 
-            c8o1 * (((vx3_PPP + vx3_MMM) + (vx3_PPM + vx3_MMP)) + ((vx3_PMM + vx3_MPP) + (vx3_PMP + vx3_MPM))) +
-            ((kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_PPP) + (kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_MMP)) + 
-            ((kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_MPP) + (kxxMyyFromfcNEQ_MPM - kxxMyyFromfcNEQ_PMP)));
-
-    a_100 = c1o4 * (((vx1_PPP - vx1_MMM) + (vx1_PPM - vx1_MMP)) + ((vx1_PMM - vx1_MPP) + (vx1_PMP - vx1_MPM)));
-    b_100 = c1o4 * (((vx2_PPP - vx2_MMM) + (vx2_PPM - vx2_MMP)) + ((vx2_PMM - vx2_MPP) + (vx2_PMP - vx2_MPM)));
-    c_100 = c1o4 * (((vx3_PPP - vx3_MMM) + (vx3_PPM - vx3_MMP)) + ((vx3_PMM - vx3_MPP) + (vx3_PMP - vx3_MPM)));
-
-    a_200 = c1o16 * ( 
-            c2o1 * (
-            ((vx2_PPP + vx2_MMM) + (vx2_PPM - vx2_MPP)) + ((vx2_MMP - vx2_PMM) - (vx2_MPM + vx2_PMP)) + 
-            ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MPP)) + ((vx3_MPM + vx3_PMP) - (vx3_MMP + vx3_PMM))) + 
-            ((kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MMM) + (kxxMyyFromfcNEQ_PPM - kxxMyyFromfcNEQ_MMP)) + 
-            ((kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_MPP) + (kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MPM)) + 
-            ((kxxMzzFromfcNEQ_PPP - kxxMzzFromfcNEQ_MMM) + (kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_MMP)) + 
-            ((kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_MPP) + (kxxMzzFromfcNEQ_PMP - kxxMzzFromfcNEQ_MPM)));
-    b_200 = c1o8 * (
-            c2o1 * (
-            -((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) + ((vx1_MPP + vx1_PMM) + (vx1_MPM + vx1_PMP))) +
-            ((kxyFromfcNEQ_PPP - kxyFromfcNEQ_MMM) + (kxyFromfcNEQ_PPM - kxyFromfcNEQ_MMP)) + 
-            ((kxyFromfcNEQ_PMM - kxyFromfcNEQ_MPP) + (kxyFromfcNEQ_PMP - kxyFromfcNEQ_MPM)));
-    c_200 = c1o8 * (
-            c2o1 * (
-            ((vx1_PPM + vx1_MMP) - (vx1_PPP + vx1_MMM)) + ((vx1_MPP + vx1_PMM) - (vx1_MPM + vx1_PMP))) +
-            ((kxzFromfcNEQ_PPP - kxzFromfcNEQ_MMM) + (kxzFromfcNEQ_PPM - kxzFromfcNEQ_MMP)) + 
-            ((kxzFromfcNEQ_PMM - kxzFromfcNEQ_MPP) + (kxzFromfcNEQ_PMP - kxzFromfcNEQ_MPM)));
-
-    a_010 = c1o4 * (((vx1_PPP - vx1_MMM) + (vx1_PPM - vx1_MMP)) + ((vx1_MPP - vx1_PMM) + (vx1_MPM - vx1_PMP)));
-    b_010 = c1o4 * (((vx2_PPP - vx2_MMM) + (vx2_PPM - vx2_MMP)) + ((vx2_MPP - vx2_PMM) + (vx2_MPM - vx2_PMP)));
-    c_010 = c1o4 * (((vx3_PPP - vx3_MMM) + (vx3_PPM - vx3_MMP)) + ((vx3_MPP - vx3_PMM) + (vx3_MPM - vx3_PMP)));
-
-    a_020 = c1o8 * (
-            c2o1 * (-((vx2_PPP + vx2_MMM) + (vx2_MMP + vx2_PPM)) + ((vx2_MPP + vx2_PMM) + (vx2_MPM + vx2_PMP))) +
-            ((kxyFromfcNEQ_PPP - kxyFromfcNEQ_MMM) + (kxyFromfcNEQ_PPM - kxyFromfcNEQ_MMP)) + 
-            ((kxyFromfcNEQ_MPP - kxyFromfcNEQ_PMM) + (kxyFromfcNEQ_MPM - kxyFromfcNEQ_PMP)));
-    b_020 = c1o16 * (
-            c2o1 * (
-            ((kxxMyyFromfcNEQ_MMM - kxxMyyFromfcNEQ_PPP) + (kxxMyyFromfcNEQ_MMP - kxxMyyFromfcNEQ_PPM)) +
-            ((kxxMyyFromfcNEQ_PMM - kxxMyyFromfcNEQ_MPP) + (kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MPM)) +
-            ((vx1_PPP + vx1_MMM) + (vx1_PPM + vx1_MMP)) - ((vx1_MPP + vx1_PMM) + (vx1_PMP + vx1_MPM)) + 
-            ((vx3_PPP + vx3_MMM) - (vx3_PPM + vx3_MMP)) + ((vx3_MPP + vx3_PMM) - (vx3_MPM + vx3_PMP))) +
-            ((kxxMzzFromfcNEQ_PPP - kxxMzzFromfcNEQ_MMM) + (kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_MMP)) + 
-            ((kxxMzzFromfcNEQ_MPP - kxxMzzFromfcNEQ_PMM) + (kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_PMP)));
-    c_020 = c1o8 * (
-            c2o1 * (((vx2_MMP + vx2_PPM) - (vx2_PPP + vx2_MMM)) + ((vx2_PMP + vx2_MPM) - (vx2_MPP + vx2_PMM))) +
-            ((kyzFromfcNEQ_PPP - kyzFromfcNEQ_MMM) + (kyzFromfcNEQ_PPM - kyzFromfcNEQ_MMP)) +
-            ((kyzFromfcNEQ_MPP - kyzFromfcNEQ_PMM) + (kyzFromfcNEQ_MPM - kyzFromfcNEQ_PMP)));
-
-    a_001 = c1o4 * (((vx1_PPP - vx1_MMM) + (vx1_MMP - vx1_PPM)) + ((vx1_MPP - vx1_PMM) + (vx1_PMP - vx1_MPM)));
-    b_001 = c1o4 * (((vx2_PPP - vx2_MMM) + (vx2_MMP - vx2_PPM)) + ((vx2_MPP - vx2_PMM) + (vx2_PMP - vx2_MPM)));
-    c_001 = c1o4 * (((vx3_PPP - vx3_MMM) + (vx3_MMP - vx3_PPM)) + ((vx3_MPP - vx3_PMM) + (vx3_PMP - vx3_MPM)));
-
-    a_002 = c1o8 * (
-            c2o1 * (((vx3_PPM + vx3_MMP) - (vx3_PPP + vx3_MMM)) + ((vx3_MPP + vx3_PMM) - (vx3_PMP + vx3_MPM))) +
-                    ((kxzFromfcNEQ_PPP - kxzFromfcNEQ_MMM) + (kxzFromfcNEQ_MMP - kxzFromfcNEQ_PPM)) +
-                    ((kxzFromfcNEQ_PMP - kxzFromfcNEQ_MPM) + (kxzFromfcNEQ_MPP - kxzFromfcNEQ_PMM)));
-    b_002 = c1o8 * (
-            c2o1 * (((vx3_PPM + vx3_MMP) - (vx3_PPP + vx3_MMM)) + ((vx3_MPM + vx3_PMP) - (vx3_PMM + vx3_MPP))) + 
-                    ((kyzFromfcNEQ_PPP - kyzFromfcNEQ_MMM) + (kyzFromfcNEQ_MMP - kyzFromfcNEQ_PPM)) + 
-                    ((kyzFromfcNEQ_PMP - kyzFromfcNEQ_MPM) + (kyzFromfcNEQ_MPP - kyzFromfcNEQ_PMM)));
-    c_002 = c1o16 * (
-            c2o1 * (
-            ((kxxMzzFromfcNEQ_MMM - kxxMzzFromfcNEQ_PPP) + (kxxMzzFromfcNEQ_PPM - kxxMzzFromfcNEQ_MMP)) + 
-            ((kxxMzzFromfcNEQ_MPM - kxxMzzFromfcNEQ_PMP) + (kxxMzzFromfcNEQ_PMM - kxxMzzFromfcNEQ_MPP)) + 
-            ((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_MPM + vx1_PMP) - (vx1_PMM + vx1_MPP)) + 
-            ((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_PMM + vx2_MPP) - (vx2_MPM + vx2_PMP))) + 
-            ((kxxMyyFromfcNEQ_PPP - kxxMyyFromfcNEQ_MMM) + (kxxMyyFromfcNEQ_MMP - kxxMyyFromfcNEQ_PPM)) +
-            ((kxxMyyFromfcNEQ_PMP - kxxMyyFromfcNEQ_MPM) + (kxxMyyFromfcNEQ_MPP - kxxMyyFromfcNEQ_PMM)));
-
-    a_110 = c1o2 * (((vx1_PPP + vx1_MMM) + (vx1_MMP + vx1_PPM)) - ((vx1_MPM + vx1_PMP) + (vx1_PMM + vx1_MPP)));
-    b_110 = c1o2 * (((vx2_PPP + vx2_MMM) + (vx2_MMP + vx2_PPM)) - ((vx2_MPM + vx2_PMP) + (vx2_PMM + vx2_MPP)));
-    c_110 = c1o2 * (((vx3_PPP + vx3_MMM) + (vx3_MMP + vx3_PPM)) - ((vx3_MPM + vx3_PMP) + (vx3_PMM + vx3_MPP)));
-
-    a_101 = c1o2 * (((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_MPM + vx1_PMP) - (vx1_PMM + vx1_MPP)));
-    b_101 = c1o2 * (((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_MPM + vx2_PMP) - (vx2_PMM + vx2_MPP)));
-    c_101 = c1o2 * (((vx3_PPP + vx3_MMM) - (vx3_MMP + vx3_PPM)) + ((vx3_MPM + vx3_PMP) - (vx3_PMM + vx3_MPP)));
-    
-    a_011 = c1o2 * (((vx1_PPP + vx1_MMM) - (vx1_MMP + vx1_PPM)) + ((vx1_PMM + vx1_MPP) - (vx1_MPM + vx1_PMP)));
-    b_011 = c1o2 * (((vx2_PPP + vx2_MMM) - (vx2_MMP + vx2_PPM)) + ((vx2_PMM + vx2_MPP) - (vx2_MPM + vx2_PMP)));
-    c_011 = c1o2 * (((vx3_PPP + vx3_MMM) - (vx3_MMP + vx3_PPM)) + ((vx3_PMM + vx3_MPP) - (vx3_MPM + vx3_PMP)));
-
-    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    real kxyAverage    = c0o1;
-    real kyzAverage    = c0o1;
-    real kxzAverage    = c0o1;
-    real kxxMyyAverage = c0o1;
-    real kxxMzzAverage = c0o1;
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Set the relative position of the offset cell {-1, 0, 1}
-    //!
-    real xoff    = neighborFineToCoarse.x[nodeIndex];
-    real yoff    = neighborFineToCoarse.y[nodeIndex];
-    real zoff    = neighborFineToCoarse.z[nodeIndex];
-     
-    real xoff_sq = xoff * xoff;
-    real yoff_sq = yoff * yoff;
-    real zoff_sq = zoff * zoff;
-
-    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    //!- Calculate coefficients for the polynomial interpolation of the pressure
-    //! 
-    real LaplaceRho = 
-        ((xoff != c0o1) || (yoff != c0o1) || (zoff != c0o1))
-        ? c0o1 : -c3o1 * (a_100 * a_100 + b_010 * b_010 + c_001 * c_001) - c6o1 * (b_100 * a_010 + c_100 * a_001 + c_010 * b_001);
-    d_000 =  c1o8 * ((((drho_PPP + drho_MMM) + (drho_PPM + drho_MMP)) + ((drho_PMM + drho_MPP) + (drho_PMP + drho_MPM))) - c2o1 * LaplaceRho);
-    d_100 = c1o4 * (((drho_PPP - drho_MMM) + (drho_PPM - drho_MMP)) + ((drho_PMM - drho_MPP) + (drho_PMP - drho_MPM)));
-    d_010 = c1o4 * (((drho_PPP - drho_MMM) + (drho_PPM - drho_MMP)) + ((drho_MPP - drho_PMM) + (drho_MPM - drho_PMP)));
-    d_001 = c1o4 * (((drho_PPP - drho_MMM) + (drho_MMP - drho_PPM)) + ((drho_MPP - drho_PMM) + (drho_PMP - drho_MPM)));
-    d_110 = c1o2 * (((drho_PPP + drho_MMM) + (drho_PPM + drho_MMP)) - ((drho_PMM + drho_MPP) + (drho_PMP + drho_MPM)));
-    d_101 = c1o2 * (((drho_PPP + drho_MMM) - (drho_PPM + drho_MMP)) + ((drho_PMP + drho_MPM) - (drho_PMM + drho_MPP)));
-    d_011 = c1o2 * (((drho_PPP + drho_MMM) - (drho_PPM + drho_MMP)) + ((drho_PMM + drho_MPP) - (drho_PMP + drho_MPM)));
-
-
-    //////////////////////////////////////////////////////////////////////////
-    //! - Extrapolation for refinement in to the wall (polynomial coefficients)
-    //!
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    //
-    // x------x
-    // |      |
-    // |   ---+--->X
-    // |      |  \
-    // x------x   \
-    //          offset-vector
-    //
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    a_000 = a_000 + xoff * a_100 + yoff * a_010 + zoff * a_001 + xoff_sq * a_200 + yoff_sq * a_020 + zoff_sq * a_002 +
-            xoff * yoff * a_110 + xoff * zoff * a_101 + yoff * zoff * a_011;
-    a_100 = a_100 + c2o1 * xoff * a_200 + yoff * a_110 + zoff * a_101;
-    a_010 = a_010 + c2o1 * yoff * a_020 + xoff * a_110 + zoff * a_011;
-    a_001 = a_001 + c2o1 * zoff * a_002 + xoff * a_101 + yoff * a_011;
-    b_000 = b_000 + xoff * b_100 + yoff * b_010 + zoff * b_001 + xoff_sq * b_200 + yoff_sq * b_020 + zoff_sq * b_002 +
-            xoff * yoff * b_110 + xoff * zoff * b_101 + yoff * zoff * b_011;
-    b_100 = b_100 + c2o1 * xoff * b_200 + yoff * b_110 + zoff * b_101;
-    b_010 = b_010 + c2o1 * yoff * b_020 + xoff * b_110 + zoff * b_011;
-    b_001 = b_001 + c2o1 * zoff * b_002 + xoff * b_101 + yoff * b_011;
-    c_000 = c_000 + xoff * c_100 + yoff * c_010 + zoff * c_001 + xoff_sq * c_200 + yoff_sq * c_020 + zoff_sq * c_002 +
-            xoff * yoff * c_110 + xoff * zoff * c_101 + yoff * zoff * c_011;
-    c_100 = c_100 + c2o1 * xoff * c_200 + yoff * c_110 + zoff * c_101;
-    c_010 = c_010 + c2o1 * yoff * c_020 + xoff * c_110 + zoff * c_011;
-    c_001 = c_001 + c2o1 * zoff * c_002 + xoff * c_101 + yoff * c_011;
-    d_000 = d_000 + xoff * d_100 + yoff * d_010 + zoff * d_001 + 
-            xoff * yoff * d_110 + xoff * zoff * d_101 + yoff * zoff * d_011;
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Set all moments to zero
-    //!
-    real m_111 = c0o1;
-    real m_211 = c0o1;
-    real m_011 = c0o1;
-    real m_121 = c0o1;
-    real m_101 = c0o1;
-    real m_112 = c0o1;
-    real m_110 = c0o1;
-    real m_221 = c0o1;
-    real m_001 = c0o1;
-    real m_201 = c0o1;
-    real m_021 = c0o1;
-    real m_212 = c0o1;
-    real m_010 = c0o1;
-    real m_210 = c0o1;
-    real m_012 = c0o1;
-    real m_122 = c0o1;
-    real m_100 = c0o1;
-    real m_120 = c0o1;
-    real m_102 = c0o1;
-    real m_222 = c0o1;
-    real m_022 = c0o1;
-    real m_202 = c0o1;
-    real m_002 = c0o1;
-    real m_220 = c0o1;
-    real m_020 = c0o1;
-    real m_200 = c0o1;
-    real m_000 = c0o1;
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Define aliases to use the same variable for the distributions (f's):
-    //!
-    real& f_000 = m_111;
-    real& f_P00 = m_211;
-    real& f_M00 = m_011;
-    real& f_0P0 = m_121;
-    real& f_0M0 = m_101;
-    real& f_00P = m_112;
-    real& f_00M = m_110;
-    real& f_PP0 = m_221;
-    real& f_MM0 = m_001;
-    real& f_PM0 = m_201;
-    real& f_MP0 = m_021;
-    real& f_P0P = m_212;
-    real& f_M0M = m_010;
-    real& f_P0M = m_210;
-    real& f_M0P = m_012;
-    real& f_0PP = m_122;
-    real& f_0MM = m_100;
-    real& f_0PM = m_120;
-    real& f_0MP = m_102;
-    real& f_PPP = m_222;
-    real& f_MPP = m_022;
-    real& f_PMP = m_202;
-    real& f_MMP = m_002;
-    real& f_PPM = m_220;
-    real& f_MPM = m_020;
-    real& f_PMM = m_200;
-    real& f_MMM = m_000;
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Declare local variables for destination nodes
-    //!
-    real vvx, vvy, vvz, vx_sq, vy_sq, vz_sq;
-    real mxxPyyPzz, mxxMyy, mxxMzz, mxxyPyzz, mxxyMyzz, mxxzPyyz, mxxzMyyz, mxyyPxzz, mxyyMxzz;
-    real useNEQ = c1o1; // zero; //one;   //.... one = on ..... zero = off
-    real press;
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    //
-    // Position Coarse 0., 0., 0.
-    //
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    // x = 0.;
-    // y = 0.;
-    // z = 0.;
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    // index of the destination node and its neighbors
-    k_000 = indicesCoarse000[nodeIndex];
-    k_M00 = neighborXcoarse [k_000];
-    k_0M0 = neighborYcoarse [k_000];
-    k_00M = neighborZcoarse [k_000];
-    k_MM0 = neighborYcoarse [k_M00];
-    k_M0M = neighborZcoarse [k_M00];
-    k_0MM = neighborZcoarse [k_0M0];
-    k_MMM = neighborZcoarse [k_MM0];
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    if(hasTurbulentViscosity) omegaC = omegaCoarse / (c1o1 + c3o1*omegaCoarse*turbulentViscosityCoarse[k_000]);
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Set macroscopic values on destination node (zeroth and first order moments)
-    //!
-    press = d_000;
-    vvx   = a_000;
-    vvy   = b_000;
-    vvz   = c_000;
-
-    m_000 = press; // m_000 is press, if drho is interpolated directly
-
-    vx_sq = vvx * vvx;
-    vy_sq = vvy * vvy;
-    vz_sq = vvz * vvz;
-
-    ////////////////////////////////////////////////////////////////////////////////
-    //! - Set moments (second to sixth order) on destination node
-    //!
-    // linear combinations for second order moments
-    mxxPyyPzz = m_000;
-
-    mxxMyy = -c2o3 * ((a_100 - b_010) + kxxMyyAverage) * eps_new / omegaC * (c1o1 + press);
-    mxxMzz = -c2o3 * ((a_100 - c_001) + kxxMzzAverage) * eps_new / omegaC * (c1o1 + press);
-
-    m_011 = -c1o3 * ((b_001 + c_010) + kyzAverage) * eps_new / omegaC * (c1o1 + press);
-    m_101 = -c1o3 * ((a_001 + c_100) + kxzAverage) * eps_new / omegaC * (c1o1 + press);
-    m_110 = -c1o3 * ((a_010 + b_100) + kxyAverage) * eps_new / omegaC * (c1o1 + press);
-
-    m_200 = c1o3 * (        mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
-    m_020 = c1o3 * (-c2o1 * mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
-    m_002 = c1o3 * (        mxxMyy - c2o1 * mxxMzz + mxxPyyPzz) * useNEQ;
-
-    // linear combinations for third order moments
-    m_111 = c0o1;
-
-    mxxyPyzz = c0o1;
-    mxxyMyzz = c0o1;
-    mxxzPyyz = c0o1;
-    mxxzMyyz = c0o1;
-    mxyyPxzz = c0o1;
-    mxyyMxzz = c0o1;
-
-    m_210 = ( mxxyMyzz + mxxyPyzz) * c1o2;
-    m_012 = (-mxxyMyzz + mxxyPyzz) * c1o2;
-    m_201 = ( mxxzMyyz + mxxzPyyz) * c1o2;
-    m_021 = (-mxxzMyyz + mxxzPyyz) * c1o2;
-    m_120 = ( mxyyMxzz + mxyyPxzz) * c1o2;
-    m_102 = (-mxyyMxzz + mxyyPxzz) * c1o2;
-
-    // fourth order moments
-    m_022 = m_000 * c1o9;
-    m_202 = m_022;
-    m_220 = m_022;
-
-    // fifth order moments
-
-    // sixth order moments
-    m_222 = m_000 * c1o27;
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Chimera transform from central moments to well conditioned distributions as defined in Appendix J in
-    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-    //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (88)-(96) in <a
-    //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040
-    //! ]</b></a>
-    //!
-    ////////////////////////////////////////////////////////////////////////////////////
-    // X - Dir
-    backwardInverseChimeraWithK(m_000, m_100, m_200, vvx, vx_sq, c1o1, c1o1);
-    backwardChimera(            m_010, m_110, m_210, vvx, vx_sq);
-    backwardInverseChimeraWithK(m_020, m_120, m_220, vvx, vx_sq, c3o1, c1o3);
-    backwardChimera(            m_001, m_101, m_201, vvx, vx_sq);
-    backwardChimera(            m_011, m_111, m_211, vvx, vx_sq);
-    backwardChimera(            m_021, m_121, m_221, vvx, vx_sq);
-    backwardInverseChimeraWithK(m_002, m_102, m_202, vvx, vx_sq, c3o1, c1o3);
-    backwardChimera(            m_012, m_112, m_212, vvx, vx_sq);
-    backwardInverseChimeraWithK(m_022, m_122, m_222, vvx, vx_sq, c9o1, c1o9);
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    // Y - Dir
-    backwardInverseChimeraWithK(m_000, m_010, m_020, vvy, vy_sq, c6o1, c1o6);
-    backwardChimera(            m_001, m_011, m_021, vvy, vy_sq);
-    backwardInverseChimeraWithK(m_002, m_012, m_022, vvy, vy_sq, c18o1, c1o18);
-    backwardInverseChimeraWithK(m_100, m_110, m_120, vvy, vy_sq, c3o2, c2o3);
-    backwardChimera(            m_101, m_111, m_121, vvy, vy_sq);
-    backwardInverseChimeraWithK(m_102, m_112, m_122, vvy, vy_sq, c9o2, c2o9);
-    backwardInverseChimeraWithK(m_200, m_210, m_220, vvy, vy_sq, c6o1, c1o6);
-    backwardChimera(            m_201, m_211, m_221, vvy, vy_sq);
-    backwardInverseChimeraWithK(m_202, m_212, m_222, vvy, vy_sq, c18o1, c1o18);
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    // Z - Dir
-    backwardInverseChimeraWithK(m_000, m_001, m_002, vvz, vz_sq, c36o1, c1o36);
-    backwardInverseChimeraWithK(m_010, m_011, m_012, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_020, m_021, m_022, vvz, vz_sq, c36o1, c1o36);
-    backwardInverseChimeraWithK(m_100, m_101, m_102, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_110, m_111, m_112, vvz, vz_sq, c9o4,  c4o9);
-    backwardInverseChimeraWithK(m_120, m_121, m_122, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_200, m_201, m_202, vvz, vz_sq, c36o1, c1o36);
-    backwardInverseChimeraWithK(m_210, m_211, m_212, vvz, vz_sq, c9o1,  c1o9);
-    backwardInverseChimeraWithK(m_220, m_221, m_222, vvz, vz_sq, c36o1, c1o36);
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Write distributions: style of reading and writing the distributions from/to
-    //! stored arrays dependent on timestep is based on the esoteric twist algorithm
-    //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
-    //! DOI:10.3390/computation5020019 ]</b></a>
-    //!
-    (distCoarse.f[DIR_000])[k_000] = f_000;
-    (distCoarse.f[DIR_P00])[k_000] = f_P00;
-    (distCoarse.f[DIR_M00])[k_M00] = f_M00;
-    (distCoarse.f[DIR_0P0])[k_000] = f_0P0;
-    (distCoarse.f[DIR_0M0])[k_0M0] = f_0M0;
-    (distCoarse.f[DIR_00P])[k_000] = f_00P;
-    (distCoarse.f[DIR_00M])[k_00M] = f_00M;
-    (distCoarse.f[DIR_PP0])[k_000] = f_PP0;
-    (distCoarse.f[DIR_MM0])[k_MM0] = f_MM0;
-    (distCoarse.f[DIR_PM0])[k_0M0] = f_PM0;
-    (distCoarse.f[DIR_MP0])[k_M00] = f_MP0;
-    (distCoarse.f[DIR_P0P])[k_000] = f_P0P;
-    (distCoarse.f[DIR_M0M])[k_M0M] = f_M0M;
-    (distCoarse.f[DIR_P0M])[k_00M] = f_P0M;
-    (distCoarse.f[DIR_M0P])[k_M00] = f_M0P;
-    (distCoarse.f[DIR_0PP])[k_000] = f_0PP;
-    (distCoarse.f[DIR_0MM])[k_0MM] = f_0MM;
-    (distCoarse.f[DIR_0PM])[k_00M] = f_0PM;
-    (distCoarse.f[DIR_0MP])[k_0M0] = f_0MP;
-    (distCoarse.f[DIR_PPP])[k_000] = f_PPP;
-    (distCoarse.f[DIR_MPP])[k_M00] = f_MPP;
-    (distCoarse.f[DIR_PMP])[k_0M0] = f_PMP;
-    (distCoarse.f[DIR_MMP])[k_MM0] = f_MMP;
-    (distCoarse.f[DIR_PPM])[k_00M] = f_PPM;
-    (distCoarse.f[DIR_MPM])[k_M0M] = f_MPM;
-    (distCoarse.f[DIR_PMM])[k_0MM] = f_PMM;
-    (distCoarse.f[DIR_MMM])[k_MMM] = f_MMM;
-    ////////////////////////////////////////////////////////////////////////////////////
+    // 1.calculate moments
+    vf::lbm::MomentsOnSourceNodeSet momentsSet;
+    vf::gpu::calculateMomentSet<hasTurbulentViscosity>(
+        momentsSet, nodeIndex, distributionsFine, neighborXfine, neighborYfine, neighborZfine, indicesFineMMM, turbulentViscosityFine, numberOfLBnodesFine, omegaFine, true);
+
+    // 2.calculate coefficients
+    vf::lbm::Coefficients coefficients;
+    momentsSet.calculateCoefficients(coefficients, neighborFineToCoarse.x[nodeIndex], neighborFineToCoarse.y[nodeIndex], neighborFineToCoarse.z[nodeIndex]);
+
+    // 3. interpolate fine to coarse
+    interpolate<hasTurbulentViscosity>(
+        coefficients,
+        nodeIndex,
+        distributionsCoarse, 
+        neighborXcoarse,
+        neighborYcoarse,
+        neighborZcoarse,
+        numberOfLBnodesCoarse,
+        indicesCoarse000,
+        omega_coarse,
+        turbulentViscosityCoarse,
+        isEvenTimestep);
 }
 
-template __global__ void scaleFC_compressible<true>( real *distributionsCoarse, real *distributionsFine, unsigned int *neighborXcoarse, unsigned int *neighborYcoarse, unsigned int *neighborZcoarse, unsigned int *neighborXfine, unsigned int *neighborYfine, unsigned int *neighborZfine, unsigned long long numberOfLBnodesCoarse, unsigned long long numberOfLBnodesFine, bool isEvenTimestep, unsigned int *indicesCoarse000, unsigned int *indicesFineMMM, unsigned int numberOfInterfaceNodes, real omegaCoarse, real omegaFine, real* turbulentViscosityCoarse, real* turbulentViscosityFine, ICellNeigh neighborFineToCoarse);
+template __global__ void scaleFC_compressible<true>(real *distributionsCoarse, real *distributionsFine, unsigned int *neighborXcoarse, unsigned int *neighborYcoarse, unsigned int *neighborZcoarse, unsigned int *neighborXfine, unsigned int *neighborYfine, unsigned int *neighborZfine, unsigned long long numberOfLBnodesCoarse, unsigned long long numberOfLBnodesFine, bool isEvenTimestep, unsigned int *indicesCoarse000, unsigned int *indicesFineMMM, unsigned int numberOfInterfaceNodes, real omegaCoarse, real omegaFine, real* turbulentViscosityCoarse, real* turbulentViscosityFine, ICellNeigh neighborFineToCoarse);
 
-template __global__ void scaleFC_compressible<false>( real *distributionsCoarse, real *distributionsFine, unsigned int *neighborXcoarse, unsigned int *neighborYcoarse, unsigned int *neighborZcoarse, unsigned int *neighborXfine, unsigned int *neighborYfine, unsigned int *neighborZfine, unsigned long long numberOfLBnodesCoarse, unsigned long long numberOfLBnodesFine, bool isEvenTimestep, unsigned int *indicesCoarse000, unsigned int *indicesFineMMM, unsigned int numberOfInterfaceNodes, real omegaCoarse, real omegaFine, real* turbulentViscosityCoarse, real* turbulentViscosityFine, ICellNeigh neighborFineToCoarse);
\ No newline at end of file
+template __global__ void scaleFC_compressible<false>(real *distributionsCoarse, real *distributionsFine, unsigned int *neighborXcoarse, unsigned int *neighborYcoarse, unsigned int *neighborZcoarse, unsigned int *neighborXfine, unsigned int *neighborYfine, unsigned int *neighborZfine, unsigned long long numberOfLBnodesCoarse, unsigned long long numberOfLBnodesFine, bool isEvenTimestep, unsigned int *indicesCoarse000, unsigned int *indicesFineMMM, unsigned int numberOfInterfaceNodes, real omegaCoarse, real omegaFine, real* turbulentViscosityCoarse, real* turbulentViscosityFine, ICellNeigh neighborFineToCoarse);
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/Kernel/Utilities/DistributionHelper.cu b/src/gpu/VirtualFluids_GPU/Kernel/Utilities/DistributionHelper.cu
index a1d9ba6665576c90406eee13084e5133acdb448c..3cc4b33f0b752943c97b1b770c62189a6c17d9c8 100644
--- a/src/gpu/VirtualFluids_GPU/Kernel/Utilities/DistributionHelper.cu
+++ b/src/gpu/VirtualFluids_GPU/Kernel/Utilities/DistributionHelper.cu
@@ -19,33 +19,33 @@ __device__ DistributionWrapper::DistributionWrapper(real *distributions, unsigne
 
 __device__ void DistributionWrapper::read()
 {
-    distribution.f[vf::lbm::dir::PZZ] = (distribution_references.f[DIR_P00])[k];
-    distribution.f[vf::lbm::dir::MZZ] = (distribution_references.f[DIR_M00])[kw];
-    distribution.f[vf::lbm::dir::ZPZ] = (distribution_references.f[DIR_0P0])[k];
-    distribution.f[vf::lbm::dir::ZMZ] = (distribution_references.f[DIR_0M0])[ks];
-    distribution.f[vf::lbm::dir::ZZP] = (distribution_references.f[DIR_00P])[k];
-    distribution.f[vf::lbm::dir::ZZM] = (distribution_references.f[DIR_00M])[kb];
-    distribution.f[vf::lbm::dir::PPZ] = (distribution_references.f[DIR_PP0])[k];
-    distribution.f[vf::lbm::dir::MMZ] = (distribution_references.f[DIR_MM0])[ksw];
-    distribution.f[vf::lbm::dir::PMZ] = (distribution_references.f[DIR_PM0])[ks];
-    distribution.f[vf::lbm::dir::MPZ] = (distribution_references.f[DIR_MP0])[kw];
-    distribution.f[vf::lbm::dir::PZP] = (distribution_references.f[DIR_P0P])[k];
-    distribution.f[vf::lbm::dir::MZM] = (distribution_references.f[DIR_M0M])[kbw];
-    distribution.f[vf::lbm::dir::PZM] = (distribution_references.f[DIR_P0M])[kb];
-    distribution.f[vf::lbm::dir::MZP] = (distribution_references.f[DIR_M0P])[kw];
-    distribution.f[vf::lbm::dir::ZPP] = (distribution_references.f[DIR_0PP])[k];
-    distribution.f[vf::lbm::dir::ZMM] = (distribution_references.f[DIR_0MM])[kbs];
-    distribution.f[vf::lbm::dir::ZPM] = (distribution_references.f[DIR_0PM])[kb];
-    distribution.f[vf::lbm::dir::ZMP] = (distribution_references.f[DIR_0MP])[ks];
-    distribution.f[vf::lbm::dir::PPP] = (distribution_references.f[DIR_PPP])[k];
-    distribution.f[vf::lbm::dir::MPP] = (distribution_references.f[DIR_MPP])[kw];
-    distribution.f[vf::lbm::dir::PMP] = (distribution_references.f[DIR_PMP])[ks];
-    distribution.f[vf::lbm::dir::MMP] = (distribution_references.f[DIR_MMP])[ksw];
-    distribution.f[vf::lbm::dir::PPM] = (distribution_references.f[DIR_PPM])[kb];
-    distribution.f[vf::lbm::dir::MPM] = (distribution_references.f[DIR_MPM])[kbw];
-    distribution.f[vf::lbm::dir::PMM] = (distribution_references.f[DIR_PMM])[kbs];
-    distribution.f[vf::lbm::dir::MMM] = (distribution_references.f[DIR_MMM])[kbsw];
-    distribution.f[vf::lbm::dir::ZZZ] = (distribution_references.f[DIR_000])[k];
+    distribution.f[vf::lbm::dir::DIR_P00] = (distribution_references.f[DIR_P00])[k];
+    distribution.f[vf::lbm::dir::DIR_M00] = (distribution_references.f[DIR_M00])[kw];
+    distribution.f[vf::lbm::dir::DIR_0P0] = (distribution_references.f[DIR_0P0])[k];
+    distribution.f[vf::lbm::dir::DIR_0M0] = (distribution_references.f[DIR_0M0])[ks];
+    distribution.f[vf::lbm::dir::DIR_00P] = (distribution_references.f[DIR_00P])[k];
+    distribution.f[vf::lbm::dir::DIR_00M] = (distribution_references.f[DIR_00M])[kb];
+    distribution.f[vf::lbm::dir::DIR_PP0] = (distribution_references.f[DIR_PP0])[k];
+    distribution.f[vf::lbm::dir::DIR_MM0] = (distribution_references.f[DIR_MM0])[ksw];
+    distribution.f[vf::lbm::dir::DIR_PM0] = (distribution_references.f[DIR_PM0])[ks];
+    distribution.f[vf::lbm::dir::DIR_MP0] = (distribution_references.f[DIR_MP0])[kw];
+    distribution.f[vf::lbm::dir::DIR_P0P] = (distribution_references.f[DIR_P0P])[k];
+    distribution.f[vf::lbm::dir::DIR_M0M] = (distribution_references.f[DIR_M0M])[kbw];
+    distribution.f[vf::lbm::dir::DIR_P0M] = (distribution_references.f[DIR_P0M])[kb];
+    distribution.f[vf::lbm::dir::DIR_M0P] = (distribution_references.f[DIR_M0P])[kw];
+    distribution.f[vf::lbm::dir::DIR_0PP] = (distribution_references.f[DIR_0PP])[k];
+    distribution.f[vf::lbm::dir::DIR_0MM] = (distribution_references.f[DIR_0MM])[kbs];
+    distribution.f[vf::lbm::dir::DIR_0PM] = (distribution_references.f[DIR_0PM])[kb];
+    distribution.f[vf::lbm::dir::DIR_0MP] = (distribution_references.f[DIR_0MP])[ks];
+    distribution.f[vf::lbm::dir::DIR_PPP] = (distribution_references.f[DIR_PPP])[k];
+    distribution.f[vf::lbm::dir::DIR_MPP] = (distribution_references.f[DIR_MPP])[kw];
+    distribution.f[vf::lbm::dir::DIR_PMP] = (distribution_references.f[DIR_PMP])[ks];
+    distribution.f[vf::lbm::dir::DIR_MMP] = (distribution_references.f[DIR_MMP])[ksw];
+    distribution.f[vf::lbm::dir::DIR_PPM] = (distribution_references.f[DIR_PPM])[kb];
+    distribution.f[vf::lbm::dir::DIR_MPM] = (distribution_references.f[DIR_MPM])[kbw];
+    distribution.f[vf::lbm::dir::DIR_PMM] = (distribution_references.f[DIR_PMM])[kbs];
+    distribution.f[vf::lbm::dir::DIR_MMM] = (distribution_references.f[DIR_MMM])[kbsw];
+    distribution.f[vf::lbm::dir::DIR_000] = (distribution_references.f[DIR_000])[k];
 }
 
 __device__ void DistributionWrapper::write()
diff --git a/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManager.cpp b/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManager.cpp
index e8fc3f318c920be36be7861a28659124a7b1e977..1c1e65fa34720a1f9d19b5ef02e4afda167b323f 100644
--- a/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManager.cpp
+++ b/src/gpu/VirtualFluids_GPU/KernelManager/BCKernelManager.cpp
@@ -415,7 +415,7 @@ void BCKernelManager::runPrecursorBCKernelPost(int level, uint t, CudaMemoryMana
         para->getParD(level)->precursorBC.current = para->getParD(level)->precursorBC.next;
         para->getParD(level)->precursorBC.next = tmp;
 
-        real loadTime = nextTime*pow(2,-level)*para->getTimeRatio();
+        real loadTime = nextTime*exp2(-level)*para->getTimeRatio();
 
         for(auto reader : para->getParH(level)->transientBCInputFileReader)
         {   
diff --git a/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/KernelUtilities.h b/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/KernelUtilities.h
index 5541bc54597ea02c5e3e89d00169b6eb6ff6564b..ebd1b8ab367b31c62fc1608b39215622819d35d9 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/KernelUtilities.h
+++ b/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/KernelUtilities.h
@@ -34,8 +34,11 @@
 #define KERNEL_UTILITIES_H
 
 #include "LBM/LB.h"
-#include "lbm/constants/D3Q27.h"
-#include "basics/constants/NumericConstants.h"
+
+#include <cassert>
+
+#include <lbm/constants/D3Q27.h>
+#include <basics/constants/NumericConstants.h>
 
 using namespace vf::basics::constant;
 using namespace vf::lbm::dir;
@@ -201,6 +204,125 @@ __inline__ __device__ bool isValidFluidNode(uint nodeType)
 }
 
 
+struct ListIndices
+{
+    __device__ ListIndices() {}
+    __device__ ListIndices(unsigned int k, unsigned int* neighborX, unsigned int* neighborY, unsigned int* neighborZ)
+    {
+        k_000 = k;
+        k_M00 = neighborX[k_000];
+        k_0M0 = neighborY[k_000];
+        k_00M = neighborZ[k_000];
+        k_MM0 = neighborY[k_M00];
+        k_M0M = neighborZ[k_M00];
+        k_0MM = neighborZ[k_0M0];
+        k_MMM = neighborZ[k_MM0];
+    }
+
+    unsigned int k_000 { 0 };
+    unsigned int k_M00 { 0 };
+    unsigned int k_0M0 { 0 };
+    unsigned int k_00M { 0 };
+    unsigned int k_MM0 { 0 };
+    unsigned int k_M0M { 0 };
+    unsigned int k_0MM { 0 };
+    unsigned int k_MMM { 0 };
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////
+//! - Read distributions: style of reading and writing the distributions from/to
+//! stored arrays dependent on timestep is based on the esoteric twist algorithm
+//! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
+//! DOI:10.3390/computation5020019 ]</b></a>
+__device__ __inline__ void read(real *f, const Distributions27 &dist, const ListIndices &indices)
+{
+    f[DIR_000] = (dist.f[DIR_000])[indices.k_000];
+    f[DIR_P00] = (dist.f[DIR_P00])[indices.k_000];
+    f[DIR_M00] = (dist.f[DIR_M00])[indices.k_M00];
+    f[DIR_0P0] = (dist.f[DIR_0P0])[indices.k_000];
+    f[DIR_0M0] = (dist.f[DIR_0M0])[indices.k_0M0];
+    f[DIR_00P] = (dist.f[DIR_00P])[indices.k_000];
+    f[DIR_00M] = (dist.f[DIR_00M])[indices.k_00M];
+    f[DIR_PP0] = (dist.f[DIR_PP0])[indices.k_000];
+    f[DIR_MM0] = (dist.f[DIR_MM0])[indices.k_MM0];
+    f[DIR_PM0] = (dist.f[DIR_PM0])[indices.k_0M0];
+    f[DIR_MP0] = (dist.f[DIR_MP0])[indices.k_M00];
+    f[DIR_P0P] = (dist.f[DIR_P0P])[indices.k_000];
+    f[DIR_M0M] = (dist.f[DIR_M0M])[indices.k_M0M];
+    f[DIR_P0M] = (dist.f[DIR_P0M])[indices.k_00M];
+    f[DIR_M0P] = (dist.f[DIR_M0P])[indices.k_M00];
+    f[DIR_0PP] = (dist.f[DIR_0PP])[indices.k_000];
+    f[DIR_0MM] = (dist.f[DIR_0MM])[indices.k_0MM];
+    f[DIR_0PM] = (dist.f[DIR_0PM])[indices.k_00M];
+    f[DIR_0MP] = (dist.f[DIR_0MP])[indices.k_0M0];
+    f[DIR_PPP] = (dist.f[DIR_PPP])[indices.k_000];
+    f[DIR_MPP] = (dist.f[DIR_MPP])[indices.k_M00];
+    f[DIR_PMP] = (dist.f[DIR_PMP])[indices.k_0M0];
+    f[DIR_MMP] = (dist.f[DIR_MMP])[indices.k_MM0];
+    f[DIR_PPM] = (dist.f[DIR_PPM])[indices.k_00M];
+    f[DIR_MPM] = (dist.f[DIR_MPM])[indices.k_M0M];
+    f[DIR_PMM] = (dist.f[DIR_PMM])[indices.k_0MM];
+    f[DIR_MMM] = (dist.f[DIR_MMM])[indices.k_MMM];
+}
+
+__device__ __inline__ void readInverse(real *f, const Distributions27 &dist, const ListIndices &indices)
+{
+    //TODO: https://git.rz.tu-bs.de/irmb/VirtualFluids_dev/-/issues/101
+    assert((false) || !fprintf(stderr, "Not implemented yet.\n")); 
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////
+//! - Write distributions: style of reading and writing the distributions from/to
+//! stored arrays dependent on timestep is based on the esoteric twist algorithm
+//! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017),
+//! DOI:10.3390/computation5020019 ]</b></a>
+__inline__ __device__ void write(Distributions27 &destination, const ListIndices &indices, const real* f)
+{
+    (destination.f[DIR_000])[indices.k_000] = f[DIR_000];
+    (destination.f[DIR_P00])[indices.k_000] = f[DIR_P00];
+    (destination.f[DIR_M00])[indices.k_M00] = f[DIR_M00];
+    (destination.f[DIR_0P0])[indices.k_000] = f[DIR_0P0];
+    (destination.f[DIR_0M0])[indices.k_0M0] = f[DIR_0M0];
+    (destination.f[DIR_00P])[indices.k_000] = f[DIR_00P];
+    (destination.f[DIR_00M])[indices.k_00M] = f[DIR_00M];
+    (destination.f[DIR_PP0])[indices.k_000] = f[DIR_PP0];
+    (destination.f[DIR_MM0])[indices.k_MM0] = f[DIR_MM0];
+    (destination.f[DIR_PM0])[indices.k_0M0] = f[DIR_PM0];
+    (destination.f[DIR_MP0])[indices.k_M00] = f[DIR_MP0];
+    (destination.f[DIR_P0P])[indices.k_000] = f[DIR_P0P];
+    (destination.f[DIR_M0M])[indices.k_M0M] = f[DIR_M0M];
+    (destination.f[DIR_P0M])[indices.k_00M] = f[DIR_P0M];
+    (destination.f[DIR_M0P])[indices.k_M00] = f[DIR_M0P];
+    (destination.f[DIR_0PP])[indices.k_000] = f[DIR_0PP];
+    (destination.f[DIR_0MM])[indices.k_0MM] = f[DIR_0MM];
+    (destination.f[DIR_0PM])[indices.k_00M] = f[DIR_0PM];
+    (destination.f[DIR_0MP])[indices.k_0M0] = f[DIR_0MP];
+    (destination.f[DIR_PPP])[indices.k_000] = f[DIR_PPP];
+    (destination.f[DIR_MPP])[indices.k_M00] = f[DIR_MPP];
+    (destination.f[DIR_PMP])[indices.k_0M0] = f[DIR_PMP];
+    (destination.f[DIR_MMP])[indices.k_MM0] = f[DIR_MMP];
+    (destination.f[DIR_PPM])[indices.k_00M] = f[DIR_PPM];
+    (destination.f[DIR_MPM])[indices.k_M0M] = f[DIR_MPM];
+    (destination.f[DIR_PMM])[indices.k_0MM] = f[DIR_PMM];
+    (destination.f[DIR_MMM])[indices.k_MMM] = f[DIR_MMM];
+}
+
+__inline__ __device__ void writeInverse(Distributions27 &destination, const ListIndices &indices, const real* f)
+{
+    //TODO: https://git.rz.tu-bs.de/irmb/VirtualFluids_dev/-/issues/101
+    assert((false) || !fprintf(stderr, "Not implemented yet.\n")); 
+}
+
+
+
+
+__inline__ __device__ real calculateOmega(const real omega_old, real turbulenceViscosity)
+{
+    return omega_old / (c1o1 + c3o1 * omega_old * turbulenceViscosity);
+}
+
 }
 
 #endif
diff --git a/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/ScalingUtilities.h b/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/ScalingUtilities.h
index a7c1390c728df1d0ca83424fb7f9f4fb09faba65..606f6b38b4f50ebc621cce23f05c2d54091934f9 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/ScalingUtilities.h
+++ b/src/gpu/VirtualFluids_GPU/LBM/GPUHelperFunctions/ScalingUtilities.h
@@ -33,9 +33,15 @@
 #ifndef SCALING_HELPER_FUNCTIONS_H
 #define SCALING_HELPER_FUNCTIONS_H
 
-#include "LBM/LB.h" 
-#include "lbm/constants/D3Q27.h"
-#include "basics/constants/NumericConstants.h"
+#include "LBM/GPUHelperFunctions/KernelUtilities.h"
+
+#include <basics/constants/NumericConstants.h>
+
+#include <lbm/constants/D3Q27.h>
+#include <lbm/KernelParameter.h>
+#include <basics/DataTypes.h>
+
+#include <lbm/refinement/Coefficients.h>
 
 using namespace vf::basics::constant;
 using namespace vf::lbm::dir;
@@ -43,94 +49,196 @@ using namespace vf::lbm::dir;
 namespace vf::gpu
 {
 
-__device__ __inline__ void calculateMomentsOnSourceNodes(Distributions27 &dist, real &omega, unsigned int &k_000,
-                                                         unsigned int &k_M00, unsigned int &k_0M0, unsigned int &k_00M,
-                                                         unsigned int &k_MM0, unsigned int &k_M0M, unsigned int &k_0MM,
-                                                         unsigned int &k_MMM, real &drho, real &velocityX,
-                                                         real &velocityY, real &velocityZ, real &kxyFromfcNEQ,
-                                                         real &kyzFromfcNEQ, real &kxzFromfcNEQ, real &kxxMyyFromfcNEQ,
-                                                         real &kxxMzzFromfcNEQ)
+template<bool hasTurbulentViscosity> __device__ void calculateMomentSet(
+    vf::lbm::MomentsOnSourceNodeSet& momentsSet,
+    const unsigned nodeIndex,
+    real *distribution,
+    unsigned int *neighborX,
+    unsigned int *neighborY,
+    unsigned int *neighborZ,
+    unsigned int *indices_MMM,
+    real* turbulentViscosity,
+    unsigned long long numberOfLBnodes,
+    const real omega,
+    bool isEvenTimestep
+)
 {
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Set local distributions (f's) on source nodes:
-    //!
-    real f_000 = (dist.f[DIR_000])[k_000];
-    real f_P00 = (dist.f[DIR_P00])[k_000];
-    real f_M00 = (dist.f[DIR_M00])[k_M00];
-    real f_0P0 = (dist.f[DIR_0P0])[k_000];
-    real f_0M0 = (dist.f[DIR_0M0])[k_0M0];
-    real f_00P = (dist.f[DIR_00P])[k_000];
-    real f_00M = (dist.f[DIR_00M])[k_00M];
-    real f_PP0 = (dist.f[DIR_PP0])[k_000];
-    real f_MM0 = (dist.f[DIR_MM0])[k_MM0];
-    real f_PM0 = (dist.f[DIR_PM0])[k_0M0];
-    real f_MP0 = (dist.f[DIR_MP0])[k_M00];
-    real f_P0P = (dist.f[DIR_P0P])[k_000];
-    real f_M0M = (dist.f[DIR_M0M])[k_M0M];
-    real f_P0M = (dist.f[DIR_P0M])[k_00M];
-    real f_M0P = (dist.f[DIR_M0P])[k_M00];
-    real f_0PP = (dist.f[DIR_0PP])[k_000];
-    real f_0MM = (dist.f[DIR_0MM])[k_0MM];
-    real f_0PM = (dist.f[DIR_0PM])[k_00M];
-    real f_0MP = (dist.f[DIR_0MP])[k_0M0];
-    real f_PPP = (dist.f[DIR_PPP])[k_000];
-    real f_MPP = (dist.f[DIR_MPP])[k_M00];
-    real f_PMP = (dist.f[DIR_PMP])[k_0M0];
-    real f_MMP = (dist.f[DIR_MMP])[k_MM0];
-    real f_PPM = (dist.f[DIR_PPM])[k_00M];
-    real f_MPM = (dist.f[DIR_MPM])[k_M0M];
-    real f_PMM = (dist.f[DIR_PMM])[k_0MM];
-    real f_MMM = (dist.f[DIR_MMM])[k_MMM];
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Calculate density and velocity using pyramid summation for low round-off errors as in Eq. (J1)-(J3) \ref
-    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
-    //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
-    //!
-    drho = ((((f_PPP + f_MMM) + (f_MPM + f_PMP)) + ((f_MPP + f_PMM) + (f_MMP + f_PPM))) +
-            (((f_0MP + f_0PM) + (f_0MM + f_0PP)) + ((f_M0P + f_P0M) + (f_M0M + f_P0P)) +
-             ((f_MP0 + f_PM0) + (f_MM0 + f_PP0))) +
-            ((f_M00 + f_P00) + (f_0M0 + f_0P0) + (f_00M + f_00P))) +
-           f_000;
-
-    real oneOverRho = c1o1 / (c1o1 + drho);
-
-    velocityX = ((((f_PPP - f_MMM) + (f_PMP - f_MPM)) + ((f_PMM - f_MPP) + (f_PPM - f_MMP))) +
-                 (((f_P0M - f_M0P) + (f_P0P - f_M0M)) + ((f_PM0 - f_MP0) + (f_PP0 - f_MM0))) + (f_P00 - f_M00)) *
-                oneOverRho;
-    velocityY = ((((f_PPP - f_MMM) + (f_MPM - f_PMP)) + ((f_MPP - f_PMM) + (f_PPM - f_MMP))) +
-                 (((f_0PM - f_0MP) + (f_0PP - f_0MM)) + ((f_MP0 - f_PM0) + (f_PP0 - f_MM0))) + (f_0P0 - f_0M0)) *
-                oneOverRho;
-    velocityZ = ((((f_PPP - f_MMM) + (f_PMP - f_MPM)) + ((f_MPP - f_PMM) + (f_MMP - f_PPM))) +
-                 (((f_0MP - f_0PM) + (f_0PP - f_0MM)) + ((f_M0P - f_P0M) + (f_P0P - f_M0M))) + (f_00P - f_00M)) *
-                oneOverRho;
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //! - Calculate second order moments for interpolation
+    real omega_ = omega;
+    Distributions27 distFine;
+    getPointersToDistributions(distFine, distribution, numberOfLBnodes, isEvenTimestep);
+
+    ListIndices indices;
+
+    //////////////////////////////////////////////////////////////////////////
+    //! - Calculate moments for each source node 
     //!
-    // example: kxxMzz: moment, second derivative in x direction minus the second derivative in z direction
-    kxyFromfcNEQ = -c3o1 * omega *
-                   ((f_MM0 + f_MMM + f_MMP - f_MP0 - f_MPM - f_MPP - f_PM0 - f_PMM - f_PMP + f_PP0 + f_PPM + f_PPP) /
-                    (c1o1 + drho) -
-                    ((velocityX * velocityY)));
-    kyzFromfcNEQ = -c3o1 * omega *
-                   ((f_0MM + f_PMM + f_MMM - f_0MP - f_PMP - f_MMP - f_0PM - f_PPM - f_MPM + f_0PP + f_PPP + f_MPP) /
-                    (c1o1 + drho) -
-                    ((velocityY * velocityZ)));
-    kxzFromfcNEQ = -c3o1 * omega *
-                   ((f_M0M + f_MMM + f_MPM - f_M0P - f_MMP - f_MPP - f_P0M - f_PMM - f_PPM + f_P0P + f_PMP + f_PPP) /
-                    (c1o1 + drho) -
-                    ((velocityX * velocityZ)));
-    kxxMyyFromfcNEQ = -c3o2 * omega *
-                      ((f_M0M + f_M00 + f_M0P - f_0MM - f_0M0 - f_0MP - f_0PM - f_0P0 - f_0PP + f_P0M + f_P00 + f_P0P) /
-                       (c1o1 + drho) -
-                       ((velocityX * velocityX - velocityY * velocityY)));
-    kxxMzzFromfcNEQ = -c3o2 * omega *
-                      ((f_MM0 + f_M00 + f_MP0 - f_0MM - f_0MP - f_00M - f_00P - f_0PM - f_0PP + f_PM0 + f_P00 + f_PP0) /
-                       (c1o1 + drho) -
-                       ((velocityX * velocityX - velocityZ * velocityZ)));
+    //////////////////////////////////////////////////////////////////////////
+    // source node BSW = MMM
+    //////////////////////////////////////////////////////////////////////////
+    // index of the base node and its neighbors
+    unsigned int k_base_000 = indices_MMM[nodeIndex];
+    unsigned int k_base_M00 = neighborX [k_base_000];
+    unsigned int k_base_0M0 = neighborY [k_base_000];
+    unsigned int k_base_00M = neighborZ [k_base_000];
+    unsigned int k_base_MM0 = neighborY [k_base_M00];
+    unsigned int k_base_M0M = neighborZ [k_base_M00];
+    unsigned int k_base_0MM = neighborZ [k_base_0M0];
+    unsigned int k_base_MMM = neighborZ [k_base_MM0];
+    //////////////////////////////////////////////////////////////////////////
+    // Set neighbor indices
+    indices.k_000 = k_base_000;
+    indices.k_M00 = k_base_M00;
+    indices.k_0M0 = k_base_0M0;
+    indices.k_00M = k_base_00M;
+    indices.k_MM0 = k_base_MM0;
+    indices.k_M0M = k_base_M0M;
+    indices.k_0MM = k_base_0MM;
+    indices.k_MMM = k_base_MMM;
+
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    real f_fine[27];
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculateMMM(f_fine, omega_);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node TSW = MMP
+    //////////////////////////////////////////////////////////////////////////
+    // Set neighbor indices - has to be recalculated for the new source node
+    indices.k_000 = indices.k_00M;
+    indices.k_M00 = indices.k_M0M;
+    indices.k_0M0 = indices.k_0MM;
+    indices.k_00M = neighborZ[indices.k_00M];
+    indices.k_MM0 = indices.k_MMM;
+    indices.k_M0M = neighborZ[indices.k_M0M];
+    indices.k_0MM = neighborZ[indices.k_0MM];
+    indices.k_MMM = neighborZ[indices.k_MMM];
+
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculateMMP(f_fine, omega_);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node TSE = PMP
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = indices.k_M00;
+    indices.k_M00 = neighborX[indices.k_M00];
+    indices.k_0M0 = indices.k_MM0;
+    indices.k_00M = indices.k_M0M;
+    indices.k_MM0 = neighborX[indices.k_MM0];
+    indices.k_M0M = neighborX[indices.k_M0M];
+    indices.k_0MM = indices.k_MMM;
+    indices.k_MMM = neighborX[indices.k_MMM];
+
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculatePMP(f_fine, omega_);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node BSE = PMM 
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_00M = indices.k_000;
+    indices.k_M0M = indices.k_M00;
+    indices.k_0MM = indices.k_0M0;
+    indices.k_MMM = indices.k_MM0;
+    indices.k_000 = k_base_M00;
+    indices.k_M00 = neighborX[k_base_M00];
+    indices.k_0M0 = k_base_MM0;
+    indices.k_MM0 = neighborX[k_base_MM0];
+
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculatePMM(f_fine, omega_);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node BNW = MPM
+    //////////////////////////////////////////////////////////////////////////
+    // index of the base node and its neighbors --> indices of all source nodes
+    k_base_000 = k_base_0M0;
+    k_base_M00 = k_base_MM0;
+    k_base_0M0 = neighborY[k_base_0M0];
+    k_base_00M = k_base_0MM;
+    k_base_MM0 = neighborY[k_base_MM0];
+    k_base_M0M = k_base_MMM;
+    k_base_0MM = neighborY[k_base_0MM];
+    k_base_MMM = neighborY[k_base_MMM];
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = k_base_000;
+    indices.k_M00 = k_base_M00;
+    indices.k_0M0 = k_base_0M0;
+    indices.k_00M = k_base_00M;
+    indices.k_MM0 = k_base_MM0;
+    indices.k_M0M = k_base_M0M;
+    indices.k_0MM = k_base_0MM;
+    indices.k_MMM = k_base_MMM;
+
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculateMPM(f_fine, omega_);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node TNW = MPP
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = indices.k_00M;
+    indices.k_M00 = indices.k_M0M;
+    indices.k_0M0 = indices.k_0MM;
+    indices.k_00M = neighborZ[indices.k_00M];
+    indices.k_MM0 = indices.k_MMM;
+    indices.k_M0M = neighborZ[indices.k_M0M];
+    indices.k_0MM = neighborZ[indices.k_0MM];
+    indices.k_MMM = neighborZ[indices.k_MMM];
+
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculateMPP(f_fine, omega_);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node TNE = PPP
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_000 = indices.k_M00;
+    indices.k_M00 = neighborX[indices.k_M00];
+    indices.k_0M0 = indices.k_MM0;
+    indices.k_00M = indices.k_M0M;
+    indices.k_MM0 = neighborX[indices.k_MM0];
+    indices.k_M0M = neighborX[indices.k_M0M];
+    indices.k_0MM = indices.k_MMM;
+    indices.k_MMM = neighborX[indices.k_MMM];
+
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculatePPP(f_fine, omega_);
+
+    //////////////////////////////////////////////////////////////////////////
+    // source node BNE = PPM
+    //////////////////////////////////////////////////////////////////////////
+    // index
+    indices.k_00M = indices.k_000;
+    indices.k_M0M = indices.k_M00;
+    indices.k_0MM = indices.k_0M0;
+    indices.k_MMM = indices.k_MM0;
+    indices.k_000 = k_base_M00;
+    indices.k_M00 = neighborX[k_base_M00];
+    indices.k_0M0 = k_base_MM0;
+    indices.k_MM0 = neighborX[k_base_MM0];
+    
+    omega_ = hasTurbulentViscosity ? calculateOmega(omega, turbulentViscosity[indices.k_000]) : omega;
+
+    read(f_fine, distFine, indices);
+    momentsSet.calculatePPM(f_fine, omega_);
 }
 
-} // namespace vf::gpu
+}
 
 #endif
diff --git a/src/gpu/VirtualFluids_GPU/LBM/LB.h b/src/gpu/VirtualFluids_GPU/LBM/LB.h
index a5ae5f5ceef213e8ec9b2306106035a09b1ffd0d..5da2a2a82c59d9a70e26849d4ee413b7c6e8f1d3 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/LB.h
+++ b/src/gpu/VirtualFluids_GPU/LBM/LB.h
@@ -107,47 +107,59 @@ constexpr std::initializer_list<CollisionTemplate> bulk_CollisionTemplate = { Co
 
 //Interface Cells
 // example of old names (pre 2023) ICellCFC: interpolation from Coarse (C) to Fine (F), indices of the Coarse cells (C)
-typedef struct ICells{
+struct ICells
+{
    uint* fineCellIndices;
    uint* coarseCellIndices;
    uint numberOfCells;
-} InterpolationCells;
+};
+
+using InterpolationCells = ICells;
 
 //! \brief stores location of neighboring cell (necessary for refinement into the wall)
-typedef struct ICellNeigh{
+struct ICellNeigh
+{
    real* x;
    real* y;
    real* z;
-} InterpolationCellNeighbor;
+};
 
-// Distribution functions g 6
-typedef struct  Distri6 { // ADD IN FUTURE RELEASE
+using InterpolationCellNeighbor = ICellNeigh;
+
+// ADD IN FUTURE RELEASE
+struct Distributions6 
+{
    real* g[6];
-} Distributions6;
+};
 
-// Distribution functions f 7
-typedef struct  Distri7{ // ADD IN FUTURE RELEASE
+// ADD IN FUTURE RELEASE
+struct  Distributions7
+{
    real* f[7];
-} Distributions7;
+};
 
-// Distribution functions f 19
-typedef struct  Distri19{ // DEPRECATED
+// DEPRECATED
+struct  Distributions19
+{
    real* f[19];
-} Distributions19;
+};
 
-// Distribution functions f 27
-typedef struct  Distri27{
+struct  Distributions27
+{
    real* f[27];
-} Distributions27, DistributionReferences27;
+};
 
-// Subgrid distances q 27
-typedef struct SubgridDist27{
+using DistributionReferences27 = Distributions27;
+
+struct SubgridDistances27
+{
    real* q[27];
-} SubgridDistances27;
+};
 
 //Q for second order BCs
 //! \struct to manage sub-grid-distances (q) for second order Boundary Conditions (BCs)
-typedef struct QforBC{
+struct QforBoundaryConditions
+{
    int* k;
    int* kN;
    long long* valueQ;
@@ -160,13 +172,15 @@ typedef struct QforBC{
    real *Vx1,     *Vy1,     *Vz1;
    real *deltaVz, *RhoBC;
    real *normalX, *normalY, *normalZ;
-}QforBoundaryConditions;
+};
 
-typedef struct QforPrecursorBC{
+struct QforPrecursorBoundaryConditions
+{
    int* k;
    int numberOfBCnodes=0;
    int sizeQ;
    int numberOfPrecursorNodes=0;
+   uint streamIndex=0;
    uint nPrecursorReads=0;
    uint timeStepsBetweenReads;
    size_t numberOfQuantities;
@@ -175,34 +189,38 @@ typedef struct QforPrecursorBC{
    real* weights0PP, *weights0PM, *weights0MP,  *weights0MM;
    real* last, *current, *next;
    real velocityX, velocityY, velocityZ;
-}QforPrecursorBoundaryConditions;
+};
 
-//BCTemp
-typedef struct TempforBC{  // ADD IN FUTURE RELEASE
+// ADD IN FUTURE RELEASE
+struct TempforBoundaryConditions
+{
    int* k;
    real* temp;
    int kTemp=0;
-}TempforBoundaryConditions;
+};
 
-//BCTempVel
-typedef struct TempVelforBC{  // ADD IN FUTURE RELEASE
+// ADD IN FUTURE RELEASE
+struct TempVelforBoundaryConditions
+{
    int* k;
    real* temp;
    real* tempPulse;
    real* velo;
    int kTemp=0;
-}TempVelforBoundaryConditions;
+};
 
-//BCTempPress
-typedef struct TempPressforBC{  // ADD IN FUTURE RELEASE
+// ADD IN FUTURE RELEASE
+struct TempPressforBoundaryConditions
+{
    int* k;
    real* temp;
    real* velo;
    int kTemp=0;
-}TempPressforBoundaryConditions;
+};
 
 // Settings for wall model used in StressBC
-typedef struct WMparas{
+struct WallModelParameters
+{
    real* z0;
    int* samplingOffset;
    bool hasMonitor;
@@ -210,11 +228,12 @@ typedef struct WMparas{
    real* Fx;
    real* Fy;
    real* Fz;
-}WallModelParameters;
+};
 
 
-//measurePoints
-typedef struct MeasP{ // ADD IN FUTURE RELEASE
+// ADD IN FUTURE RELEASE
+struct MeasurePoints
+{
    std::string name;
    uint k;
    std::vector<real> Vx;
@@ -225,10 +244,11 @@ typedef struct MeasP{ // ADD IN FUTURE RELEASE
    //real* Vy;
    //real* Vz;
    //real* Rho;
-}MeasurePoints;
+};
+
 
-//Process Neighbors
-typedef struct PN27{
+struct ProcessNeighbor27
+{
    real* f[27];
    uint memsizeFs;
    int* index;
@@ -236,9 +256,11 @@ typedef struct PN27{
    uint rankNeighbor;
    int numberOfNodes;
    int numberOfFs;
-}ProcessNeighbor27;
+};
 
-typedef struct PN_F3 { // ADD IN FUTURE RELEASE
+// ADD IN FUTURE RELEASE
+struct ProcessNeighborF3
+{
    real* g[6];
    uint memsizeGs;
    int* index;
@@ -246,10 +268,11 @@ typedef struct PN_F3 { // ADD IN FUTURE RELEASE
    uint rankNeighbor;
    int numberOfNodes;
    int numberOfGs;
-}ProcessNeighborF3;
+};
 
-//path line particles // DEPRECATED
-typedef struct PLP{
+// DEPRECATED
+struct PathLineParticles
+{
    bool *stuck, *hot;
    real *coordXabsolut, *coordYabsolut, *coordZabsolut;
    real *coordXlocal,   *coordYlocal,   *coordZlocal;
@@ -260,13 +283,12 @@ typedef struct PLP{
    uint *cellBaseID;
    uint numberOfParticles, numberOfTimestepsParticles;
    uint memSizeID, memSizeTimestep, memSizerealAll, memSizereal, memSizeBool, memSizeBoolBC;
-}PathLineParticles;
+};
 
 //////////////////////////////////////////////////////////////////////////
 // DEPRECATED
-inline int vectorPosition(int i, int j, int k, int Lx, int Ly )
+inline int vectorPosition(int i, int j, int k, int Lx, int Ly)
 {
-   //return((j+15)*(Lx+2*16)+(i+15));
    return((Lx+2*STARTOFFX)*((Ly+2*STARTOFFY)*(k+STARTOFFZ)+(j+STARTOFFY))+(i+STARTOFFX));
 }
 //////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp b/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
index 55c0250223901a94d03bd1e65bbb72438bcc99c3..dddc795ccda96b49a03373c05a701f32662e9565 100644
--- a/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
+++ b/src/gpu/VirtualFluids_GPU/LBM/Simulation.cpp
@@ -139,9 +139,8 @@ void Simulation::init(GridProvider &gridProvider, BoundaryConditionFactory *bcFa
     //////////////////////////////////////////////////////////////////////////
     // CUDA streams
     if (para->getUseStreams()) {
-        para->getStreamManager()->registerStream(CudaStreamIndex::SubDomainBorder);
-        para->getStreamManager()->registerStream(CudaStreamIndex::Bulk);
-        para->getStreamManager()->launchStreams();
+        para->getStreamManager()->registerAndLaunchStream(CudaStreamIndex::SubDomainBorder);
+        para->getStreamManager()->registerAndLaunchStream(CudaStreamIndex::Bulk);
         para->getStreamManager()->createCudaEvents();
     }
     //////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
index cb8cefa389c141b7f38bbc54a68d8cf9841ba699..e28c802429c1703314c59402e2d4d490388b8ce1 100644
--- a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
@@ -8,7 +8,7 @@
 #include "FileWriter.h"
 #include <logger/Logger.h>
 
-#include <stdio.h>
+#include <cstdio>
 #include <fstream>
 #include <sstream>
 #include <cmath>
@@ -23,6 +23,37 @@
 
 #include <basics/writer/WbWriterVtkXmlBinary.h>
 
+std::string makePartFileNameEnding(int level, int ID, int part, int timestep)
+{
+    return "_lev_" + StringUtil::toString<int>(level) + "_ID_" + StringUtil::toString<int>(ID) + "_Part_" + StringUtil::toString<int>(part) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk";
+}
+
+std::string makeCollectionFileNameEnding(int ID, int timestep)
+{
+    return "_ID_" + StringUtil::toString<int>(ID) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk";
+}
+
+std::string makePartFileName(const std::string &prefix, int level, int ID, int part, int timestep)
+{
+    return prefix + "_bin" + makePartFileNameEnding(level, ID, part, timestep);
+}
+
+std::string makeMedianPartFileName(const std::string &prefix, int level, int ID, int part, int timestep)
+{
+    return prefix + "_bin_median" + makePartFileNameEnding(level, ID, part, timestep);
+}
+
+
+std::string makeCollectionFileName(const std::string &prefix, int ID, int timestep)
+{
+    return prefix + "_bin" + makeCollectionFileNameEnding(ID, timestep);
+}
+
+std::string makeMedianCollectionFileName(const std::string &prefix, int ID, int timestep)
+{
+    return prefix + "_bin_median" + makeCollectionFileNameEnding(ID, timestep);
+}
+
 void FileWriter::writeInit(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> cudaMemoryManager)
 {
     unsigned int timestep = para->getTimestepInit();
@@ -50,30 +81,29 @@ void FileWriter::writeTimestep(std::shared_ptr<Parameter> para, unsigned int tim
 
 void FileWriter::writeTimestep(std::shared_ptr<Parameter> para, unsigned int timestep, int level)
 {
-    const unsigned int numberOfParts = (uint)para->getParH(level)->numberOfNodes / para->getlimitOfNodesForVTK() + 1;
-    std::vector<std::string> fname;
-    std::vector<std::string> fnameMed;
+    const unsigned int numberOfParts = (uint)para->getParH(level)->numberOfNodes / para->getLimitOfNodesForVTK() + 1;
+    std::vector<std::string> fnames;
+    std::vector<std::string> fnamesMed;
 
     for (unsigned int i = 1; i <= numberOfParts; i++)
     {
-        fname.push_back(para->getFName() + "_bin_lev_" + StringUtil::toString<int>(level) + "_ID_" + StringUtil::toString<int>(para->getMyProcessID()) + "_Part_" + StringUtil::toString<int>(i) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk");
-        fnameMed.push_back(para->getFName() + "_bin_median_lev_" + StringUtil::toString<int>(level) + "_ID_" + StringUtil::toString<int>(para->getMyProcessID()) + "_Part_" + StringUtil::toString<int>(i) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk");
+        std::string fname = makePartFileName(para->getFName(), level, para->getMyProcessID(), i, timestep); 
+        std::string fnameMed = makeMedianPartFileName(para->getFName(), level, para->getMyProcessID(), i, timestep); 
 
-        this->fileNamesForCollectionFile.push_back( fname.back() );
-        this->fileNamesForCollectionFileMedian.push_back( fnameMed.back() );
+        fnames.push_back(fname);
+        fnamesMed.push_back(fnameMed);
     }
 
-    if (para->getDiffOn() == true)
-        writeUnstrucuredGridLTConc(para, level, fname);
-    else
-        writeUnstrucuredGridLT(para, level, fname);
+    std::vector<std::string> fnamesLong = writeUnstructuredGridLT(para, level, fnames);
+    for(auto fname : fnamesLong)
+        this->fileNamesForCollectionFile.push_back(fname.substr( fname.find_last_of('/') + 1 ));
+
 
     if (para->getCalcMedian())
     {
-        if (para->getDiffOn() == true)
-            writeUnstrucuredGridMedianLTConc(para, level, fnameMed);
-        else
-            writeUnstrucuredGridMedianLT(para, level, fnameMed);
+        std::vector<std::string> fnamesMedianLong = writeUnstructuredGridMedianLT(para, level, fnamesMed);
+        for(auto fname : fnamesMedianLong)
+            this->fileNamesForCollectionFileMedian.push_back(fname.substr( fname.find_last_of('/') + 1 ));
     }
 }
 
@@ -84,194 +114,169 @@ bool FileWriter::isPeriodicCell(std::shared_ptr<Parameter> para, int level, unsi
            (para->getParH(level)->coordinateZ[number5] < para->getParH(level)->coordinateZ[number1]);
 }
 
-void VIRTUALFLUIDS_GPU_EXPORT FileWriter::writeCollectionFile(std::shared_ptr<Parameter> para, unsigned int timestep)
+std::vector<std::string> FileWriter::getNodeDataNames(std::shared_ptr<Parameter> para)
 {
 
-    std::string filename = para->getFName() + "_bin_ID_" + StringUtil::toString<int>(para->getMyProcessID()) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk";
-
-    std::ofstream file;
-
-    file.open( filename + ".pvtu" );
-
-    //////////////////////////////////////////////////////////////////////////
-    file << "<?xml version=\"1.0\"?>" << std::endl;
-    file << "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << std::endl;
-    file << "  <PUnstructuredGrid GhostLevel=\"1\">" << std::endl;
+    std::vector<std::string> nodeDataNames;
+    nodeDataNames.push_back("press");
+    nodeDataNames.push_back("rho");
+    nodeDataNames.push_back("vx1");
+    nodeDataNames.push_back("vx2");
+    nodeDataNames.push_back("vx3");
+    nodeDataNames.push_back("geo");
 
-    file << "    <PPointData>" << std::endl;
-    file << "       <PDataArray type=\"Float64\" Name=\"press\" /> " << std::endl;
-    file << "       <PDataArray type=\"Float64\" Name=\"rho\"   /> " << std::endl;
-    file << "       <PDataArray type=\"Float64\" Name=\"vx1\"   /> " << std::endl;
-    file << "       <PDataArray type=\"Float64\" Name=\"vx2\"   /> " << std::endl;
-    file << "       <PDataArray type=\"Float64\" Name=\"vx3\"   /> " << std::endl;
-    file << "       <PDataArray type=\"Float64\" Name=\"geo\"   /> " << std::endl;
-    if( para->getDiffOn() ) file << "       <PDataArray type=\"Float64\" Name=\"conc\"  /> " << std::endl;
-    file << "    </PPointData>" << std::endl;
+    if(para->getDiffOn()) 
+        nodeDataNames.push_back("conc");
 
-    file << "    <PPoints>" << std::endl;
-    file << "      <PDataArray type=\"Float32\" Name=\"Points\" NumberOfComponents=\"3\"/>" << std::endl;
-    file << "    </PPoints>" << std::endl;
-
-    for( auto& fname : this->fileNamesForCollectionFile )
+    if(para->getIsBodyForce())
     {
-        const auto filenameWithoutPath=fname.substr( fname.find_last_of('/') + 1 );
-        file << "    <Piece Source=\"" << filenameWithoutPath << ".bin.vtu\"/>" << std::endl;
+        nodeDataNames.push_back("Fx");
+        nodeDataNames.push_back("Fy");
+        nodeDataNames.push_back("Fz");
     }
 
-    file << "  </PUnstructuredGrid>" << std::endl;
-    file << "</VTKFile>" << std::endl;
+    if(para->getUseTurbulentViscosity())
+    {
+        nodeDataNames.push_back("nut");
+    }
 
-    //////////////////////////////////////////////////////////////////////////
+    if (para->getCalcTurbulenceIntensity()) {
+        nodeDataNames.push_back("vxx");
+        nodeDataNames.push_back("vyy");
+        nodeDataNames.push_back("vzz");
+        nodeDataNames.push_back("vxy");
+        nodeDataNames.push_back("vxz");
+        nodeDataNames.push_back("vyz");
+    }
+    return nodeDataNames;
+}
 
-    file.close();
+std::vector<std::string> FileWriter::getMedianNodeDataNames(std::shared_ptr<Parameter> para)
+{
+    std::vector<std::string> nodeDataNames;
+    
+    if(para->getDiffOn()) 
+        nodeDataNames.push_back("conc");
+    nodeDataNames.push_back("pressMed");
+    nodeDataNames.push_back("rhoMed");
+    nodeDataNames.push_back("vx1Med");
+    nodeDataNames.push_back("vx2Med");
+    nodeDataNames.push_back("vx3Med");
+    nodeDataNames.push_back("geo");
+
+    return nodeDataNames;
+}
 
+std::string VIRTUALFLUIDS_GPU_EXPORT FileWriter::writeCollectionFile(std::shared_ptr<Parameter> para, unsigned int timestep)
+{
+    std::string filename = makeCollectionFileName(para->getFName(), para->getMyProcessID(), timestep);
+    auto nodeDataNames = this->getNodeDataNames(para);
+    std::vector<std::string> cellDataNames;
+    std::string pFileName= WbWriterVtkXmlBinary::getInstance()->writeParallelFile(filename, this->fileNamesForCollectionFile, nodeDataNames, cellDataNames);
     this->fileNamesForCollectionFile.clear();
+    return pFileName;
 }
 
-void VIRTUALFLUIDS_GPU_EXPORT FileWriter::writeCollectionFileMedian(std::shared_ptr<Parameter> para, unsigned int timestep)
+std::string VIRTUALFLUIDS_GPU_EXPORT FileWriter::writeCollectionFileMedian(std::shared_ptr<Parameter> para, unsigned int timestep)
 {
-
-    std::string filename = para->getFName() + "_bin_median_ID_" + StringUtil::toString<int>(para->getMyProcessID()) + "_t_" + StringUtil::toString<int>(timestep) + ".vtk";
-
-    std::ofstream file;
-
-    file.open( filename + ".pvtu" );
-
-    //////////////////////////////////////////////////////////////////////////
-
-    file << "<VTKFile type=\"PUnstructuredGrid\" version=\"1.0\" byte_order=\"LittleEndian\" header_type=\"UInt64\">" << std::endl;
-    file << "  <PUnstructuredGrid GhostLevel=\"1\">" << std::endl;
-
-    file << "    <PPointData>" << std::endl;
-    if( para->getDiffOn() ) file << "       <DataArray type=\"Float32\" Name=\"concMed\"  /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"pressMed\" /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"rhoMed\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"vx1Med\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"vx2Med\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"vx3Med\"   /> " << std::endl;
-    file << "       <DataArray type=\"Float32\" Name=\"geo\"   /> " << std::endl;
-    file << "    </PPointData>" << std::endl;
-
-    file << "    <PPoints>" << std::endl;
-    file << "      <PDataArray type=\"Float32\" Name=\"Points\" NumberOfComponents=\"3\"/>" << std::endl;
-    file << "    </PPoints>" << std::endl;
-
-    for( auto& fname : this->fileNamesForCollectionFileMedian )
-    {
-        const auto filenameWithoutPath=fname.substr( fname.find_last_of('/') + 1 );
-        file << "    <Piece Source=\"" << filenameWithoutPath << ".bin.vtu\"/>" << std::endl;
-    }
-
-    file << "  </PUnstructuredGrid>" << std::endl;
-    file << "</VTKFile>" << std::endl;
-
-    //////////////////////////////////////////////////////////////////////////
-
-    file.close();
-
+    std::string filename = makeMedianCollectionFileName(para->getFName(), para->getMyProcessID(), timestep);
+    std::vector<std::string> nodeDataNames = getMedianNodeDataNames(para);
+    std::vector<std::string> cellDataNames;
+    std::string pFileName =  WbWriterVtkXmlBinary::getInstance()->writeParallelFile(filename, this->fileNamesForCollectionFileMedian, nodeDataNames, cellDataNames);
     this->fileNamesForCollectionFileMedian.clear();
+    return pFileName;
 }
 
-void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
+std::vector<std::string> FileWriter::writeUnstructuredGridLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
 {
     std::vector< UbTupleFloat3 > nodes;
     std::vector< UbTupleUInt8 > cells;
-    std::vector< std::string > nodedatanames;
-    nodedatanames.push_back("press");
-    nodedatanames.push_back("rho");
-    nodedatanames.push_back("vx1");
-    nodedatanames.push_back("vx2");
-    nodedatanames.push_back("vx3");
-    nodedatanames.push_back("geo");
+    std::vector< std::string > nodeDataNames = getNodeDataNames(para);
+
+    std::vector< std::string > outFNames;
+
+    uint dataIndex = 6;
+
+    uint firstConcNode = dataIndex;
+    if(para->getDiffOn()) dataIndex++;
     
-    uint firstBodyForceNode = (uint) nodedatanames.size();
-    if(para->getIsBodyForce())
-    {
-        nodedatanames.push_back("Fx");
-        nodedatanames.push_back("Fy");
-        nodedatanames.push_back("Fz");
-    }
+    uint firstBodyForceNode = dataIndex;
+    if(para->getIsBodyForce()) dataIndex+=3;
 
-    uint firstNutNode = (uint) nodedatanames.size();
-    if(para->getUseTurbulentViscosity())
-    {
-        nodedatanames.push_back("nut");
-    }
+    uint firstNutNode = dataIndex;
+    if(para->getUseTurbulentViscosity()) dataIndex++;
 
-    uint firstTurbNode = (uint) nodedatanames.size();
-    if (para->getCalcTurbulenceIntensity()) {
-        nodedatanames.push_back("vxx");
-        nodedatanames.push_back("vyy");
-        nodedatanames.push_back("vzz");
-        nodedatanames.push_back("vxy");
-        nodedatanames.push_back("vxz");
-        nodedatanames.push_back("vyz");
-    }
+    uint firstTurbulenceNode = dataIndex;
+    if (para->getCalcTurbulenceIntensity()) dataIndex += 6;
     unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
     uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
     bool neighborsAreFluid;
-    unsigned int startpos = 0;
-    unsigned int endpos = 0;
-    unsigned int sizeOfNodes = 0;
-    std::vector< std::vector< double > > nodedata(nodedatanames.size());
+    unsigned int startPosition;
+    unsigned int endPosition;
+    unsigned int sizeOfNodes;
+    std::vector< std::vector< double > > nodeData(nodeDataNames.size());
 
     for (unsigned int part = 0; part < fname.size(); part++)
     {
-        if (((part + 1)*para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
-            sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+        if (((part + 1)*para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
         else
-            sizeOfNodes = para->getlimitOfNodesForVTK();
+            sizeOfNodes = para->getLimitOfNodesForVTK();
 
         //////////////////////////////////////////////////////////////////////////
-        startpos = part * para->getlimitOfNodesForVTK();
-        endpos = startpos + sizeOfNodes;
+        startPosition = part * para->getLimitOfNodesForVTK();
+        endPosition = startPosition + sizeOfNodes;
         //////////////////////////////////////////////////////////////////////////
         cells.clear();
         nodes.resize(sizeOfNodes);
-        for (uint i = 0; i < (uint)nodedatanames.size(); i++)
-            nodedata[i].resize(sizeOfNodes);
+        for (uint i = 0; i < (uint)nodeDataNames.size(); i++)
+            nodeData[i].resize(sizeOfNodes);
 
         //////////////////////////////////////////////////////////////////////////
-        for (unsigned int pos = startpos; pos < endpos; pos++)
+        for (unsigned int pos = startPosition; pos < endPosition; pos++)
         {
             if (para->getParH(level)->typeOfGridNode[pos] == GEO_FLUID)
             {
+
                 //////////////////////////////////////////////////////////////////////////
                 double x1 = para->getParH(level)->coordinateX[pos];
                 double x2 = para->getParH(level)->coordinateY[pos];
                 double x3 = para->getParH(level)->coordinateZ[pos];
                 //////////////////////////////////////////////////////////////////////////
                 number1 = pos;
-                dn1 = pos - startpos;
+                dn1 = pos - startPosition;
                 neighborsAreFluid = true;
                 //////////////////////////////////////////////////////////////////////////
                 nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
-                nodedata[0][dn1] = (double)para->getParH(level)->pressure[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
-                nodedata[1][dn1] = (double)para->getParH(level)->rho[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
-                nodedata[2][dn1] = (double)para->getParH(level)->velocityX[pos] * (double)para->getVelocityRatio();
-                nodedata[3][dn1] = (double)para->getParH(level)->velocityY[pos] * (double)para->getVelocityRatio();
-                nodedata[4][dn1] = (double)para->getParH(level)->velocityZ[pos] * (double)para->getVelocityRatio();
-                nodedata[5][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
+                nodeData[0][dn1] = (double)para->getParH(level)->pressure[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
+                nodeData[1][dn1] = (double)para->getParH(level)->rho[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
+                nodeData[2][dn1] = (double)para->getParH(level)->velocityX[pos] * (double)para->getVelocityRatio();
+                nodeData[3][dn1] = (double)para->getParH(level)->velocityY[pos] * (double)para->getVelocityRatio();
+                nodeData[4][dn1] = (double)para->getParH(level)->velocityZ[pos] * (double)para->getVelocityRatio();
+                nodeData[5][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
+
+                if(para->getDiffOn())
+                    nodeData[firstConcNode][dn1] = (double)para->getParH(level)->concentration[pos];
 
                 if(para->getIsBodyForce())
                 {
-                    nodedata[firstBodyForceNode    ][dn1] = (double)para->getParH(level)->forceX_SP[pos] * (double)para->getScaledForceRatio(level);
-                    nodedata[firstBodyForceNode + 1][dn1] = (double)para->getParH(level)->forceY_SP[pos] * (double)para->getScaledForceRatio(level);
-                    nodedata[firstBodyForceNode + 2][dn1] = (double)para->getParH(level)->forceZ_SP[pos] * (double)para->getScaledForceRatio(level);
+                    nodeData[firstBodyForceNode    ][dn1] = (double)para->getParH(level)->forceX_SP[pos] * (double)para->getScaledForceRatio(level);
+                    nodeData[firstBodyForceNode + 1][dn1] = (double)para->getParH(level)->forceY_SP[pos] * (double)para->getScaledForceRatio(level);
+                    nodeData[firstBodyForceNode + 2][dn1] = (double)para->getParH(level)->forceZ_SP[pos] * (double)para->getScaledForceRatio(level);
                 }
 
                 if(para->getUseTurbulentViscosity())
                 {
-                    nodedata[firstNutNode][dn1] = (double)para->getParH(level)->turbViscosity[pos] * (double)para->getScaledViscosityRatio(level);
+                    nodeData[firstNutNode][dn1] = (double)para->getParH(level)->turbViscosity[pos] * (double)para->getScaledViscosityRatio(level);
                 }
 
                 if (para->getCalcTurbulenceIntensity()) {
-                    nodedata[firstTurbNode    ][dn1] = (double)para->getParH(level)->vxx[pos];
-                    nodedata[firstTurbNode + 1][dn1] = (double)para->getParH(level)->vyy[pos];
-                    nodedata[firstTurbNode + 2][dn1] = (double)para->getParH(level)->vzz[pos];
-                    nodedata[firstTurbNode + 3][dn1] = (double)para->getParH(level)->vxy[pos];
-                    nodedata[firstTurbNode + 4][dn1] = (double)para->getParH(level)->vxz[pos];
-                    nodedata[firstTurbNode + 5][dn1] = (double)para->getParH(level)->vyz[pos];
+                    nodeData[firstTurbulenceNode    ][dn1] = (double)para->getParH(level)->vxx[pos];
+                    nodeData[firstTurbulenceNode + 1][dn1] = (double)para->getParH(level)->vyy[pos];
+                    nodeData[firstTurbulenceNode + 2][dn1] = (double)para->getParH(level)->vzz[pos];
+                    nodeData[firstTurbulenceNode + 3][dn1] = (double)para->getParH(level)->vxy[pos];
+                    nodeData[firstTurbulenceNode + 4][dn1] = (double)para->getParH(level)->vxz[pos];
+                    nodeData[firstTurbulenceNode + 5][dn1] = (double)para->getParH(level)->vyz[pos];
                 }
 
                 //////////////////////////////////////////////////////////////////////////
@@ -291,21 +296,21 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
                     para->getParH(level)->typeOfGridNode[number7] != GEO_FLUID ||
                     para->getParH(level)->typeOfGridNode[number8] != GEO_FLUID)  neighborsAreFluid = false;
                 //////////////////////////////////////////////////////////////////////////
-                if (number2 > endpos ||
-                    number3 > endpos ||
-                    number4 > endpos ||
-                    number5 > endpos ||
-                    number6 > endpos ||
-                    number7 > endpos ||
-                    number8 > endpos)  neighborsAreFluid = false;
-                //////////////////////////////////////////////////////////////////////////
-                dn2 = number2 - startpos;
-                dn3 = number3 - startpos;
-                dn4 = number4 - startpos;
-                dn5 = number5 - startpos;
-                dn6 = number6 - startpos;
-                dn7 = number7 - startpos;
-                dn8 = number8 - startpos;
+                if (number2 > endPosition ||
+                    number3 > endPosition ||
+                    number4 > endPosition ||
+                    number5 > endPosition ||
+                    number6 > endPosition ||
+                    number7 > endPosition ||
+                    number8 > endPosition)  neighborsAreFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                dn2 = number2 - startPosition;
+                dn3 = number3 - startPosition;
+                dn4 = number4 - startPosition;
+                dn5 = number5 - startPosition;
+                dn6 = number6 - startPosition;
+                dn7 = number7 - startPosition;
+                dn8 = number8 - startPosition;
                 //////////////////////////////////////////////////////////////////////////
                 if (isPeriodicCell(para, level, number2, number1, number3, number5))
                     continue;
@@ -314,164 +319,53 @@ void FileWriter::writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int lev
                     cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
             }
         }
-        WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
+        outFNames.push_back( WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodeDataNames, nodeData) );
     }
+    return outFNames;
 }
 
-void FileWriter::writeUnstrucuredGridLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
+std::vector<std::string> FileWriter::writeUnstructuredGridMedianLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
 {
-    std::vector< UbTupleFloat3 > nodes;
-    std::vector< UbTupleUInt8 > cells;
-    std::vector< std::string > nodedatanames;
-    nodedatanames.push_back("press");
-    nodedatanames.push_back("rho");
-    nodedatanames.push_back("vx1");
-    nodedatanames.push_back("vx2");
-    nodedatanames.push_back("vx3");
-    nodedatanames.push_back("geo");
-    nodedatanames.push_back("conc");
-    unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
-    uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
-    bool neighborsAreFluid;
-    unsigned int startpos = 0;
-    unsigned int endpos = 0;
-    unsigned int sizeOfNodes = 0;
-    std::vector< std::vector< double > > nodedata(nodedatanames.size());
+    std::vector< std::string > outFNames;
 
-    for (unsigned int part = 0; part < fname.size(); part++)
-    {
-        if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
-            sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
-        else
-            sizeOfNodes = para->getlimitOfNodesForVTK();
-
-        //////////////////////////////////////////////////////////////////////////
-        startpos = part * para->getlimitOfNodesForVTK();
-        endpos = startpos + sizeOfNodes;
-        //////////////////////////////////////////////////////////////////////////
-        cells.clear();
-        nodes.resize(sizeOfNodes);
-        nodedata[0].resize(sizeOfNodes);
-        nodedata[1].resize(sizeOfNodes);
-        nodedata[2].resize(sizeOfNodes);
-        nodedata[3].resize(sizeOfNodes);
-        nodedata[4].resize(sizeOfNodes);
-        nodedata[5].resize(sizeOfNodes);
-        nodedata[6].resize(sizeOfNodes);
-        //////////////////////////////////////////////////////////////////////////
-        for (unsigned int pos = startpos; pos < endpos; pos++)
-        {
-            if (para->getParH(level)->typeOfGridNode[pos] == GEO_FLUID)
-            {
-                //////////////////////////////////////////////////////////////////////////
-                double x1 = para->getParH(level)->coordinateX[pos];
-                double x2 = para->getParH(level)->coordinateY[pos];
-                double x3 = para->getParH(level)->coordinateZ[pos];
-                //////////////////////////////////////////////////////////////////////////
-                number1 = pos;
-                dn1 = pos - startpos;
-                neighborsAreFluid = true;
-                //////////////////////////////////////////////////////////////////////////
-                nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
-                nodedata[0][dn1] = (double)para->getParH(level)->pressure[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
-                nodedata[1][dn1] = (double)para->getParH(level)->rho[pos] / (double)3.0 * (double)para->getDensityRatio() * (double)para->getVelocityRatio() * (double)para->getVelocityRatio();
-                nodedata[2][dn1] = (double)para->getParH(level)->velocityX[pos] * (double)para->getVelocityRatio();
-                nodedata[3][dn1] = (double)para->getParH(level)->velocityY[pos] * (double)para->getVelocityRatio();
-                nodedata[4][dn1] = (double)para->getParH(level)->velocityZ[pos] * (double)para->getVelocityRatio();
-                nodedata[5][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
-                nodedata[6][dn1] = (double)para->getParH(level)->concentration[pos];
-                //////////////////////////////////////////////////////////////////////////
-                number2 = para->getParH(level)->neighborX[number1];
-                number3 = para->getParH(level)->neighborY[number2];
-                number4 = para->getParH(level)->neighborY[number1];
-                number5 = para->getParH(level)->neighborZ[number1];
-                number6 = para->getParH(level)->neighborZ[number2];
-                number7 = para->getParH(level)->neighborZ[number3];
-                number8 = para->getParH(level)->neighborZ[number4];
-                //////////////////////////////////////////////////////////////////////////
-                if (para->getParH(level)->typeOfGridNode[number2] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number3] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number4] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number5] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number6] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number7] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number8] != GEO_FLUID)  neighborsAreFluid = false;
-                //////////////////////////////////////////////////////////////////////////
-                if (number2 > endpos ||
-                    number3 > endpos ||
-                    number4 > endpos ||
-                    number5 > endpos ||
-                    number6 > endpos ||
-                    number7 > endpos ||
-                    number8 > endpos)  neighborsAreFluid = false;
-                //////////////////////////////////////////////////////////////////////////
-                dn2 = number2 - startpos;
-                dn3 = number3 - startpos;
-                dn4 = number4 - startpos;
-                dn5 = number5 - startpos;
-                dn6 = number6 - startpos;
-                dn7 = number7 - startpos;
-                dn8 = number8 - startpos;
-                //////////////////////////////////////////////////////////////////////////
-                if (isPeriodicCell(para, level, number2, number1, number3, number5))
-                    continue;
-                //////////////////////////////////////////////////////////////////////////
-                if (neighborsAreFluid)
-                    cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
-            }
-        }
-        WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
-    }
-}
-
-void FileWriter::writeUnstrucuredGridMedianLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
-{
     std::vector< UbTupleFloat3 > nodes;
     std::vector< UbTupleUInt8 > cells;
     //std::vector< UbTupleUInt8 > cells2;
-    std::vector< std::string > nodedatanames;
-    nodedatanames.push_back("pressMed");
-    nodedatanames.push_back("rhoMed");
-    nodedatanames.push_back("vx1Med");
-    nodedatanames.push_back("vx2Med");
-    nodedatanames.push_back("vx3Med");
-    nodedatanames.push_back("geo");
+    std::vector< std::string > nodeDataNames = getMedianNodeDataNames(para);
+    int startIndex = para->getDiffOn()? 1 : 0;
+
     unsigned int number1, number2, number3, number4, number5, number6, number7, number8;
     unsigned int dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
     bool neighborsFluid;
-    unsigned int startpos = 0;
-    unsigned int endpos = 0;
-    unsigned int sizeOfNodes = 0;
-    std::vector< std::vector< double > > nodedata(nodedatanames.size());
+    unsigned int startPosition;
+    unsigned int endPosition;
+    unsigned int sizeOfNodes;
+    std::vector< std::vector< double > > nodeData(nodeDataNames.size());
 
     //printf("\n test for if... \n");
     for (unsigned int part = 0; part < fname.size(); part++)
     {
         //printf("\n test in if I... \n");
         //////////////////////////////////////////////////////////////////////////
-        if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+        if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
         {
-            sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+            sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
         }
         else
         {
-            sizeOfNodes = para->getlimitOfNodesForVTK();
+            sizeOfNodes = para->getLimitOfNodesForVTK();
         }
         //////////////////////////////////////////////////////////////////////////
-        startpos = part * para->getlimitOfNodesForVTK();
-        endpos = startpos + sizeOfNodes;
+        startPosition = part * para->getLimitOfNodesForVTK();
+        endPosition = startPosition + sizeOfNodes;
         //////////////////////////////////////////////////////////////////////////
         cells.clear();
         nodes.resize(sizeOfNodes);
-        nodedata[0].resize(sizeOfNodes);
-        nodedata[1].resize(sizeOfNodes);
-        nodedata[2].resize(sizeOfNodes);
-        nodedata[3].resize(sizeOfNodes);
-        nodedata[4].resize(sizeOfNodes);
-        nodedata[5].resize(sizeOfNodes);
+        for (size_t i = 0; i < nodeDataNames.size(); i++)
+            nodeData[i].resize(sizeOfNodes);
         //////////////////////////////////////////////////////////////////////////
         //printf("\n test in if II... \n");
-        for (unsigned int pos = startpos; pos < endpos; pos++)
+        for (unsigned int pos = startPosition; pos < endPosition; pos++)
         {
             if (para->getParH(level)->typeOfGridNode[pos] == GEO_FLUID)
             {
@@ -481,16 +375,18 @@ void FileWriter::writeUnstrucuredGridMedianLT(std::shared_ptr<Parameter> para, i
                 double x3 = para->getParH(level)->coordinateZ[pos];
                 //////////////////////////////////////////////////////////////////////////
                 number1 = pos;
-                dn1 = pos - startpos;
+                dn1 = pos - startPosition;
                 neighborsFluid = true;
                 //////////////////////////////////////////////////////////////////////////
                 nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
-                nodedata[0][dn1] = para->getParH(level)->press_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-                nodedata[1][dn1] = para->getParH(level)->rho_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-                nodedata[2][dn1] = para->getParH(level)->vx_SP_Med_Out[pos] * para->getVelocityRatio();
-                nodedata[3][dn1] = para->getParH(level)->vy_SP_Med_Out[pos] * para->getVelocityRatio();
-                nodedata[4][dn1] = para->getParH(level)->vz_SP_Med_Out[pos] * para->getVelocityRatio();
-                nodedata[5][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
+                if(para->getDiffOn())
+                    nodeData[0][dn1] = (double)para->getParH(level)->Conc_Med_Out[pos];
+                nodeData[startIndex    ][dn1] = para->getParH(level)->press_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
+                nodeData[startIndex + 1][dn1] = para->getParH(level)->rho_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
+                nodeData[startIndex + 2][dn1] = para->getParH(level)->vx_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodeData[startIndex + 3][dn1] = para->getParH(level)->vy_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodeData[startIndex + 4][dn1] = para->getParH(level)->vz_SP_Med_Out[pos] * para->getVelocityRatio();
+                nodeData[startIndex + 5][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
                 //////////////////////////////////////////////////////////////////////////
                 number2 = para->getParH(level)->neighborX[number1];
                 number3 = para->getParH(level)->neighborY[number2];
@@ -508,21 +404,21 @@ void FileWriter::writeUnstrucuredGridMedianLT(std::shared_ptr<Parameter> para, i
                     para->getParH(level)->typeOfGridNode[number7] != GEO_FLUID ||
                     para->getParH(level)->typeOfGridNode[number8] != GEO_FLUID)  neighborsFluid = false;
                 //////////////////////////////////////////////////////////////////////////
-                if (number2 > endpos ||
-                    number3 > endpos ||
-                    number4 > endpos ||
-                    number5 > endpos ||
-                    number6 > endpos ||
-                    number7 > endpos ||
-                    number8 > endpos)  neighborsFluid = false;
-                //////////////////////////////////////////////////////////////////////////
-                dn2 = number2 - startpos;
-                dn3 = number3 - startpos;
-                dn4 = number4 - startpos;
-                dn5 = number5 - startpos;
-                dn6 = number6 - startpos;
-                dn7 = number7 - startpos;
-                dn8 = number8 - startpos;
+                if (number2 > endPosition ||
+                    number3 > endPosition ||
+                    number4 > endPosition ||
+                    number5 > endPosition ||
+                    number6 > endPosition ||
+                    number7 > endPosition ||
+                    number8 > endPosition)  neighborsFluid = false;
+                //////////////////////////////////////////////////////////////////////////
+                dn2 = number2 - startPosition;
+                dn3 = number3 - startPosition;
+                dn4 = number4 - startPosition;
+                dn5 = number5 - startPosition;
+                dn6 = number6 - startPosition;
+                dn7 = number7 - startPosition;
+                dn8 = number8 - startPosition;
                 //////////////////////////////////////////////////////////////////////////
                 if (isPeriodicCell(para, level, number2, number1, number3, number5))
                     continue;
@@ -531,122 +427,8 @@ void FileWriter::writeUnstrucuredGridMedianLT(std::shared_ptr<Parameter> para, i
                 //////////////////////////////////////////////////////////////////////////
             }
         }
-        WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
+        outFNames.push_back(WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodeDataNames, nodeData));
         //////////////////////////////////////////////////////////////////////////
     }
-}
-
-void FileWriter::writeUnstrucuredGridMedianLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
-{
-    std::vector< UbTupleFloat3 > nodes;
-    std::vector< UbTupleUInt8 > cells;
-    std::vector< std::string > nodedatanames;
-    nodedatanames.push_back("concMed");
-    nodedatanames.push_back("pressMed");
-    nodedatanames.push_back("rhoMed");
-    nodedatanames.push_back("vx1Med");
-    nodedatanames.push_back("vx2Med");
-    nodedatanames.push_back("vx3Med");
-    nodedatanames.push_back("geo");
-    uint number1, number2, number3, number4, number5, number6, number7, number8;
-    uint dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8;
-    bool neighborsFluid;
-    uint startpos = 0;
-    uint endpos = 0;
-    uint sizeOfNodes = 0;
-    std::vector< std::vector< double > > nodedata(nodedatanames.size());
-
-    for (unsigned int part = 0; part < fname.size(); part++)
-    {
-        if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
-            sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
-        else
-            sizeOfNodes = para->getlimitOfNodesForVTK();
-        //////////////////////////////////////////////////////////////////////////
-        startpos = part * para->getlimitOfNodesForVTK();
-        endpos = startpos + sizeOfNodes;
-        //////////////////////////////////////////////////////////////////////////
-        cells.clear();
-        nodes.resize(sizeOfNodes);
-        nodedata[0].resize(sizeOfNodes);
-        nodedata[1].resize(sizeOfNodes);
-        nodedata[2].resize(sizeOfNodes);
-        nodedata[3].resize(sizeOfNodes);
-        nodedata[4].resize(sizeOfNodes);
-        nodedata[5].resize(sizeOfNodes);
-        nodedata[6].resize(sizeOfNodes);
-        //////////////////////////////////////////////////////////////////////////
-        for (unsigned int pos = startpos; pos < endpos; pos++)
-        {
-            if (para->getParH(level)->typeOfGridNode[pos] == GEO_FLUID)
-            {
-                //////////////////////////////////////////////////////////////////////////
-                double x1 = para->getParH(level)->coordinateX[pos];
-                double x2 = para->getParH(level)->coordinateY[pos];
-                double x3 = para->getParH(level)->coordinateZ[pos];
-                //////////////////////////////////////////////////////////////////////////
-                number1 = pos;
-                dn1 = pos - startpos;
-                neighborsFluid = true;
-                //////////////////////////////////////////////////////////////////////////
-                nodes[dn1] = (makeUbTuple((float)(x1), (float)(x2), (float)(x3)));
-                nodedata[0][dn1] = (double)para->getParH(level)->Conc_Med_Out[pos];
-                nodedata[1][dn1] = (double)para->getParH(level)->press_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-                nodedata[2][dn1] = (double)para->getParH(level)->rho_SP_Med_Out[pos] / 3.0f * para->getDensityRatio() * para->getVelocityRatio() * para->getVelocityRatio();
-                nodedata[3][dn1] = (double)para->getParH(level)->vx_SP_Med_Out[pos] * para->getVelocityRatio();
-                nodedata[4][dn1] = (double)para->getParH(level)->vy_SP_Med_Out[pos] * para->getVelocityRatio();
-                nodedata[5][dn1] = (double)para->getParH(level)->vz_SP_Med_Out[pos] * para->getVelocityRatio();
-                nodedata[6][dn1] = (double)para->getParH(level)->typeOfGridNode[pos];
-                //////////////////////////////////////////////////////////////////////////
-                number2 = para->getParH(level)->neighborX[number1];
-                number3 = para->getParH(level)->neighborY[number2];
-                number4 = para->getParH(level)->neighborY[number1];
-                number5 = para->getParH(level)->neighborZ[number1];
-                number6 = para->getParH(level)->neighborZ[number2];
-                number7 = para->getParH(level)->neighborZ[number3];
-                number8 = para->getParH(level)->neighborZ[number4];
-                //////////////////////////////////////////////////////////////////////////
-                if (para->getParH(level)->typeOfGridNode[number2] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number3] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number4] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number5] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number6] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number7] != GEO_FLUID ||
-                    para->getParH(level)->typeOfGridNode[number8] != GEO_FLUID)  neighborsFluid = false;
-                //////////////////////////////////////////////////////////////////////////
-                if (number2 > endpos ||
-                    number3 > endpos ||
-                    number4 > endpos ||
-                    number5 > endpos ||
-                    number6 > endpos ||
-                    number7 > endpos ||
-                    number8 > endpos)  neighborsFluid = false;
-                //////////////////////////////////////////////////////////////////////////
-                dn2 = number2 - startpos;
-                dn3 = number3 - startpos;
-                dn4 = number4 - startpos;
-                dn5 = number5 - startpos;
-                dn6 = number6 - startpos;
-                dn7 = number7 - startpos;
-                dn8 = number8 - startpos;
-                //////////////////////////////////////////////////////////////////////////
-                if (isPeriodicCell(para, level, number2, number1, number3, number5))
-                    continue;
-                //////////////////////////////////////////////////////////////////////////
-                if (neighborsFluid)
-                    cells.push_back(makeUbTuple(dn1, dn2, dn3, dn4, dn5, dn6, dn7, dn8));
-                //////////////////////////////////////////////////////////////////////////
-            }
-        }
-        WbWriterVtkXmlBinary::getInstance()->writeOctsWithNodeData(fname[part], nodes, cells, nodedatanames, nodedata);
-        //////////////////////////////////////////////////////////////////////////
-    }
-}
-//////////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-
+    return outFNames;
+}
\ No newline at end of file
diff --git a/src/gpu/VirtualFluids_GPU/Output/FileWriter.h b/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
index 2d7c176fa067ea86573849e90bd91dab259526b4..73794f957f573d9dc29f57adff4e15d1f6ba7e18 100644
--- a/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
+++ b/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
@@ -11,27 +11,26 @@
 
 class Parameter;
 class CudaMemoryManager;
-struct PN27;
 
 class FileWriter : public DataWriter
 {
 public:
-	void writeInit(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> cudaMemoryManager) override;
-	void writeTimestep(std::shared_ptr<Parameter> para, unsigned int timestep) override;
+    void writeInit(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> cudaMemoryManager) override;
+    void writeTimestep(std::shared_ptr<Parameter> para, unsigned int timestep) override;
 
 private:
-	void writeTimestep(std::shared_ptr<Parameter> para, unsigned int timestep, int level) override;
-	//void writeParticle(Parameter* para, unsigned int t);
-    void writeUnstrucuredGridLT(std::shared_ptr<Parameter> para, int level,
+    void writeTimestep(std::shared_ptr<Parameter> para, unsigned int timestep, int level) override;
+    std::vector<std::string> writeUnstructuredGridLT(std::shared_ptr<Parameter> para, int level,
                                                          std::vector<std::string> &fname);
-	void writeUnstrucuredGridLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname);
-	void writeUnstrucuredGridMedianLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname);
-	void writeUnstrucuredGridMedianLTConc(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname);
-	bool isPeriodicCell(std::shared_ptr<Parameter> para, int level, unsigned int number2, unsigned int number1, unsigned int number3, unsigned int number5);
+    std::vector<std::string> writeUnstructuredGridMedianLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname);
+    bool isPeriodicCell(std::shared_ptr<Parameter> para, int level, unsigned int number2, unsigned int number1, unsigned int number3, unsigned int number5);
 
-    void writeCollectionFile( std::shared_ptr<Parameter> para, unsigned int timestep );
+    std::string writeCollectionFile( std::shared_ptr<Parameter> para, unsigned int timestep );
 
-    void writeCollectionFileMedian( std::shared_ptr<Parameter> para, unsigned int timestep );
+    std::string writeCollectionFileMedian( std::shared_ptr<Parameter> para, unsigned int timestep );
+
+    std::vector<std::string> getNodeDataNames(std::shared_ptr<Parameter> para);
+    std::vector<std::string> getMedianNodeDataNames(std::shared_ptr<Parameter> para);
 
     std::vector< std::string > fileNamesForCollectionFile;
     std::vector< std::string > fileNamesForCollectionFileMedian;
diff --git a/src/gpu/VirtualFluids_GPU/Output/UnstructuredGridWriter.hpp b/src/gpu/VirtualFluids_GPU/Output/UnstructuredGridWriter.hpp
index cafe70205455ae8592c1efe86e4ba9de8e1ba170..5d5548ba7e64a23152126446e3c438da1c7e7653 100644
--- a/src/gpu/VirtualFluids_GPU/Output/UnstructuredGridWriter.hpp
+++ b/src/gpu/VirtualFluids_GPU/Output/UnstructuredGridWriter.hpp
@@ -197,16 +197,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-			if ( ((part+1)*para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+			if ( ((part+1)*para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -340,16 +340,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -479,16 +479,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -628,16 +628,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -771,16 +771,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -1342,16 +1342,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-			if ( ((part+1)*para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+			if ( ((part+1)*para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -1465,16 +1465,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -1595,16 +1595,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -1975,16 +1975,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -2080,16 +2080,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
@@ -2192,16 +2192,16 @@ namespace UnstructuredGridWriter
 			vxmax = 0;
 			//printf("\n test in if I... \n");
 			//////////////////////////////////////////////////////////////////////////
-            if (((part + 1) * para->getlimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
+            if (((part + 1) * para->getLimitOfNodesForVTK()) > (uint)para->getParH(level)->numberOfNodes)
 			{
-                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getlimitOfNodesForVTK());
+                sizeOfNodes = (uint)para->getParH(level)->numberOfNodes - (part * para->getLimitOfNodesForVTK());
 			}
 			else
 			{
-				sizeOfNodes = para->getlimitOfNodesForVTK();
+				sizeOfNodes = para->getLimitOfNodesForVTK();
 			}
 			//////////////////////////////////////////////////////////////////////////
-			startpos = part * para->getlimitOfNodesForVTK();
+			startpos = part * para->getLimitOfNodesForVTK();
 			endpos = startpos + sizeOfNodes;
 			//////////////////////////////////////////////////////////////////////////
 			cells.clear();
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.cpp b/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.cpp
index 3cc771e413134e90b0d09d8eeb6dfee791f8a1e2..c6db87138610a6c029a06e32b70f496dc2306a83 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.cpp
+++ b/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.cpp
@@ -31,15 +31,14 @@
 #include <helper_cuda.h>
 #include <iostream>
 
-void CudaStreamManager::registerStream(CudaStreamIndex streamIndex)
+int CudaStreamManager::registerAndLaunchStream(CudaStreamIndex streamIndex)
 {   
-    if(streamIndex != CudaStreamIndex::Legacy)
-        cudaStreams.emplace(streamIndex, nullptr);
-}
-void CudaStreamManager::launchStreams()
-{
-    for (auto &stream : cudaStreams)
-        cudaStreamCreate(&stream.second);
+    if(streamIndex == CudaStreamIndex::Legacy) return 0;
+
+    cudaStream_t new_stream = nullptr;
+    cudaStreamCreate(&new_stream);
+    cudaStreams.emplace(streamIndex, new_stream);
+    return int(cudaStreams.count(streamIndex) - 1);
 }
 
 void CudaStreamManager::terminateStreams()
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.h b/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.h
index 631a945a653e6b4b60924a650e94b3873ebacc7d..98032ef16adebf56f10d8ed5e9c04bbf517876c3 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.h
+++ b/src/gpu/VirtualFluids_GPU/Parameter/CudaStreamManager.h
@@ -1,28 +1,28 @@
 //=======================================================================================
-// ____          ____    __    ______     __________   __      __       __        __         
-// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
-//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
-//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
-//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
-//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
-//      \    \  |    |   ________________________________________________________________    
-//       \    \ |    |  |  ______________________________________________________________|   
-//        \    \|    |  |  |         __          __     __     __     ______      _______    
-//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
-//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
 //           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
 //
-//  This file is part of VirtualFluids. VirtualFluids is free software: you can 
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can
 //  redistribute it and/or modify it under the terms of the GNU General Public
-//  License as published by the Free Software Foundation, either version 3 of 
+//  License as published by the Free Software Foundation, either version 3 of
 //  the License, or (at your option) any later version.
-//  
-//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT 
-//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+//
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 //  for more details.
-//  
+//
 //  You should have received a copy of the GNU General Public License along
 //  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
 //
@@ -43,27 +43,26 @@ enum class CudaStreamIndex
         Precursor,
         ActuatorFarm
     };
+
 class CudaStreamManager
-{   
+{
 private:
     std::multimap<CudaStreamIndex, cudaStream_t> cudaStreams;
     cudaEvent_t startBulkKernel = NULL;
     cudaStream_t legacyStream = CU_STREAM_LEGACY;
 
-
 public:
-    void registerStream(CudaStreamIndex streamIndex);
-    void launchStreams();
+    int registerAndLaunchStream(CudaStreamIndex streamIndex);
     void terminateStreams();
-    cudaStream_t &getStream(CudaStreamIndex streamIndex, uint multiStreamIndex=0);
+    cudaStream_t &getStream(CudaStreamIndex streamIndex, uint multiStreamIndex = 0);
 
     bool streamIsRegistered(CudaStreamIndex streamIndex);
     // Events
     void createCudaEvents();
     void destroyCudaEvents();
 
-    void triggerStartBulkKernel(CudaStreamIndex streamIndex, uint multiStreamIndex=0);
-    void waitOnStartBulkKernelEvent(CudaStreamIndex streamIndex, uint multiStreamIndex=0);
+    void triggerStartBulkKernel(CudaStreamIndex streamIndex, uint multiStreamIndex = 0);
+    void waitOnStartBulkKernelEvent(CudaStreamIndex streamIndex, uint multiStreamIndex = 0);
 };
 
 #endif
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
index e3758ca951e2d84f6377bdcb213f076383678ad4..207debefb76c503bd331d8374556ac2bb46af940 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
@@ -1721,7 +1721,7 @@ unsigned int Parameter::getOutputCount()
 {
     return this->outputCount;
 }
-unsigned int Parameter::getlimitOfNodesForVTK()
+unsigned int Parameter::getLimitOfNodesForVTK()
 {
     return this->limitOfNodesForVTK;
 }
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
index 68d56a683692c5ff8d4230b5206a5db3ec6a73ae..ea2511a4f3112cff78c9f65ffd783ec600ba101d 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
@@ -700,7 +700,7 @@ public:
     real getEndXHotWall();
     unsigned int getStepEnsight();
     unsigned int getOutputCount();
-    unsigned int getlimitOfNodesForVTK();
+    unsigned int getLimitOfNodesForVTK();
     unsigned int getStartTurn();
     bool getEvenOrOdd(int level);
     bool getDiffOn();
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/ActuatorFarm.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/ActuatorFarm.cu
index bcdd63657d13cd8a9dcef3372fe02760a337b057..f2d4b27a159c3f3687bd58933b55558ca08cd16d 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/ActuatorFarm.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/ActuatorFarm.cu
@@ -310,7 +310,7 @@ void ActuatorFarm::init(Parameter* para, GridProvider* gridProvider, CudaMemoryM
     this->initBladeVelocities(cudaMemoryManager);
     this->initBladeForces(cudaMemoryManager);
     this->initBoundingSpheres(para, cudaMemoryManager);
-    this->streamIndex = 0;
+    this->streamIndex = para->getStreamManager()->registerAndLaunchStream(CudaStreamIndex::ActuatorFarm);
 }
 
 void ActuatorFarm::interact(Parameter* para, CudaMemoryManager* cudaMemoryManager, int level, unsigned int t)
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PreCollisionInteractor.h b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PreCollisionInteractor.h
index 811045a32b18fd0f5d7f71be39b0dfec8982b352..90c434bd60e623175d5c8bfbbf23fa41f01e8a37 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PreCollisionInteractor.h
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PreCollisionInteractor.h
@@ -16,8 +16,6 @@ class CudaMemoryManager;
 
 class VIRTUALFLUIDS_GPU_EXPORT PreCollisionInteractor
 {
-private:
-    SPtr<Parameter> para;
 
 protected:
     PreCollisionInteractor()
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PrecursorWriter.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PrecursorWriter.cu
index 99c60fd3d2aae2e796e0c95e624b9d5d33c30ef1..b1ebaf28edc7966074f7cc96e31bf8489ca8e4a9 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PrecursorWriter.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/PrecursorWriter.cu
@@ -208,7 +208,7 @@ void PrecursorWriter::init(Parameter* para, GridProvider* gridProvider, CudaMemo
         precursorStructs[level]->origin = makeUbTuple(lowestY, lowestZ);
         precursorStructs[level]->extent = makeUbTuple(0, ny-1, 0, nz-1);
         precursorStructs[level]->numberOfPointsInData = ny*nz;
-        precursorStructs[level]->numberOfTimestepsPerFile = min(para->getlimitOfNodesForVTK()/(ny*nz), maxtimestepsPerFile);
+        precursorStructs[level]->numberOfTimestepsPerFile = min(para->getLimitOfNodesForVTK()/(ny*nz), maxtimestepsPerFile);
         precursorStructs[level]->numberOfFilesWritten = 0;
         precursorStructs[level]->numberOfTimestepsBuffered = 0;
         
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu
index e89d392b5d4bf5983f9bb47642fef81d0f06cc89..705b7173606d1956c50c59d5cc1f7635a4b7883b 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.cu
@@ -16,9 +16,11 @@
 #include "DataStructureInitializer/GridProvider.h"
 #include "GPU/CudaMemoryManager.h"
 #include "GPU/GPU_Interface.h"
+#include "basics/constants/NumericConstants.h"
 
 #include <algorithm>
 
+using namespace vf::basics::constant;
 ///////////////////////////////////////////////////////////////////////////////////
 /// Functors for thrust reductions
 ///////////////////////////////////////////////////////////////////////////////////
@@ -307,7 +309,7 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
         neighborInplane2 = para->getParD(level)->neighborY;
     }
 
-    bool doTmpAveraging = t_level>=(this->getTStartTmpAveraging()*pow(2,level));
+    bool doTmpAveraging = t_level>=(this->getTStartTmpAveraging()*exp2(level));
 
     // Pointer casts to use device arrays in thrust reductions
     thrust::device_ptr<uint> indices_thrust = thrust::device_pointer_cast(probeStruct->pointIndicesD);
@@ -317,7 +319,7 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
     thrust::device_ptr<real> nut_thrust = thrust::device_pointer_cast(para->getParD(level)->turbViscosity);
 
     real N = (real)probeStruct->nIndices;
-    real n = (real)probeStruct->vals;
+    real invNumberOfTimestepsInTmpAvg = c1o1/real(probeStruct->timestepInTimeAverage+1);
     uint nPoints = probeStruct->nPoints;
     // Permutation iterators for direct iteration over the velocities of the planes
     typedef thrust::device_vector<real>::iterator valIterator;
@@ -353,17 +355,17 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
 
             if(probeStruct->quantitiesH[int(Statistic::SpatioTemporalMeans)] && doTmpAveraging)
             {
-            uint arrOff = probeStruct->arrayOffsetsH[int(Statistic::SpatioTemporalMeans)];
-            real spatTmpMean_vx_old = probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node];
-            real spatTmpMean_vy_old = probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node];
-            real spatTmpMean_vz_old = probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node];
-            real spatTmpMean_nut_old;
-            if(para->getUseTurbulentViscosity()) spatTmpMean_nut_old = probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node];;
-
-            probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_vx-spatTmpMean_vx_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_vy-spatTmpMean_vy_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_vz-spatTmpMean_vz_old)/n;
-            if(para->getUseTurbulentViscosity()) probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node] += (spatMean_nut-spatTmpMean_nut_old)/n;
+                uint arrOff = probeStruct->arrayOffsetsH[int(Statistic::SpatioTemporalMeans)];
+                real spatTmpMean_vx_old = probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node];
+                real spatTmpMean_vy_old = probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node];
+                real spatTmpMean_vz_old = probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node];
+                real spatTmpMean_nut_old;
+                if(para->getUseTurbulentViscosity()) spatTmpMean_nut_old = probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node];;
+
+                probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_vx-spatTmpMean_vx_old)*invNumberOfTimestepsInTmpAvg;
+                probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_vy-spatTmpMean_vy_old)*invNumberOfTimestepsInTmpAvg;
+                probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_vz-spatTmpMean_vz_old)*invNumberOfTimestepsInTmpAvg;
+                if(para->getUseTurbulentViscosity()) probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node] += (spatMean_nut-spatTmpMean_nut_old)*invNumberOfTimestepsInTmpAvg;
 
             }
         
@@ -400,12 +402,12 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
                     real spatTmpMean_vxvz_old = probeStruct->quantitiesArrayH[(arrOff+4)*nPoints+node];
                     real spatTmpMean_vyvz_old = probeStruct->quantitiesArrayH[(arrOff+5)*nPoints+node];
 
-                    probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_vxvx-spatTmpMean_vxvx_old)/n;
-                    probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_vyvy-spatTmpMean_vyvy_old)/n;
-                    probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_vzvz-spatTmpMean_vzvz_old)/n;
-                    probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node] += (spatMean_vxvy-spatTmpMean_vxvy_old)/n;
-                    probeStruct->quantitiesArrayH[(arrOff+4)*nPoints+node] += (spatMean_vxvz-spatTmpMean_vxvz_old)/n;
-                    probeStruct->quantitiesArrayH[(arrOff+5)*nPoints+node] += (spatMean_vyvz-spatTmpMean_vyvz_old)/n;
+                    probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_vxvx-spatTmpMean_vxvx_old)*invNumberOfTimestepsInTmpAvg;
+                    probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_vyvy-spatTmpMean_vyvy_old)*invNumberOfTimestepsInTmpAvg;
+                    probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_vzvz-spatTmpMean_vzvz_old)*invNumberOfTimestepsInTmpAvg;
+                    probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+node] += (spatMean_vxvy-spatTmpMean_vxvy_old)*invNumberOfTimestepsInTmpAvg;
+                    probeStruct->quantitiesArrayH[(arrOff+4)*nPoints+node] += (spatMean_vxvz-spatTmpMean_vxvz_old)*invNumberOfTimestepsInTmpAvg;
+                    probeStruct->quantitiesArrayH[(arrOff+5)*nPoints+node] += (spatMean_vyvz-spatTmpMean_vyvz_old)*invNumberOfTimestepsInTmpAvg;
                 }
 
                 if(probeStruct->quantitiesH[int(Statistic::SpatialSkewness)])
@@ -435,9 +437,9 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
                         real spatTmpMean_Sy_old = probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node];
                         real spatTmpMean_Sz_old = probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node];
 
-                        probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_Sx-spatTmpMean_Sx_old)/n;
-                        probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_Sy-spatTmpMean_Sy_old)/n;
-                        probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_Sz-spatTmpMean_Sz_old)/n;
+                        probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_Sx-spatTmpMean_Sx_old)*invNumberOfTimestepsInTmpAvg;
+                        probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_Sy-spatTmpMean_Sy_old)*invNumberOfTimestepsInTmpAvg;
+                        probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_Sz-spatTmpMean_Sz_old)*invNumberOfTimestepsInTmpAvg;
                     }
 
                     if(probeStruct->quantitiesH[int(Statistic::SpatialFlatness)])
@@ -464,9 +466,9 @@ void PlanarAverageProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Para
                             real spatTmpMean_Fy_old = probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node];
                             real spatTmpMean_Fz_old = probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node];
 
-                            probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_Fx-spatTmpMean_Fx_old)/n;
-                            probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_Fy-spatTmpMean_Fy_old)/n;
-                            probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_Fz-spatTmpMean_Fz_old)/n;
+                            probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+node] += (spatMean_Fx-spatTmpMean_Fx_old)*invNumberOfTimestepsInTmpAvg;
+                            probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+node] += (spatMean_Fy-spatTmpMean_Fy_old)*invNumberOfTimestepsInTmpAvg;
+                            probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+node] += (spatMean_Fz-spatTmpMean_Fz_old)*invNumberOfTimestepsInTmpAvg;
                         }
                     }
                 }
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h
index 3d3533f74501e776f9150c83c9d9101a0be7ecbc..c2370231c0bc341ca9b3980578ce4aadc1b75c7a 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlanarAverageProbe.h
@@ -90,6 +90,8 @@ private:
                     std::vector<real>& pointCoordsX_level, std::vector<real>& pointCoordsY_level, std::vector<real>& pointCoordsZ_level,
                     int level) override;
     void calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t, int level) override;
+    void getTaggedFluidNodes(Parameter *para, GridProvider* gridProvider) override {};
+
 
 private:
     real posX, posY, posZ;
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu
index f55045505bff0e3b5b0b1426be4e9e1a3832d088..19f7f6c62ae7ac83c90fc2a7aff0e286a70063d1 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PlaneProbe.cu
@@ -102,10 +102,23 @@ void PlaneProbe::findPoints(Parameter* para, GridProvider* gridProvider, std::ve
 void PlaneProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t, int level)
 {
     vf::cuda::CudaGrid grid = vf::cuda::CudaGrid(para->getParH(level)->numberofthreads, probeStruct->nPoints);
-    calcQuantitiesKernel<<<grid.grid, grid.threads>>>(  probeStruct->pointIndicesD, probeStruct->nPoints, probeStruct->vals,
-    para->getParD(level)->velocityX, para->getParD(level)->velocityY, para->getParD(level)->velocityZ, para->getParD(level)->rho, 
-    para->getParD(level)->neighborX, para->getParD(level)->neighborY, para->getParD(level)->neighborZ, 
-    probeStruct->quantitiesD, probeStruct->arrayOffsetsD, probeStruct->quantitiesArrayD);
+    calcQuantitiesKernel<<<grid.grid, grid.threads>>>(  probeStruct->pointIndicesD,
+                                                        probeStruct->nPoints,
+                                                        0,
+                                                        0,
+                                                        probeStruct->timestepInTimeAverage,
+                                                        probeStruct->nTimesteps,
+                                                        para->getParD(level)->velocityX,
+                                                        para->getParD(level)->velocityY,
+                                                        para->getParD(level)->velocityZ,
+                                                        para->getParD(level)->rho,
+                                                        para->getParD(level)->neighborX,
+                                                        para->getParD(level)->neighborY,
+                                                        para->getParD(level)->neighborZ,
+                                                        probeStruct->quantitiesD,
+                                                        probeStruct->arrayOffsetsD,
+                                                        probeStruct->quantitiesArrayD
+                                                        );
 }
 
 void PlaneProbe::getTaggedFluidNodes(Parameter *para, GridProvider* gridProvider)
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu
index 89e1f6b87687ed42c079415a5340f1d385c8d62c..19c170608a606227d21c25791776bd3195b16e04 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.cu
@@ -103,13 +103,22 @@ void PointProbe::findPoints(Parameter* para, GridProvider* gridProvider, std::ve
 void PointProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t, int level)
 {
     vf::cuda::CudaGrid grid = vf::cuda::CudaGrid(para->getParH(level)->numberofthreads, probeStruct->nPoints);
-    interpAndCalcQuantitiesKernel<<<grid.grid, grid.threads>>>(  probeStruct->pointIndicesD, probeStruct->nPoints, probeStruct->vals,
+    int oldTimestepInTimeseries = this->outputTimeSeries ? calcOldTimestep(probeStruct->timestepInTimeseries, probeStruct->lastTimestepInOldTimeseries) : 0;
+    int currentTimestep = this->outputTimeSeries ? probeStruct->timestepInTimeseries : 0;
+    interpAndCalcQuantitiesKernel<<<grid.grid, grid.threads>>>(  probeStruct->pointIndicesD, probeStruct->nPoints, oldTimestepInTimeseries, currentTimestep, probeStruct->timestepInTimeAverage, probeStruct->nTimesteps,
                                                 probeStruct->distXD, probeStruct->distYD, probeStruct->distZD,
                                                 para->getParD(level)->velocityX, para->getParD(level)->velocityY, para->getParD(level)->velocityZ, para->getParD(level)->rho, 
                                                 para->getParD(level)->neighborX, para->getParD(level)->neighborY, para->getParD(level)->neighborZ, 
                                                 probeStruct->quantitiesD, probeStruct->arrayOffsetsD, probeStruct->quantitiesArrayD);
 }
 
+void PointProbe::addProbePoint(real pointCoordX, real pointCoordY, real pointCoordZ)
+{
+    this->pointCoordsX.push_back(pointCoordX);
+    this->pointCoordsY.push_back(pointCoordY);
+    this->pointCoordsZ.push_back(pointCoordZ);
+}
+
 void PointProbe::addProbePointsFromList(std::vector<real>& _pointCoordsX, std::vector<real>& _pointCoordsY, std::vector<real>& _pointCoordsZ)
 {
     bool isSameLength = ( (_pointCoordsX.size()==_pointCoordsY.size()) && (_pointCoordsY.size()==_pointCoordsZ.size()));
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.h b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.h
index 08c359705f03b20fbd3276fe209b6ff4d782a5e5..b26211dc859bf4601b42a640d25e656b3552300b 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.h
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/PointProbe.h
@@ -50,7 +50,8 @@ public:
         uint _tStartAvg,
         uint _tAvg,
         uint _tStartOut,
-        uint _tOut
+        uint _tOut,
+        bool _outputTimeseries = false
     ): Probe(_probeName, 
              _outputPath,
              _tStartAvg, 
@@ -59,9 +60,10 @@ public:
              _tStartOut, 
              _tOut,
              true,
-             false)
+             _outputTimeseries)
     {}
 
+    void addProbePoint(real pointCoordX, real pointCoordY, real pointCoordZ);
     void addProbePointsFromList(std::vector<real>& _pointCoordsX, std::vector<real>& _pointCoordsY, std::vector<real>& _pointCoordsZ);
     void addProbePointsFromXNormalPlane(real pos_x, real pos0_y, real pos0_z, real pos1_y, real pos1_z, uint n_y, uint n_z);
     void getTaggedFluidNodes(Parameter *para, GridProvider* gridProvider) override;
@@ -80,6 +82,8 @@ private:
 
 private:
     std::vector<real> pointCoordsX, pointCoordsY, pointCoordsZ; 
+    uint getNumberOfTimestepsInTimeseries(Parameter* para, int level) override { return outputTimeSeries ? tOut*exp2(level) : 1; }
+
 
 };
 
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu
index a7a0e79c0bcbf0f7a9e13e879debfb378e23f69d..2be8743bb28e45234533cb63673a9aebd6b0cf10 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.cu
@@ -47,69 +47,92 @@
 
 using namespace vf::basics::constant;
 
-__device__ void calculatePointwiseQuantities(uint n, real* quantityArray, bool* quantities, uint* quantityArrayOffsets, uint nPoints, uint node, real vx, real vy, real vz, real rho)
+__host__ __device__ int calcArrayIndex(int node, int nNodes, int timestep, int nTimesteps, int array)
+{
+    return node+nNodes*(timestep+nTimesteps*array);
+}
+
+uint calcOldTimestep(uint currentTimestep, uint lastTimestepInOldSeries)
+{
+    return currentTimestep > 0 ? currentTimestep - 1 : lastTimestepInOldSeries; 
+}
+
+__device__ void calculatePointwiseQuantities(
+    uint oldTimestepInTimeseries,
+    uint timestepInTimeseries,
+    uint timestepInAverage,
+    uint nTimesteps,
+    real* quantityArray,
+    bool* quantities,
+    uint* quantityArrayOffsets,
+    uint nPoints,
+    uint node,
+    real vx,
+    real vy,
+    real vz,
+    real rho)
 {
     //"https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm"
     // also has extensions for higher order and covariances
+    int n = timestepInAverage+1;
     real inv_n = 1/real(n);
 
-    if(quantities[int(Statistic::Instantaneous)])
+    if (quantities[int(Statistic::Instantaneous)])
     {
         uint arrOff = quantityArrayOffsets[int(Statistic::Instantaneous)];
-        quantityArray[(arrOff+0)*nPoints+node] = vx;
-        quantityArray[(arrOff+1)*nPoints+node] = vy;
-        quantityArray[(arrOff+2)*nPoints+node] = vz;
-        quantityArray[(arrOff+3)*nPoints+node] = rho;
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 0)] = vx;
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 1)] = vy;
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 2)] = vz;
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 3)] = rho;
     }
 
-    if(quantities[int(Statistic::Means)])
+    if (quantities[int(Statistic::Means)])
     {
-        
         uint arrOff = quantityArrayOffsets[int(Statistic::Means)];
-        real vx_m_old  = quantityArray[(arrOff+0)*nPoints+node];
-        real vy_m_old  = quantityArray[(arrOff+1)*nPoints+node];
-        real vz_m_old  = quantityArray[(arrOff+2)*nPoints+node];
-        real rho_m_old = quantityArray[(arrOff+3)*nPoints+node];
-
-        real vx_m_new  = ( (n-1)*vx_m_old + vx  )*inv_n;
-        real vy_m_new  = ( (n-1)*vy_m_old + vy  )*inv_n;
-        real vz_m_new  = ( (n-1)*vz_m_old + vz  )*inv_n;
-        real rho_m_new = ( (n-1)*rho_m_old+ rho )*inv_n;
-
-        quantityArray[(arrOff+0)*nPoints+node] = vx_m_new;
-        quantityArray[(arrOff+1)*nPoints+node] = vy_m_new;
-        quantityArray[(arrOff+2)*nPoints+node] = vz_m_new;
-        quantityArray[(arrOff+3)*nPoints+node] = rho_m_new;
-    
-        if(quantities[int(Statistic::Variances)])
+        real vx_m_old  = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 0)];
+        real vy_m_old  = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 1)];
+        real vz_m_old  = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 2)];
+        real rho_m_old = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 3)];
+
+        real vx_m_new  = ((n - 1) * vx_m_old  + vx)  * inv_n;
+        real vy_m_new  = ((n - 1) * vy_m_old  + vy)  * inv_n;
+        real vz_m_new  = ((n - 1) * vz_m_old  + vz)  * inv_n;
+        real rho_m_new = ((n - 1) * rho_m_old + rho) * inv_n;
+
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 0)] = vx_m_new;
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 1)] = vy_m_new;
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 2)] = vz_m_new;
+        quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 3)] = rho_m_new;
+
+        if (quantities[int(Statistic::Variances)])
         {
             arrOff = quantityArrayOffsets[int(Statistic::Variances)];
 
-            real vx_var_old  = quantityArray[(arrOff+0)*nPoints+node];
-            real vy_var_old  = quantityArray[(arrOff+1)*nPoints+node];
-            real vz_var_old  = quantityArray[(arrOff+2)*nPoints+node];
-            real rho_var_old = quantityArray[(arrOff+3)*nPoints+node];
+            real vx_var_old  = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 0)];
+            real vy_var_old  = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 1)];
+            real vz_var_old  = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 2)];
+            real rho_var_old = quantityArray[calcArrayIndex(node, nPoints, oldTimestepInTimeseries, nTimesteps, arrOff + 3)];
 
-            real vx_var_new  = ( (n-1)*(vx_var_old )+(vx  - vx_m_old )*(vx  - vx_m_new ) )*inv_n;
-            real vy_var_new  = ( (n-1)*(vy_var_old )+(vy  - vy_m_old )*(vy  - vy_m_new ) )*inv_n;
-            real vz_var_new  = ( (n-1)*(vz_var_old )+(vz  - vz_m_old )*(vz  - vz_m_new ) )*inv_n;
-            real rho_var_new = ( (n-1)*(rho_var_old)+(rho - rho_m_old)*(rho - rho_m_new) )*inv_n;
+            real vx_var_new  = ((n - 1) * (vx_var_old)  + (vx  - vx_m_old)  * (vx  - vx_m_new))  * inv_n;
+            real vy_var_new  = ((n - 1) * (vy_var_old)  + (vy  - vy_m_old)  * (vy  - vy_m_new))  * inv_n;
+            real vz_var_new  = ((n - 1) * (vz_var_old)  + (vz  - vz_m_old)  * (vz  - vz_m_new))  * inv_n;
+            real rho_var_new = ((n - 1) * (rho_var_old) + (rho - rho_m_old) * (rho - rho_m_new)) * inv_n;
 
-            quantityArray[(arrOff+0)*nPoints+node] = vx_var_new;
-            quantityArray[(arrOff+1)*nPoints+node] = vy_var_new;
-            quantityArray[(arrOff+2)*nPoints+node] = vz_var_new;
-            quantityArray[(arrOff+3)*nPoints+node] = rho_var_new; 
+            quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 0)] = vx_var_new;
+            quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 1)] = vy_var_new;
+            quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 2)] = vz_var_new;
+            quantityArray[calcArrayIndex(node, nPoints, timestepInTimeseries, nTimesteps, arrOff + 3)] = rho_var_new;
         }
     }
 }
 
 __global__ void calcQuantitiesKernel(   uint* pointIndices,
-                                    uint nPoints, uint n,
+                                    uint nPoints, uint oldTimestepInTimeseries, uint timestepInTimeseries, uint timestepInAverage, uint nTimesteps,
                                     real* vx, real* vy, real* vz, real* rho,            
                                     uint* neighborX, uint* neighborY, uint* neighborZ,
                                     bool* quantities,
                                     uint* quantityArrayOffsets, real* quantityArray
-                                )
+                                    )
 {
     const uint x = threadIdx.x; 
     const uint y = blockIdx.x;
@@ -132,12 +155,12 @@ __global__ void calcQuantitiesKernel(   uint* pointIndices,
     u_interpZ = vz[k];
     rho_interp = rho[k];
 
-    calculatePointwiseQuantities(n, quantityArray, quantities, quantityArrayOffsets, nPoints, node, u_interpX, u_interpY, u_interpZ, rho_interp);
+    calculatePointwiseQuantities(oldTimestepInTimeseries, timestepInTimeseries, timestepInAverage, nTimesteps, quantityArray, quantities, quantityArrayOffsets, nPoints, node, u_interpX, u_interpY, u_interpZ, rho_interp);
 
 }
 
 __global__ void interpAndCalcQuantitiesKernel(   uint* pointIndices,
-                                    uint nPoints, uint n,
+                                    uint nPoints, uint oldTimestepInTimeseries, uint timestepInTimeseries, uint timestepInAverage, uint nTimesteps,
                                     real* distX, real* distY, real* distZ,
                                     real* vx, real* vy, real* vz, real* rho,            
                                     uint* neighborX, uint* neighborY, uint* neighborZ,
@@ -173,7 +196,7 @@ __global__ void interpAndCalcQuantitiesKernel(   uint* pointIndices,
     u_interpZ  = trilinearInterpolation( dW, dE, dN, dS, dT, dB, k, ke, kn, kt, kne, kte, ktn, ktne, vz );
     rho_interp = trilinearInterpolation( dW, dE, dN, dS, dT, dB, k, ke, kn, kt, kne, kte, ktn, ktne, rho );
 
-    calculatePointwiseQuantities(n, quantityArray, quantities, quantityArrayOffsets, nPoints, node, u_interpX, u_interpY, u_interpZ, rho_interp);
+    calculatePointwiseQuantities(oldTimestepInTimeseries, timestepInTimeseries, timestepInAverage, nTimesteps, quantityArray, quantities, quantityArrayOffsets, nPoints, node, u_interpX, u_interpY, u_interpZ, rho_interp);
 
 }
 
@@ -207,26 +230,28 @@ void Probe::init(Parameter* para, GridProvider* gridProvider, CudaMemoryManager*
                        pointCoordsX_level, pointCoordsY_level, pointCoordsZ_level,
                        level);
         
-        this->addProbeStruct(cudaMemoryManager, probeIndices_level, 
+        this->addProbeStruct(para, cudaMemoryManager, probeIndices_level, 
                             distX_level, distY_level, distZ_level, 
                             pointCoordsX_level, pointCoordsY_level, pointCoordsZ_level, 
                             level);
+
+        if(this->outputTimeSeries) timeseriesFileNames.push_back(this->writeTimeseriesHeader(para, level));
     }
 }
 
-void Probe::addProbeStruct(CudaMemoryManager* cudaMemoryManager, std::vector<int>& probeIndices,
-                                      std::vector<real>& distX, std::vector<real>& distY, std::vector<real>& distZ,   
-                                      std::vector<real>& pointCoordsX, std::vector<real>& pointCoordsY, std::vector<real>& pointCoordsZ,
-                                      int level)
+void Probe::addProbeStruct( Parameter* para, CudaMemoryManager* cudaMemoryManager, std::vector<int>& probeIndices,
+                            std::vector<real>& distX, std::vector<real>& distY, std::vector<real>& distZ,   
+                            std::vector<real>& pointCoordsX, std::vector<real>& pointCoordsY, std::vector<real>& pointCoordsZ,
+                            int level)
 {
     probeParams[level] = SPtr<ProbeStruct>(new ProbeStruct);
-    probeParams[level]->vals = 1;
+    probeParams[level]->nTimesteps = this->getNumberOfTimestepsInTimeseries(para, level);
     probeParams[level]->nPoints  = uint(pointCoordsX.size()); // Note, need to have both nPoints and nIndices because they differ in PlanarAverage
     probeParams[level]->nIndices = uint(probeIndices.size());
 
-    probeParams[level]->pointCoordsX = (real*)malloc(probeParams[level]->nPoints*sizeof(real));
-    probeParams[level]->pointCoordsY = (real*)malloc(probeParams[level]->nPoints*sizeof(real));
-    probeParams[level]->pointCoordsZ = (real*)malloc(probeParams[level]->nPoints*sizeof(real));
+    probeParams[level]->pointCoordsX = (real*)malloc(probeParams[level]->nPoints * sizeof(real));
+    probeParams[level]->pointCoordsY = (real*)malloc(probeParams[level]->nPoints * sizeof(real));
+    probeParams[level]->pointCoordsZ = (real*)malloc(probeParams[level]->nPoints * sizeof(real));
 
     std::copy(pointCoordsX.begin(), pointCoordsX.end(), probeParams[level]->pointCoordsX);
     std::copy(pointCoordsY.begin(), pointCoordsY.end(), probeParams[level]->pointCoordsY);
@@ -267,39 +292,57 @@ void Probe::addProbeStruct(CudaMemoryManager* cudaMemoryManager, std::vector<int
 
     cudaMemoryManager->cudaAllocProbeQuantityArray(this, level);
 
-    for(uint arr=0; arr<probeParams[level]->nArrays; arr++)
-    {
-        for( uint point=0; point<probeParams[level]->nPoints; point++)
-        {
-            probeParams[level]->quantitiesArrayH[arr*probeParams[level]->nPoints+point] = 0.0f;
-        }
-    }
+    std::fill_n(probeParams[level]->quantitiesArrayH, probeParams[level]->nArrays*probeParams[level]->nPoints*probeParams[level]->nTimesteps, c0o1);
+
     if(this->hasDeviceQuantityArray)
         cudaMemoryManager->cudaCopyProbeQuantityArrayHtoD(this, level);
+
 }
 
 void Probe::interact(Parameter* para, CudaMemoryManager* cudaMemoryManager, int level, uint t)
 {
     uint t_level = para->getTimeStep(level, t, false);
 
+    SPtr<ProbeStruct> probeStruct = this->getProbeStruct(level);
+
+    //!Skip empty probes
+    if(probeStruct->nPoints==0) return;
+
     //! if tAvg==1 the probe will be evaluated in every sub-timestep of each respective level
     //! else, the probe will only be evaluated in each synchronous time step tAvg
 
-    uint tAvg_level = this->tAvg==1? this->tAvg: this->tAvg*pow(2,level);          
+    uint level_coefficient = exp2(level);
 
-    if(max(int(t_level) - int(this->tStartAvg*pow(2,level)), -1) % tAvg_level==0)
+    uint tAvg_level = this->tAvg == 1 ? this->tAvg : this->tAvg * level_coefficient;
+    uint tOut_level = this->tOut * level_coefficient;
+    uint tStartOut_level = this->tStartOut * level_coefficient;
+    uint tStartAvg_level = this->tStartAvg * level_coefficient;
+
+    uint tAfterStartAvg = t_level - tStartAvg_level;
+    uint tAfterStartOut = t_level - tStartOut_level;
+
+    if( (t > this->tStartAvg) && (tAfterStartAvg % tAvg_level == 0))
     {
-        SPtr<ProbeStruct> probeStruct = this->getProbeStruct(level);
         this->calculateQuantities(probeStruct, para, t_level, level);
-        if(t_level>=(this->tStartTmpAveraging*pow(2,level))) probeStruct->vals++;
+
+        if(t > this->tStartTmpAveraging) probeStruct->timestepInTimeAverage++;
+        if(this->outputTimeSeries && (t_level >= tStartOut_level)) probeStruct->timestepInTimeseries++;
     }
 
     //! output only in synchronous timesteps
-    if(max(int(t_level) - int(this->tStartOut*pow(2,level)), -1) % int(this->tOut*pow(2,level)) == 0)
+    if( (t > this->tStartOut) && (tAfterStartOut % tOut_level == 0) )
     {   
         if(this->hasDeviceQuantityArray)
             cudaMemoryManager->cudaCopyProbeQuantityArrayDtoH(this, level);
         this->write(para, level, t);
+        
+        if(level == 0&& !this->outputTimeSeries) this->writeParallelFile(para, t);
+
+        if(this->outputTimeSeries)
+        {
+            probeStruct->lastTimestepInOldTimeseries = probeStruct->timestepInTimeseries > 0 ? probeStruct->timestepInTimeseries - 1: 0;
+            probeStruct->timestepInTimeseries = 0;
+        }
     }
 }
 
@@ -315,11 +358,6 @@ void Probe::free(Parameter* para, CudaMemoryManager* cudaMemoryManager)
     }
 }
 
-void Probe::getTaggedFluidNodes(Parameter *para, GridProvider* gridProvider)
-{
-    // Do nothing
-};
-
 
 void Probe::addStatistic(Statistic variable)
 {
@@ -335,22 +373,32 @@ void Probe::addStatistic(Statistic variable)
     }
 }
 
+template<typename T>
+std::string nameComponent(std::string name, T value)
+{
+    return "_" + name + "_" + StringUtil::toString<T>(value); 
+}
+
 std::string Probe::makeParallelFileName(int id, int t)
 {
-    return this->probeName + "_bin_ID_" + StringUtil::toString<int>(id) 
-                                           + "_t_" + StringUtil::toString<int>(t) 
-                                           + ".vtk";
+    return this->probeName + "_bin" + nameComponent<int>("ID", id) + nameComponent<int>("t", t) + ".vtk"; 
+
 }
 
 std::string Probe::makeGridFileName(int level, int id, int t, uint part)
 {
-    return this->probeName + "_bin_lev_" + StringUtil::toString<int>(level)
-                                         + "_ID_" + StringUtil::toString<int>(id)
-                                         + "_Part_" + StringUtil::toString<int>(part) 
-                                         + "_t_" + StringUtil::toString<int>(t) 
-                                         + ".vtk";
+    return this->probeName + "_bin" + nameComponent<int>("lev", level)
+                                    + nameComponent<int>("ID", id)
+                                    + nameComponent<int>("Part", part)
+                                    + nameComponent<int>("t", t) + ".vtk";
 }
 
+std::string Probe::makeTimeseriesFileName(int level, int id)
+{
+    return this->probeName + "_timeseries" + nameComponent<int>("lev", level)
+                                    + nameComponent<int>("ID", id)
+                                    + ".txt";
+}
 void Probe::addAllAvailableStatistics()
 {
     for( int var=0; var < int(Statistic::LAST); var++)
@@ -362,16 +410,23 @@ void Probe::addAllAvailableStatistics()
 
 void Probe::write(Parameter* para, int level, int t)
 {
-    int t_write = this->fileNameLU ? t: t/this->tOut; 
+    if(this->outputTimeSeries)
+    {
+        this->appendTimeseriesFile(para, level, t);
+    }
+    else
+    {
+        int t_write = this->fileNameLU ? t: t/this->tOut; 
 
-    const uint numberOfParts = this->getProbeStruct(level)->nPoints / para->getlimitOfNodesForVTK() + 1;
+        const uint numberOfParts = this->getProbeStruct(level)->nPoints / para->getLimitOfNodesForVTK() + 1;
 
-    std::vector<std::string> fnames;
-    for (uint i = 1; i <= numberOfParts; i++)
-	{
-        this->writeGridFile(para, level, t_write, i);
+        std::vector<std::string> fnames;
+        for (uint i = 1; i <= numberOfParts; i++)
+        {
+            this->writeGridFile(para, level, t_write, i);
+        }
     }
-    if(level == 0&& !this->outputTimeSeries) this->writeParallelFile(para, t);
+
 }
 
 void Probe::writeParallelFile(Parameter* para, int t)
@@ -398,8 +453,8 @@ void Probe::writeGridFile(Parameter* para, int level, int t, uint part)
 
     SPtr<ProbeStruct> probeStruct = this->getProbeStruct(level);
 
-    uint startpos = (part-1) * para->getlimitOfNodesForVTK();
-    uint sizeOfNodes = min(para->getlimitOfNodesForVTK(), probeStruct->nPoints - startpos);
+    uint startpos = (part-1) * para->getLimitOfNodesForVTK();
+    uint sizeOfNodes = min(para->getLimitOfNodesForVTK(), probeStruct->nPoints - startpos);
     uint endpos = startpos + sizeOfNodes;
 
     //////////////////////////////////////////////////////////////////////////
@@ -414,25 +469,28 @@ void Probe::writeGridFile(Parameter* para, int level, int t, uint part)
 
     for( auto it=nodedata.begin(); it!=nodedata.end(); it++) it->resize(sizeOfNodes);
 
-    for( int var=0; var < int(Statistic::LAST); var++){           
+    uint arrLen = probeStruct->nPoints;
+    int nTimesteps = probeStruct->nTimesteps;
+    int timestep = probeStruct->timestepInTimeseries;
+
+    for( int var=0; var < int(Statistic::LAST); var++)
+    {           
         if(this->quantities[var])
         {
-            Statistic statistic = static_cast<Statistic>(var);
-            real coeff;
 
+            Statistic statistic = static_cast<Statistic>(var);
             std::vector<PostProcessingVariable> postProcessingVariables = this->getPostProcessingVariables(statistic);
             uint n_arrs = uint(postProcessingVariables.size());
 
             uint arrOff = probeStruct->arrayOffsetsH[var];
-            uint arrLen = probeStruct->nPoints;
 
             for(uint arr=0; arr<n_arrs; arr++)
             {
-                coeff = postProcessingVariables[arr].conversionFactor(level);
+                real coeff = postProcessingVariables[arr].conversionFactor(level);
                 
                 for (uint pos = startpos; pos < endpos; pos++)
                 {
-                    nodedata[arrOff+arr][pos-startpos] = double(probeStruct->quantitiesArrayH[(arrOff+arr)*arrLen+pos]*coeff);
+                    nodedata[arrOff+arr][pos-startpos] = double(probeStruct->quantitiesArrayH[calcArrayIndex(pos, arrLen, timestep, nTimesteps, arrOff+arr)]*coeff);
                 }
             }
         }
@@ -441,6 +499,91 @@ void Probe::writeGridFile(Parameter* para, int level, int t, uint part)
     this->fileNamesForCollectionFile.push_back(fullName.substr(fullName.find_last_of('/') + 1));
 }
 
+std::string Probe::writeTimeseriesHeader(Parameter* para, int level)
+{
+/*
+File Layout:
+TimeseriesOutput
+Quantities: Quant1 Quant2 Quant3
+Positions:
+point1.x, point1.y, point1.z
+point2.x, point2.y, point2.z
+...
+t0 point1.quant1 point2.quant1 ... point1.quant2 point2.quant2 ...
+t1 point1.quant1 point2.quant1 ... point1.quant2 point2.quant2 ...
+*/
+    auto probeStruct = this->getProbeStruct(level);
+    std::string fname = this->outputPath + "/" + this->makeTimeseriesFileName(level, para->getMyProcessID());
+    std::ofstream out(fname.c_str(), std::ios::out | std::ios::binary);
+
+    if(!out.is_open()) throw std::runtime_error("Could not open timeseries file!");
+
+    out << "TimeseriesOutput \n";
+    out << "Quantities: ";
+    for(std::string name : getVarNames())
+        out << name << ", ";
+    out << "\n";
+    out << "Number of points in this file: \n";
+    out << probeStruct->nPoints << "\n";
+    out << "Positions: x, y, z\n";
+    for( uint i=0; i<probeStruct->nPoints; i++)
+        out << probeStruct->pointCoordsX[i] << ", " << probeStruct->pointCoordsY[i] << ", " << probeStruct->pointCoordsZ[i] << "\n";
+
+    out.close();
+
+    return fname;
+}
+
+void Probe::appendTimeseriesFile(Parameter* para, int level, int t)
+{
+    std::ofstream out(this->timeseriesFileNames[level], std::ios::app | std::ios::binary);
+
+    uint t_level = para->getTimeStep(level, t, false);
+    uint tAvg_level = this->tAvg==1 ? this->tAvg: this->tAvg*exp2(-level);
+
+    real dt = para->getTimeRatio()*tAvg_level;
+    auto probeStruct = this->getProbeStruct(level);
+
+    real t_start = ( t-this->tOut )*para->getTimeRatio();
+
+    int vals_per_timestep = probeStruct->nPoints*probeStruct->nArrays+1;
+
+    real* timestep_array = (real*) malloc(vals_per_timestep*sizeof(real));
+
+    for(uint timestep=0; timestep<probeStruct->timestepInTimeseries; timestep++)
+    {
+        int val = 0;
+        timestep_array[val] = t_start+timestep*dt;
+        val++;
+
+        for( int var=0; var < int(Statistic::LAST); var++)
+        {           
+            if(!this->quantities[var]) continue;
+            
+            Statistic statistic = static_cast<Statistic>(var);
+            std::vector<PostProcessingVariable> postProcessingVariables = this->getPostProcessingVariables(statistic);
+            uint n_arrs = uint(postProcessingVariables.size());
+
+            uint arrOff = probeStruct->arrayOffsetsH[var];
+
+            for(uint arr=0; arr<n_arrs; arr++)
+            {
+                real coeff = postProcessingVariables[arr].conversionFactor(level);
+                for(uint point=0; point<probeStruct->nPoints; point++)
+                {
+                    timestep_array[val] = probeStruct->quantitiesArrayH[calcArrayIndex(point, probeStruct->nPoints, timestep, probeStruct->nTimesteps, arrOff+arr)]*coeff;
+                    val++;
+                }
+            }
+            
+        }
+        out.write((char*) timestep_array, sizeof(real)*vals_per_timestep);
+    }
+    out.close();
+}
+
+
+
 std::vector<std::string> Probe::getVarNames()
 {
     std::vector<std::string> varNames;
@@ -454,4 +597,4 @@ std::vector<std::string> Probe::getVarNames()
         }
     }
     return varNames;
-}
\ No newline at end of file
+}
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h
index aaf294e87d23c64707a16692b9337d6e9ff9c896..c7391e2a3d6b858facfd4fba094d7942f2bf4505 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/Probe.h
@@ -100,7 +100,11 @@ typedef struct PostProcessingVariable{
 } PostProcessingVariable;
 
 struct ProbeStruct{
-    uint nPoints, nIndices, nArrays, vals;
+    uint nPoints, nIndices, nArrays;
+    uint nTimesteps=1;
+    uint timestepInTimeseries=0;
+    uint timestepInTimeAverage=0;
+    uint lastTimestepInOldTimeseries=0;
     uint *pointIndicesH, *pointIndicesD;
     real *pointCoordsX, *pointCoordsY, *pointCoordsZ;
     bool hasDistances=false;
@@ -110,9 +114,10 @@ struct ProbeStruct{
     uint *arrayOffsetsH, *arrayOffsetsD;
     bool isEvenTAvg = true;
 };
+__host__ __device__ int calcArrayIndex(int node, int nNodes, int timestep, int nTimesteps, int array);
 
 __global__ void calcQuantitiesKernel(   uint* pointIndices,
-                                    uint nPoints, uint n,
+                                    uint nPoints, uint oldTimestepInTimeseries, uint timestepInTimeseries, uint timestepInAverage, uint nTimesteps,
                                     real* vx, real* vy, real* vz, real* rho,            
                                     uint* neighborX, uint* neighborY, uint* neighborZ,
                                     bool* quantities,
@@ -120,7 +125,7 @@ __global__ void calcQuantitiesKernel(   uint* pointIndices,
                                 );
 
 __global__ void interpAndCalcQuantitiesKernel(   uint* pointIndices,
-                                    uint nPoints, uint n,
+                                    uint nPoints, uint oldTimestepInTimeseries, uint timestepInTimeseries, uint timestepInAverage, uint nTimesteps,
                                     real* distX, real* distY, real* distZ,
                                     real* vx, real* vy, real* vz, real* rho,            
                                     uint* neighborX, uint* neighborY, uint* neighborZ,
@@ -128,6 +133,7 @@ __global__ void interpAndCalcQuantitiesKernel(   uint* pointIndices,
                                     uint* quantityArrayOffsets, real* quantityArray
                                 );
 
+uint calcOldTimestep(uint currentTimestep, uint lastTimestepInOldSeries);
 
 class Probe : public PreCollisionInteractor 
 {
@@ -135,13 +141,13 @@ public:
     Probe(
         const std::string _probeName,
         const std::string _outputPath,
-        uint _tStartAvg,
-        uint _tStartTmpAvg,
-        uint _tAvg,
-        uint _tStartOut,
-        uint _tOut,
-        bool _hasDeviceQuantityArray,
-        bool _outputTimeSeries
+        const uint _tStartAvg,
+        const uint _tStartTmpAvg,
+        const uint _tAvg,
+        const uint _tStartOut,
+        const uint _tOut,
+        const bool _hasDeviceQuantityArray,
+        const bool _outputTimeSeries
     ):  probeName(_probeName),
         outputPath(_outputPath),
         tStartAvg(_tStartAvg),
@@ -153,13 +159,12 @@ public:
         outputTimeSeries(_outputTimeSeries),        
         PreCollisionInteractor()
     {
-        if (_tStartOut<_tStartAvg)      throw std::runtime_error("Probe: tStartOut must be larger than tStartAvg!");
+        if (tStartOut < tStartAvg)      throw std::runtime_error("Probe: tStartOut must be larger than tStartAvg!");
     }
     
     void init(Parameter* para, GridProvider* gridProvider, CudaMemoryManager* cudaMemoryManager) override;
     void interact(Parameter* para, CudaMemoryManager* cudaMemoryManager, int level, uint t) override;
     void free(Parameter* para, CudaMemoryManager* cudaMemoryManager) override;
-    virtual void getTaggedFluidNodes(Parameter *para, GridProvider* gridProvider) override;
 
     SPtr<ProbeStruct> getProbeStruct(int level){ return this->probeParams[level]; }
 
@@ -170,7 +175,6 @@ public:
     uint getTStartTmpAveraging(){return this->tStartTmpAveraging;}
 
     void setFileNameToNOut(){this->fileNameLU = false;}
-    void setTStartTmpAveraging(uint _tStartTmpAveraging){this->tStartTmpAveraging = _tStartTmpAveraging;}
 
 protected:
     virtual WbWriterVtkXmlBinary* getWriter(){ return WbWriterVtkXmlBinary::getInstance(); };
@@ -185,7 +189,7 @@ private:
                        std::vector<real>& distX_level, std::vector<real>& distY_level, std::vector<real>& distZ_level,      
                        std::vector<real>& pointCoordsX_level, std::vector<real>& pointCoordsY_level, std::vector<real>& pointCoordsZ_level,
                        int level) = 0;
-    void addProbeStruct(CudaMemoryManager* cudaMemoryManager, std::vector<int>& probeIndices,
+    void addProbeStruct(Parameter* para, CudaMemoryManager* cudaMemoryManager, std::vector<int>& probeIndices,
                         std::vector<real>& distX, std::vector<real>& distY, std::vector<real>& distZ,   
                         std::vector<real>& pointCoordsX, std::vector<real>& pointCoordsY, std::vector<real>& pointCoordsZ,
                         int level);
@@ -194,10 +198,15 @@ private:
     virtual void write(Parameter* para, int level, int t);
     virtual void writeParallelFile(Parameter* para, int t);
     virtual void writeGridFile(Parameter* para, int level, int t, uint part);
+    std::string writeTimeseriesHeader(Parameter* para, int level);
+    void appendTimeseriesFile(Parameter* para, int level, int t);
 
     std::vector<std::string> getVarNames();
     std::string makeGridFileName(int level, int id, int t, uint part);
     std::string makeParallelFileName(int id, int t);
+    std::string makeTimeseriesFileName(int leve, int id);
+
+    virtual uint getNumberOfTimestepsInTimeseries(Parameter* para, int level){ return 1; }
 
 protected:
     const std::string probeName;
@@ -205,20 +214,19 @@ protected:
 
     std::vector<SPtr<ProbeStruct>> probeParams;
     bool quantities[int(Statistic::LAST)] = {};
-    bool hasDeviceQuantityArray;    //!> flag initiating memCopy in Point and PlaneProbe. Other probes are only based on thrust reduce functions and therefore dont need explict memCopy in interact()
-    bool outputTimeSeries;          //!> flag initiating overwrite of output vtk files, skipping collection files and limiting the length of the written data to the current time step (currently only used for WallModelProbe)
+    const bool hasDeviceQuantityArray;    //!> flag initiating memCopy in Point and PlaneProbe. Other probes are only based on thrust reduce functions and therefore dont need explict memCopy in interact()
+    const bool outputTimeSeries;        //!> flag initiating time series output in Point and WallModelProbe.
     std::vector<std::string> fileNamesForCollectionFile;
+    std::vector<std::string> timeseriesFileNames;
 
     bool fileNameLU = true; //!> if true, written file name contains time step in LU, else is the number of the written probe files
 
 protected:
-    uint tStartAvg;
-    uint tStartTmpAveraging; //!> only non-zero in PlanarAverageProbe and WallModelProbe to switch on Spatio-temporal averaging (while only doing spatial averaging for t<tStartTmpAveraging) 
-    uint tAvg;  //! for tAvg==1 the probe will be evaluated in every sub-timestep of each respective level, else, the probe will only be evaluated in each synchronous time step 
-    uint tStartOut;
-    uint tOut;
-
-    uint tProbe = 0; //!> counter for number of probe evaluations. Only used when outputting timeseries
+    const uint tStartAvg;
+    const uint tStartTmpAveraging; //!> only non-zero in PlanarAverageProbe and WallModelProbe to switch on Spatio-temporal averaging (while only doing spatial averaging for t<tStartTmpAveraging) 
+    const uint tAvg;  //! for tAvg==1 the probe will be evaluated in every sub-timestep of each respective level, else, the probe will only be evaluated in each synchronous time step 
+    const uint tStartOut;
+    const uint tOut;
 
     std::function<real(int)> velocityRatio;
     std::function<real(int)> densityRatio;
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu
index 3341111c134ace7ca6ff64eeb7f87b38f8014656..f52c666c920a049012888e8e1b71578e68d3da31 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.cu
@@ -10,63 +10,15 @@
 #include <thrust/device_vector.h>
 #include <thrust/reduce.h>
 #include <thrust/device_ptr.h>
-#include <thrust/inner_product.h>
 
 #include "Parameter/Parameter.h"
 #include "DataStructureInitializer/GridProvider.h"
 #include "GPU/CudaMemoryManager.h"
+#include "basics/constants/NumericConstants.h"
 
-
-///////////////////////////////////////////////////////////////////////////////////
-/// Functors for thrust reductions
-///////////////////////////////////////////////////////////////////////////////////
-
-template<typename T>
-struct pow2 : public thrust::unary_function<T,T>
-{
-  __host__ __device__ T operator()(const T &x) const
-  {
-    return x * x;
-  }
-};
-
-template<typename T>
-struct pow3 : public thrust::unary_function<T,T>
-{
-  __host__ __device__ T operator()(const T &x) const
-  {
-    return x * x * x;
-  }
-};
-
-template<typename T>
-struct pow4 : public thrust::unary_function<T,T>
-{
-  __host__ __device__ T operator()(const T &x) const
-  {
-    return x * x * x * x;
-  }
-};
-
-struct nth_moment
-{
-    const float mean;
-    const int n;
-
-    nth_moment(float _mean, int _n) : mean(_mean), n(_n) {}
-
-    __host__ __device__
-        float operator()(const float& x) const { 
-            
-            real fluctuation = x-mean;
-            real moment = fluctuation;
-            for(int i = 1; i<n; i++) moment *= fluctuation;
-            
-            return moment;
-        }
-};
-
-
+using namespace vf::basics::constant;
+typedef thrust::device_vector<real>::iterator valIterator;
+typedef thrust::device_vector<uint>::iterator indIterator;
 ///////////////////////////////////////////////////////////////////////////////////
 bool WallModelProbe::isAvailableStatistic(Statistic _variable)
 {
@@ -156,16 +108,10 @@ void WallModelProbe::findPoints(Parameter* para, GridProvider* gridProvider, std
                             int level)
 {
     if ( !para->getHasWallModelMonitor())                    throw std::runtime_error("WallModelProbe::findPoints(): !para->getHasWallModelMonitor() !");
-
-    real dt = para->getTimeRatio();
-    uint nt = uint((para->getTimestepEnd()-this->tStartAvg)/this->tAvg);
     
-    for(uint t=0; t<nt; t++)
-    {
-        pointCoordsX_level.push_back(dt*(t*this->tAvg)+this->tStartAvg); // x coord will serve as time in this probe
-        pointCoordsY_level.push_back(0);
-        pointCoordsZ_level.push_back(0);
-    }
+    pointCoordsX_level.push_back(0); 
+    pointCoordsY_level.push_back(0);
+    pointCoordsZ_level.push_back(0);
 
     if(this->evaluatePressureGradient)
     {
@@ -183,118 +129,109 @@ void WallModelProbe::findPoints(Parameter* para, GridProvider* gridProvider, std
 
 ///////////////////////////////////////////////////////////////////////////////////
 
+template<typename T>
+T spatial_mean(T* device_pointer, uint numberOfPoints)
+{
+    thrust::device_ptr<T> thrust_pointer = thrust::device_pointer_cast(device_pointer);
+    return thrust::reduce(thrust_pointer, thrust_pointer+numberOfPoints)/real(numberOfPoints);
+}
+
+template<typename T>
+T index_based_spatial_mean(T* device_pointer, thrust::device_ptr<uint> indeces_ptr, uint numberOfIndeces)
+{
+    thrust::device_ptr<T> thrust_pointer = thrust::device_pointer_cast(device_pointer);
+
+    thrust::permutation_iterator<valIterator, indIterator> iter_begin(thrust_pointer, indeces_ptr);
+    thrust::permutation_iterator<valIterator, indIterator> iter_end  (thrust_pointer, indeces_ptr+numberOfIndeces);
+    return thrust::reduce(iter_begin, iter_end)/real(numberOfIndeces);
+}
+
+template<typename T>
+T compute_and_save_mean(T* device_pointer, uint numberOfPoints, T* quantitiesArray, uint timestep, uint numberOfTimesteps, uint indexOfArray)
+{
+    T mean = spatial_mean(device_pointer, numberOfPoints);
+    quantitiesArray[calcArrayIndex(0, 1, timestep, numberOfTimesteps, indexOfArray)] = mean;
+    return mean;
+}
+
+template<typename T>
+T compute_and_save_index_based_mean(T* device_pointer, thrust::device_ptr<uint> indeces_ptr, uint numberOfIndices, T* quantitiesArray, uint timestep, uint numberOfTimesteps, uint indexOfArray)
+{
+    T mean = index_based_spatial_mean(device_pointer, indeces_ptr, numberOfIndices);
+    quantitiesArray[calcArrayIndex(0, 1, timestep, numberOfTimesteps, indexOfArray)] = mean;
+    return mean;
+}
+
+template<typename T>
+void temporal_average(T* quantitiesArray, T currentValue, uint currentTimestep, uint numberOfTimesteps, uint oldTimestep, uint indexOfArray, real invNumberOfAverages)
+{
+    T oldMean = quantitiesArray[calcArrayIndex(0, 1, oldTimestep, numberOfTimesteps, indexOfArray)];
+    quantitiesArray[calcArrayIndex(0, 1, currentTimestep, numberOfTimesteps, indexOfArray)] = oldMean + (currentValue-oldMean)*invNumberOfAverages;
+}
+
 void WallModelProbe::calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t, int level)
 {   
     bool doTmpAveraging = (t>this->getTStartTmpAveraging());
-    real N = para->getParD(level)->stressBC.numberOfBCnodes;
-    if(N<1) return; //Skipping levels without StressBC
-    real n = (real)probeStruct->vals;
-    int nPoints = probeStruct->nPoints;
-
-    // Pointer casts to use device arrays in thrust reductions
-    thrust::device_ptr<real> u_el_thrust    = thrust::device_pointer_cast(para->getParD(level)->stressBC.Vx);
-    thrust::device_ptr<real> v_el_thrust    = thrust::device_pointer_cast(para->getParD(level)->stressBC.Vy);
-    thrust::device_ptr<real> w_el_thrust    = thrust::device_pointer_cast(para->getParD(level)->stressBC.Vz);
-    thrust::device_ptr<real> u1_thrust      = thrust::device_pointer_cast(para->getParD(level)->stressBC.Vx1);
-    thrust::device_ptr<real> v1_thrust      = thrust::device_pointer_cast(para->getParD(level)->stressBC.Vy1);
-    thrust::device_ptr<real> w1_thrust      = thrust::device_pointer_cast(para->getParD(level)->stressBC.Vz1);
-    thrust::device_ptr<real> u_star_thrust  = thrust::device_pointer_cast(para->getParD(level)->wallModel.u_star);
-    thrust::device_ptr<real> Fx_thrust      = thrust::device_pointer_cast(para->getParD(level)->wallModel.Fx);
-    thrust::device_ptr<real> Fy_thrust      = thrust::device_pointer_cast(para->getParD(level)->wallModel.Fy);
-    thrust::device_ptr<real> Fz_thrust      = thrust::device_pointer_cast(para->getParD(level)->wallModel.Fz);
-    thrust::device_ptr<real> dpdx_thrust    = thrust::device_pointer_cast(para->getParD(level)->forceX_SP);
-    thrust::device_ptr<real> dpdy_thrust    = thrust::device_pointer_cast(para->getParD(level)->forceY_SP);
-    thrust::device_ptr<real> dpdz_thrust    = thrust::device_pointer_cast(para->getParD(level)->forceZ_SP);
+    uint numberOfStressBCPoints = para->getParD(level)->stressBC.numberOfBCnodes;
+    if(numberOfStressBCPoints<1) return; //Skipping levels without StressBC
+    uint timestep = probeStruct->timestepInTimeseries;
+    real inv_n = c1o1/real(probeStruct->timestepInTimeAverage+1);
+    uint oldTimestep = calcOldTimestep(timestep, probeStruct->lastTimestepInOldTimeseries);
 
     thrust::device_ptr<uint> indices_thrust = thrust::device_pointer_cast(probeStruct->pointIndicesD);
-    typedef thrust::device_vector<real>::iterator valIterator;
-    typedef thrust::device_vector<uint>::iterator indIterator;
-    thrust::permutation_iterator<valIterator, indIterator> dpdx_iter_begin(dpdx_thrust, indices_thrust);
-    thrust::permutation_iterator<valIterator, indIterator> dpdx_iter_end  (dpdx_thrust, indices_thrust+probeStruct->nIndices);
-    thrust::permutation_iterator<valIterator, indIterator> dpdy_iter_begin(dpdy_thrust, indices_thrust);
-    thrust::permutation_iterator<valIterator, indIterator> dpdy_iter_end  (dpdy_thrust, indices_thrust+probeStruct->nIndices);
-    thrust::permutation_iterator<valIterator, indIterator> dpdz_iter_begin(dpdz_thrust, indices_thrust);
-    thrust::permutation_iterator<valIterator, indIterator> dpdz_iter_end  (dpdz_thrust, indices_thrust+probeStruct->nIndices);
 
     if(probeStruct->quantitiesH[int(Statistic::SpatialMeans)])
     {
-        // Compute the instantaneous spatial means of the velocity moments 
-        real spatMean_u_el      = thrust::reduce(u_el_thrust, u_el_thrust+N)/N;
-        real spatMean_v_el      = thrust::reduce(v_el_thrust, v_el_thrust+N)/N;
-        real spatMean_w_el      = thrust::reduce(w_el_thrust, w_el_thrust+N)/N;
-        real spatMean_u1        = thrust::reduce(u1_thrust, u1_thrust+N)/N;
-        real spatMean_v1        = thrust::reduce(v1_thrust, v1_thrust+N)/N;
-        real spatMean_w1        = thrust::reduce(w1_thrust, w1_thrust+N)/N;
-        real spatMean_u_star    = thrust::reduce(u_star_thrust, u_star_thrust+N)/N;
-        real spatMean_Fx        = thrust::reduce(Fx_thrust, Fx_thrust+N)/N;
-        real spatMean_Fy        = thrust::reduce(Fy_thrust, Fy_thrust+N)/N;
-        real spatMean_Fz        = thrust::reduce(Fz_thrust, Fz_thrust+N)/N;
-
         uint arrOff = probeStruct->arrayOffsetsH[int(Statistic::SpatialMeans)];
-        probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+tProbe] = spatMean_u_el;
-        probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+tProbe] = spatMean_v_el;
-        probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+tProbe] = spatMean_w_el;
-        probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+tProbe] = spatMean_u1;
-        probeStruct->quantitiesArrayH[(arrOff+4)*nPoints+tProbe] = spatMean_v1;
-        probeStruct->quantitiesArrayH[(arrOff+5)*nPoints+tProbe] = spatMean_w1;
-        probeStruct->quantitiesArrayH[(arrOff+6)*nPoints+tProbe] = spatMean_u_star;
-        probeStruct->quantitiesArrayH[(arrOff+7)*nPoints+tProbe] = spatMean_Fx;
-        probeStruct->quantitiesArrayH[(arrOff+8)*nPoints+tProbe] = spatMean_Fy;
-        probeStruct->quantitiesArrayH[(arrOff+9)*nPoints+tProbe] = spatMean_Fz;
+        // Compute the instantaneous spatial means of the velocity moments 
+        real spatMean_u_el      = compute_and_save_mean(para->getParD(level)->stressBC.Vx     , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+0);
+        real spatMean_v_el      = compute_and_save_mean(para->getParD(level)->stressBC.Vy     , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+1);
+        real spatMean_w_el      = compute_and_save_mean(para->getParD(level)->stressBC.Vz     , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+2);
+        real spatMean_u1        = compute_and_save_mean(para->getParD(level)->stressBC.Vx1    , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+3);
+        real spatMean_v1        = compute_and_save_mean(para->getParD(level)->stressBC.Vy1    , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+4);
+        real spatMean_w1        = compute_and_save_mean(para->getParD(level)->stressBC.Vz1    , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+5);
+        real spatMean_u_star    = compute_and_save_mean(para->getParD(level)->wallModel.u_star, numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+6);
+        real spatMean_Fx        = compute_and_save_mean(para->getParD(level)->wallModel.Fx    , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+7);
+        real spatMean_Fy        = compute_and_save_mean(para->getParD(level)->wallModel.Fy    , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+8);
+        real spatMean_Fz        = compute_and_save_mean(para->getParD(level)->wallModel.Fz    , numberOfStressBCPoints, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+9);
 
         real spatMean_dpdx;
         real spatMean_dpdy;
         real spatMean_dpdz;
         if(this->evaluatePressureGradient)
         {
-            real N_fluid = (real)probeStruct->nIndices;
-            spatMean_dpdx      = thrust::reduce(dpdx_iter_begin, dpdx_iter_end)/N_fluid;
-            spatMean_dpdy      = thrust::reduce(dpdy_iter_begin, dpdy_iter_end)/N_fluid;
-            spatMean_dpdz      = thrust::reduce(dpdz_iter_begin, dpdz_iter_end)/N_fluid;
-            probeStruct->quantitiesArrayH[(arrOff+10)*nPoints+tProbe] = spatMean_dpdx;
-            probeStruct->quantitiesArrayH[(arrOff+11)*nPoints+tProbe] = spatMean_dpdy;
-            probeStruct->quantitiesArrayH[(arrOff+12)*nPoints+tProbe] = spatMean_dpdz;
+            spatMean_dpdx = compute_and_save_index_based_mean(para->getParD(level)->forceX_SP, indices_thrust, probeStruct->nIndices, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+10);
+            spatMean_dpdy = compute_and_save_index_based_mean(para->getParD(level)->forceY_SP, indices_thrust, probeStruct->nIndices, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+11);
+            spatMean_dpdz = compute_and_save_index_based_mean(para->getParD(level)->forceZ_SP, indices_thrust, probeStruct->nIndices, probeStruct->quantitiesArrayH, timestep, probeStruct->nTimesteps, arrOff+12);
         }
 
         if(probeStruct->quantitiesH[int(Statistic::SpatioTemporalMeans)] && doTmpAveraging)
         {
             uint arrOff = probeStruct->arrayOffsetsH[int(Statistic::SpatioTemporalMeans)];
-            real spatMean_u_el_old      = probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+tProbe-1];
-            real spatMean_v_el_old      = probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+tProbe-1];
-            real spatMean_w_el_old      = probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+tProbe-1];
-            real spatMean_u1_old        = probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+tProbe-1];
-            real spatMean_v1_old        = probeStruct->quantitiesArrayH[(arrOff+4)*nPoints+tProbe-1];
-            real spatMean_w1_old        = probeStruct->quantitiesArrayH[(arrOff+5)*nPoints+tProbe-1];
-            real spatMean_u_star_old    = probeStruct->quantitiesArrayH[(arrOff+6)*nPoints+tProbe-1];
-            real spatMean_Fx_old        = probeStruct->quantitiesArrayH[(arrOff+7)*nPoints+tProbe-1];
-            real spatMean_Fy_old        = probeStruct->quantitiesArrayH[(arrOff+8)*nPoints+tProbe-1];
-            real spatMean_Fz_old        = probeStruct->quantitiesArrayH[(arrOff+9)*nPoints+tProbe-1];
-
-            probeStruct->quantitiesArrayH[(arrOff+0)*nPoints+tProbe] = spatMean_u_el_old + (spatMean_u_el-spatMean_u_el_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+1)*nPoints+tProbe] = spatMean_v_el_old + (spatMean_v_el-spatMean_v_el_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+2)*nPoints+tProbe] = spatMean_w_el_old + (spatMean_w_el-spatMean_w_el_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+3)*nPoints+tProbe] = spatMean_u1_old + (spatMean_u1-spatMean_u1_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+4)*nPoints+tProbe] = spatMean_v1_old + (spatMean_v1-spatMean_v1_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+5)*nPoints+tProbe] = spatMean_w1_old + (spatMean_w1-spatMean_w1_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+6)*nPoints+tProbe] = spatMean_u_star_old +(spatMean_u_star-spatMean_u_star_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+7)*nPoints+tProbe] = spatMean_Fx_old + (spatMean_Fx-spatMean_Fx_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+8)*nPoints+tProbe] = spatMean_Fy_old + (spatMean_Fy-spatMean_Fy_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+9)*nPoints+tProbe] = spatMean_Fz_old + (spatMean_Fz-spatMean_Fz_old)/n;
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_u_el  , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+0, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_v_el  , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+1, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_w_el  , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+2, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_u1    , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+3, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_v1    , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+4, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_w1    , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+5, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_u_star, timestep, probeStruct->nTimesteps, oldTimestep, arrOff+6, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_Fx    , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+7, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_Fy    , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+8, inv_n);
+            temporal_average(probeStruct->quantitiesArrayH, spatMean_Fz    , timestep, probeStruct->nTimesteps, oldTimestep, arrOff+9, inv_n);
 
             if(this->evaluatePressureGradient)
             {
-            real spatMean_dpdx_old     = probeStruct->quantitiesArrayH[(arrOff+10)*nPoints+tProbe-1];
-            real spatMean_dpdy_old     = probeStruct->quantitiesArrayH[(arrOff+11)*nPoints+tProbe-1];
-            real spatMean_dpdz_old     = probeStruct->quantitiesArrayH[(arrOff+12)*nPoints+tProbe-1];
-            probeStruct->quantitiesArrayH[(arrOff+10)*nPoints+tProbe] = spatMean_dpdx_old + (spatMean_dpdx-spatMean_dpdx_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+11)*nPoints+tProbe] = spatMean_dpdy_old + (spatMean_dpdy-spatMean_dpdy_old)/n;
-            probeStruct->quantitiesArrayH[(arrOff+12)*nPoints+tProbe] = spatMean_dpdz_old + (spatMean_dpdz-spatMean_dpdz_old)/n;
+                temporal_average(probeStruct->quantitiesArrayH, spatMean_dpdx, timestep, probeStruct->nTimesteps, oldTimestep, arrOff+10, inv_n);
+                temporal_average(probeStruct->quantitiesArrayH, spatMean_dpdy, timestep, probeStruct->nTimesteps, oldTimestep, arrOff+11, inv_n);
+                temporal_average(probeStruct->quantitiesArrayH, spatMean_dpdz, timestep, probeStruct->nTimesteps, oldTimestep, arrOff+12, inv_n);
             }
         }    
     }
-        
-
-    this->tProbe += 1;
     getLastCudaError("WallModelProbe::calculateQuantities execution failed");
 }
 
+uint WallModelProbe::getNumberOfTimestepsInTimeseries(Parameter* para, int level)
+{
+    return this->tOut*exp2(level)/this->tAvg+1; 
+}
+
diff --git a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.h b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.h
index 4ea90f74c7a0d57af4995e1b5874234967f1e901..c912656d2dcbb9551b8a156f7fe9818de0f315a4 100644
--- a/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.h
+++ b/src/gpu/VirtualFluids_GPU/PreCollisionInteractor/Probes/WallModelProbe.h
@@ -81,6 +81,8 @@ private:
                     std::vector<real>& pointCoordsX_level, std::vector<real>& pointCoordsY_level, std::vector<real>& pointCoordsZ_level,
                     int level) override;
     void calculateQuantities(SPtr<ProbeStruct> probeStruct, Parameter* para, uint t, int level) override;
+    void getTaggedFluidNodes(Parameter *para, GridProvider* gridProvider) override {};
+    uint getNumberOfTimestepsInTimeseries(Parameter* para, int level) override;
 
 private:
     bool outputStress = false; //!> if true, output wall force is converted to a stress 
diff --git a/src/lbm/MacroscopicQuantities.h b/src/lbm/MacroscopicQuantities.h
index 5a93222a5efae2d1814411053360d66ef132d62c..e1b066a104874a95701ff3a77f6747884c5a54d7 100644
--- a/src/lbm/MacroscopicQuantities.h
+++ b/src/lbm/MacroscopicQuantities.h
@@ -53,6 +53,14 @@ inline __host__ __device__ real getIncompressibleVelocityX3(const real *const &f
             (((f[dir::DIR_0MP] - f[dir::DIR_0PM]) + (f[dir::DIR_0PP] - f[dir::DIR_0MM])) + ((f[dir::DIR_M0P] - f[dir::DIR_P0M]) + (f[dir::DIR_P0P] - f[dir::DIR_M0M]))) + (f[dir::DIR_00P] - f[dir::DIR_00M]));
 }
 
+inline __host__ __device__ void getIncompressibleMacroscopicValues(const real *const &f /*[27]*/, real &rho, real &vx1, real &vx2, real &vx3)
+{
+    rho = getDensity(f);
+    vx1 = getIncompressibleVelocityX1(f);
+    vx2 = getIncompressibleVelocityX2(f);
+    vx3 = getIncompressibleVelocityX3(f);
+}
+
 
 
 /*
@@ -75,6 +83,25 @@ inline __host__ __device__ real getCompressibleVelocityX3(const real *const &f27
     return getIncompressibleVelocityX3(f27) / (rho + basics::constant::c1o1);
 }
 
+inline __host__ __device__ void getCompressibleMacroscopicValues(const real *const &f /*[27]*/, real &drho, real& oneOverRho, real &vx1, real &vx2, real &vx3)
+{
+    drho = getDensity(f);
+    vx1 = getIncompressibleVelocityX1(f);
+    vx2 = getIncompressibleVelocityX2(f);
+    vx3 = getIncompressibleVelocityX3(f);
+    oneOverRho = vf::basics::constant::c1o1 / (drho + vf::basics::constant::c1o1);
+    vx1 *= oneOverRho;
+    vx2 *= oneOverRho;
+    vx3 *= oneOverRho;
+}
+
+inline __host__ __device__ void getCompressibleMacroscopicValues(const real *const &f /*[27]*/, real &drho, real &vx1, real &vx2, real &vx3)
+{
+    real oneOverRho;
+    getCompressibleMacroscopicValues(f, drho, oneOverRho, vx1, vx2, vx3);
+}
+
+
 /*
 * Pressure
 */
diff --git a/src/lbm/MacroscopicQuantitiesTests.cpp b/src/lbm/MacroscopicQuantitiesTests.cpp
index 382ec180e7a97749c4a005734a61f96ec7a146d5..b39387ae7ac741cc4dc36b4c58de4bad43052793 100644
--- a/src/lbm/MacroscopicQuantitiesTests.cpp
+++ b/src/lbm/MacroscopicQuantitiesTests.cpp
@@ -1,30 +1,43 @@
 #include <gmock/gmock.h>
+#include <array>
 
 #include "MacroscopicQuantities.h"
 #include "constants/D3Q27.h"
 
+#include <basics/tests/testUtilities.h>
+
 
 /*
 * given distributions, which are all one.
 */
-real f[27] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+// real f[27] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+
+class MacroscopicQuantitiesTest : public testing::Test {
+
+    void SetUp() override {
+       f = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+    }
+
+    public:
+    std::array<real, 27> f;
+};
 
 using namespace vf::lbm;
 
 
-TEST(MacroscopicQuantitiesTest, check_density)
+TEST_F(MacroscopicQuantitiesTest, check_density)
 {
-    const double density = getDensity(f);
+    const double density = getDensity(f.data());
 
     const double expected_density = 27.;
     ASSERT_THAT(density, testing::DoubleEq(expected_density));
 }
 
-TEST(MacroscopicQuantitiesTest, whenFsAreEqual_velocityInEachDirectionShouldBeZero)
+TEST_F(MacroscopicQuantitiesTest, whenFsAreEqual_velocityInEachDirectionShouldBeZero)
 {
-    const double velocityX1 = getIncompressibleVelocityX1(f);
-    const double velocityX2 = getIncompressibleVelocityX2(f);
-    const double velocityX3 = getIncompressibleVelocityX3(f);
+    const double velocityX1 = getIncompressibleVelocityX1(f.data());
+    const double velocityX2 = getIncompressibleVelocityX2(f.data());
+    const double velocityX3 = getIncompressibleVelocityX3(f.data());
 
     const double expected_velocity = 0.;
     EXPECT_THAT(velocityX1, testing::DoubleEq(expected_velocity));
@@ -32,13 +45,13 @@ TEST(MacroscopicQuantitiesTest, whenFsAreEqual_velocityInEachDirectionShouldBeZe
     EXPECT_THAT(velocityX3, testing::DoubleEq(expected_velocity));
 }
 
-TEST(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Eis2_velocityInX1ShouldBeOne)
+TEST_F(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Eis2_velocityInX1ShouldBeOne)
 {
     f[dir::DIR_P00] = 2.;
 
-    const double velocityX1 = getIncompressibleVelocityX1(f);
-    const double velocityX2 = getIncompressibleVelocityX2(f);
-    const double velocityX3 = getIncompressibleVelocityX3(f);
+    const double velocityX1 = getIncompressibleVelocityX1(f.data());
+    const double velocityX2 = getIncompressibleVelocityX2(f.data());
+    const double velocityX3 = getIncompressibleVelocityX3(f.data());
 
     const double expected_velocity_x1 = 1.;
     const double expected_velocity_x2 = 0.;
@@ -49,23 +62,41 @@ TEST(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Eis2_velocityInX1ShouldBeO
     EXPECT_THAT(velocityX3, testing::DoubleEq(expected_velocity_x3));
 }
 
-TEST(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Nis2_velocityInX2ShouldBeOne)
+TEST_F(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Nis2_velocityInX2ShouldBeOne)
 {
     f[dir::DIR_0P0] = 2.;
 
-    const double velocity = getIncompressibleVelocityX2(f);
+    const double velocity = getIncompressibleVelocityX2(f.data());
 
     const double expected_velocity = 1.;
     ASSERT_THAT(velocity, testing::DoubleEq(expected_velocity));
 }
 
 
-TEST(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Tis2_velocityInX3ShouldBeOne)
+TEST_F(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Tis2_velocityInX3ShouldBeOne)
 {
     f[dir::DIR_00P] = 2.;
 
-    const double velocity = getIncompressibleVelocityX3(f);
+    const double velocity = getIncompressibleVelocityX3(f.data());
 
     const double expected_velocity = 1.;
     ASSERT_THAT(velocity, testing::DoubleEq(expected_velocity));
 }
+
+TEST_F(MacroscopicQuantitiesTest, givenAllFsAreOne_checkCompressibleValues)
+{
+    f[dir::DIR_P00] = 2.;
+
+    real rho{0}, vx1{0}, vx2{0}, vx3{0};
+    getCompressibleMacroscopicValues(f.data(), rho, vx1, vx2, vx3);
+
+    std::cout << getIncompressibleVelocityX1(f.data()) << std::endl;
+
+    const real expected_rho = 28.;
+    const real expected_velocity = (1. / (1 + expected_rho));
+
+    EXPECT_THAT(rho, RealEq(expected_rho));
+    EXPECT_THAT(vx1, RealEq(expected_velocity));
+    EXPECT_THAT(vx2, RealEq(0.));
+    EXPECT_THAT(vx3, RealEq(0.));
+}
diff --git a/src/lbm/refinement/Coefficients.h b/src/lbm/refinement/Coefficients.h
new file mode 100644
index 0000000000000000000000000000000000000000..441c2567327c34b67c52754e33c5087a4d3d253b
--- /dev/null
+++ b/src/lbm/refinement/Coefficients.h
@@ -0,0 +1,436 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __         
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
+//      \    \  |    |   ________________________________________________________________    
+//       \    \ |    |  |  ______________________________________________________________|   
+//        \    \|    |  |  |         __          __     __     __     ______      _______    
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//
+//  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/>.
+//
+//=======================================================================================
+#ifndef LBM_SCALING_HELPER_FUNCTIONS_H
+#define LBM_SCALING_HELPER_FUNCTIONS_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+
+#include "lbm/constants/D3Q27.h"
+#include <basics/constants/NumericConstants.h>
+
+#include "lbm/KernelParameter.h"
+#include "lbm/MacroscopicQuantities.h"
+
+
+using namespace vf::basics::constant;
+using namespace vf::lbm::dir;
+
+namespace vf::lbm
+{
+
+// The Coefficients struct needs be created like this:
+// Coefficients coeffs;
+// MomentsOnSourceNodeSet momentsSet;
+// momentsSet.calculatePPP(f, omega);
+// ... and so on
+// Coefficients coeffs;
+// momentsSet.calculateCoefficients(coeffs);
+
+// Coefficient which are used in the interpolation
+struct Coefficients
+{
+    real a000, a100, a010, a001, a200, a020, a002, a110, a101, a011;
+    real b000, b100, b010, b001, b200, b020, b002, b110, b101, b011;
+    real c000, c100, c010, c001, c200, c020, c002, c110, c101, c011;
+    real d000, d100, d010, d001, d110, d101, d011;
+    real a111, b111, c111, d111;
+    real LaplaceRho;
+};
+
+
+// Private struct - is only used within the MomentsOnSourceNodeSet
+struct MomentsOnSourceNode 
+{
+    real drho;
+    real velocityX;
+    real velocityY;
+    real velocityZ;
+    real kxyFromfcNEQ;
+    real kyzFromfcNEQ;
+    real kxzFromfcNEQ;
+    real kxxMyyFromfcNEQ;
+    real kxxMzzFromfcNEQ;
+
+    __host__ __device__ void calculate(const real* const f, const real omega)
+    {
+        // const real f_000 = f[dir::DIR_000];
+        const real fP00 = f[dir::DIR_P00];
+        const real fM00 = f[dir::DIR_M00];
+        const real f0P0 = f[dir::DIR_0P0];
+        const real f0M0 = f[dir::DIR_0M0];
+        const real f00P = f[dir::DIR_00P];
+        const real f00M = f[dir::DIR_00M];
+        const real fPP0 = f[dir::DIR_PP0];
+        const real fMM0 = f[dir::DIR_MM0];
+        const real fPM0 = f[dir::DIR_PM0];
+        const real fMP0 = f[dir::DIR_MP0];
+        const real fP0P = f[dir::DIR_P0P];
+        const real fM0M = f[dir::DIR_M0M];
+        const real fP0M = f[dir::DIR_P0M];
+        const real fM0P = f[dir::DIR_M0P];
+        const real f0PP = f[dir::DIR_0PP];
+        const real f0MM = f[dir::DIR_0MM];
+        const real f0PM = f[dir::DIR_0PM];
+        const real f0MP = f[dir::DIR_0MP];
+        const real fPPP = f[dir::DIR_PPP];
+        const real fMPP = f[dir::DIR_MPP];
+        const real fPMP = f[dir::DIR_PMP];
+        const real fMMP = f[dir::DIR_MMP];
+        const real fPPM = f[dir::DIR_PPM];
+        const real fMPM = f[dir::DIR_MPM];
+        const real fPMM = f[dir::DIR_PMM];
+        const real fMMM = f[dir::DIR_MMM];
+
+        real oneOverRho;
+        getCompressibleMacroscopicValues(f, this->drho, oneOverRho, this->velocityX, this->velocityY, this->velocityZ);
+
+        ////////////////////////////////////////////////////////////////////////////////////
+        //! - Calculate second order moments for interpolation
+        //!
+        // example: kxxMzz: moment, second derivative in x direction minus the second derivative in z direction
+
+        this->kxyFromfcNEQ = -c3o1 * omega *
+                    ((fMM0 + fMMM + fMMP - fMP0 - fMPM - fMPP - fPM0 - fPMM - fPMP + fPP0 + fPPM + fPPP) *
+                        oneOverRho -
+                        ((this->velocityX * this->velocityY)));
+        this->kyzFromfcNEQ = -c3o1 * omega *
+                    ((f0MM + fPMM + fMMM - f0MP - fPMP - fMMP - f0PM - fPPM - fMPM + f0PP + fPPP + fMPP) *
+                        oneOverRho -
+                        ((this->velocityY * this->velocityZ)));
+        this->kxzFromfcNEQ = -c3o1 * omega *
+                    ((fM0M + fMMM + fMPM - fM0P - fMMP - fMPP - fP0M - fPMM - fPPM + fP0P + fPMP + fPPP) *
+                        oneOverRho -
+                        ((this->velocityX * this->velocityZ)));
+        this->kxxMyyFromfcNEQ = -c3o2 * omega *
+                        ((fM0M + fM00 + fM0P - f0MM - f0M0 - f0MP - f0PM - f0P0 - f0PP + fP0M + fP00 + fP0P) *
+                        oneOverRho -
+                        ((this->velocityX * this->velocityX - this->velocityY * this->velocityY)));
+        this->kxxMzzFromfcNEQ = -c3o2 * omega *
+                        ((fMM0 + fM00 + fMP0 - f0MM - f0MP - f00M - f00P - f0PM - f0PP + fPM0 + fP00 + fPP0) *
+                        oneOverRho -
+                        ((this->velocityX * this->velocityX - this->velocityZ * this->velocityZ)));
+    }
+
+};
+
+class MomentsOnSourceNodeSet
+{
+private:
+    vf::lbm::MomentsOnSourceNode momentsPPP;
+    vf::lbm::MomentsOnSourceNode momentsMPP;
+    vf::lbm::MomentsOnSourceNode momentsPMP;
+    vf::lbm::MomentsOnSourceNode momentsMMP;
+    vf::lbm::MomentsOnSourceNode momentsPPM;
+    vf::lbm::MomentsOnSourceNode momentsMPM;
+    vf::lbm::MomentsOnSourceNode momentsPMM;
+    vf::lbm::MomentsOnSourceNode momentsMMM;
+
+public:
+    __host__ __device__ void calculatePPP(const real *const f, const real omega)
+    {
+        momentsPPP.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculateMPP(const real *const f, const real omega)
+    {
+        momentsMPP.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculatePMP(const real *const f, const real omega)
+    {
+        momentsPMP.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculateMMP(const real *const f, const real omega)
+    {
+        momentsMMP.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculatePPM(const real *const f, const real omega)
+    {
+        momentsPPM.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculateMPM(const real *const f, const real omega)
+    {
+        momentsMPM.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculatePMM(const real *const f, const real omega)
+    {
+        momentsPMM.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculateMMM(const real *const f, const real omega)
+    {
+        momentsMMM.calculate(f, omega);
+    }
+
+    __host__ __device__ void calculateCoefficients(Coefficients &coefficients, real xoff, real yoff, real zoff) const
+    {
+        real& a000 = coefficients.a000;
+        real& b000 = coefficients.b000;
+        real& c000 = coefficients.c000;
+        real& d000 = coefficients.d000;
+
+        real& a100 = coefficients.a100;
+        real& b100 = coefficients.b100;
+        real& c100 = coefficients.c100;
+        real& d100 = coefficients.d100;
+
+        real& a010 = coefficients.a010;
+        real& b010 = coefficients.b010;
+        real& c010 = coefficients.c010;
+        real& d010 = coefficients.d010;
+
+        real& a001 = coefficients.a001;
+        real& b001 = coefficients.b001;
+        real& c001 = coefficients.c001;
+        real& d001 = coefficients.d001;
+
+        real& d110 = coefficients.d110, &d101 = coefficients.d101, &d011 = coefficients.d011;
+        
+        real& a200 = coefficients.a200, &a020 = coefficients.a020, &a002 = coefficients.a002;
+        real& b200 = coefficients.b200, &b020 = coefficients.b020, &b002 = coefficients.b002;
+        real& c200 = coefficients.c200, &c020 = coefficients.c020, &c002 = coefficients.c002;
+
+        real& a110 = coefficients.a110, &a101 = coefficients.a101, &a011 = coefficients.a011;
+        real& b110 = coefficients.b110, &b101 = coefficients.b101, &b011 = coefficients.b011;
+        real& c110 = coefficients.c110, &c101 = coefficients.c101, &c011 = coefficients.c011;
+
+        real &a111 = coefficients.a111, &b111 = coefficients.b111, &c111 = coefficients.c111, &d111 = coefficients.d111;
+
+        real &LaplaceRho = coefficients.LaplaceRho;
+
+        const real xoffsq = xoff * xoff;
+        const real yoffsq = yoff * yoff;
+        const real zoffsq = zoff * zoff;
+
+        const real drhoPPP = momentsPPP.drho, vx1PPP = momentsPPP.velocityX, vx2PPP = momentsPPP.velocityY, vx3PPP = momentsPPP.velocityZ;
+        const real drhoMPP = momentsMPP.drho, vx1MPP = momentsMPP.velocityX, vx2MPP = momentsMPP.velocityY, vx3MPP = momentsMPP.velocityZ;
+        const real drhoPMP = momentsPMP.drho, vx1PMP = momentsPMP.velocityX, vx2PMP = momentsPMP.velocityY, vx3PMP = momentsPMP.velocityZ;
+        const real drhoMMP = momentsMMP.drho, vx1MMP = momentsMMP.velocityX, vx2MMP = momentsMMP.velocityY, vx3MMP = momentsMMP.velocityZ;
+        const real drhoPPM = momentsPPM.drho, vx1PPM = momentsPPM.velocityX, vx2PPM = momentsPPM.velocityY, vx3PPM = momentsPPM.velocityZ;
+        const real drhoMPM = momentsMPM.drho, vx1MPM = momentsMPM.velocityX, vx2MPM = momentsMPM.velocityY, vx3MPM = momentsMPM.velocityZ;
+        const real drhoPMM = momentsPMM.drho, vx1PMM = momentsPMM.velocityX, vx2PMM = momentsPMM.velocityY, vx3PMM = momentsPMM.velocityZ;
+        const real drhoMMM = momentsMMM.drho, vx1MMM = momentsMMM.velocityX, vx2MMM = momentsMMM.velocityY, vx3MMM = momentsMMM.velocityZ;
+
+        // second order moments at the source nodes
+        const real kxyFromfcNEQPPP = momentsPPP.kxyFromfcNEQ, kyzFromfcNEQPPP = momentsPPP.kyzFromfcNEQ, kxzFromfcNEQPPP = momentsPPP.kxzFromfcNEQ, kxxMyyFromfcNEQPPP = momentsPPP.kxxMyyFromfcNEQ, kxxMzzFromfcNEQPPP = momentsPPP.kxxMzzFromfcNEQ;
+        const real kxyFromfcNEQMPP = momentsMPP.kxyFromfcNEQ, kyzFromfcNEQMPP = momentsMPP.kyzFromfcNEQ, kxzFromfcNEQMPP = momentsMPP.kxzFromfcNEQ, kxxMyyFromfcNEQMPP = momentsMPP.kxxMyyFromfcNEQ, kxxMzzFromfcNEQMPP = momentsMPP.kxxMzzFromfcNEQ;
+        const real kxyFromfcNEQPMP = momentsPMP.kxyFromfcNEQ, kyzFromfcNEQPMP = momentsPMP.kyzFromfcNEQ, kxzFromfcNEQPMP = momentsPMP.kxzFromfcNEQ, kxxMyyFromfcNEQPMP = momentsPMP.kxxMyyFromfcNEQ, kxxMzzFromfcNEQPMP = momentsPMP.kxxMzzFromfcNEQ;
+        const real kxyFromfcNEQMMP = momentsMMP.kxyFromfcNEQ, kyzFromfcNEQMMP = momentsMMP.kyzFromfcNEQ, kxzFromfcNEQMMP = momentsMMP.kxzFromfcNEQ, kxxMyyFromfcNEQMMP = momentsMMP.kxxMyyFromfcNEQ, kxxMzzFromfcNEQMMP = momentsMMP.kxxMzzFromfcNEQ;
+        const real kxyFromfcNEQPPM = momentsPPM.kxyFromfcNEQ, kyzFromfcNEQPPM = momentsPPM.kyzFromfcNEQ, kxzFromfcNEQPPM = momentsPPM.kxzFromfcNEQ, kxxMyyFromfcNEQPPM = momentsPPM.kxxMyyFromfcNEQ, kxxMzzFromfcNEQPPM = momentsPPM.kxxMzzFromfcNEQ;
+        const real kxyFromfcNEQMPM = momentsMPM.kxyFromfcNEQ, kyzFromfcNEQMPM = momentsMPM.kyzFromfcNEQ, kxzFromfcNEQMPM = momentsMPM.kxzFromfcNEQ, kxxMyyFromfcNEQMPM = momentsMPM.kxxMyyFromfcNEQ, kxxMzzFromfcNEQMPM = momentsMPM.kxxMzzFromfcNEQ;
+        const real kxyFromfcNEQPMM = momentsPMM.kxyFromfcNEQ, kyzFromfcNEQPMM = momentsPMM.kyzFromfcNEQ, kxzFromfcNEQPMM = momentsPMM.kxzFromfcNEQ, kxxMyyFromfcNEQPMM = momentsPMM.kxxMyyFromfcNEQ, kxxMzzFromfcNEQPMM = momentsPMM.kxxMzzFromfcNEQ;
+        const real kxyFromfcNEQMMM = momentsMMM.kxyFromfcNEQ, kyzFromfcNEQMMM = momentsMMM.kyzFromfcNEQ, kxzFromfcNEQMMM = momentsMMM.kxzFromfcNEQ, kxxMyyFromfcNEQMMM = momentsMMM.kxxMyyFromfcNEQ, kxxMzzFromfcNEQMMM = momentsMMM.kxxMzzFromfcNEQ;
+
+        a000 = c1o64 * (
+                c2o1 * (
+                ((kxyFromfcNEQMMM - kxyFromfcNEQPPP) + (kxyFromfcNEQMMP - kxyFromfcNEQPPM)) + ((kxyFromfcNEQPMM - kxyFromfcNEQMPP) + (kxyFromfcNEQPMP - kxyFromfcNEQMPM)) + 
+                ((kxzFromfcNEQMMM - kxzFromfcNEQPPP) + (kxzFromfcNEQPPM - kxzFromfcNEQMMP)) + ((kxzFromfcNEQPMM - kxzFromfcNEQMPP) + (kxzFromfcNEQMPM - kxzFromfcNEQPMP)) + 
+                ((vx2PPP + vx2MMM) + (vx2PPM + vx2MMP)) - ((vx2MPP + vx2PMM) + (vx2MPM + vx2PMP)) + 
+                ((vx3PPP + vx3MMM) - (vx3PPM + vx3MMP)) + ((vx3PMP + vx3MPM) - (vx3MPP + vx3PMM))) + 
+                c8o1 * (((vx1PPP + vx1MMM) + (vx1PPM + vx1MMP)) + ((vx1MPP + vx1PMM) + (vx1PMP + vx1MPM))) +
+                ((kxxMyyFromfcNEQMMM - kxxMyyFromfcNEQPPP) + (kxxMyyFromfcNEQMMP - kxxMyyFromfcNEQPPM)) + 
+                ((kxxMyyFromfcNEQMPP - kxxMyyFromfcNEQPMM) + (kxxMyyFromfcNEQMPM - kxxMyyFromfcNEQPMP)) +
+                ((kxxMzzFromfcNEQMMM - kxxMzzFromfcNEQPPP) + (kxxMzzFromfcNEQMMP - kxxMzzFromfcNEQPPM)) + 
+                ((kxxMzzFromfcNEQMPP - kxxMzzFromfcNEQPMM) + (kxxMzzFromfcNEQMPM - kxxMzzFromfcNEQPMP)));
+        b000 = c1o64 * (
+                c2o1 * (
+                ((kxxMyyFromfcNEQPPP - kxxMyyFromfcNEQMMM) + (kxxMyyFromfcNEQPPM - kxxMyyFromfcNEQMMP)) + 
+                ((kxxMyyFromfcNEQMPP - kxxMyyFromfcNEQPMM) + (kxxMyyFromfcNEQMPM - kxxMyyFromfcNEQPMP)) + 
+                ((kxyFromfcNEQMMM - kxyFromfcNEQPPP) + (kxyFromfcNEQMMP - kxyFromfcNEQPPM)) + 
+                ((kxyFromfcNEQMPP - kxyFromfcNEQPMM) + (kxyFromfcNEQMPM - kxyFromfcNEQPMP)) + 
+                ((kyzFromfcNEQMMM - kyzFromfcNEQPPP) + (kyzFromfcNEQPPM - kyzFromfcNEQMMP)) + 
+                ((kyzFromfcNEQPMM - kyzFromfcNEQMPP) + (kyzFromfcNEQMPM - kyzFromfcNEQPMP)) + 
+                ((vx1PPP + vx1MMM) + (vx1PPM + vx1MMP)) - ((vx1MPM + vx1MPP) + (vx1PMM + vx1PMP)) + 
+                ((vx3PPP + vx3MMM) - (vx3PPM + vx3MMP)) + ((vx3MPP + vx3PMM) - (vx3MPM + vx3PMP))) + 
+                c8o1 * (((vx2PPP + vx2MMM) + (vx2PPM + vx2MMP)) + ((vx2MPP + vx2PMM) + (vx2MPM + vx2PMP))) + 
+                ((kxxMzzFromfcNEQMMM - kxxMzzFromfcNEQPPP) + (kxxMzzFromfcNEQMMP - kxxMzzFromfcNEQPPM)) +
+                ((kxxMzzFromfcNEQPMM - kxxMzzFromfcNEQMPP) + (kxxMzzFromfcNEQPMP - kxxMzzFromfcNEQMPM)));
+        c000 = c1o64 * ( 
+                c2o1 * (
+                ((kxxMzzFromfcNEQPPP - kxxMzzFromfcNEQMMM) + (kxxMzzFromfcNEQMMP - kxxMzzFromfcNEQPPM)) + 
+                ((kxxMzzFromfcNEQMPP - kxxMzzFromfcNEQPMM) + (kxxMzzFromfcNEQPMP - kxxMzzFromfcNEQMPM)) + 
+                ((kxzFromfcNEQMMM - kxzFromfcNEQPPP) + (kxzFromfcNEQMMP - kxzFromfcNEQPPM)) + 
+                ((kxzFromfcNEQMPP - kxzFromfcNEQPMM) + (kxzFromfcNEQMPM - kxzFromfcNEQPMP)) + 
+                ((kyzFromfcNEQMMM - kyzFromfcNEQPPP) + (kyzFromfcNEQMMP - kyzFromfcNEQPPM)) + 
+                ((kyzFromfcNEQPMM - kyzFromfcNEQMPP) + (kyzFromfcNEQPMP - kyzFromfcNEQMPM)) + 
+                ((vx1PPP + vx1MMM) - (vx1MMP + vx1PPM)) + ((vx1MPM + vx1PMP) - (vx1MPP + vx1PMM)) + 
+                ((vx2PPP + vx2MMM) - (vx2MMP + vx2PPM)) + ((vx2MPP + vx2PMM) - (vx2MPM + vx2PMP))) + 
+                c8o1 * (((vx3PPP + vx3MMM) + (vx3PPM + vx3MMP)) + ((vx3PMM + vx3MPP) + (vx3PMP + vx3MPM))) +
+                ((kxxMyyFromfcNEQMMM - kxxMyyFromfcNEQPPP) + (kxxMyyFromfcNEQPPM - kxxMyyFromfcNEQMMP)) + 
+                ((kxxMyyFromfcNEQPMM - kxxMyyFromfcNEQMPP) + (kxxMyyFromfcNEQMPM - kxxMyyFromfcNEQPMP)));
+
+        a100 = c1o4 * (((vx1PPP - vx1MMM) + (vx1PPM - vx1MMP)) + ((vx1PMM - vx1MPP) + (vx1PMP - vx1MPM)));
+        b100 = c1o4 * (((vx2PPP - vx2MMM) + (vx2PPM - vx2MMP)) + ((vx2PMM - vx2MPP) + (vx2PMP - vx2MPM)));
+        c100 = c1o4 * (((vx3PPP - vx3MMM) + (vx3PPM - vx3MMP)) + ((vx3PMM - vx3MPP) + (vx3PMP - vx3MPM)));
+
+        a200 = c1o16 * ( 
+                c2o1 * (
+                ((vx2PPP + vx2MMM) + (vx2PPM - vx2MPP)) + ((vx2MMP - vx2PMM) - (vx2MPM + vx2PMP)) + 
+                ((vx3PPP + vx3MMM) - (vx3PPM + vx3MPP)) + ((vx3MPM + vx3PMP) - (vx3MMP + vx3PMM))) + 
+                ((kxxMyyFromfcNEQPPP - kxxMyyFromfcNEQMMM) + (kxxMyyFromfcNEQPPM - kxxMyyFromfcNEQMMP)) + 
+                ((kxxMyyFromfcNEQPMM - kxxMyyFromfcNEQMPP) + (kxxMyyFromfcNEQPMP - kxxMyyFromfcNEQMPM)) + 
+                ((kxxMzzFromfcNEQPPP - kxxMzzFromfcNEQMMM) + (kxxMzzFromfcNEQPPM - kxxMzzFromfcNEQMMP)) + 
+                ((kxxMzzFromfcNEQPMM - kxxMzzFromfcNEQMPP) + (kxxMzzFromfcNEQPMP - kxxMzzFromfcNEQMPM)));
+        b200 = c1o8 * (
+                c2o1 * (
+                -((vx1PPP + vx1MMM) + (vx1PPM + vx1MMP)) + ((vx1MPP + vx1PMM) + (vx1MPM + vx1PMP))) +
+                ((kxyFromfcNEQPPP - kxyFromfcNEQMMM) + (kxyFromfcNEQPPM - kxyFromfcNEQMMP)) + 
+                ((kxyFromfcNEQPMM - kxyFromfcNEQMPP) + (kxyFromfcNEQPMP - kxyFromfcNEQMPM)));
+        c200 = c1o8 * (
+                c2o1 * (
+                ((vx1PPM + vx1MMP) - (vx1PPP + vx1MMM)) + ((vx1MPP + vx1PMM) - (vx1MPM + vx1PMP))) +
+                ((kxzFromfcNEQPPP - kxzFromfcNEQMMM) + (kxzFromfcNEQPPM - kxzFromfcNEQMMP)) + 
+                ((kxzFromfcNEQPMM - kxzFromfcNEQMPP) + (kxzFromfcNEQPMP - kxzFromfcNEQMPM)));
+
+        a010 = c1o4 * (((vx1PPP - vx1MMM) + (vx1PPM - vx1MMP)) + ((vx1MPP - vx1PMM) + (vx1MPM - vx1PMP)));
+        b010 = c1o4 * (((vx2PPP - vx2MMM) + (vx2PPM - vx2MMP)) + ((vx2MPP - vx2PMM) + (vx2MPM - vx2PMP)));
+        c010 = c1o4 * (((vx3PPP - vx3MMM) + (vx3PPM - vx3MMP)) + ((vx3MPP - vx3PMM) + (vx3MPM - vx3PMP)));
+
+        a020 = c1o8 * (
+                c2o1 * (-((vx2PPP + vx2MMM) + (vx2MMP + vx2PPM)) + ((vx2MPP + vx2PMM) + (vx2MPM + vx2PMP))) +
+                ((kxyFromfcNEQPPP - kxyFromfcNEQMMM) + (kxyFromfcNEQPPM - kxyFromfcNEQMMP)) + 
+                ((kxyFromfcNEQMPP - kxyFromfcNEQPMM) + (kxyFromfcNEQMPM - kxyFromfcNEQPMP)));
+        b020 = c1o16 * (
+                c2o1 * (
+                ((kxxMyyFromfcNEQMMM - kxxMyyFromfcNEQPPP) + (kxxMyyFromfcNEQMMP - kxxMyyFromfcNEQPPM)) +
+                ((kxxMyyFromfcNEQPMM - kxxMyyFromfcNEQMPP) + (kxxMyyFromfcNEQPMP - kxxMyyFromfcNEQMPM)) +
+                ((vx1PPP + vx1MMM) + (vx1PPM + vx1MMP)) - ((vx1MPP + vx1PMM) + (vx1PMP + vx1MPM)) + 
+                ((vx3PPP + vx3MMM) - (vx3PPM + vx3MMP)) + ((vx3MPP + vx3PMM) - (vx3MPM + vx3PMP))) +
+                ((kxxMzzFromfcNEQPPP - kxxMzzFromfcNEQMMM) + (kxxMzzFromfcNEQPPM - kxxMzzFromfcNEQMMP)) + 
+                ((kxxMzzFromfcNEQMPP - kxxMzzFromfcNEQPMM) + (kxxMzzFromfcNEQMPM - kxxMzzFromfcNEQPMP)));
+        c020 = c1o8 * (
+                c2o1 * (((vx2MMP + vx2PPM) - (vx2PPP + vx2MMM)) + ((vx2PMP + vx2MPM) - (vx2MPP + vx2PMM))) +
+                ((kyzFromfcNEQPPP - kyzFromfcNEQMMM) + (kyzFromfcNEQPPM - kyzFromfcNEQMMP)) +
+                ((kyzFromfcNEQMPP - kyzFromfcNEQPMM) + (kyzFromfcNEQMPM - kyzFromfcNEQPMP)));
+
+        a001 = c1o4 * (((vx1PPP - vx1MMM) + (vx1MMP - vx1PPM)) + ((vx1MPP - vx1PMM) + (vx1PMP - vx1MPM)));
+        b001 = c1o4 * (((vx2PPP - vx2MMM) + (vx2MMP - vx2PPM)) + ((vx2MPP - vx2PMM) + (vx2PMP - vx2MPM)));
+        c001 = c1o4 * (((vx3PPP - vx3MMM) + (vx3MMP - vx3PPM)) + ((vx3MPP - vx3PMM) + (vx3PMP - vx3MPM)));
+
+        a002 = c1o8 * (
+                c2o1 * (((vx3PPM + vx3MMP) - (vx3PPP + vx3MMM)) + ((vx3MPP + vx3PMM) - (vx3PMP + vx3MPM))) +
+                        ((kxzFromfcNEQPPP - kxzFromfcNEQMMM) + (kxzFromfcNEQMMP - kxzFromfcNEQPPM)) +
+                        ((kxzFromfcNEQPMP - kxzFromfcNEQMPM) + (kxzFromfcNEQMPP - kxzFromfcNEQPMM)));
+        b002 = c1o8 * (
+                c2o1 * (((vx3PPM + vx3MMP) - (vx3PPP + vx3MMM)) + ((vx3MPM + vx3PMP) - (vx3PMM + vx3MPP))) + 
+                        ((kyzFromfcNEQPPP - kyzFromfcNEQMMM) + (kyzFromfcNEQMMP - kyzFromfcNEQPPM)) + 
+                        ((kyzFromfcNEQPMP - kyzFromfcNEQMPM) + (kyzFromfcNEQMPP - kyzFromfcNEQPMM)));
+        c002 = c1o16 * (
+                c2o1 * (
+                ((kxxMzzFromfcNEQMMM - kxxMzzFromfcNEQPPP) + (kxxMzzFromfcNEQPPM - kxxMzzFromfcNEQMMP)) + 
+                ((kxxMzzFromfcNEQMPM - kxxMzzFromfcNEQPMP) + (kxxMzzFromfcNEQPMM - kxxMzzFromfcNEQMPP)) + 
+                ((vx1PPP + vx1MMM) - (vx1MMP + vx1PPM)) + ((vx1MPM + vx1PMP) - (vx1PMM + vx1MPP)) + 
+                ((vx2PPP + vx2MMM) - (vx2MMP + vx2PPM)) + ((vx2PMM + vx2MPP) - (vx2MPM + vx2PMP))) + 
+                ((kxxMyyFromfcNEQPPP - kxxMyyFromfcNEQMMM) + (kxxMyyFromfcNEQMMP - kxxMyyFromfcNEQPPM)) +
+                ((kxxMyyFromfcNEQPMP - kxxMyyFromfcNEQMPM) + (kxxMyyFromfcNEQMPP - kxxMyyFromfcNEQPMM)));
+
+        a110 = c1o2 * (((vx1PPP + vx1MMM) + (vx1MMP + vx1PPM)) - ((vx1MPM + vx1PMP) + (vx1PMM + vx1MPP)));
+        b110 = c1o2 * (((vx2PPP + vx2MMM) + (vx2MMP + vx2PPM)) - ((vx2MPM + vx2PMP) + (vx2PMM + vx2MPP)));
+        c110 = c1o2 * (((vx3PPP + vx3MMM) + (vx3MMP + vx3PPM)) - ((vx3MPM + vx3PMP) + (vx3PMM + vx3MPP)));
+
+        a101 = c1o2 * (((vx1PPP + vx1MMM) - (vx1MMP + vx1PPM)) + ((vx1MPM + vx1PMP) - (vx1PMM + vx1MPP)));
+        b101 = c1o2 * (((vx2PPP + vx2MMM) - (vx2MMP + vx2PPM)) + ((vx2MPM + vx2PMP) - (vx2PMM + vx2MPP)));
+        c101 = c1o2 * (((vx3PPP + vx3MMM) - (vx3MMP + vx3PPM)) + ((vx3MPM + vx3PMP) - (vx3PMM + vx3MPP)));
+        
+        a011 = c1o2 * (((vx1PPP + vx1MMM) - (vx1MMP + vx1PPM)) + ((vx1PMM + vx1MPP) - (vx1MPM + vx1PMP)));
+        b011 = c1o2 * (((vx2PPP + vx2MMM) - (vx2MMP + vx2PPM)) + ((vx2PMM + vx2MPP) - (vx2MPM + vx2PMP)));
+        c011 = c1o2 * (((vx3PPP + vx3MMM) - (vx3MMP + vx3PPM)) + ((vx3PMM + vx3MPP) - (vx3MPM + vx3PMP)));
+
+        a111 = ((vx1PPP - vx1MMM) + (vx1MMP - vx1PPM)) + ((vx1MPM - vx1PMP) + (vx1PMM - vx1MPP));
+        b111 = ((vx2PPP - vx2MMM) + (vx2MMP - vx2PPM)) + ((vx2MPM - vx2PMP) + (vx2PMM - vx2MPP));
+        c111 = ((vx3PPP - vx3MMM) + (vx3MMP - vx3PPM)) + ((vx3MPM - vx3PMP) + (vx3PMM - vx3MPP));
+
+        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+        //!- Calculate coefficients for the polynomial interpolation of the pressure
+        //! 
+        LaplaceRho = 
+            ((xoff != c0o1) || (yoff != c0o1) || (zoff != c0o1))
+            ? c0o1 : -c3o1 * (a100 * a100 + b010 * b010 + c001 * c001) - c6o1 * (b100 * a010 + c100 * a001 + c010 * b001);
+        d000 = c1o8 * (((drhoPPP + drhoMMM) + (drhoPPM + drhoMMP)) + ((drhoPMM + drhoMPP) + (drhoPMP + drhoMPM)));
+        d100 = c1o4 * (((drhoPPP - drhoMMM) + (drhoPPM - drhoMMP)) + ((drhoPMM - drhoMPP) + (drhoPMP - drhoMPM)));
+        d010 = c1o4 * (((drhoPPP - drhoMMM) + (drhoPPM - drhoMMP)) + ((drhoMPP - drhoPMM) + (drhoMPM - drhoPMP)));
+        d001 = c1o4 * (((drhoPPP - drhoMMM) + (drhoMMP - drhoPPM)) + ((drhoMPP - drhoPMM) + (drhoPMP - drhoMPM)));
+        d110 = c1o2 * (((drhoPPP + drhoMMM) + (drhoPPM + drhoMMP)) - ((drhoPMM + drhoMPP) + (drhoPMP + drhoMPM)));
+        d101 = c1o2 * (((drhoPPP + drhoMMM) - (drhoPPM + drhoMMP)) + ((drhoPMP + drhoMPM) - (drhoPMM + drhoMPP)));
+        d011 = c1o2 * (((drhoPPP + drhoMMM) - (drhoPPM + drhoMMP)) + ((drhoPMM + drhoMPP) - (drhoPMP + drhoMPM)));
+
+        d111 = (((drhoPPP - drhoMMM) + (drhoMMP - drhoPPM)) + ((drhoPMM - drhoMPP) + (drhoMPM - drhoPMP)));
+
+        //////////////////////////////////////////////////////////////////////////
+        //! - Extrapolation for refinement in to the wall (polynomial coefficients)
+        //!
+        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+        //
+        // x------x
+        // |      |
+        // |   ---+--->X
+        // |      |  |
+        // x------x  |
+        //          offset-vector
+        //
+        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+        a000 = a000 + xoff * a100 + yoff * a010 + zoff * a001 + xoffsq * a200 + yoffsq * a020 + zoffsq * a002 +
+            xoff * yoff * a110 + xoff * zoff * a101 + yoff * zoff * a011;
+        a100 = a100 + c2o1 * xoff * a200 + yoff * a110 + zoff * a101;
+        a010 = a010 + c2o1 * yoff * a020 + xoff * a110 + zoff * a011;
+        a001 = a001 + c2o1 * zoff * a002 + xoff * a101 + yoff * a011;
+        b000 = b000 + xoff * b100 + yoff * b010 + zoff * b001 + xoffsq * b200 + yoffsq * b020 + zoffsq * b002 +
+                xoff * yoff * b110 + xoff * zoff * b101 + yoff * zoff * b011;
+        b100 = b100 + c2o1 * xoff * b200 + yoff * b110 + zoff * b101;
+        b010 = b010 + c2o1 * yoff * b020 + xoff * b110 + zoff * b011;
+        b001 = b001 + c2o1 * zoff * b002 + xoff * b101 + yoff * b011;
+        c000 = c000 + xoff * c100 + yoff * c010 + zoff * c001 + xoffsq * c200 + yoffsq * c020 + zoffsq * c002 +
+                xoff * yoff * c110 + xoff * zoff * c101 + yoff * zoff * c011;
+        c100 = c100 + c2o1 * xoff * c200 + yoff * c110 + zoff * c101;
+        c010 = c010 + c2o1 * yoff * c020 + xoff * c110 + zoff * c011;
+        c001 = c001 + c2o1 * zoff * c002 + xoff * c101 + yoff * c011;
+        d000 = d000 + xoff * d100 + yoff * d010 + zoff * d001 + 
+                xoff * yoff * d110 + xoff * zoff * d101 + yoff * zoff * d011;
+
+        d100 = d100 + yoff * d110 + zoff * d101;
+        d010 = d010 + xoff * d110 + zoff * d011;
+        d001 = d001 + xoff * d101 + yoff * d011;
+    }
+
+};
+
+}
+
+#endif
diff --git a/src/lbm/refinement/InterpolationCF.h b/src/lbm/refinement/InterpolationCF.h
new file mode 100644
index 0000000000000000000000000000000000000000..82b8df256ce8ebecdc37e202e0dbe763331a1a65
--- /dev/null
+++ b/src/lbm/refinement/InterpolationCF.h
@@ -0,0 +1,310 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __         
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
+//      \    \  |    |   ________________________________________________________________    
+//       \    \ |    |  |  ______________________________________________________________|   
+//        \    \|    |  |  |         __          __     __     __     ______      _______    
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//
+//  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/>.
+//
+//=======================================================================================
+#ifndef LBM_INTERPOLATION_CF_H
+#define LBM_INTERPOLATION_CF_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+#include <basics/constants/NumericConstants.h>
+
+#include "lbm/constants/D3Q27.h"
+
+#include "lbm/KernelParameter.h"
+#include "lbm/Chimera.h"
+
+#include "lbm/refinement/Coefficients.h"
+
+using namespace vf::basics::constant;
+using namespace vf::lbm::dir;
+
+namespace vf::lbm
+{
+
+inline __host__ __device__ void interpolateCF(real* const f, const real& omegaF, const real& epsnew, const Coefficients &coefficients, const real& x, const real& y, const real& z)
+{
+    const real useNEQ = c1o1;
+
+    const real kxyAverage    = c0o1;
+    const real kyzAverage    = c0o1;
+    const real kxzAverage    = c0o1;
+    const real kxxMyyAverage = c0o1;
+    const real kxxMzzAverage = c0o1;
+
+    const real& a000 = coefficients.a000;
+    const real& b000 = coefficients.b000;
+    const real& c000 = coefficients.c000;
+    const real& d000 = coefficients.d000;
+
+    const real& a100 = coefficients.a100;
+    const real& b100 = coefficients.b100;
+    const real& c100 = coefficients.c100;
+    const real& d100 = coefficients.d100;
+
+    const real& a010 = coefficients.a010;
+    const real& b010 = coefficients.b010;
+    const real& c010 = coefficients.c010;
+    const real& d010 = coefficients.d010;
+
+    const real& a001 = coefficients.a001;
+    const real& b001 = coefficients.b001;
+    const real& c001 = coefficients.c001;
+    const real& d001 = coefficients.d001;
+
+    const real& d110 = coefficients.d110, &d101 = coefficients.d101, &d011 = coefficients.d011;
+    
+    const real& a200 = coefficients.a200, &a020 = coefficients.a020, &a002 = coefficients.a002;
+    const real& b200 = coefficients.b200, &b020 = coefficients.b020, &b002 = coefficients.b002;
+    const real& c200 = coefficients.c200, &c020 = coefficients.c020, &c002 = coefficients.c002;
+
+    const real& a110 = coefficients.a110, &a101 = coefficients.a101, &a011 = coefficients.a011;
+    const real& b110 = coefficients.b110, &b101 = coefficients.b101, &b011 = coefficients.b011;
+    const real& c110 = coefficients.c110, &c101 = coefficients.c101, &c011 = coefficients.c011;
+
+    const real &a111 = coefficients.a111, &b111 = coefficients.b111, &c111 = coefficients.c111, &d111 = coefficients.d111;
+
+    const real &LaplaceRho = coefficients.LaplaceRho;
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Set all moments to zero
+    //!      
+    real m111 = c0o1;
+    real m211 = c0o1;
+    real m011 = c0o1;
+    real m121 = c0o1;
+    real m101 = c0o1;
+    real m112 = c0o1;
+    real m110 = c0o1;
+    real m221 = c0o1;
+    real m001 = c0o1;
+    real m201 = c0o1;
+    real m021 = c0o1;
+    real m212 = c0o1;
+    real m010 = c0o1;
+    real m210 = c0o1;
+    real m012 = c0o1;
+    real m122 = c0o1;
+    real m100 = c0o1;
+    real m120 = c0o1;
+    real m102 = c0o1;
+    real m222 = c0o1;
+    real m022 = c0o1;
+    real m202 = c0o1;
+    real m002 = c0o1;
+    real m220 = c0o1;
+    real m020 = c0o1;
+    real m200 = c0o1;
+    real m000 = c0o1;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Define aliases to use the same variable for the distributions (f's):
+    //!
+    real& f000 = m111;
+    real& fP00 = m211;
+    real& fM00 = m011;
+    real& f0P0 = m121;
+    real& f0M0 = m101;
+    real& f00P = m112;
+    real& f00M = m110;
+    real& fPP0 = m221;
+    real& fMM0 = m001;
+    real& fPM0 = m201;
+    real& fMP0 = m021;
+    real& fP0P = m212;
+    real& fM0M = m010;
+    real& fP0M = m210;
+    real& fM0P = m012;
+    real& f0PP = m122;
+    real& f0MM = m100;
+    real& f0PM = m120;
+    real& f0MP = m102;
+    real& fPPP = m222;
+    real& fMPP = m022;
+    real& fPMP = m202;
+    real& fMMP = m002;
+    real& fPPM = m220;
+    real& fMPM = m020;
+    real& fPMM = m200;
+    real& fMMM = m000;
+
+
+    ////////////////////////////////////////////////////////////////////////////////
+    //! - Set macroscopic values on destination node (zeroth and first order moments)
+    //!
+    real press = d000 + x * d100 + y * d010 + z * d001 +
+                 x * y * d110 + x * z * d101 + y * z * d011 + x * y * z * d111 + c3o1 * x * x * LaplaceRho;
+    real vvx   = a000 + x * a100 + y * a010 + z * a001 +
+                 x * x * a200 + y * y * a020 + z * z * a002 +
+                 x * y * a110 + x * z * a101 + y * z * a011 + x * y * z * a111;
+    real vvy   = b000 + x * b100 + y * b010 + z * b001 +
+                 x * x * b200 + y * y * b020 + z * z * b002 +
+                 x * y * b110 + x * z * b101 + y * z * b011 + x * y * z * b111;
+    real vvz   = c000 + x * c100 + y * c010 + z * c001 +
+                 x * x * c200 + y * y * c020 + z * z * c002 +
+                 x * y * c110 + x * z * c101 + y * z * c011 + x * y * z * c111;
+
+    m000 = press; // m000 is press, if drho is interpolated directly
+
+    ////////////////////////////////////////////////////////////////////////////////
+    //! - Set moments (second to sixth order) on destination node
+    //!
+    // linear combinations for second order moments
+    real mxxPyyPzz = m000;
+
+    real mxxMyy = -c2o3 * (a100 - b010 + kxxMyyAverage + c2o1 * a200 * x - b110 * x + a110 * y
+                  -c2o1 * b020 * y + a101 * z - b011 * z - b111 * x * z + a111 * y * z) * epsnew/ omegaF * (c1o1 + press);
+    real mxxMzz = -c2o3 * (a100 - c001 + kxxMzzAverage + c2o1 * a200 * x - c101 * x + a110 * y
+                  -c011 * y - c111 * x * y + a101 * z - c2o1 * c002 * z + a111 * y * z) * epsnew/ omegaF * (c1o1 + press);
+
+    m011 = -c1o3 * (b001 + c010 + kyzAverage + b101 * x + c110 * x + b011 * y + c2o1 * c020 * y
+            + b111 * x * y + c2o1 * b002 * z + c011 * z + c111 * x * z) * epsnew / omegaF * (c1o1 + press);
+    m101 = -c1o3 * (a001 + c100 + kxzAverage + a101 * x + c2o1 * c200 * x + a011 * y + c110 * y
+            + a111 * x * y + c2o1 * a002 * z + c101 * z + c111 * y * z) * epsnew / omegaF * (c1o1 + press);
+    m110 = -c1o3 * (a010 + b100 + kxyAverage + a110 * x + c2o1 * b200 * x + c2o1 * a020 * y
+            + b110 * y + a011 * z + b101 * z + a111 * x * z + b111 * y * z) * epsnew / omegaF * (c1o1 + press);
+
+    m200 = c1o3 * (        mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
+    m020 = c1o3 * (-c2o1 * mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
+    m002 = c1o3 * (        mxxMyy - c2o1 * mxxMzz + mxxPyyPzz) * useNEQ;
+
+    // linear combinations for third order moments
+    m111 = c0o1;
+
+    real mxxyPyzz = c0o1;
+    real mxxyMyzz = c0o1;
+    real mxxzPyyz = c0o1;
+    real mxxzMyyz = c0o1;
+    real mxyyPxzz = c0o1;
+    real mxyyMxzz = c0o1;
+
+    m210 = ( mxxyMyzz + mxxyPyzz) * c1o2;
+    m012 = (-mxxyMyzz + mxxyPyzz) * c1o2;
+    m201 = ( mxxzMyyz + mxxzPyyz) * c1o2;
+    m021 = (-mxxzMyyz + mxxzPyyz) * c1o2;
+    m120 = ( mxyyMxzz + mxyyPxzz) * c1o2;
+    m102 = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+    // fourth order moments
+    m022 = m000 * c1o9;
+    m202 = m022;
+    m220 = m022;
+
+    // fifth order moments
+
+    // sixth order moment
+    m222 = m000 * c1o27;
+
+    real vxsq = vvx * vvx;
+    real vysq = vvy * vvy;
+    real vzsq = vvz * vvz;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Chimera transform from central moments to well conditioned distributions as defined in Appendix J in
+    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
+    //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (88)-(96) in <a
+    //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040
+    //! ]</b></a>
+    //!
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // X - Dir
+    backwardInverseChimeraWithK(m000, m100, m200, vvx, vxsq, c1o1, c1o1);
+    backwardChimera(            m010, m110, m210, vvx, vxsq);
+    backwardInverseChimeraWithK(m020, m120, m220, vvx, vxsq, c3o1, c1o3);
+    backwardChimera(            m001, m101, m201, vvx, vxsq);
+    backwardChimera(            m011, m111, m211, vvx, vxsq);
+    backwardChimera(            m021, m121, m221, vvx, vxsq);
+    backwardInverseChimeraWithK(m002, m102, m202, vvx, vxsq, c3o1, c1o3);
+    backwardChimera(            m012, m112, m212, vvx, vxsq);
+    backwardInverseChimeraWithK(m022, m122, m222, vvx, vxsq, c9o1, c1o9);
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Y - Dir
+    backwardInverseChimeraWithK(m000, m010, m020, vvy, vysq, c6o1, c1o6);
+    backwardChimera(            m001, m011, m021, vvy, vysq);
+    backwardInverseChimeraWithK(m002, m012, m022, vvy, vysq, c18o1, c1o18);
+    backwardInverseChimeraWithK(m100, m110, m120, vvy, vysq, c3o2, c2o3);
+    backwardChimera(            m101, m111, m121, vvy, vysq);
+    backwardInverseChimeraWithK(m102, m112, m122, vvy, vysq, c9o2, c2o9);
+    backwardInverseChimeraWithK(m200, m210, m220, vvy, vysq, c6o1, c1o6);
+    backwardChimera(            m201, m211, m221, vvy, vysq);
+    backwardInverseChimeraWithK(m202, m212, m222, vvy, vysq, c18o1, c1o18);
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Z - Dir
+    backwardInverseChimeraWithK(m000, m001, m002, vvz, vzsq, c36o1, c1o36);
+    backwardInverseChimeraWithK(m010, m011, m012, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m020, m021, m022, vvz, vzsq, c36o1, c1o36);
+    backwardInverseChimeraWithK(m100, m101, m102, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m110, m111, m112, vvz, vzsq, c9o4,  c4o9);
+    backwardInverseChimeraWithK(m120, m121, m122, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m200, m201, m202, vvz, vzsq, c36o1, c1o36);
+    backwardInverseChimeraWithK(m210, m211, m212, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m220, m221, m222, vvz, vzsq, c36o1, c1o36);
+
+    f[DIR_000] = f000;
+    f[DIR_P00] = fP00;
+    f[DIR_M00] = fM00;
+    f[DIR_0P0] = f0P0;
+    f[DIR_0M0] = f0M0;
+    f[DIR_00P] = f00P;
+    f[DIR_00M] = f00M;
+    f[DIR_PP0] = fPP0;
+    f[DIR_MM0] = fMM0;
+    f[DIR_PM0] = fPM0;
+    f[DIR_MP0] = fMP0;
+    f[DIR_P0P] = fP0P;
+    f[DIR_M0M] = fM0M;
+    f[DIR_P0M] = fP0M;
+    f[DIR_M0P] = fM0P;
+    f[DIR_0PP] = f0PP;
+    f[DIR_0MM] = f0MM;
+    f[DIR_0PM] = f0PM;
+    f[DIR_0MP] = f0MP;
+    f[DIR_PPP] = fPPP;
+    f[DIR_MPP] = fMPP;
+    f[DIR_PMP] = fPMP;
+    f[DIR_MMP] = fMMP;
+    f[DIR_PPM] = fPPM;
+    f[DIR_MPM] = fMPM;
+    f[DIR_PMM] = fPMM;
+    f[DIR_MMM] = fMMM;
+}
+
+
+
+}
+
+#endif
diff --git a/src/lbm/refinement/InterpolationFC.h b/src/lbm/refinement/InterpolationFC.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3e6384476033880c40b4b6f4c73890ba1e33ae7
--- /dev/null
+++ b/src/lbm/refinement/InterpolationFC.h
@@ -0,0 +1,265 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __         
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
+//      \    \  |    |   ________________________________________________________________    
+//       \    \ |    |  |  ______________________________________________________________|   
+//        \    \|    |  |  |         __          __     __     __     ______      _______    
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//
+//  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/>.
+//
+//=======================================================================================
+#ifndef LBM_INTERPOLATION_FC_H
+#define LBM_INTERPOLATION_FC_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+#include <basics/constants/NumericConstants.h>
+
+#include "lbm/constants/D3Q27.h"
+#include "lbm/KernelParameter.h"
+#include "lbm/Chimera.h"
+
+#include "lbm/refinement/Coefficients.h"
+
+using namespace vf::basics::constant;
+using namespace vf::lbm::dir;
+
+namespace vf::lbm
+{
+
+inline __host__ __device__ void interpolateFC(real* const f, const real epsnew, const real omegaC, const Coefficients& coefficients)
+{
+
+    const real kxyAverage    = c0o1;
+    const real kyzAverage    = c0o1;
+    const real kxzAverage    = c0o1;
+    const real kxxMyyAverage = c0o1;
+    const real kxxMzzAverage = c0o1;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Set all moments to zero
+    //!
+    real m111 = c0o1;
+    real m211 = c0o1;
+    real m011 = c0o1;
+    real m121 = c0o1;
+    real m101 = c0o1;
+    real m112 = c0o1;
+    real m110 = c0o1;
+    real m221 = c0o1;
+    real m001 = c0o1;
+    real m201 = c0o1;
+    real m021 = c0o1;
+    real m212 = c0o1;
+    real m010 = c0o1;
+    real m210 = c0o1;
+    real m012 = c0o1;
+    real m122 = c0o1;
+    real m100 = c0o1;
+    real m120 = c0o1;
+    real m102 = c0o1;
+    real m222 = c0o1;
+    real m022 = c0o1;
+    real m202 = c0o1;
+    real m002 = c0o1;
+    real m220 = c0o1;
+    real m020 = c0o1;
+    real m200 = c0o1;
+    real m000 = c0o1;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Define aliases to use the same variable for the distributions (f's):
+    //!
+    real& f000 = m111;
+    real& fP00 = m211;
+    real& fM00 = m011;
+    real& f0P0 = m121;
+    real& f0M0 = m101;
+    real& f00P = m112;
+    real& f00M = m110;
+    real& fPP0 = m221;
+    real& fMM0 = m001;
+    real& fPM0 = m201;
+    real& fMP0 = m021;
+    real& fP0P = m212;
+    real& fM0M = m010;
+    real& fP0M = m210;
+    real& fM0P = m012;
+    real& f0PP = m122;
+    real& f0MM = m100;
+    real& f0PM = m120;
+    real& f0MP = m102;
+    real& fPPP = m222;
+    real& fMPP = m022;
+    real& fPMP = m202;
+    real& fMMP = m002;
+    real& fPPM = m220;
+    real& fMPM = m020;
+    real& fPMM = m200;
+    real& fMMM = m000;
+
+    ////////////////////////////////////////////////////////////////////////////////
+    //! - Declare local variables for destination nodes
+    //!
+    real vvx, vvy, vvz, vxsq, vysq, vzsq;
+    real mxxPyyPzz, mxxMyy, mxxMzz, mxxyPyzz, mxxyMyzz, mxxzPyyz, mxxzMyyz, mxyyPxzz, mxyyMxzz;
+    real useNEQ = c1o1; // zero; //one;   //.... one = on ..... zero = off
+    real press;
+
+    ////////////////////////////////////////////////////////////////////////////////
+    //! - Set macroscopic values on destination node (zeroth and first order moments)
+    //!
+    press = coefficients.d000 - c2o1 * coefficients.LaplaceRho * c1o8;
+    vvx   = coefficients.a000;
+    vvy   = coefficients.b000;
+    vvz   = coefficients.c000;
+
+    m000 = press; // m000 is press, if drho is interpolated directly
+
+    vxsq = vvx * vvx;
+    vysq = vvy * vvy;
+    vzsq = vvz * vvz;
+
+    ////////////////////////////////////////////////////////////////////////////////
+    //! - Set moments (second to sixth order) on destination node
+    //!
+    // linear combinations for second order moments
+    mxxPyyPzz = m000;
+
+    mxxMyy = -c2o3 * ((coefficients.a100 - coefficients.b010) + kxxMyyAverage) * epsnew / omegaC * (c1o1 + press);
+    mxxMzz = -c2o3 * ((coefficients.a100 - coefficients.c001) + kxxMzzAverage) * epsnew / omegaC * (c1o1 + press);
+
+    m011 = -c1o3 * ((coefficients.b001 + coefficients.c010) + kyzAverage) * epsnew / omegaC * (c1o1 + press);
+    m101 = -c1o3 * ((coefficients.a001 + coefficients.c100) + kxzAverage) * epsnew / omegaC * (c1o1 + press);
+    m110 = -c1o3 * ((coefficients.a010 + coefficients.b100) + kxyAverage) * epsnew / omegaC * (c1o1 + press);
+
+    m200 = c1o3 * (        mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
+    m020 = c1o3 * (-c2o1 * mxxMyy +        mxxMzz + mxxPyyPzz) * useNEQ;
+    m002 = c1o3 * (        mxxMyy - c2o1 * mxxMzz + mxxPyyPzz) * useNEQ;
+
+    // linear combinations for third order moments
+    m111 = c0o1;
+
+    mxxyPyzz = c0o1;
+    mxxyMyzz = c0o1;
+    mxxzPyyz = c0o1;
+    mxxzMyyz = c0o1;
+    mxyyPxzz = c0o1;
+    mxyyMxzz = c0o1;
+
+    m210 = ( mxxyMyzz + mxxyPyzz) * c1o2;
+    m012 = (-mxxyMyzz + mxxyPyzz) * c1o2;
+    m201 = ( mxxzMyyz + mxxzPyyz) * c1o2;
+    m021 = (-mxxzMyyz + mxxzPyyz) * c1o2;
+    m120 = ( mxyyMxzz + mxyyPxzz) * c1o2;
+    m102 = (-mxyyMxzz + mxyyPxzz) * c1o2;
+
+    // fourth order moments
+    m022 = m000 * c1o9;
+    m202 = m022;
+    m220 = m022;
+
+    // fifth order moments
+
+    // sixth order moments
+    m222 = m000 * c1o27;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Chimera transform from central moments to well conditioned distributions as defined in Appendix J in
+    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015),
+    //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (88)-(96) in <a
+    //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040
+    //! ]</b></a>
+    //!
+    ////////////////////////////////////////////////////////////////////////////////////
+    // X - Dir
+    backwardInverseChimeraWithK(m000, m100, m200, vvx, vxsq, c1o1, c1o1);
+    backwardChimera(            m010, m110, m210, vvx, vxsq);
+    backwardInverseChimeraWithK(m020, m120, m220, vvx, vxsq, c3o1, c1o3);
+    backwardChimera(            m001, m101, m201, vvx, vxsq);
+    backwardChimera(            m011, m111, m211, vvx, vxsq);
+    backwardChimera(            m021, m121, m221, vvx, vxsq);
+    backwardInverseChimeraWithK(m002, m102, m202, vvx, vxsq, c3o1, c1o3);
+    backwardChimera(            m012, m112, m212, vvx, vxsq);
+    backwardInverseChimeraWithK(m022, m122, m222, vvx, vxsq, c9o1, c1o9);
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Y - Dir
+    backwardInverseChimeraWithK(m000, m010, m020, vvy, vysq, c6o1, c1o6);
+    backwardChimera(            m001, m011, m021, vvy, vysq);
+    backwardInverseChimeraWithK(m002, m012, m022, vvy, vysq, c18o1, c1o18);
+    backwardInverseChimeraWithK(m100, m110, m120, vvy, vysq, c3o2, c2o3);
+    backwardChimera(            m101, m111, m121, vvy, vysq);
+    backwardInverseChimeraWithK(m102, m112, m122, vvy, vysq, c9o2, c2o9);
+    backwardInverseChimeraWithK(m200, m210, m220, vvy, vysq, c6o1, c1o6);
+    backwardChimera(            m201, m211, m221, vvy, vysq);
+    backwardInverseChimeraWithK(m202, m212, m222, vvy, vysq, c18o1, c1o18);
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Z - Dir
+    backwardInverseChimeraWithK(m000, m001, m002, vvz, vzsq, c36o1, c1o36);
+    backwardInverseChimeraWithK(m010, m011, m012, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m020, m021, m022, vvz, vzsq, c36o1, c1o36);
+    backwardInverseChimeraWithK(m100, m101, m102, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m110, m111, m112, vvz, vzsq, c9o4,  c4o9);
+    backwardInverseChimeraWithK(m120, m121, m122, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m200, m201, m202, vvz, vzsq, c36o1, c1o36);
+    backwardInverseChimeraWithK(m210, m211, m212, vvz, vzsq, c9o1,  c1o9);
+    backwardInverseChimeraWithK(m220, m221, m222, vvz, vzsq, c36o1, c1o36);
+
+    f[DIR_000] = f000;
+    f[DIR_P00] = fP00;
+    f[DIR_M00] = fM00;
+    f[DIR_0P0] = f0P0;
+    f[DIR_0M0] = f0M0;
+    f[DIR_00P] = f00P;
+    f[DIR_00M] = f00M;
+    f[DIR_PP0] = fPP0;
+    f[DIR_MM0] = fMM0;
+    f[DIR_PM0] = fPM0;
+    f[DIR_MP0] = fMP0;
+    f[DIR_P0P] = fP0P;
+    f[DIR_M0M] = fM0M;
+    f[DIR_P0M] = fP0M;
+    f[DIR_M0P] = fM0P;
+    f[DIR_0PP] = f0PP;
+    f[DIR_0MM] = f0MM;
+    f[DIR_0PM] = f0PM;
+    f[DIR_0MP] = f0MP;
+    f[DIR_PPP] = fPPP;
+    f[DIR_MPP] = fMPP;
+    f[DIR_PMP] = fPMP;
+    f[DIR_MMP] = fMMP;
+    f[DIR_PPM] = fPPM;
+    f[DIR_MPM] = fMPM;
+    f[DIR_PMM] = fPMM;
+    f[DIR_MMM] = fMMM;
+}
+
+}
+
+#endif
diff --git a/src/logger/Logger.h b/src/logger/Logger.h
index 3a25fea02eb7d5ea1ab9bffebea08bfc9f512b04..f3c41c0e3bfb8aa12c94677040273fdaaaff64a3 100644
--- a/src/logger/Logger.h
+++ b/src/logger/Logger.h
@@ -39,10 +39,10 @@
 // The default log level is set to trace. Supported levels: trace < debug < info < warning < critical
 // 
 // The logging is realized in 3 different log sinks:
-// 1. colorded console output
+// 1. colored console output
 // 2. a daily log file
 // 3. a log file from the last run of VirtualFluids
-// The default file path is relativ to executed command logs/
+// The default file path is relative to executed command logs/
 // File path can be changed via changeLogPath()
 
 #define VF_LOG_TRACE(...) spdlog::trace(__VA_ARGS__)
@@ -57,7 +57,7 @@ namespace vf::logging
     class Logger
     {
     public:
-        // initalizing the above named logger
+        // initializing the above named logger
         static void initializeLogger();
 
         // changing the path of the log files