diff --git a/.clang-format b/.clang-format
index 1bdc80ff8929a640ee9753cb3249805508b9259b..dcd3860f6268d6f47ebf528641f36a8b31eef848 100644
--- a/.clang-format
+++ b/.clang-format
@@ -4,7 +4,7 @@ Language:        Cpp
 AccessModifierOffset: -4
 AlignAfterOpenBracket: Align
 AlignConsecutiveMacros: false
-AlignConsecutiveAssignments: true
+AlignConsecutiveAssignments: false
 AlignConsecutiveDeclarations: false
 AlignEscapedNewlines: Right
 AlignOperands:   true
@@ -14,7 +14,7 @@ AllowAllConstructorInitializersOnNextLine: true
 AllowAllParametersOfDeclarationOnNextLine: true
 AllowShortBlocksOnASingleLine: Never
 AllowShortCaseLabelsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: All
+AllowShortFunctionsOnASingleLine: None
 AllowShortLambdasOnASingleLine: All
 AllowShortIfStatementsOnASingleLine: Never
 AllowShortLoopsOnASingleLine: false
diff --git a/.cmake-format.yaml b/.cmake-format.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d11c25002bb06b3db16ca63853faa096aac70c91
--- /dev/null
+++ b/.cmake-format.yaml
@@ -0,0 +1,76 @@
+parse:
+  additional_commands:
+    foo:
+      flags:
+      - BAR
+      - BAZ
+      kwargs:
+        HEADERS: '*'
+        SOURCES: '*'
+        DEPENDS: '*'
+  override_spec: {}
+  _help_vartags:
+  vartags: []
+  proptags: []
+
+format:
+  disable: false
+  line_width: 120
+  tab_size: 4
+  use_tabchars: false
+  fractional_tab_policy: use-space
+  max_subgroups_hwrap: 2
+  max_pargs_hwrap: 6
+  max_rows_cmdline: 2
+  separate_ctrl_name_with_space: false
+  separate_fn_name_with_space: false
+  dangle_parens: false
+  dangle_align: prefix
+  min_prefix_chars: 4
+  max_prefix_chars: 10
+  max_lines_hwrap: 2
+  line_ending: unix
+  command_case: canonical
+  keyword_case: unchanged
+  always_wrap: []
+  enable_sort: true
+  autosort: false
+  require_valid_layout: false
+  layout_passes: {}
+
+markup:
+  bullet_char: '*'
+  enum_char: .
+  first_comment_is_literal: false
+  literal_comment_pattern: null
+  fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$
+  ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$
+  explicit_trailing_pattern: '#<'
+  hashruler_min_length: 10
+  canonicalize_hashrulers: true
+  enable_markup: true
+
+lint:
+  disabled_codes: []
+  function_pattern: '[0-9a-z_]+'
+  macro_pattern: '[0-9A-Z_]+'
+  global_var_pattern: '[A-Z][0-9A-Z_]+'
+  internal_var_pattern: _[A-Z][0-9A-Z_]+
+  local_var_pattern: '[a-z][a-z0-9_]+'
+  private_var_pattern: _[0-9a-z_]+
+  public_var_pattern: '[A-Z][0-9A-Z_]+'
+  argument_var_pattern: '[a-z][a-z0-9_]+'
+  keyword_pattern: '[A-Z][0-9A-Z_]+'
+  max_conditionals_custom_parser: 2
+  min_statement_spacing: 1
+  max_statement_spacing: 2
+  max_returns: 6
+  max_branches: 12
+  max_arguments: 5
+  max_localvars: 15
+  max_statements: 50
+
+encode:
+  emit_byteorder_mark: false
+  input_encoding: utf-8
+  output_encoding: utf-8
\ No newline at end of file
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000000000000000000000000000000000..f78e30c81f1c787e4d5748a0c624e561521f0922
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,14 @@
+{
+    "name": "virtual-fluids-environment",
+    "extensions": [
+        "mhutchie.git-graph",
+        "donjayamanne.githistory",
+        "twxs.cmake",
+        "ms-vscode.cpptools",
+        "visualstudioexptteam.vscodeintellicode",
+        "xaver.clang-format",
+        "notskm.clang-tidy"
+    ],
+    "runArgs": ["--gpus","all"],
+    "image": "git.rz.tu-bs.de:4567/irmb/virtualfluids/ubuntu20_04:1.2"
+}
diff --git a/.gitignore b/.gitignore
index c037614b4043653fb6607e90c542e24f9042eded..8708a2906743e7953fd79b8277927031b1f6a32d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,24 @@
 # build directories
 build/
 bin/
-MSVC2017/
-VS2017/
+cmake-build-debug/
+run/
+
+# Python
+_skbuild/
+dist/
+*.egg-info/
+__pycache__/
+.venv/
 
 # IDE
 .vscode/
 .sync/
 .idea/
-.devcontainer/
+
+# Simulation results
+output/
+logs/
 
 # MacOS
 .DS_Store
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 280f682ba981ac695fafc2de9d897cce0e4c8198..cad485aff121d552d49296b3ab4cc42659169162 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -24,6 +24,7 @@ stages:
   cache:
     key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
     paths:
+      - $BUILD_FOLDER
       - $CI_PROJECT_DIR/cache
 
   artifacts:
@@ -31,14 +32,12 @@ stages:
     paths:
       - $BUILD_FOLDER
 
-  before_script:
-    - export CC=gcc
-    - export CXX=g++
+  script:
     - export CCACHE_BASEDIR=$CI_PROJECT_DIR
     - export CCACHE_DIR=$CI_PROJECT_DIR/cache
-    - ccache -s
-
-  script:
+    - export CCACHE_COMPILERCHECK=content
+    - ccache --zero-stats
+    - ccache --show-stats
     - $CXX --version
     - $CC --version
     - cmake --version
@@ -46,12 +45,12 @@ stages:
     - mkdir -p $CI_PROJECT_DIR/$BUILD_FOLDER
     - cd $CI_PROJECT_DIR/$BUILD_FOLDER
     - rm -r -f ./*
-    - cmake ..
-      --preset=all_make_ccache
+    - cmake .. -LAH
+      --preset=all_make
       -DBUILD_WARNINGS_AS_ERRORS=ON
       -DCMAKE_CUDA_ARCHITECTURES=60
-    - cmake . -LAH
     - make -j4
+    - ccache --show-stats
 
   variables:
     BUILD_FOLDER: "build"
@@ -60,8 +59,10 @@ stages:
 gcc_9:
   extends: .gnu_build_template
 
+  before_script:
+    - export CC=gcc
+    - export CXX=g++
 ###############################################################################
-
 clang_10:
   extends: .gnu_build_template
 
@@ -181,7 +182,8 @@ clang_build_analyzer_clang_10:
     - mkdir -p $CI_PROJECT_DIR/build
     - cd $CI_PROJECT_DIR/build
     - cmake ..
-      --preset=all_make
+      -DBUILD_VF_CPU=ON
+      -DBUILD_VF_GPU=ON
       -DCMAKE_CUDA_ARCHITECTURES=60
       -DCMAKE_CXX_FLAGS=-ftime-trace
     - ClangBuildAnalyzer --start .
@@ -213,7 +215,8 @@ include_what_you_use_clang_10:
     - mkdir -p $CI_PROJECT_DIR/build
     - cd $CI_PROJECT_DIR/build
     - cmake ..
-      --preset=all_make
+      -DBUILD_VF_CPU=ON
+      -DBUILD_VF_GPU=ON
       -DCMAKE_CUDA_ARCHITECTURES=60
       -DBUILD_VF_INCLUDE_WHAT_YOU_USE=ON
     - make
@@ -236,11 +239,9 @@ cppcheck:
     - cd $CI_PROJECT_DIR
     - cppcheck --version
     - cppcheck src --enable=all --xml 2> cppcheck.xml
-    - cppcheck-htmlreport --file=cppcheck.xml --report-dir=html_report --source-dir=.
-
   artifacts:
+    expire_in: 1 week
     paths:
-      - html_report/
       - cppcheck.xml
 
 ###############################################################################
@@ -267,6 +268,7 @@ lizard:
     - lizard -l cpp src/ > lizard.txt --warnings_only --ignore_warnings 400
 
   artifacts:
+    expire_in: 1 week
     paths:
       - lizard.txt
 
@@ -284,7 +286,7 @@ gcov_gcc_9:
   before_script:
     - export DEBIAN_FRONTEND=noninteractive
     - apt-get update
-    - pip3 install gcovr
+    - pip3 install 'jinja2<3.1' gcovr==5.0
     - gcovr --version
 
   script:
@@ -301,9 +303,9 @@ gcov_gcc_9:
     - gcovr -r $CI_PROJECT_DIR -k build -f "src" --print-summary --html coverage/coverage.html --html-details --xml coverage/coverage.xml
 
   artifacts:
+    expire_in: 1 week
     paths:
       - coverage/
-      - build/
 
     reports:
       cobertura: coverage/coverage.xml
@@ -324,6 +326,8 @@ clang-tidy:
 
   needs: []
 
+  allow_failure: true
+
   before_script:
     - run-clang-tidy -h
 
@@ -331,12 +335,14 @@ clang-tidy:
     - mkdir -p $CI_PROJECT_DIR/build
     - cd $CI_PROJECT_DIR/build
     - cmake ..
-      --preset=cpu_make
-      -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
+      -DBUILD_VF_CPU=ON
+      -DBUILD_VF_GPU=OFF
     - python3 ../utilities/filterCompileCommands.py compile_commands.json
     - run-clang-tidy -quiet > clangtidy.txt
 
   artifacts:
+    when: always
+    expire_in: 1 week
     paths:
       - build/clangtidy.txt
       - build/compile_commands.json
@@ -359,7 +365,7 @@ pages:
   - mv docs/build/html/ public/
 
   artifacts:
-    expire_in: 1 week
+    expire_in: 1 hrs
     paths:
     - public
 
@@ -404,9 +410,12 @@ sonar-scanner:
 ##                              Release                                      ##
 ###############################################################################
 create_release:
-  image: registry.gitlab.com/gitlab-org/release-cli:latest
   stage: release
+
+  image: registry.gitlab.com/gitlab-org/release-cli:latest
+
   needs: ["build_singularity_image"]
+
   rules:
     - if: $CI_COMMIT_TAG
 
diff --git a/AUTHORS.md b/AUTHORS.md
index 96cdf03c757bcf2d111b2eb6265278bf36ab5857..554a5f1614a41f8bf7528e24b13d0a8569cb210d 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -1,26 +1,28 @@
-AUTHORS
-============
-
+# AUTHORS
 VF has been developed essentially over the last fifteen years by various researchers at IRMB including (in alphabetical order):
 
 
 Damilola Adekanye, M.Sc.
-Dr. Benjamin Ahrenholz  
-Dr. Hussein Alihussein  
-Dr. Sebastian Bindick  
-J.Prof. Dr. Martin Geier  
-Dr. Sebastian Geller  
-Dr. Ehsan Goraki Fard  
-Dr. Jan Hegewald  
-Dr. Christian Janßen  
+Dr. Benjamin Ahrenholz
+Dr. Hussein Alihussein
+Dr. Sebastian Bindick
+Aileen Brendel, B.Sc.
+J.Prof. Dr. Martin Geier
+Dr. Sebastian Geller
+Dr. Ehsan Goraki Fard
+Dr. Jan Hegewald
+Dr. Christian Janßen
 Prof. Dr.-Ing. habil. Manfred Krafczyk
-Dr. Konstantin Kutscher  
-Dr. Stephan Lenz  
-Dr. Jan Linxweiler  
-Sören Peters, M.Sc.   
-Dr. Hesameddin Safari  
-Dr. Martin Schönherr  
-Dipl.-Ing. Maik Stiebler  
-Dr. Sören Textor (aka Freudiger)  
-PD Dr. Jonas Tölke  
-Dr. Sonja Uphoff  
+Dr. Konstantin Kutscher
+Dr. Stephan Lenz
+Dr. Jan Linxweiler
+Lennard Lux, B.Sc.
+Sören Peters, M.Sc.
+Sven Marcus, M.Sc.
+Dr. Hesameddin Safari
+Dr. Martin Schönherr
+Dipl.-Ing. Maik Stiebler
+Dr. Sören Textor (aka Freudiger)
+PD Dr. Jonas Tölke
+Dr. Sonja Uphoff
+Anna Wellmann, M.Sc.
diff --git a/CMake/3rd/vtk.cmake b/CMake/3rd/vtk.cmake
index 83cf22e8849298d2b42909664cacd5fd9044903e..7bba91a5a25da622ef752d670845754a6349815c 100644
--- a/CMake/3rd/vtk.cmake
+++ b/CMake/3rd/vtk.cmake
@@ -3,9 +3,8 @@
 # VTK_DIR needs to bet set to the VTK build directory in the config file.
 #########################################################################
 find_package(VTK REQUIRED)
-    vf_get_library_name(library_name)
+vf_get_library_name(library_name)
 
-    include(${VTK_USE_FILE})
-    target_include_directories(${library_name} PRIVATE ${VTK_INCLUDE_DIRS})
+target_include_directories(${library_name} PRIVATE ${VTK_INCLUDE_DIRS})
 
-    target_link_libraries(${library_name} PRIVATE ${VTK_LIBRARIES})
+target_link_libraries(${library_name} PRIVATE ${VTK_LIBRARIES})
diff --git a/CMake/CMakeSetCompilerFlags.cmake b/CMake/CMakeSetCompilerFlags.cmake
index 2ea8c0b2faf0a398681e32232aa7d247b511c72c..26eeca2a08436c910d1b936b665ef471ed3e557b 100644
--- a/CMake/CMakeSetCompilerFlags.cmake
+++ b/CMake/CMakeSetCompilerFlags.cmake
@@ -47,7 +47,7 @@ endmacro()
 ################################################################
 ###             ADD_COMPILER_FLAGS_TO_PROJECT                ###
 ################################################################
-function(addAdditionalFlags project_name)
+function(addAdditionalFlags library_name)
 
     status_lib("additional compiler flags CXX: ${CS_COMPILER_FLAGS_CXX}")
     status_lib("additional compiler flags CXX debug: ${CS_COMPILER_FLAGS_CXX_DEBUG}")
@@ -67,18 +67,18 @@ function(addAdditionalFlags project_name)
 
     # compile options
     foreach(flag IN LISTS CS_COMPILER_FLAGS_CXX)
-        target_compile_options(${project_name} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${flag}>")
+        target_compile_options(${library_name} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${flag}>")
         if(MSVC)
-            target_compile_options(${project_name} PRIVATE "$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=${flag}>")
+            target_compile_options(${library_name} PRIVATE "$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=${flag}>")
         endif()
     endforeach()
 
     foreach(flag IN LISTS CS_COMPILER_FLAGS_CXX_DEBUG)
-        target_compile_options(${project_name} PRIVATE "$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>:${flag}>")
+        target_compile_options(${library_name} PRIVATE "$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>:${flag}>")
     endforeach()
 
     foreach(flag IN LISTS CS_COMPILER_FLAGS_CXX_RELEASE)
-        target_compile_options(${project_name} PRIVATE "$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>:${flag}>")
+        target_compile_options(${library_name} PRIVATE "$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>:${flag}>")
     endforeach()
 
 endfunction()
\ No newline at end of file
diff --git a/CMake/Cache.cmake b/CMake/Cache.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..5cd6b500bb9d38afa095fc0eb1087b228ee48ab2
--- /dev/null
+++ b/CMake/Cache.cmake
@@ -0,0 +1,31 @@
+option(ENABLE_CACHE "Enable cache if available" ON)
+if(NOT ENABLE_CACHE)
+  return()
+endif()
+
+set(CACHE_OPTION
+    "ccache"
+    CACHE STRING "Compiler cache to be used")
+set(CACHE_OPTION_VALUES "ccache" "sccache")
+set_property(CACHE CACHE_OPTION PROPERTY STRINGS ${CACHE_OPTION_VALUES})
+list(
+  FIND
+  CACHE_OPTION_VALUES
+  ${CACHE_OPTION}
+  CACHE_OPTION_INDEX)
+
+if(${CACHE_OPTION_INDEX} EQUAL -1)
+  message(
+    STATUS
+      "Using custom compiler cache system: '${CACHE_OPTION}', explicitly supported entries are ${CACHE_OPTION_VALUES}")
+endif()
+
+find_program(CACHE_BINARY ${CACHE_OPTION})
+if(CACHE_BINARY)
+  message(STATUS "${CACHE_OPTION} found and enabled")
+  set(CMAKE_CXX_COMPILER_LAUNCHER ${CACHE_BINARY})
+  set(CMAKE_CUDA_COMPILER_LAUNCHER ${CACHE_BINARY})
+  set(CMAKE_C_COMPILER_LAUNCHER ${CACHE_BINARY})
+else()
+  message(STATUS "${CACHE_OPTION} is enabled but was not found. Not using it")
+endif()
diff --git a/CMake/CompilerWarnings.cmake b/CMake/CompilerWarnings.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..eafc2f7a85068ab66d9e113848e94c4a2569bdff
--- /dev/null
+++ b/CMake/CompilerWarnings.cmake
@@ -0,0 +1,77 @@
+# from here:
+#
+# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md
+
+function(set_project_warnings project_name)
+
+  set(MSVC_WARNINGS
+      /W4 # Baseline reasonable warnings
+      /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data
+      /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
+      /w14263 # 'function': member function does not override any base class virtual member function
+      /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not
+              # be destructed correctly
+      /w14287 # 'operator': unsigned/negative constant mismatch
+      /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside
+              # the for-loop scope
+      /w14296 # 'operator': expression is always 'boolean_value'
+      /w14311 # 'variable': pointer truncation from 'type1' to 'type2'
+      /w14545 # expression before comma evaluates to a function which is missing an argument list
+      /w14546 # function call before comma missing argument list
+      /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect
+      /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'?
+      /w14555 # expression has no effect; expected expression with side- effect
+      /w14619 # pragma warning: there is no warning number 'number'
+      /w14640 # Enable warning on thread un-safe static member initialization
+      /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
+      /w14905 # wide string literal cast to 'LPSTR'
+      /w14906 # string literal cast to 'LPWSTR'
+      /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied
+      /permissive- # standards conformance mode for MSVC compiler.
+  )
+
+  set(CLANG_WARNINGS
+      -Wall
+      -Wextra # reasonable and standard
+      -Wshadow # warn the user if a variable declaration shadows one from a parent context
+      -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
+                         # catch hard to track down memory errors
+      -Wold-style-cast # warn for c-style casts
+      -Wcast-align # warn for potential performance problem casts
+      -Wunused # warn on anything being unused
+      -Woverloaded-virtual # warn if you overload (not override) a virtual function
+      -Wpedantic # warn if non-standard C++ is used
+      -Wconversion # warn on type conversions that may lose data
+      -Wsign-conversion # warn on sign conversions
+      -Wnull-dereference # warn if a null dereference is detected
+      -Wdouble-promotion # warn if float is implicit promoted to double
+      -Wformat=2 # warn on security issues around functions that format output (ie printf)
+  )
+
+  if(BUILD_WARNINGS_AS_ERRORS)
+    set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror)
+    set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX)
+  endif()
+
+  set(GCC_WARNINGS
+      ${CLANG_WARNINGS}
+      -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist
+      -Wduplicated-cond # warn if if / else chain has duplicated conditions
+      -Wduplicated-branches # warn if if / else branches have duplicated code
+      -Wlogical-op # warn about logical operations being used where bitwise were probably wanted
+      -Wuseless-cast # warn if you perform a cast to the same type
+  )
+
+  if(MSVC)
+    set(PROJECT_WARNINGS ${MSVC_WARNINGS})
+  elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
+    set(PROJECT_WARNINGS ${CLANG_WARNINGS})
+  elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+    set(PROJECT_WARNINGS ${GCC_WARNINGS})
+  else()
+    message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.")
+  endif()
+
+  target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS})
+
+endfunction()
diff --git a/CMake/Sanitizers.cmake b/CMake/Sanitizers.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..6f16207fefbc2f9ca72f065950b242a4333d442e
--- /dev/null
+++ b/CMake/Sanitizers.cmake
@@ -0,0 +1,60 @@
+function(enable_sanitizers project_name)
+
+  if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
+
+    set(SANITIZERS "")
+
+    option(ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" FALSE)
+    if(ENABLE_SANITIZER_ADDRESS)
+      list(APPEND SANITIZERS "address")
+    endif()
+
+    option(ENABLE_SANITIZER_LEAK "Enable leak sanitizer" FALSE)
+    if(ENABLE_SANITIZER_LEAK)
+      list(APPEND SANITIZERS "leak")
+    endif()
+
+    option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" FALSE)
+    if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR)
+      list(APPEND SANITIZERS "undefined")
+    endif()
+
+    option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" FALSE)
+    if(ENABLE_SANITIZER_THREAD)
+      if("address" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS)
+        message(WARNING "Thread sanitizer does not work with Address and Leak sanitizer enabled")
+      else()
+        list(APPEND SANITIZERS "thread")
+      endif()
+    endif()
+
+    option(ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" FALSE)
+    if(ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
+      if("address" IN_LIST SANITIZERS
+         OR "thread" IN_LIST SANITIZERS
+         OR "leak" IN_LIST SANITIZERS)
+        message(WARNING "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled")
+      else()
+        list(APPEND SANITIZERS "memory")
+      endif()
+    endif()
+
+    list(
+      JOIN
+      SANITIZERS
+      ","
+      LIST_OF_SANITIZERS)
+
+  endif()
+
+  if(LIST_OF_SANITIZERS)
+    if(NOT
+       "${LIST_OF_SANITIZERS}"
+       STREQUAL
+       "")
+      target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
+      target_link_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
+    endif()
+  endif()
+
+endfunction()
diff --git a/CMake/VirtualFluidsMacros.cmake b/CMake/VirtualFluidsMacros.cmake
index debb5ee7826d7dc3d6499b3813070dcab4b94bd4..fbe0d9404e6c923bfb866e7d8dea7844b51ae17a 100644
--- a/CMake/VirtualFluidsMacros.cmake
+++ b/CMake/VirtualFluidsMacros.cmake
@@ -21,6 +21,7 @@ endfunction()
 include(${VF_CMAKE_DIR}/CMakeSetCompilerFlags.cmake)
 include(${VF_CMAKE_DIR}/FileUtilities.cmake)
 include(${VF_CMAKE_DIR}/3rd.cmake)
+include(${VF_CMAKE_DIR}/Sanitizers.cmake)
 
 ###############################################################################################################
 # Reset the compiler and linker flags
@@ -80,7 +81,7 @@ endfunction()
 #################################################################################
 function (vf_get_library_test_name library_test_name)
     vf_get_library_name (folder_name)
-    set (${library_test_name} ${library_name}Tests PARENT_SCOPE)
+    set (${library_test_name} ${folder_name}Tests PARENT_SCOPE)
 endfunction()
 
 
@@ -103,11 +104,11 @@ endfunction()
 function(vf_add_library)
 
     set( options )
-    set( oneValueArgs )
-    set( multiValueArgs NAME BUILDTYPE PUBLIC_LINK PRIVATE_LINK FILES FOLDER EXCLUDE)
+    set( oneValueArgs NAME BUILDTYPE)
+    set( multiValueArgs PUBLIC_LINK PRIVATE_LINK FILES FOLDER EXCLUDE)
     cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
 
-    if(${ARG_NAME})
+    if(DEFINED ARG_NAME)
         set(library_name ${ARG_NAME})
     else()
         vf_get_library_name (library_name)
@@ -131,18 +132,18 @@ function(vf_add_library)
     #################################################################
     ###   ADD TARGET                                              ###
     #################################################################
-    IF(${ARG_BUILDTYPE} MATCHES binary)
-        ADD_EXECUTABLE(${library_name} ${MY_SRCS} )
+    if(${ARG_BUILDTYPE} MATCHES binary)
+        add_executable(${library_name} ${MY_SRCS} )
         groupTarget(${library_name} ${appFolder})
-    ELSEIF(${ARG_BUILDTYPE} MATCHES shared)
-        ADD_LIBRARY(${library_name} SHARED ${MY_SRCS} )
+    elseif(${ARG_BUILDTYPE} MATCHES shared)
+        add_library(${library_name} SHARED ${MY_SRCS} )
         groupTarget(${library_name} ${libraryFolder})
-    ELSEIF(${ARG_BUILDTYPE} MATCHES static)
-        ADD_LIBRARY(${library_name} STATIC ${MY_SRCS} )
+        elseif(${ARG_BUILDTYPE} MATCHES static)
+        add_library(${library_name} STATIC ${MY_SRCS} )
         groupTarget(${library_name} ${libraryFolder})
-    ELSE()
-        MESSAGE(FATAL_ERROR "build_type=${ARG_BUILDTYPE} doesn't match BINARY, SHARED or STATIC")
-    ENDIF()
+    else()
+        message(FATAL_ERROR "build_type=${ARG_BUILDTYPE} doesn't match BINARY, SHARED or STATIC")
+    endif()
 
     # Set the output directory for build artifacts
     set_target_properties(${library_name}
@@ -152,6 +153,24 @@ function(vf_add_library)
             ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
             PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
 
+    # sanitizers
+    enable_sanitizers(${library_name})
+
+    # link time optimization
+    if(BUILD_VF_LTO)
+        if(NOT ${ARG_BUILDTYPE} MATCHES binary)
+            include(CheckIPOSupported)
+            check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error LANGUAGES CXX)
+
+            if( ipo_supported )
+                status_lib("IPO / LTO enabled")
+                set_target_properties(${library_name} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
+            else()
+                status_lib("IPO / LTO not supported: <${ipo_error}>")
+            endif()
+        endif()
+    endif()
+
     # clang-tidy
     if(BUILD_VF_CLANG_TIDY)
         find_program(CLANG_TIDY_PROGRAM NAMES clang-tidy)
@@ -286,6 +305,9 @@ function(vf_add_tests)
     # link googlemock
     linkGMOCK()
 
+    # add the target to ctest
+    gtest_add_tests(TARGET ${library_test_name})
+
 endfunction()
 
 #################################################################################
diff --git a/CMake/compilerflags/GNU.cmake b/CMake/compilerflags/GNU.cmake
index 3e67b79e9c84d29b51b2881b17e2b74f5510bbd2..8d54b52a434719a1e99aa705b121593973f3375a 100644
--- a/CMake/compilerflags/GNU.cmake
+++ b/CMake/compilerflags/GNU.cmake
@@ -38,6 +38,7 @@ list(APPEND CS_COMPILER_FLAGS_CXX "-Wno-unused-parameter")
 list(APPEND CS_COMPILER_FLAGS_CXX "-Wno-reorder")
 list(APPEND CS_COMPILER_FLAGS_CXX "-Wno-unknown-pragmas")
 list(APPEND CS_COMPILER_FLAGS_CXX "-Wno-cast-function-type")
+list(APPEND CS_COMPILER_FLAGS_CXX "-Wno-strict-aliasing")
 
 #############################################################################################################
 # linker options
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 03ed97b484e3cd3fc53d73d2ad0247f12503ea9c..aef9cc07ee2f578385e3fc07e4f7fae40dbdae1e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,15 +6,18 @@
 # |___/_/_/   \__/\__,_/\__,_/_/_/   /_/\__,_/_/\__,_/____/
 #
 #################################################################################
-#  required cmake versions
-#  CMAKE 3.13: target_link_options
-#  CMAKE 3.15: CMAKE_MSVC_RUNTIME_LIBRARY
-#################################################################################
-cmake_minimum_required(VERSION 3.15..3.19 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.15..3.20 FATAL_ERROR)
 
-project(VirtualFluids CXX)
+project(VirtualFluids
+        VERSION 1.0.0
+        DESCRIPTION "CFD code based on the Lattice Boltzmann Method"
+        HOMEPAGE_URL "https://www.tu-braunschweig.de/irmb/forschung/virtualfluids"
+        LANGUAGES CXX)
 
-set(CMAKE_BUILD_TYPE Release)
+if(NOT CMAKE_BUILD_TYPE)
+    set(CMAKE_BUILD_TYPE Release)
+endif()
+message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
 
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -31,6 +34,11 @@ set (VF_THIRD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty)
 set (VF_SRC_DIR   ${CMAKE_CURRENT_SOURCE_DIR}/src)
 set (VF_ROOT_DIR  ${CMAKE_CURRENT_SOURCE_DIR})
 
+if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
+  message(FATAL_ERROR "In-source builds are prohibited. "
+    "Create a new directory and build there.")
+endif ()
+
 #################################################################################
 #  OPTIONS
 #################################################################################
@@ -38,10 +46,10 @@ option(BUILD_VF_CPU "Build VirtualFluids cpu variant" OFF)
 option(BUILD_VF_GPU "Build VirtualFluids gpu variant" OFF)
 
 option(BUILD_USE_OPENMP "Build VirtualFluids with openmp" ON)
-
+option(BUILD_USE_BOOST "Build VirtualFluids with boost" OFF)
+option(BUILD_USE_MPI "include MPI library support" ON)
 
 # vf gpu
-option(BUILD_VF_GPU          "Build VirtualFluids GPU"     ON )
 option(BUILD_VF_GKS          "Build VirtualFluids GKS"     OFF )
 option(BUILD_VF_TRAFFIC      "Build VirtualFluids Traffic" OFF)
 option(BUILD_JSONCPP         "Builds json cpp "            OFF)
@@ -53,6 +61,8 @@ option(BUILD_VF_INCLUDE_WHAT_YOU_USE "Add IWYU to the targets" OFF)
 option(BUILD_VF_CPPCHECK "Add cppcheck to the targets" OFF)
 option(BUILD_VF_COVERAGE "Add the -coverage compiler flag." OFF)
 
+option(BUILD_CUDA_LTO "Enables the cuda link optimization." OFF)
+
 option(BUILD_SHARED_LIBS "" OFF)
 option(BUILD_WARNINGS_AS_ERRORS "" OFF)
 
@@ -71,6 +81,15 @@ option(BUILD_VF_DOUBLE_ACCURACY "Use double accuracy" OFF)
 #################################################################################
 #  MACROS
 #################################################################################
+add_library(project_warnings INTERFACE)
+
+# standard compiler warnings - Link this 'library' to use the warnings specified in CompilerWarnings.cmake
+include(${VF_CMAKE_DIR}/CompilerWarnings.cmake)
+set_project_warnings(project_warnings)
+
+# enable cache system
+include(${VF_CMAKE_DIR}/Cache.cmake)
+
 include(CMakePrintHelpers)
 include(${VF_CMAKE_DIR}/VirtualFluidsMacros.cmake)
 
@@ -78,26 +97,8 @@ IF( BUILD_VF_DOUBLE_ACCURACY )
     list(APPEND VF_COMPILER_DEFINITION VF_DOUBLE_ACCURACY)
 ENDIF()
 
-#################################################################################
-#  COMMON LIBRARIES
-#################################################################################
-if(BUILD_USE_OPENMP)
-    find_package(OpenMP REQUIRED)
-endif()
-
-find_package(MPI REQUIRED)
-
-
-add_subdirectory(src/basics)
-
-#################################################################################
-#  VIRTUAL FLUIDS CPU / GPU
-#################################################################################
-if (BUILD_VF_CPU)
-    include (cpu.cmake)
-endif()
-if(BUILD_VF_GPU)
-
+# set gpu features
+if(BUILD_VF_GPU OR BUILD_VF_GKS)
     include(CheckLanguage)
     check_language(CUDA)
 
@@ -105,33 +106,102 @@ if(BUILD_VF_GPU)
         message(FATAL_ERROR "CUDA Compiler was requested but is not found on the system.")
     endif()
 
-    if(MSVC) 
-        # With the MSVC compiler we got this warning: nvcc : The -std=c++14 flag is not supported with the configured host compiler. Flag will be ignored.
-        # But we build the c++ code with C++14. Until we have not a solution here, we set the standard to 11 here.
-        set(CMAKE_CUDA_STANDARD 11)
-    else()
-        set(CMAKE_CUDA_STANDARD 14)
-    endif()
-
+    set(CMAKE_CUDA_STANDARD 17)
     set(CMAKE_CUDA_STANDARD_REQUIRED TRUE)
 
-    set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number")
+    enable_language(CUDA)
 
     if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
         message(WARNING "CMAKE_CUDA_ARCHITECTURES was not defined and is set to 30 (CUDA support until 10.1 only).")
         set(CMAKE_CUDA_ARCHITECTURES 30)
     endif()
 
-    message("CUDA Architecture: ${CMAKE_CUDA_ARCHITECTURES}")
 
-    include (gpu.cmake)
+    if(BUILD_CUDA_LTO)
+       if(CMAKE_CUDA_ARCHITECTURES LESS 50)
+            message(FATAL_ERROR "CUDA Link time optimization requires CUDA 11.2 and CC 5.0.")
+       else()
+
+        set(CMAKE_CUDA_FLAGS "-dlto -arch=sm_${CMAKE_CUDA_ARCHITECTURES}")
+        set(CMAKE_CUDA_ARCHITECTURES OFF)
+
+        list(APPEND VF_COMPILER_DEFINITION BUILD_CUDA_LTO)
+
+       endif()
+    endif()
+
+    set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --extended-lambda")
+
+    message(STATUS "CMAKE_CUDA_FLAGS: ${CMAKE_CUDA_FLAGS}")
+    message(STATUS "CUDA Architecture: ${CMAKE_CUDA_ARCHITECTURES}")
+    set(CMAKE_CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}" CACHE STRING "Cuda Architecture (compute capabilitiy)")
 endif()
 
+
 #################################################################################
-#  3rd Party Libraries
+#  COMMON LIBRARIES
 #################################################################################
+include(FetchContent)
+
+set(spdlog_version "v1.9.1")
+set(spdlog_url "https://github.com/gabime/spdlog")
+message(STATUS "Fetching spdlog: ${spdlog_version}")
+FetchContent_Declare(
+        spdlog
+        GIT_REPOSITORY ${spdlog_url}
+        GIT_TAG        ${spdlog_version}
+)
+
+FetchContent_MakeAvailable(spdlog)
+target_compile_options(spdlog PRIVATE "-fPIC")
+groupTarget(spdlog ${thirdFolder})
+
 if(BUILD_VF_UNIT_TESTS)
-    if(NOT BUILD_NUMERIC_TESTS) # in this case googletest is already included.
-        add_subdirectory(${VF_THIRD_DIR}/googletest)
-    endif()
+    add_subdirectory(${VF_THIRD_DIR}/googletest)
+    include(GoogleTest)
+    enable_testing()
+endif()
+
+if(BUILD_USE_OPENMP)
+    find_package(OpenMP REQUIRED)
+endif()
+
+if(BUILD_USE_MPI)
+    find_package(MPI REQUIRED)
+    list(APPEND VF_COMPILER_DEFINITION VF_MPI)
+endif()
+
+# boost
+IF(BUILD_USE_BOOST)
+    list(APPEND VF_COMPILER_DEFINITION BUILD_USE_BOOST)
+
+    set(Boost_USE_STATIC_LIBS ON)
+    set(Boost_USE_MULTITHREADED ON)
+    set(Boost_USE_STATIC_RUNTIME ON)
+
+    # minimum boost version: 1.60
+    # no packages specfied - only headeronly libraries
+    find_package(Boost 1.60 REQUIRED)
+ENDIF()
+
+add_subdirectory(src/logger)
+add_subdirectory(src/basics)
+add_subdirectory(src/mpi)
+add_subdirectory(src/lbm)
+
+
+#################################################################################
+#  VIRTUAL FLUIDS CPU / GPU
+#################################################################################
+if (BUILD_VF_CPU)
+    include (cpu.cmake)
+endif()
+if(BUILD_VF_GPU OR BUILD_VF_GKS)
+    add_subdirectory(src/cuda)
+    include (gpu.cmake)
+endif()
+
+if (BUILD_VF_PYTHON_BINDINGS)
+    add_subdirectory(${VF_THIRD_DIR}/pybind11/pybind11-2.6.0)
+    add_subdirectory(pythonbindings)
 endif()
diff --git a/CMakePresets.json b/CMakePresets.json
index 6863446af85b177bb4dc99eed475aa52f4d50269..0f360fd303cdcad923b01d56df5c6d48ad62ca2c 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -1,133 +1,137 @@
 {
-  "version": 1,
-  "cmakeMinimumRequired": {
-    "major": 3,
-    "minor": 19,
-    "patch": 0
-  },
-  "configurePresets": [
-    {
-      "name": "default",
-      "hidden": true,
-      "binaryDir": "${sourceDir}/build/",
-      "cacheVariables": {
-        "BUILD_VF_UNIT_TESTS": "ON"
-      }
-    },
-    {
-      "name": "default_make",
-      "inherits": "default",
-      "hidden": true,
-      "generator": "Unix Makefiles"
-    },
-    {
-      "name": "default_ccache_make",
-      "inherits": "default_make",
-      "hidden": true,
-      "cacheVariables": {
-        "CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
-        "CMAKE_CUDA_COMPILER_LAUNCHER": "ccache",
-        "CMAKE_C_COMPILER_LAUNCHER": "ccache"
-      }
-    },
-    {
-      "name": "default_msvc",
-      "inherits": "default",
-      "hidden": true,
-      "generator": "Visual Studio 16 2019",
-      "architecture": "x64"
-    },
-    {
-      "name": "default_cpu",
-      "hidden": true,
-      "description": "CPU build of VirtualFluids",
-      "cacheVariables": {
-        "BUILD_VF_CPU": "ON"
-      }
-    },
-    {
-      "name": "default_gpu",
-      "hidden": true,
-      "description": "GPU build of VirtualFluids",
-      "cacheVariables": {
-        "BUILD_VF_GPU": "ON"
-      }
-    },
-    {
-      "name": "default_gpu_numerical_tests",
-      "inherits": ["default_gpu"],
-      "hidden": true,
-      "description": "GPU numerical tests of VirtualFluids",
-      "cacheVariables": {
-        "BUILD_VF_DOUBLE_ACCURACY": "ON",
-        "BUILD_NUMERIC_TESTS": "ON"
-      }
-    },
-    {
-      "name": "default_all",
-      "hidden": true,
-      "description": "All build of VirtualFluids",
-      "inherits": ["default_cpu", "default_gpu"]
-    },
-    {
-      "name": "cpu_make",
-      "inherits": ["default_make", "default_cpu"],
-      "displayName": "cpu make configuration"
-    },
-    {
-      "name": "cpu_make_ccache",
-      "inherits": ["default_ccache_make", "default_cpu"],
-      "displayName": "cpu ccache make configuration"
-    },
-    {
-      "name": "cpu_msvc",
-      "inherits": ["default_msvc", "default_cpu"],
-      "displayName": "cpu msvc configuration"
-    },
-    {
-      "name": "gpu_make",
-      "inherits": ["default_make", "default_gpu"],
-      "displayName": "gpu make configuration"
-    },
-    {
-      "name": "gpu_make_ccache",
-      "inherits": ["default_ccache_make", "default_gpu"],
-      "displayName": "gpu ccache make configuration"
-    },
-    {
-      "name": "gpu_msvc",
-      "inherits": ["default_msvc", "default_gpu"],
-      "displayName": "gpu msvc configuration"
-    },
-    {
-      "name": "all_make",
-      "inherits": ["default_make", "default_all"],
-      "displayName": "all make configuration"
-    },
-    {
-      "name": "all_make_ccache",
-      "inherits": ["default_ccache_make", "default_all"],
-      "displayName": "all ccache make configuration"
-    },
-    {
-      "name": "all_msvc",
-      "inherits": ["default_msvc", "default_all"],
-      "displayName": "all msvc configuration"
-    },
-    {
-      "name": "gpu_numerical_tests_make",
-      "inherits": ["default_make", "default_gpu_numerical_tests"],
-      "displayName": "gpu numerical tests make configuration"
-    },
-    {
-      "name": "gpu_numerical_tests_ccache_make",
-      "inherits": ["default_ccache_make", "default_gpu_numerical_tests"],
-      "displayName": "gpu numerical tests ccache make configuration"
-    },
-    {
-      "name": "gpu_numerical_tests_msvc",
-      "inherits": ["default_msvc", "default_gpu_numerical_tests"],
-      "displayName": "gpu numerical tests msvc configuration"
-    }
-  ]
+    "version": 2,
+    "cmakeMinimumRequired": {
+        "major": 3,
+        "minor": 20,
+        "patch": 0
+    },
+    "configurePresets": [
+        {
+            "name": "default",
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build/",
+            "cacheVariables": {
+                "BUILD_VF_UNIT_TESTS": "ON"
+            }
+        },
+        {
+            "name": "default_make",
+            "inherits": "default",
+            "hidden": true,
+            "generator": "Unix Makefiles"
+        },
+        {
+            "name": "default_msvc",
+            "inherits": "default",
+            "hidden": true,
+            "generator": "Visual Studio 16 2019",
+            "architecture": "x64"
+        },
+        {
+            "name": "default_cpu",
+            "hidden": true,
+            "description": "CPU build of VirtualFluids",
+            "cacheVariables": {
+                "BUILD_VF_CPU": "ON",
+                "BUILD_VF_DOUBLE_ACCURACY": "ON"
+            }
+        },
+        {
+            "name": "default_gpu",
+            "hidden": true,
+            "description": "GPU build of VirtualFluids",
+            "cacheVariables": {
+                "BUILD_VF_GPU": "ON",
+                "BUILD_VF_DOUBLE_ACCURACY": "OFF"
+            }
+        },
+        {
+            "name": "default_gpu_numerical_tests",
+            "inherits": [
+                "default_gpu"
+            ],
+            "hidden": true,
+            "description": "GPU numerical tests of VirtualFluids",
+            "cacheVariables": {
+                "BUILD_VF_DOUBLE_ACCURACY": "ON",
+                "BUILD_NUMERIC_TESTS": "ON"
+            }
+        },
+        {
+            "name": "default_all",
+            "hidden": true,
+            "description": "All build of VirtualFluids",
+            "inherits": [
+                "default_cpu",
+                "default_gpu"
+            ],
+            "cacheVariables": {
+                "BUILD_VF_DOUBLE_ACCURACY": "ON"
+            }
+        },
+        {
+            "name": "cpu_make",
+            "inherits": [
+                "default_make",
+                "default_cpu"
+            ],
+            "displayName": "cpu make configuration"
+        },
+        {
+            "name": "cpu_msvc",
+            "inherits": [
+                "default_msvc",
+                "default_cpu"
+            ],
+            "displayName": "cpu msvc configuration"
+        },
+        {
+            "name": "gpu_make",
+            "inherits": [
+                "default_make",
+                "default_gpu"
+            ],
+            "displayName": "gpu make configuration"
+        },
+        {
+            "name": "gpu_msvc",
+            "inherits": [
+                "default_msvc",
+                "default_gpu"
+            ],
+            "displayName": "gpu msvc configuration"
+        },
+        {
+            "name": "all_make",
+            "inherits": [
+                "default_make",
+                "default_all"
+            ],
+            "displayName": "all make configuration"
+        },
+        {
+            "name": "all_msvc",
+            "inherits": [
+                "default_msvc",
+                "default_all"
+            ],
+            "displayName": "all msvc configuration"
+        },
+        {
+            "name": "gpu_numerical_tests_make",
+            "inherits": [
+                "default_make",
+                "default_gpu_numerical_tests"
+            ],
+            "displayName": "gpu numerical tests make configuration"
+        },
+        {
+            "name": "gpu_numerical_tests_msvc",
+            "inherits": [
+                "default_msvc",
+                "default_gpu_numerical_tests"
+            ],
+            "displayName": "gpu numerical tests msvc configuration"
+        }
+    ]
 }
diff --git a/README.md b/README.md
index 14d8b2515f3201a93e03de6abf6257956e943506..7b8d6c973808e209a22b2f2da99d23862aa76dc7 100644
--- a/README.md
+++ b/README.md
@@ -10,17 +10,17 @@ VirtualFluids has been used on a variety of platforms:
  - Windows
  - Cygwin
 ### Software Requirements
- 
+
  - [CMake](https://cmake.org/) (minimum version 3.15)
  - C++ compiler with C++14 support
  - [Paraview](https://www.paraview.org/) (most recent version)
 
-with usage of the GPU:  
+with usage of the GPU:
  - CUDA [developer.nvidia.com/cuda-zone](https://developer.nvidia.com/cuda-zone):
     * Minimum CUDA Version 9.0
     * Minimum Compute Capability 3.0, because of maximal number of Blocks in x direction
     * Recommended Compute Capability 6.0, because of atomics for double precision floating point data (GKS only)
-    
+
 
 ### Contributing
 To contribute to VirtualFluids please follow these [instructions](CONTRIBUTING.md).
@@ -41,11 +41,11 @@ Alternatively enable the options via the cmake-gui.
 ### <a id="options"></a> Options
 - BUILD_VF_CPU
   - Build VirtualFluids CPU variant
-- BUILD_VF_GPU 
+- BUILD_VF_GPU
   - Build VirtualFluids GPU variant
 - BUILD_VF_UNIT_TESTS
   -  Build VirtualFluids unit tests
-- VF_DOUBLE_ACCURACY 
+- VF_DOUBLE_ACCURACY
     - GPU change between Double and Single Precision
 
 ### Result Files
@@ -62,7 +62,7 @@ The doxygen generated documentation can be found [here](https://irmb.gitlab-page
 
 
 ## Known Issues
-If you notice any problems on your platform, please report an [issue](https://git.rz.tu-bs.de/irmb/virtualfluids/-/issues/new). 
+If you notice any problems on your platform, please report an [issue](https://git.rz.tu-bs.de/irmb/virtualfluids/-/issues/new).
 
 
 ## Authors
diff --git a/apps/cpu/LidDrivenCavityCPU/LidDrivenCavity.cpp b/apps/cpu/LidDrivenCavityCPU/LidDrivenCavity.cpp
index 3c86719f24cad32142cfc60908e276fb33996747..8b378f34dfb72453b2140505d93a7bc29245f3d2 100644
--- a/apps/cpu/LidDrivenCavityCPU/LidDrivenCavity.cpp
+++ b/apps/cpu/LidDrivenCavityCPU/LidDrivenCavity.cpp
@@ -79,7 +79,7 @@ int main(int /*argc*/, char * /*argv*/[])
         double g_maxX3 = 0.5;
 
         // NullCommunicator is a place-holder for interprocess communication
-        SPtr<Communicator> comm = NullCommunicator::getInstance();
+        SPtr<vf::mpi::Communicator> comm = vf::mpi::NullCommunicator::getInstance();
         // new grid object
         SPtr<Grid3D> grid(new Grid3D(comm));
         // set grid spacing
diff --git a/src/basics/CMakeLists.txt b/src/basics/CMakeLists.txt
index 1703d6269c1cebe36005226373da85b14c5515f6..7f871424b2c6849d2c0f6e8d277b17214fa5cd9c 100644
--- a/src/basics/CMakeLists.txt
+++ b/src/basics/CMakeLists.txt
@@ -1,7 +1,7 @@
 
 include(Core/buildInfo.cmake)
 
-vf_add_library(PUBLIC_LINK MPI::MPI_CXX EXCLUDE buildInfo.in.cpp)
+vf_add_library(PUBLIC_LINK logger MPI::MPI_CXX EXCLUDE buildInfo.in.cpp)
 
 vf_get_library_name (library_name)
 target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Core)
diff --git a/src/basics/Core/RealConstants.h b/src/basics/Core/RealConstants.h
index 697d628986bb417ab124c465526d0538b2734438..5cb42584e29d0e0a1a9cf1b40f50736dd13169f0 100644
--- a/src/basics/Core/RealConstants.h
+++ b/src/basics/Core/RealConstants.h
@@ -30,226 +30,226 @@
 //! \ingroup Core
 //! \author Martin Schoenherr
 //=======================================================================================
-#ifndef REAL_CONSTANT_H
-#define REAL_CONSTANT_H
-
-#ifdef VF_DOUBLE_ACCURACY
-#define c1o2 0.5
-#define c3o2 1.5
-#define c1o3 0.333333333333333
-#define c2o3 0.666666666666667
-#define c1o4 0.25
-#define c3o4 0.75
-#define c1o6 0.166666666666667
-#define c1o7 0.142857142857143
-#define c1o8 0.125
-#define c1o9 0.111111111111111
-#define c2o9 0.222222222222222
-#define c4o9 0.444444444444444
-#define c1o10 0.1
-#define c1o12 0.083333333333333
-#define c1o16 0.0625
-#define c3o16 0.1875
-#define c9o16 0.5625
-#define c1o18 0.055555555555556
-#define c1o20 0.05
-#define c19o20 0.95
-#define c21o20 1.05
-#define c1o24 0.041666666666667
-#define c1o27 0.037037037037037
-#define c3o32 0.09375
-#define c4o32 0.125
-#define c1o36 0.027777777777778
-#define c1o48 0.020833333333333
-#define c1o64 0.015625
-#define c3o64 0.046875
-#define c9o64 0.140625
-#define c27o64 0.421875
-#define c1o66 0.015151515151515
-#define c1o72 0.013888888888889
-#define c1o264 0.003787878787879
-#define c8o27 0.296296296296296
-#define c2o27 0.074074074074074
-#define c1o54 0.018518518518519
-#define c1o100 0.01
-#define c99o100 0.99
-#define c1o126 0.007936507936508
-#define c1o216 0.004629629629630
-#define c5o4 1.25
-#define c9o4 2.25
-#define c5o2 2.5
-#define c9o2 4.5
-
-#define c0o1 0.
-#define c1o1 1.
-#define c2o1 2.
-#define c3o1 3.
-#define c4o1 4.
-#define c5o1 5.
-#define c6o1 6.
-#define c7o1 7.
-#define c8o1 8.
-#define c9o1 9.
-#define c10o1 10.
-#define c11o1 11.
-#define c12o1 12.
-#define c13o1 13.
-#define c14o1 14.
-#define c15o1 15.
-#define c16o1 16.
-#define c17o1 17.
-#define c18o1 18.
-#define c21o1 21.
-#define c24o1 24.
-#define c25o1 25.
-#define c26o1 26.
-#define c27o1 27.
-#define c28o1 28.
-#define c29o1 29.
-#define c30o1 30.
-#define c32o1 32.
-#define c33o1 33.
-#define c34o1 34.
-#define c36o1 36.
-#define c40o1 40.
-#define c42o1 42.
-#define c46o1 46.
-#define c48o1 48.
-#define c50o1 50.
-#define c52o1 52.
-#define c54o1 54.
-#define c56o1 56.
-#define c64o1 64.
-#define c66o1 66.
-#define c68o1 68.
-#define c69o1 69.
-#define c72o1 72.
-#define c84o1 84.
-#define c88o1 88.
-#define c96o1 96.
-#define c100o1 100.0
-#define c130o1 130.0
-#define c152o1 152.0
-#define c166o1 166.0
-#define c195o1 195.0
-#define c216o1 216.0
-#define c264o1 264.0
-#define c290o1 290.0
-#define c367o1 367.0
-
-#define Op0000002 0.0000002
-#define c10eM30 1e-30
-#define c10eM10 1e-10
-#define smallSingle 0.0000000002
-
-#else
-#define c1o2 0.5f
-#define c3o2 1.5f
-#define c1o3 (1.0f / 3.0f)
-#define c2o3 (2.0f / 3.0f)
-#define c1o4 0.25f
-#define c3o4 0.75f
-#define c1o6 (1.0f / 6.0f)
-#define c1o7 (1.0f / 7.0f)
-#define c1o8 0.125f
-#define c1o9 (1.0f / 9.0f)
-#define c2o9 (2.0f / 9.0f)
-#define c4o9 (4.0f / 9.0f)
-#define c1o10 0.1f
-#define c1o12 (1.0f / 12.0f)
-#define c1o16 0.0625f
-#define c3o16 0.1875f
-#define c9o16 0.5625f
-#define c1o18 (1.0f / 18.0f)
-#define c1o20 0.05f
-#define c19o20 0.95f
-#define c21o20 1.05f
-#define c1o24 (1.0f / 24.0f)
-#define c1o27 (1.0f / 27.0f)
-#define c3o32 0.09375f
-#define c4o32 0.125f
-#define c1o36 (1.0f / 36.0f)
-#define c1o48 (1.0f / 48.0f)
-#define c1o64 0.015625f
-#define c3o64 0.046875f
-#define c9o64 0.140625f
-#define c27o64 0.421875f
-#define c1o66 (1.0f / 66.0f)
-#define c1o72 (1.0f / 72.0f)
-#define c1o264 (1.0f / 264.0f)
-#define c8o27 (8.0f / 27.0f)
-#define c2o27 (2.0f / 27.0f)
-#define c1o54 (1.0f / 54.0f)
-#define c1o100 0.01f
-#define c99o100 0.99f
-#define c1o126 (1.0f / 126.0f)
-#define c1o216 (1.0f / 216.0f)
-#define c5o4 1.25f
-#define c9o4 2.25f
-#define c5o2 2.5f
-#define c9o2 4.5f
-
-#define c0o1 0.f
-#define c1o1 1.f
-#define c2o1 2.f
-#define c3o1 3.f
-#define c4o1 4.f
-#define c5o1 5.f
-#define c6o1 6.f
-#define c7o1 7.f
-#define c8o1 8.f
-#define c9o1 9.f
-#define c10o1 10.f
-#define c11o1 11.f
-#define c12o1 12.f
-#define c13o1 13.f
-#define c14o1 14.f
-#define c15o1 15.f
-#define c16o1 16.f
-#define c17o1 17.f
-#define c18o1 18.f
-#define c21o1 21.f
-#define c24o1 24.f
-#define c25o1 25.f
-#define c26o1 26.f
-#define c27o1 27.f
-#define c28o1 28.f
-#define c29o1 29.f
-#define c30o1 30.f
-#define c32o1 32.f
-#define c33o1 33.f
-#define c34o1 34.f
-#define c36o1 36.f
-#define c40o1 40.f
-#define c42o1 42.f
-#define c46o1 46.f
-#define c48o1 48.f
-#define c50o1 50.f
-#define c52o1 52.f
-#define c54o1 54.f
-#define c56o1 56.f
-#define c64o1 64.f
-#define c66o1 66.f
-#define c68o1 68.f
-#define c69o1 69.f
-#define c72o1 72.f
-#define c84o1 84.f
-#define c88o1 88.f
-#define c96o1 96.f
-#define c100o1 100.0f
-#define c130o1 130.0f
-#define c152o1 152.0f
-#define c166o1 166.0f
-#define c195o1 195.0f
-#define c216o1 216.0f
-#define c264o1 264.0f
-#define c290o1 290.0f
-#define c367o1 367.0f
-
-#define Op0000002 0.0000002f
-#define c10eM30 1e-30
-#define c10eM10 1e-10
-#define smallSingle 0.0000000002f
-#endif
-
-#endif
\ No newline at end of file
+//#ifndef REAL_CONSTANT_H
+//#define REAL_CONSTANT_H
+//
+//#ifdef VF_DOUBLE_ACCURACY
+//#define c1o2 0.5
+//#define c3o2 1.5
+//#define c1o3 0.333333333333333
+//#define c2o3 0.666666666666667
+//#define c1o4 0.25
+//#define c3o4 0.75
+//#define c1o6 0.166666666666667
+//#define c1o7 0.142857142857143
+//#define c1o8 0.125
+//#define c1o9 0.111111111111111
+//#define c2o9 0.222222222222222
+//#define c4o9 0.444444444444444
+//#define c1o10 0.1
+//#define c1o12 0.083333333333333
+//#define c1o16 0.0625
+//#define c3o16 0.1875
+//#define c9o16 0.5625
+//#define c1o18 0.055555555555556
+//#define c1o20 0.05
+//#define c19o20 0.95
+//#define c21o20 1.05
+//#define c1o24 0.041666666666667
+//#define c1o27 0.037037037037037
+//#define c3o32 0.09375
+//#define c4o32 0.125
+//#define c1o36 0.027777777777778
+//#define c1o48 0.020833333333333
+//#define c1o64 0.015625
+//#define c3o64 0.046875
+//#define c9o64 0.140625
+//#define c27o64 0.421875
+//#define c1o66 0.015151515151515
+//#define c1o72 0.013888888888889
+//#define c1o264 0.003787878787879
+//#define c8o27 0.296296296296296
+//#define c2o27 0.074074074074074
+//#define c1o54 0.018518518518519
+//#define c1o100 0.01
+//#define c99o100 0.99
+//#define c1o126 0.007936507936508
+//#define c1o216 0.004629629629630
+//#define c5o4 1.25
+//#define c9o4 2.25
+//#define c5o2 2.5
+//#define c9o2 4.5
+//
+//#define c0o1 0.
+//#define c1o1 1.
+//#define c2o1 2.
+//#define c3o1 3.
+//#define c4o1 4.
+//#define c5o1 5.
+//#define c6o1 6.
+//#define c7o1 7.
+//#define c8o1 8.
+//#define c9o1 9.
+//#define c10o1 10.
+//#define c11o1 11.
+//#define c12o1 12.
+//#define c13o1 13.
+//#define c14o1 14.
+//#define c15o1 15.
+//#define c16o1 16.
+//#define c17o1 17.
+//#define c18o1 18.
+//#define c21o1 21.
+//#define c24o1 24.
+//#define c25o1 25.
+//#define c26o1 26.
+//#define c27o1 27.
+//#define c28o1 28.
+//#define c29o1 29.
+//#define c30o1 30.
+//#define c32o1 32.
+//#define c33o1 33.
+//#define c34o1 34.
+//#define c36o1 36.
+//#define c40o1 40.
+//#define c42o1 42.
+//#define c46o1 46.
+//#define c48o1 48.
+//#define c50o1 50.
+//#define c52o1 52.
+//#define c54o1 54.
+//#define c56o1 56.
+//#define c64o1 64.
+//#define c66o1 66.
+//#define c68o1 68.
+//#define c69o1 69.
+//#define c72o1 72.
+//#define c84o1 84.
+//#define c88o1 88.
+//#define c96o1 96.
+//#define c100o1 100.0
+//#define c130o1 130.0
+//#define c152o1 152.0
+//#define c166o1 166.0
+//#define c195o1 195.0
+//#define c216o1 216.0
+//#define c264o1 264.0
+//#define c290o1 290.0
+//#define c367o1 367.0
+//
+//#define Op0000002 0.0000002
+//#define c10eM30 1e-30
+//#define c10eM10 1e-10
+//#define smallSingle 0.0000000002
+//
+//#else
+//#define c1o2 0.5f
+//#define c3o2 1.5f
+//#define c1o3 (1.0f / 3.0f)
+//#define c2o3 (2.0f / 3.0f)
+//#define c1o4 0.25f
+//#define c3o4 0.75f
+//#define c1o6 (1.0f / 6.0f)
+//#define c1o7 (1.0f / 7.0f)
+//#define c1o8 0.125f
+//#define c1o9 (1.0f / 9.0f)
+//#define c2o9 (2.0f / 9.0f)
+//#define c4o9 (4.0f / 9.0f)
+//#define c1o10 0.1f
+//#define c1o12 (1.0f / 12.0f)
+//#define c1o16 0.0625f
+//#define c3o16 0.1875f
+//#define c9o16 0.5625f
+//#define c1o18 (1.0f / 18.0f)
+//#define c1o20 0.05f
+//#define c19o20 0.95f
+//#define c21o20 1.05f
+//#define c1o24 (1.0f / 24.0f)
+//#define c1o27 (1.0f / 27.0f)
+//#define c3o32 0.09375f
+//#define c4o32 0.125f
+//#define c1o36 (1.0f / 36.0f)
+//#define c1o48 (1.0f / 48.0f)
+//#define c1o64 0.015625f
+//#define c3o64 0.046875f
+//#define c9o64 0.140625f
+//#define c27o64 0.421875f
+//#define c1o66 (1.0f / 66.0f)
+//#define c1o72 (1.0f / 72.0f)
+//#define c1o264 (1.0f / 264.0f)
+//#define c8o27 (8.0f / 27.0f)
+//#define c2o27 (2.0f / 27.0f)
+//#define c1o54 (1.0f / 54.0f)
+//#define c1o100 0.01f
+//#define c99o100 0.99f
+//#define c1o126 (1.0f / 126.0f)
+//#define c1o216 (1.0f / 216.0f)
+//#define c5o4 1.25f
+//#define c9o4 2.25f
+//#define c5o2 2.5f
+//#define c9o2 4.5f
+//
+//#define c0o1 0.f
+//#define c1o1 1.f
+//#define c2o1 2.f
+//#define c3o1 3.f
+//#define c4o1 4.f
+//#define c5o1 5.f
+//#define c6o1 6.f
+//#define c7o1 7.f
+//#define c8o1 8.f
+//#define c9o1 9.f
+//#define c10o1 10.f
+//#define c11o1 11.f
+//#define c12o1 12.f
+//#define c13o1 13.f
+//#define c14o1 14.f
+//#define c15o1 15.f
+//#define c16o1 16.f
+//#define c17o1 17.f
+//#define c18o1 18.f
+//#define c21o1 21.f
+//#define c24o1 24.f
+//#define c25o1 25.f
+//#define c26o1 26.f
+//#define c27o1 27.f
+//#define c28o1 28.f
+//#define c29o1 29.f
+//#define c30o1 30.f
+//#define c32o1 32.f
+//#define c33o1 33.f
+//#define c34o1 34.f
+//#define c36o1 36.f
+//#define c40o1 40.f
+//#define c42o1 42.f
+//#define c46o1 46.f
+//#define c48o1 48.f
+//#define c50o1 50.f
+//#define c52o1 52.f
+//#define c54o1 54.f
+//#define c56o1 56.f
+//#define c64o1 64.f
+//#define c66o1 66.f
+//#define c68o1 68.f
+//#define c69o1 69.f
+//#define c72o1 72.f
+//#define c84o1 84.f
+//#define c88o1 88.f
+//#define c96o1 96.f
+//#define c100o1 100.0f
+//#define c130o1 130.0f
+//#define c152o1 152.0f
+//#define c166o1 166.0f
+//#define c195o1 195.0f
+//#define c216o1 216.0f
+//#define c264o1 264.0f
+//#define c290o1 290.0f
+//#define c367o1 367.0f
+//
+//#define Op0000002 0.0000002f
+//#define c10eM30 1e-30
+//#define c10eM10 1e-10
+//#define smallSingle 0.0000000002f
+//#endif
+//
+//#endif
\ No newline at end of file
diff --git a/src/cpu/VirtualFluidsCore/Parallel/Communicator.h b/src/basics/Singelton.h
similarity index 73%
rename from src/cpu/VirtualFluidsCore/Parallel/Communicator.h
rename to src/basics/Singelton.h
index b79508c6b22e4cda36d8713bd62fdb2424c07942..f0979b5dd3d89e26ebbe4b4e82d2336e1f59a07e 100644
--- a/src/cpu/VirtualFluidsCore/Parallel/Communicator.h
+++ b/src/basics/Singelton.h
@@ -26,35 +26,33 @@
 //  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 Communicator.h
-//! \ingroup Parallel
-//! \author Konstantin Kutscher
+//! \author Soeren Peters
 //=======================================================================================
 
-#ifndef COMMUNICATOR_H
-#define COMMUNICATOR_H
+#ifndef BASICS_SINGELTON_H
+#define BASICS_SINGELTON_H
 
-#include <string>
-#include <vector>
-
-#include <PointerDefinitions.h>
+namespace vf::basics
+{
 
-//! \brief An abstract class for communication between processes in parallel computation
-class Communicator
+template<typename T>
+class Singleton
 {
 public:
-    virtual ~Communicator() = default;
-    static SPtr<Communicator> getInstance();
-    virtual int getProcessID()         = 0;
-    virtual int getNumberOfProcesses() = 0;
-    virtual bool isRoot()              = 0;
-    virtual int getRoot()              = 0;
-    virtual int getProcessRoot()       = 0;
+   Singleton(const Singleton&) = delete;
+   Singleton & operator=(const Singleton& rhs) = delete;
 
 protected:
-    Communicator()                     = default;
-    Communicator(const Communicator &) = default;
-    static SPtr<Communicator> instance;
+   Singleton() = default;
+
+public:
+   static std::shared_ptr<Singleton> getInstance()
+   {
+     static std::shared_ptr<Singleton> s{new T};
+     return s;
+   }
 };
 
-#endif
+}
+
+#endif
\ No newline at end of file
diff --git a/src/basics/basics/utilities/UbException.h b/src/basics/basics/utilities/UbException.h
index 9a458980688145c199bf7193000131aeb5fb5e30..5c9fef87bb65b12c1216111ddb9ca1e5eba58ab3 100644
--- a/src/basics/basics/utilities/UbException.h
+++ b/src/basics/basics/utilities/UbException.h
@@ -114,7 +114,7 @@ public:
     /*==========================================================*/
     virtual void addInfo(const std::string &err_str)
     {
-        exceptionData.push_back(makeUbTuple((std::string) "-", 0, (std::string) "unknown", err_str));
+        exceptionData.push_back(makeUbTuple(std::string("-"), 0, std::string("unknown"), err_str));
     }
     /*==========================================================*/
     // add exception
diff --git a/src/basics/basics/utilities/UbFileInputASCII.cpp b/src/basics/basics/utilities/UbFileInputASCII.cpp
index 2d73804f4d06df62e38b0180b9fb0a244eb13887..f988c52f7e381b988830a4506c72e77221c177d9 100644
--- a/src/basics/basics/utilities/UbFileInputASCII.cpp
+++ b/src/basics/basics/utilities/UbFileInputASCII.cpp
@@ -180,9 +180,9 @@ int UbFileInputASCII::readIntegerAfterString(const string &var)
     infile.seekg(0L, ios::beg); // Positionszeiger der Datei auf den Anfang setzen
 
     char line[512];
+
     do {
         infile.getline(line, 512);
-
         if (infile.eof())
             UB_THROW(UbException(UB_EXARGS, "error at reading in file \"" + filename + "\" -> " + var +
                                                 " wasn't found in " + this->filename));
@@ -236,6 +236,7 @@ string UbFileInputASCII::readStringAfterString(const string &var) //,char *value
 
     char line[512];
     // string line_copy[512];
+
     do {
         infile.getline(line, 512);
         if (infile.eof())
@@ -243,17 +244,6 @@ string UbFileInputASCII::readStringAfterString(const string &var) //,char *value
                                                 " wasn't found in " + this->filename));
     } while (strstr(line, var.c_str()) != line); // Ende Schleife, wenn varname ganz in zeile vorkommt
 
-    // std::string lineRead;
-    // while(getline(infile, lineRead))
-    // {
-    //     if(lineRead.find(toSearch, 0) < lineRead.length())
-    //     {
-    //         occurenceNumber++;
-    //         cout << counter << ":" << lineRead << endl;
-
-    //     }
-    // }
-
     std::string temp{ line };
     temp = temp.substr(var.size()); // zeile um "varname" kuerzen
 
diff --git a/src/basics/basics/utilities/UbFileInputASCIITest.cpp b/src/basics/basics/utilities/UbFileInputASCIITest.cpp
index f22c385841d3b516d93650b505a0bf93c9ae85a6..87cb5ce58eb359239d3c3e29babf04e600edc64c 100644
--- a/src/basics/basics/utilities/UbFileInputASCIITest.cpp
+++ b/src/basics/basics/utilities/UbFileInputASCIITest.cpp
@@ -4,7 +4,7 @@
 #include <basics/utilities/UbFileInputASCII.h>
 
 
-TEST(DISABLED_UbFileInputASCIITest, readIntegerAfterString)
+TEST(UbFileInputASCIITest, readIntegerAfterString)
 {
     // assuming that the config files is stored parallel to this file.
     std::filesystem::path filePath = __FILE__;
diff --git a/src/cpu/VirtualFluids.h b/src/cpu/VirtualFluids.h
index e7a2505e16e3e1c8f306605d25a2ba7e42dc920d..d60ac5c29ff7d1853f2efac187d91b298fd7e235 100644
--- a/src/cpu/VirtualFluids.h
+++ b/src/cpu/VirtualFluids.h
@@ -40,9 +40,15 @@
 #include <omp.h>
 #endif
 
+
+#include <mpi/Communicator.h>
+#include <mpi/MPICommunicator.h>
+#include <mpi/NullCommunicator.h>
+
 #include <basics/PointerDefinitions.h>
 
-#include <muParser.h>
+#include <basics/config/ConfigurationFile.h>
+#include <logger/Logger.h>
 
 #include <basics/container/CbArray2D.h>
 #include <basics/container/CbArray3D.h>
@@ -65,7 +71,6 @@
 #include <basics/utilities/UbSystem.h>
 #include <basics/utilities/UbTiming.h>
 #include <basics/utilities/UbTuple.h>
-
 #include <basics/writer/WbWriter.h>
 #include <basics/writer/WbWriterVtkXmlASCII.h>
 #include <basics/writer/WbWriterVtkXmlBinary.h>
@@ -126,8 +131,6 @@
 #include <geometry3d/GbTriangle3D.h>
 #include <geometry3d/GbVector3D.h>
 
-#include <Parallel/Communicator.h>
-#include <Parallel/NullCommunicator.h>
 
 #include <Utilities/MemoryUtil.h>
 
diff --git a/src/cpu/VirtualFluidsCore/CMakeLists.txt b/src/cpu/VirtualFluidsCore/CMakeLists.txt
index ac9da38b2c28d52a9be8d8489abf42247f65506e..fb03d00c225e209b842edc115930215f9b032e2d 100644
--- a/src/cpu/VirtualFluidsCore/CMakeLists.txt
+++ b/src/cpu/VirtualFluidsCore/CMakeLists.txt
@@ -1,11 +1,11 @@
 
 
-set(CAB_ADDITIONAL_LINK_LIBRARIES "")
+set(VF_LIBRARIES "")
 if(BUILD_USE_OPENMP)
-list(APPEND CAB_ADDITIONAL_LINK_LIBRARIES OpenMP::OpenMP_CXX)
+    list(APPEND VF_LIBRARIES OpenMP::OpenMP_CXX)
 endif()
 
-vf_add_library(BUILDTYPE static PUBLIC_LINK basics muparser MPI::MPI_CXX ${CAB_ADDITIONAL_LINK_LIBRARIES})
+vf_add_library(BUILDTYPE static PUBLIC_LINK basics muparser ${VF_LIBRARIES} PRIVATE_LINK lbm mpi logger)
 
 vf_get_library_name(library_name)
 
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.cpp b/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.cpp
index 46cbba0df4b96fddec45c7c696de51d74e9bc6eb..633ffd26f3ed77c58ac83200fdf18cb6f0385979 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.cpp
@@ -33,12 +33,12 @@
 
 #include "NUPSCounterCoProcessor.h"
 
-#include "Communicator.h"
+#include <mpi/Communicator.h>
 #include "Grid3D.h"
 #include "UbScheduler.h"
 
 NUPSCounterCoProcessor::NUPSCounterCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, int numOfThreads,
-                                               SPtr<Communicator> comm)
+                                               std::shared_ptr<vf::mpi::Communicator> comm)
     : CoProcessor(grid, s), numOfThreads(numOfThreads), nup(0), nup_t(0), nupsStep(0.0), comm(comm)
 {
     if (comm->getProcessID() == comm->getRoot()) {
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.h b/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.h
index 61d2ba0b69a96959b07d5e1901da62ab7abdaa1a..ce6b16996824be9e614e131c6e05fad0d1a507fd 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.h
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/NUPSCounterCoProcessor.h
@@ -39,7 +39,7 @@
 #include "CoProcessor.h"
 #include "basics/utilities/UbTiming.h"
 
-class Communicator;
+namespace vf::mpi {class Communicator;}
 class Grid3D;
 class UbScheduler;
 
@@ -54,7 +54,7 @@ public:
     //! \param s is UbScheduler object for scheduling of observer
     //! \param numOfThreads is number of threads
     //! \param comm is Communicator object
-    NUPSCounterCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, int numOfThreads, SPtr<Communicator> comm);
+    NUPSCounterCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, int numOfThreads, std::shared_ptr<vf::mpi::Communicator> comm);
     ~NUPSCounterCoProcessor() override;
 
     void process(double step) override;
@@ -70,7 +70,7 @@ protected:
     double nup;
     double nup_t;
     double nupsStep;
-    SPtr<Communicator> comm;
+    std::shared_ptr<vf::mpi::Communicator> comm;
 };
 
 #endif
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.cpp b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.cpp
index bac7c9c346c24198b56ce8a77cf884c0a660bb1f..536d2ee133517279aa2458d06aea8edcee1dd20f 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.cpp
@@ -33,15 +33,16 @@
 
 #include "WriteBlocksCoProcessor.h"
 #include "basics/writer/WbWriterVtkXmlASCII.h"
+#include <logger/Logger.h>
 
 #include "Block3D.h"
-#include "Communicator.h"
+#include <mpi/Communicator.h>
 #include "D3Q27System.h"
 #include "Grid3D.h"
 #include "UbScheduler.h"
 
 WriteBlocksCoProcessor::WriteBlocksCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, const std::string &path,
-                                               WbWriter *const writer, SPtr<Communicator> comm)
+                                               WbWriter *const writer, std::shared_ptr<vf::mpi::Communicator> comm)
     : CoProcessor(grid, s), path(path), writer(writer), comm(comm)
 {
 }
@@ -180,6 +181,6 @@ void WriteBlocksCoProcessor::collectData(double step)
                                                                      istep, false);
         }
 
-        UBLOG(logINFO, "WriteBlocksCoProcessor step: " << istep);
+        VF_LOG_INFO("WriteBlocksCoProcessor step: {}", istep);
     }
 }
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.h b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.h
index b26cdeebb29fcb1a9ba5b96f010c3c4af83e4c99..837d9bbad7533d0f097c07851b352c50cccf5465 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.h
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBlocksCoProcessor.h
@@ -39,7 +39,7 @@
 
 #include "CoProcessor.h"
 
-class Communicator;
+namespace vf::mpi {class Communicator;}
 class Grid3D;
 class UbScheduler;
 class WbWriter;
@@ -57,7 +57,7 @@ public:
     //! \param writer is WbWriter object
     //! \param comm is Communicator object
     WriteBlocksCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, const std::string &path, WbWriter *const writer,
-                           SPtr<Communicator> comm);
+                           std::shared_ptr<vf::mpi::Communicator> comm);
     ~WriteBlocksCoProcessor() override;
 
     void process(double step) override;
@@ -69,7 +69,7 @@ protected:
 
     std::string path;
     WbWriter *writer;
-    SPtr<Communicator> comm;
+    std::shared_ptr<vf::mpi::Communicator> comm;
 };
 
 #endif
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.cpp b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.cpp
index e85f2806df40e11c7f30cca1c86bcb5dc639ee73..7a618622e1b0316d9634ade3f491736cc5c7c640 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.cpp
@@ -37,10 +37,12 @@
 #include <string>
 #include <vector>
 
+#include <logger/Logger.h>
+
 #include "BCArray3D.h"
 #include "Block3D.h"
 #include "CbArray3D.h"
-#include "Communicator.h"
+#include <mpi/Communicator.h>
 #include "Grid3D.h"
 #include "LBMUnitConverter.h"
 #include "UbScheduler.h"
@@ -53,7 +55,7 @@ WriteBoundaryConditionsCoProcessor::WriteBoundaryConditionsCoProcessor() = defau
 //////////////////////////////////////////////////////////////////////////
 WriteBoundaryConditionsCoProcessor::WriteBoundaryConditionsCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s,
                                                                        const std::string &path, WbWriter *const writer,
-                                                                       SPtr<Communicator> comm)
+                                                                       std::shared_ptr<vf::mpi::Communicator> comm)
     : CoProcessor(grid, s), path(path), writer(writer), comm(comm)
 {
     gridRank     = comm->getProcessID();
@@ -115,7 +117,7 @@ void WriteBoundaryConditionsCoProcessor::collectData(double step)
         } else {
             WbWriterVtkXmlASCII::getInstance()->addFilesToCollection(cfilePath, filenames, istep, false);
         }
-        UBLOG(logINFO, "WriteBoundaryConditionsCoProcessor step: " << istep);
+        VF_LOG_INFO("WriteBoundaryConditionsCoProcessor step: {}", istep);
     }
 
     clearData();
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.h b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.h
index ad29abca5e90c1267d7ab1768c1b3600fbd535c7..2608a3ae8df931a5f0b347b77ad525712676aeab 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.h
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/WriteBoundaryConditionsCoProcessor.h
@@ -41,7 +41,7 @@
 #include "CoProcessor.h"
 #include "UbTuple.h"
 
-class Communicator;
+namespace vf::mpi {class Communicator;}
 class Grid3D;
 class UbScheduler;
 class WbWriter;
@@ -61,7 +61,7 @@ public:
     //! \param writer is WbWriter object
     //! \param comm is Communicator object
     WriteBoundaryConditionsCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, const std::string &path,
-                                       WbWriter *const writer, SPtr<Communicator> comm);
+                                       WbWriter *const writer, std::shared_ptr<vf::mpi::Communicator> comm);
     ~WriteBoundaryConditionsCoProcessor() override = default;
 
     void process(double step) override;
@@ -84,6 +84,6 @@ private:
     int minInitLevel;
     int maxInitLevel;
     int gridRank;
-    SPtr<Communicator> comm;
+    std::shared_ptr<vf::mpi::Communicator> comm;
 };
 #endif
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.cpp b/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.cpp
index eef7d3bf6a0d0ad80aa1bdd7d83dfb469b044584..1eecdf3b238025b83c8150c61a191d178a55db44 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.cpp
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.cpp
@@ -39,7 +39,7 @@
 
 #include "BCArray3D.h"
 #include "Block3D.h"
-#include "Communicator.h"
+#include <mpi/Communicator.h>
 #include "DataSet3D.h"
 #include "Grid3D.h"
 #include "LBMUnitConverter.h"
@@ -52,7 +52,7 @@ WriteMacroscopicQuantitiesCoProcessor::WriteMacroscopicQuantitiesCoProcessor(SPt
                                                                              const std::string &path,
                                                                              WbWriter *const writer,
                                                                              SPtr<LBMUnitConverter> conv,
-                                                                             SPtr<Communicator> comm)
+                                                                             std::shared_ptr<vf::mpi::Communicator> comm)
         : CoProcessor(grid, s), path(path), writer(writer), conv(conv), comm(comm)
 {
     gridRank = comm->getProcessID();
diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h b/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h
index 91df3acf3dc3f584516820e45ca000365dc5d94f..7fb1844e08cf7454294b658f539b95c38eb3fa34 100644
--- a/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h
+++ b/src/cpu/VirtualFluidsCore/CoProcessors/WriteMacroscopicQuantitiesCoProcessor.h
@@ -42,7 +42,7 @@
 #include "LBMSystem.h"
 #include "UbTuple.h"
 
-class Communicator;
+namespace vf::mpi {class Communicator;}
 class Grid3D;
 class UbScheduler;
 class LBMUnitConverter;
@@ -63,7 +63,7 @@ public:
     //! \param conv is LBMUnitConverter object
     //! \param comm is Communicator object
     WriteMacroscopicQuantitiesCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, const std::string &path,
-                                          WbWriter *const writer, SPtr<LBMUnitConverter> conv, SPtr<Communicator> comm);
+                                          WbWriter *const writer, SPtr<LBMUnitConverter> conv, std::shared_ptr<vf::mpi::Communicator> comm);
     ~WriteMacroscopicQuantitiesCoProcessor() override = default;
 
     void process(double step) override;
@@ -90,7 +90,7 @@ private:
     int minInitLevel;
     int maxInitLevel;
     int gridRank;
-    SPtr<Communicator> comm;
+    std::shared_ptr<vf::mpi::Communicator> comm;
 
     using CalcMacrosFct = void (*)(const LBMReal *const &, LBMReal &, LBMReal &, LBMReal &, LBMReal &);
     CalcMacrosFct calcMacros;
diff --git a/src/cpu/VirtualFluidsCore/Connectors/Block3DConnector.h b/src/cpu/VirtualFluidsCore/Connectors/Block3DConnector.h
index a61dcc00b9b23acb0bf09949b0457a4d89a46f9c..747b60acba6448ad2d8f95b4aa092734ca439e33 100644
--- a/src/cpu/VirtualFluidsCore/Connectors/Block3DConnector.h
+++ b/src/cpu/VirtualFluidsCore/Connectors/Block3DConnector.h
@@ -31,8 +31,8 @@
 //! \author Konstantin Kutscher
 //=======================================================================================
 
-#ifndef BLOCK2DCONNECTOR_H
-#define BLOCK2DCONNECTOR_H
+#ifndef BLOCK3DCONNECTOR_H
+#define BLOCK3DCONNECTOR_H
 
 #include <string>
 #include <vector>
diff --git a/src/cpu/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp b/src/cpu/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp
index 6f8a6e74664cf82a550b9000071d4f6beb9ebac2..5e762c68bab806ee7c892c000869bce8c76431af 100644
--- a/src/cpu/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp
+++ b/src/cpu/VirtualFluidsCore/Data/D3Q27EsoTwist3DSplittedVector.cpp
@@ -84,7 +84,7 @@ void D3Q27EsoTwist3DSplittedVector::getDistribution(LBMReal *const f, size_t x1,
     f[D3Q27System::BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1 + 1, x2, x3 + 1);
     f[D3Q27System::BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1);
 
-    f[D3Q27System::ZERO] = (*this->zeroDistributions)(x1, x2, x3);
+    f[D3Q27System::REST] = (*this->zeroDistributions)(x1, x2, x3);
 }
 //////////////////////////////////////////////////////////////////////////
 void D3Q27EsoTwist3DSplittedVector::setDistribution(const LBMReal *const f, size_t x1, size_t x2, size_t x3)
@@ -117,7 +117,7 @@ void D3Q27EsoTwist3DSplittedVector::setDistribution(const LBMReal *const f, size
     (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1 + 1, x2, x3 + 1)     = f[D3Q27System::INV_BNW];
     (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1)         = f[D3Q27System::INV_BNE];
 
-    (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::ZERO];
+    (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::REST];
 }
 //////////////////////////////////////////////////////////////////////////
 void D3Q27EsoTwist3DSplittedVector::getDistributionInv(LBMReal *const f, size_t x1, size_t x2, size_t x3)
@@ -150,7 +150,7 @@ void D3Q27EsoTwist3DSplittedVector::getDistributionInv(LBMReal *const f, size_t
     f[D3Q27System::INV_BNW] = (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1 + 1, x2, x3 + 1);
     f[D3Q27System::INV_BNE] = (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1);
 
-    f[D3Q27System::ZERO] = (*this->zeroDistributions)(x1, x2, x3);
+    f[D3Q27System::REST] = (*this->zeroDistributions)(x1, x2, x3);
 }
 //////////////////////////////////////////////////////////////////////////
 void D3Q27EsoTwist3DSplittedVector::setDistributionInv(const LBMReal *const f, size_t x1, size_t x2, size_t x3)
@@ -183,7 +183,7 @@ void D3Q27EsoTwist3DSplittedVector::setDistributionInv(const LBMReal *const f, s
     (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1 + 1, x2, x3 + 1)     = f[D3Q27System::BNW];
     (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1)         = f[D3Q27System::BNE];
 
-    (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::ZERO];
+    (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::REST];
 }
 //////////////////////////////////////////////////////////////////////////
 void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(const LBMReal *const f, size_t x1, size_t x2, size_t x3,
@@ -241,8 +241,8 @@ void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(const LBMReal *c
         (*this->localDistributions)(D3Q27System::ET_TSW, x1 + 1, x2 + 1, x3) = f[D3Q27System::BNE];
     if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
         (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1) = f[D3Q27System::TSW];
-    if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
-        (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::ZERO];
+    if ((direction & EsoTwistD3Q27System::REST) == EsoTwistD3Q27System::REST)
+        (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::REST];
 }
 //////////////////////////////////////////////////////////////////////////
 void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(LBMReal f, size_t x1, size_t x2, size_t x3,
@@ -327,7 +327,7 @@ void D3Q27EsoTwist3DSplittedVector::setDistributionForDirection(LBMReal f, size_
         case D3Q27System::TSW:
             (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1) = f;
             break;
-        case D3Q27System::ZERO:
+        case D3Q27System::REST:
             (*this->zeroDistributions)(x1, x2, x3) = f;
             break;
         default:
@@ -390,8 +390,8 @@ void D3Q27EsoTwist3DSplittedVector::setDistributionInvForDirection(const LBMReal
         (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1) = f[D3Q27System::BNE];
     if ((direction & EsoTwistD3Q27System::etTSW) == EsoTwistD3Q27System::etTSW)
         (*this->localDistributions)(D3Q27System::ET_TSW, x1 + 1, x2 + 1, x3) = f[D3Q27System::TSW];
-    if ((direction & EsoTwistD3Q27System::ZERO) == EsoTwistD3Q27System::ZERO)
-        (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::ZERO];
+    if ((direction & EsoTwistD3Q27System::REST) == EsoTwistD3Q27System::REST)
+        (*this->zeroDistributions)(x1, x2, x3) = f[D3Q27System::REST];
 }
 //////////////////////////////////////////////////////////////////////////
 void D3Q27EsoTwist3DSplittedVector::setDistributionInvForDirection(LBMReal f, size_t x1, size_t x2, size_t x3,
@@ -476,7 +476,7 @@ void D3Q27EsoTwist3DSplittedVector::setDistributionInvForDirection(LBMReal f, si
         case D3Q27System::TSW:
             (*this->localDistributions)(D3Q27System::ET_TSW, x1 + 1, x2 + 1, x3) = f;
             break;
-        case D3Q27System::ZERO:
+        case D3Q27System::REST:
             (*this->zeroDistributions)(x1, x2, x3) = f;
             break;
         default:
@@ -539,7 +539,7 @@ LBMReal D3Q27EsoTwist3DSplittedVector::getDistributionForDirection(size_t x1, si
             return (*this->localDistributions)(D3Q27System::ET_TSW, x1 + 1, x2 + 1, x3);
         case D3Q27System::BNE:
             return (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1);
-        case D3Q27System::ZERO:
+        case D3Q27System::REST:
             return (*this->zeroDistributions)(x1, x2, x3);
         default:
             UB_THROW(UbException(UB_EXARGS, "Direction didn't find"));
@@ -601,7 +601,7 @@ LBMReal D3Q27EsoTwist3DSplittedVector::getDistributionInvForDirection(size_t x1,
             return (*this->localDistributions)(D3Q27System::ET_TSW, x1 + 1, x2 + 1, x3);
         case D3Q27System::TSW:
             return (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3 + 1);
-        case D3Q27System::ZERO:
+        case D3Q27System::REST:
             return (*this->zeroDistributions)(x1, x2, x3);
         default:
             UB_THROW(UbException(UB_EXARGS, "Direction didn't find"));
diff --git a/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp b/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp
index 1a13aa008ab49a48f1d16c7a2a71ea39dfb191ab..c456be678449744475a0ac6932850dceb0ee6f1c 100644
--- a/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp
+++ b/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.cpp
@@ -35,7 +35,7 @@
 
 // index                                                              0   1   2   3   4   5  6   7   8    9  10  11  12
 // 13  14  15  16  17  18  19  20  21  22  23  24  25  26 f: E,  W,  N,  S,  T,  B, NE, SW, SE, NW, TE, BW, BE, TW, TN,
-// BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW ZERO
+// BS, BN, TS, TNE TNW TSE TSW BNE BNW BSE BSW REST
 const int EsoTwistD3Q27System::ETX1[EsoTwistD3Q27System::ENDF + 1] = { 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1,
                                                                        0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
 const int EsoTwistD3Q27System::ETX2[EsoTwistD3Q27System::ENDF + 1] = { 0, 0, 0,  1, 0, 0,  0, 1, 0, -1, 0, 0, 0, 0,
@@ -49,7 +49,7 @@ const int EsoTwistD3Q27System::etINVDIR[EsoTwistD3Q27System::ENDF + 1] = {
     D3Q27System::INV_TE,  D3Q27System::INV_BW,  D3Q27System::INV_BE,  D3Q27System::INV_TW,  D3Q27System::INV_TN,
     D3Q27System::INV_BS,  D3Q27System::INV_BN,  D3Q27System::INV_TS,  D3Q27System::INV_TNE, D3Q27System::INV_TNW,
     D3Q27System::INV_TSE, D3Q27System::INV_TSW, D3Q27System::INV_BNE, D3Q27System::INV_BNW, D3Q27System::INV_BSE,
-    D3Q27System::INV_BSW, D3Q27System::ZERO
+    D3Q27System::INV_BSW, D3Q27System::REST
 };
 
 const unsigned long int EsoTwistD3Q27System::etDIR[EsoTwistD3Q27System::ENDF + 1] = {
diff --git a/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.h b/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.h
index a9214673ec4b4a66a52fa53f9b625ead0180768b..21752cc48a84b02bc24cb7efe9e3c5912f476dfd 100644
--- a/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.h
+++ b/src/cpu/VirtualFluidsCore/Data/EsoTwistD3Q27System.h
@@ -47,7 +47,7 @@ struct EsoTwistD3Q27System {
     const static int STARTDIR = D3Q27System::STARTDIR;
     const static int ENDDIR   = D3Q27System::ENDDIR;
 
-    static const int ZERO = D3Q27System::ZERO; /*f0 */
+    static const int REST = D3Q27System::REST; /*f0 */
     static const int E    = D3Q27System::E;    /*f1 */
     static const int W    = D3Q27System::W;    /*f2 */
     static const int N    = D3Q27System::N;    /*f3 */
diff --git a/src/cpu/VirtualFluidsCore/Grid/Grid3D.cpp b/src/cpu/VirtualFluidsCore/Grid/Grid3D.cpp
index 92be5ed5a06e1909a34144cdd0d1b31000309281..579301e18508541466467370f6b2085c8e05b7be 100644
--- a/src/cpu/VirtualFluidsCore/Grid/Grid3D.cpp
+++ b/src/cpu/VirtualFluidsCore/Grid/Grid3D.cpp
@@ -50,14 +50,14 @@ using namespace std;
 
 Grid3D::Grid3D() { levelSet.resize(Grid3DSystem::MAXLEVEL + 1); }
 //////////////////////////////////////////////////////////////////////////
-Grid3D::Grid3D(SPtr<Communicator> comm)
+Grid3D::Grid3D(std::shared_ptr<vf::mpi::Communicator> comm)
 
 {
     levelSet.resize(Grid3DSystem::MAXLEVEL + 1);
     rank = comm->getProcessID();
 }
 //////////////////////////////////////////////////////////////////////////
-Grid3D::Grid3D(SPtr<Communicator> comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3)
+Grid3D::Grid3D(std::shared_ptr<vf::mpi::Communicator> comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3)
     :
 
       blockNx1(blockNx1), blockNx2(blockNx2), blockNx3(blockNx2), nx1(gridNx1), nx2(gridNx2), nx3(gridNx3)
@@ -1339,7 +1339,7 @@ void Grid3D::getNeighborBlocksForDirectionWithDirZero(int dir, int ix1, int ix2,
         case Grid3DSystem::BSW:
             this->getNeighborsBottomSouthWest(ix1, ix2, ix3, level, levelDepth, blocks);
             break;
-        case Grid3DSystem::ZERO:
+        case Grid3DSystem::REST:
             this->getNeighborsZero(ix1, ix2, ix3, level, levelDepth, blocks);
             break;
         default:
diff --git a/src/cpu/VirtualFluidsCore/Grid/Grid3D.h b/src/cpu/VirtualFluidsCore/Grid/Grid3D.h
index 84c821e84b8c98f17e39814a211de3262e75f804..af71a9a9e345b4d8608dc5d0ff428e702368d471 100644
--- a/src/cpu/VirtualFluidsCore/Grid/Grid3D.h
+++ b/src/cpu/VirtualFluidsCore/Grid/Grid3D.h
@@ -47,7 +47,7 @@ class CoordinateTransformation3D;
 #include <Block3DVisitor.h>
 #include <Grid3DVisitor.h>
 
-class Communicator;
+namespace vf::mpi {class Communicator;}
 class Block3D;
 class Interactor3D;
 
@@ -66,8 +66,8 @@ public:
 
 public:
     Grid3D();
-    Grid3D(SPtr<Communicator> comm);
-    Grid3D(SPtr<Communicator> comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3);
+    Grid3D(std::shared_ptr<vf::mpi::Communicator> comm);
+    Grid3D(std::shared_ptr<vf::mpi::Communicator> comm, int blockNx1, int blockNx2, int blockNx3, int gridNx1, int gridNx2, int gridNx3);
     virtual ~Grid3D() = default;
     //////////////////////////////////////////////////////////////////////////
     // blocks control
diff --git a/src/cpu/VirtualFluidsCore/Grid/Grid3DSystem.h b/src/cpu/VirtualFluidsCore/Grid/Grid3DSystem.h
index ee61b8f7327e76a9393d4d3caa13c3a796470c08..94c3bf2a75bf8e7137b08c113c1caa878d8c0896 100644
--- a/src/cpu/VirtualFluidsCore/Grid/Grid3DSystem.h
+++ b/src/cpu/VirtualFluidsCore/Grid/Grid3DSystem.h
@@ -71,7 +71,7 @@ static const int BNE          = 22;
 static const int BNW          = 23;
 static const int BSE          = 24;
 static const int BSW          = 25;
-static const int ZERO /*f0 */ = 26;
+static const int REST /*f0 */ = 26;
 
 static const int ENDDIR = 25;
 
diff --git a/src/cpu/VirtualFluidsCore/LBM/CumulantK17LBMKernel.h b/src/cpu/VirtualFluidsCore/LBM/CumulantK17LBMKernel.h
index 10cfd49264bb829eac1fc6b9bedeee3b6eace265..aab4d669655efe5bd489feb3829da28e67aa9ecb 100644
--- a/src/cpu/VirtualFluidsCore/LBM/CumulantK17LBMKernel.h
+++ b/src/cpu/VirtualFluidsCore/LBM/CumulantK17LBMKernel.h
@@ -79,7 +79,7 @@ protected:
 };
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief forward chimera transformation \ref forwardInverseChimeraWithK 
+//! \brief forward chimera transformation \ref forwardInverseChimeraWithK
 //! Transformation from distributions to central moments according to Eq. (6)-(14) 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>
 //! Modified for lower round-off errors.
@@ -112,7 +112,7 @@ inline void CumulantK17LBMKernel::backwardInverseChimeraWithK(LBMReal& mfa, LBMR
     mfb = m1;
 }
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief forward chimera transformation \ref forwardChimera 
+//! \brief forward chimera transformation \ref forwardChimera
 //! Transformation from distributions to central moments according to Eq. (6)-(14) 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>
 //! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations.
@@ -128,7 +128,7 @@ inline void CumulantK17LBMKernel::forwardChimera(LBMReal& mfa, LBMReal& mfb, LBM
     mfa = m1;
 }
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief backward chimera transformation \ref backwardChimera 
+//! \brief backward chimera transformation \ref backwardChimera
 //! Transformation from central moments to distributions according to Eq. (57)-(65) 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>
 //! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations.
@@ -144,4 +144,4 @@ inline void CumulantK17LBMKernel::backwardChimera(LBMReal& mfa, LBMReal& mfb, LB
     mfa = ma;
 }
 
-#endif // CumulantK17LBMKernel_h__
\ No newline at end of file
+#endif // CumulantK17LBMKernel_h__
diff --git a/src/cpu/VirtualFluidsCore/LBM/D3Q27System.h b/src/cpu/VirtualFluidsCore/LBM/D3Q27System.h
index b5d88d6c3791d716cd0dca567d7aaa803e863536..767fe1e7271771ee4ce758e466ff972f18618c92 100644
--- a/src/cpu/VirtualFluidsCore/LBM/D3Q27System.h
+++ b/src/cpu/VirtualFluidsCore/LBM/D3Q27System.h
@@ -89,7 +89,7 @@ static const int BNE  = 22;
 static const int BNW  = 23;
 static const int BSE  = 24;
 static const int BSW  = 25;
-static const int ZERO = 26;
+static const int REST = 26;
 
 static const int INV_E   = W;
 static const int INV_W   = E;
@@ -155,7 +155,7 @@ static LBMReal getDensity(const LBMReal *const &f /*[27]*/)
     return ((f[TNE] + f[BSW]) + (f[TSE] + f[BNW])) + ((f[BSE] + f[TNW]) + (f[TSW] + f[BNE])) +
            (((f[NE] + f[SW]) + (f[SE] + f[NW])) + ((f[TE] + f[BW]) + (f[BE] + f[TW])) +
             ((f[BN] + f[TS]) + (f[TN] + f[BS]))) +
-           ((f[E] + f[W]) + (f[N] + f[S]) + (f[T] + f[B])) + f[ZERO];
+           ((f[E] + f[W]) + (f[N] + f[S]) + (f[T] + f[B])) + f[REST];
 }
 /*=====================================================================*/
 // ATTENTION: does not apply to all models -> use certificate instead of static! to do
@@ -184,7 +184,7 @@ static void calcDensity(const LBMReal *const &f /*[27]*/, LBMReal &rho)
     rho = ((f[TNE] + f[BSW]) + (f[TSE] + f[BNW])) + ((f[BSE] + f[TNW]) + (f[TSW] + f[BNE])) +
           (((f[NE] + f[SW]) + (f[SE] + f[NW])) + ((f[TE] + f[BW]) + (f[BE] + f[TW])) +
            ((f[BN] + f[TS]) + (f[TN] + f[BS]))) +
-          ((f[E] + f[W]) + (f[N] + f[S]) + (f[T] + f[B])) + f[ZERO];
+          ((f[E] + f[W]) + (f[N] + f[S]) + (f[T] + f[B])) + f[REST];
 }
 /*=====================================================================*/
 static void calcIncompVelocityX1(const LBMReal *const &f /*[27]*/, LBMReal &vx1)
@@ -279,7 +279,7 @@ static LBMReal getCompFeqForDirection(const int &direction, const LBMReal &drho,
     ////-----
     LBMReal rho = drho + c1;
     switch (direction) {
-        case ZERO:
+        case REST:
             return REAL_CAST(c8o27 * (drho + rho * (-cu_sq)));
         case E:
             return REAL_CAST(c2o27 * (drho + rho * (3.0 * (vx1) + c9o2 * (vx1) * (vx1)-cu_sq)));
@@ -354,7 +354,7 @@ static void calcCompFeq(LBMReal *const &feq /*[27]*/, const LBMReal &drho, const
     LBMReal cu_sq = 1.5 * (vx1 * vx1 + vx2 * vx2 + vx3 * vx3);
     LBMReal rho   = drho + c1;
 
-    feq[ZERO] = c8o27 * (drho + rho * (-cu_sq));
+    feq[REST] = c8o27 * (drho + rho * (-cu_sq));
     feq[E]    = c2o27 * (drho + rho * (3.0 * (vx1) + c9o2 * (vx1) * (vx1)-cu_sq));
     feq[W]    = c2o27 * (drho + rho * (3.0 * (-vx1) + c9o2 * (-vx1) * (-vx1) - cu_sq));
     feq[N]    = c2o27 * (drho + rho * (3.0 * (vx2) + c9o2 * (vx2) * (vx2)-cu_sq));
@@ -395,7 +395,7 @@ static LBMReal getIncompFeqForDirection(const int &direction, const LBMReal &drh
     LBMReal cu_sq = 1.5f * (vx1 * vx1 + vx2 * vx2 + vx3 * vx3);
 
     switch (direction) {
-        case ZERO:
+        case REST:
             return REAL_CAST(c8o27 * (drho - cu_sq));
         case E:
             return REAL_CAST(c2o27 * (drho + 3.0 * (vx1) + c9o2 * (vx1) * (vx1)-cu_sq));
@@ -469,7 +469,7 @@ static void calcIncompFeq(LBMReal *const &feq /*[27]*/, const LBMReal &drho, con
 
     LBMReal cu_sq = 1.5 * (vx1 * vx1 + vx2 * vx2 + vx3 * vx3);
 
-    feq[ZERO] = c8o27 * (drho - cu_sq);
+    feq[REST] = c8o27 * (drho - cu_sq);
     feq[E]    = c2o27 * (drho + 3.0 * (vx1) + c9o2 * (vx1) * (vx1)-cu_sq);
     feq[W]    = c2o27 * (drho + 3.0 * (-vx1) + c9o2 * (-vx1) * (-vx1) - cu_sq);
     feq[N]    = c2o27 * (drho + 3.0 * (vx2) + c9o2 * (vx2) * (vx2)-cu_sq);
diff --git a/src/cpu/VirtualFluidsCore/LBM/ILBMKernel.h b/src/cpu/VirtualFluidsCore/LBM/ILBMKernel.h
index 4dbe8eee09a37c0c220f47619b72bade2e6ec527..bde61d9d314b61327ff8f8a2a71d2864d50cc7f5 100644
--- a/src/cpu/VirtualFluidsCore/LBM/ILBMKernel.h
+++ b/src/cpu/VirtualFluidsCore/LBM/ILBMKernel.h
@@ -36,6 +36,8 @@
 
 #include <PointerDefinitions.h>
 
+#include "LBMSystem.h"
+
 class BCProcessor;
 class DataSet3D;
 
@@ -57,7 +59,7 @@ public:
     virtual void setCollisionFactor(double collFactor)                               = 0;
     virtual bool isInsideOfDomain(const int &x1, const int &x2, const int &x3) const = 0;
     virtual int getGhostLayerWidth() const                                           = 0;
-    virtual double getDeltaT() const                                                 = 0;
+    virtual LBMReal getDeltaT() const                                                = 0;
     virtual bool getWithForcing() const                                              = 0;
 };
 
diff --git a/src/cpu/VirtualFluidsCore/LBM/LBMSystem.h b/src/cpu/VirtualFluidsCore/LBM/LBMSystem.h
index d24775aef0fbe6822fbdc03d42e2acfeb3021430..14b4d223b2e07e3dbca9947cefd89de045bfb3cf 100644
--- a/src/cpu/VirtualFluidsCore/LBM/LBMSystem.h
+++ b/src/cpu/VirtualFluidsCore/LBM/LBMSystem.h
@@ -37,6 +37,8 @@
 #include <iostream>
 #include <string>
 
+#include "basics/Core/DataTypes.h"
+
 //! \brief namespace for global system-functions
 
 namespace LBMSystem
@@ -45,10 +47,10 @@ namespace LBMSystem
 //#define SINGLEPRECISION
 
 #ifdef SINGLEPRECISION
-typedef float real;
+//using real = float;
 #define REAL_CAST(x) ((LBMSystem::real)(x))
 #else
-using real = double;
+//using real = double;
 #define REAL_CAST(x) (x)
 #endif
 
@@ -82,6 +84,7 @@ static real calcOmega2(real viscosity, real deltaT) { return REAL_CAST(1.0 / (4.
 } // namespace LBMSystem
 
 // some typedefs for global namespace
-using LBMReal = LBMSystem::real;
+//using LBMReal = LBMSystem::real;
+using LBMReal = real;
 
 #endif
diff --git a/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.cpp b/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.cpp
index 6cfdb7bf66c821d667d340433d589fd4ed162d61..db7c5a03c98c43a83dd6f5bd2f3306eacba9f33b 100644
--- a/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.cpp
+++ b/src/cpu/VirtualFluidsCore/Visitors/InitDistributionsBlockVisitor.cpp
@@ -294,7 +294,7 @@ void InitDistributionsBlockVisitor::visit(const SPtr<Grid3D> grid, SPtr<Block3D>
                     f[BNW]  = f_TSE + feq[BNW];
                     f[BSE]  = f_TNW + feq[BSE];
                     f[BSW]  = f_TNE + feq[BSW];
-                    f[ZERO] = f_ZERO + feq[ZERO];
+                    f[REST] = f_ZERO + feq[REST];
 
                     // calcFeqsFct(f,rho,vx1,vx2,vx3);
                     // distributions->setDistribution(f, ix1, ix2, ix3);
diff --git a/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.cpp b/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.cpp
index c0efdcc6135b1e06f766621dd4528f96fa32247d..e2732cc6890cec789a4356f05857f01af71ad0b9 100644
--- a/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.cpp
+++ b/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.cpp
@@ -37,7 +37,7 @@
 #include "Grid3D.h"
 #include "Grid3DSystem.h"
 
-SetConnectorsBlockVisitor::SetConnectorsBlockVisitor(SPtr<Communicator> comm, bool fullConnector, int dirs, LBMReal nue)
+SetConnectorsBlockVisitor::SetConnectorsBlockVisitor(std::shared_ptr<vf::mpi::Communicator> comm, bool fullConnector, int dirs, LBMReal nue)
     : Block3DVisitor(0, Grid3DSystem::MAXLEVEL), comm(comm), fullConnector(fullConnector), dirs(dirs), nue(nue)
 {
 }
diff --git a/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.h b/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.h
index f6eb15206371af2ff6106a5c82c6c71eba26fb34..4b9cb72d0ea153e161bf5103e2ad2d63dc79134c 100644
--- a/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.h
+++ b/src/cpu/VirtualFluidsCore/Visitors/SetConnectorsBlockVisitor.h
@@ -42,20 +42,20 @@
 
 class Grid3D;
 class Block3D;
-class Communicator;
+namespace vf::mpi {class Communicator;}
 class InterpolationProcessor;
 
 //! \brief  A class sets connectors between blocks.
 class SetConnectorsBlockVisitor : public Block3DVisitor
 {
 public:
-    SetConnectorsBlockVisitor(SPtr<Communicator> comm, bool fullConnector, int dirs, LBMReal nue);
+    SetConnectorsBlockVisitor(std::shared_ptr<vf::mpi::Communicator> comm, bool fullConnector, int dirs, LBMReal nue);
     ~SetConnectorsBlockVisitor() = default;
     void visit(SPtr<Grid3D> grid, SPtr<Block3D> block) override;
     //////////////////////////////////////////////////////////////////////////
 protected:
     void setSameLevelConnectors(SPtr<Grid3D> grid, SPtr<Block3D> block);
-    SPtr<Communicator> comm;
+    std::shared_ptr<vf::mpi::Communicator> comm;
     bool fullConnector;
     int dirs;
     int gridRank;
diff --git a/src/cuda/CMakeLists.txt b/src/cuda/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4d49cfedc903f3578b64916966405ea48bf28901
--- /dev/null
+++ b/src/cuda/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(cuda LANGUAGES CUDA CXX)
+
+vf_add_library(NAME vf_cuda PUBLIC_LINK logger)
diff --git a/src/cuda/CudaGrid.cpp b/src/cuda/CudaGrid.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c7267972859f04931d9a69cfca073c7ac3267b9f
--- /dev/null
+++ b/src/cuda/CudaGrid.cpp
@@ -0,0 +1,30 @@
+#include "CudaGrid.h"
+
+#include <logger/Logger.h>
+
+namespace vf::cuda
+{
+
+CudaGrid::CudaGrid(unsigned int numberOfThreads, unsigned int numberOfEntities)
+{
+    unsigned int Grid = (numberOfEntities / numberOfThreads) + 1;
+    unsigned int Grid1, Grid2;
+    if (Grid > 512) {
+        Grid1 = 512;
+        Grid2 = (Grid / Grid1) + 1;
+    } else {
+        Grid1 = 1;
+        Grid2 = Grid;
+    }
+    
+    grid = dim3(Grid1, Grid2);
+    threads = dim3(numberOfThreads, 1, 1);
+}
+
+void CudaGrid::print() const
+{
+    VF_LOG_INFO("blocks: ({},{},{}), threads: ({},{},{})", grid.x, grid.y, grid.z, threads.x, threads.y, threads.z);
+}
+
+
+}
diff --git a/src/cuda/CudaGrid.h b/src/cuda/CudaGrid.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9926c3861749f648da529f2b45554d13599a302
--- /dev/null
+++ b/src/cuda/CudaGrid.h
@@ -0,0 +1,24 @@
+#ifndef CUDA_GRID_H
+#define CUDA_GRID_H
+
+
+#include <cuda_runtime.h>
+
+namespace vf::cuda
+{
+
+struct CudaGrid 
+{
+    dim3 threads;
+    dim3 grid;
+
+    CudaGrid(unsigned int numberOfThreads, unsigned int numberOfEntities);
+    CudaGrid() = default;
+
+    void print() const;
+};
+
+
+}
+
+#endif
diff --git a/src/cuda/CudaTimer.cpp b/src/cuda/CudaTimer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..97a2c0977058b712ab345f6d2c1299b3e2448198
--- /dev/null
+++ b/src/cuda/CudaTimer.cpp
@@ -0,0 +1,56 @@
+#include "CudaTimer.h"
+
+namespace vf::cuda
+{
+
+void CudaTimer::createSdkTimer()
+{
+    sdkCreateTimer(&sdkTimer);
+}
+
+void CudaTimer::startSdkTimer()
+{
+    sdkStartTimer(&sdkTimer);
+}
+
+void CudaTimer::createEventTimer()
+{
+    checkCudaErrors(cudaEventCreate(&start_t));
+    checkCudaErrors(cudaEventCreate(&stop_t));
+}
+
+void CudaTimer::startEventTimer()
+{
+    checkCudaErrors(cudaEventRecord(start_t));
+}
+
+void CudaTimer::stopSdkTimer(float &timeSinceLastStop,double &totalTime)
+{
+    sdkStopTimer(&sdkTimer);
+    timeSinceLastStop = sdkGetTimerValue(&sdkTimer);
+    sdkResetTimer(&sdkTimer);
+    ftimeS += timeSinceLastStop;
+    totalTime = ftimeS;
+}
+
+void CudaTimer::stopEventTimer(float &timeSinceLastStop,double &totalTime)
+{
+    checkCudaErrors(cudaEventRecord(stop_t));
+    checkCudaErrors(cudaEventSynchronize(stop_t));
+    checkCudaErrors(cudaEventElapsedTime(&timeSinceLastStop, start_t, stop_t));
+    ftimeE += timeSinceLastStop;
+    totalTime = ftimeE;
+}
+
+void CudaTimer::deleteSdkTimer()
+{
+    sdkDeleteTimer(&sdkTimer);
+}
+
+void CudaTimer::deleteEventTimer()
+{
+    checkCudaErrors(cudaEventDestroy(start_t));
+    checkCudaErrors(cudaEventDestroy(stop_t));
+}
+
+}
diff --git a/src/cuda/CudaTimer.h b/src/cuda/CudaTimer.h
new file mode 100644
index 0000000000000000000000000000000000000000..51193c2f73959e31dab8661a952756f2d0882e06
--- /dev/null
+++ b/src/cuda/CudaTimer.h
@@ -0,0 +1,37 @@
+#ifndef CUDA_CudaTimer_H
+#define CUDA_CudaTimer_H
+
+
+#include <cuda_runtime.h>
+#include <helper_functions.h>
+#include <helper_cuda.h>
+
+namespace vf::cuda
+{
+
+class CudaTimer
+{
+public:
+    void createSdkTimer();
+    void startSdkTimer();
+    void stopSdkTimer(float &timeSinceLastStop,double &totalTime);
+    void deleteSdkTimer();
+
+    void createEventTimer();
+    void startEventTimer();
+    void stopEventTimer(float &timeSinceLastStop,double &totalTime);
+    void deleteEventTimer();
+
+private:
+    StopWatchInterface *sdkTimer;
+    double ftimeS = {0.0};
+
+    cudaEvent_t stop_t;
+    cudaEvent_t start_t;
+    double ftimeE {0.0};
+
+};
+
+}
+
+#endif
diff --git a/src/cuda/DeviceInfo.cpp b/src/cuda/DeviceInfo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..20ea2c4f6ba098b17e444f55625a6791e46141e5
--- /dev/null
+++ b/src/cuda/DeviceInfo.cpp
@@ -0,0 +1,123 @@
+#include "DeviceInfo.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <cuda_runtime.h>
+
+#include <logger/Logger.h>
+
+namespace vf::cuda
+{
+
+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));
+    }
+    if (deviceId > device_count) {
+        throw std::runtime_error("chosen gpudevice >=  device_count ... exiting\n");
+    }
+}
+
+void verifyComputeCapability(int deviceId)
+{
+    cudaDeviceProp deviceProp;
+    cudaError_t errorId = cudaGetDeviceProperties(&deviceProp, deviceId);
+
+    if(errorId != cudaSuccess){
+        VF_LOG_CRITICAL("Error while accessing the device properties occurs: {}", 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");
+    }
+}
+
+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));
+    } 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));
+        }
+    }
+}
+
+void verifyAndSetDevice(int deviceId)
+{
+    verifyNumberOfDevices(deviceId);
+    verifyComputeCapability(deviceId);
+
+    setCudaDevice(deviceId);
+}
+
+
+
+void printCudaInformation(int deviceId) 
+{
+    cudaDeviceProp prop;
+    cudaError_t errorId = cudaGetDeviceProperties(&prop, deviceId);
+
+    if(errorId != cudaSuccess){
+        VF_LOG_CRITICAL("Error while accessing the device properties occurs: {}", cudaGetErrorString(errorId));
+    }
+
+    printf(" --- General Information for device %d ---\n", deviceId);
+    printf("Name: %s\n", prop.name);
+    printf("Compute capability: %d.%d\n", prop.major, prop.minor);
+    printf("Clock rate: %d\n", prop.clockRate);
+    printf("Device copy overlap: ");
+    if (prop.deviceOverlap)
+        printf("Enabled\n");
+    else
+        printf("Disabled\n");
+    printf("Kernel execition timeout : ");
+    if (prop.kernelExecTimeoutEnabled)
+        printf("Enabled\n");
+    else
+        printf("Disabled\n");
+    printf(" --- Memory Information for device %d ---\n", deviceId);
+    printf("Total global mem: %zu\n", prop.totalGlobalMem);
+    printf("Total constant Mem: %zu\n", prop.totalConstMem);
+    printf("Max mem pitch: %zu\n", prop.memPitch);
+    printf("Texture Alignment: %zu\n", prop.textureAlignment);
+    printf("max Texture 1D: %d\n", prop.maxTexture1D);
+    printf("max Texture 2D: %d, %d\n", prop.maxTexture2D[0], prop.maxTexture2D[1]);
+    printf("max Texture 3D: %d, %d, %d\n", prop.maxTexture3D[0], prop.maxTexture3D[1], prop.maxTexture3D[2]);
+    printf(" --- MP Information for device %d ---\n", deviceId);
+    printf("Multiprocessor count: %d\n",
+        prop.multiProcessorCount);
+    printf("Shared mem per mp: %zd\n", prop.sharedMemPerBlock);
+    printf("Registers per mp: %d\n", prop.regsPerBlock);
+    printf("Threads in warp: %d\n", prop.warpSize);
+    printf("Max threads per block: %d\n",
+        prop.maxThreadsPerBlock);
+    printf("Max thread dimensions: (%d, %d, %d)\n",
+        prop.maxThreadsDim[0], prop.maxThreadsDim[1],
+        prop.maxThreadsDim[2]);
+    printf("Max grid dimensions: (%d, %d, %d)\n",
+        prop.maxGridSize[0], prop.maxGridSize[1],
+        prop.maxGridSize[2]);
+    printf(" --- -------------------------------- ---\n");
+    printf("\n");
+
+    cudaSetDevice(deviceId);
+    size_t free;
+    size_t total;
+    cudaMemGetInfo(&free, &total);
+    printf("Free: %zu Bytes, Total: %zu Bytes\n", free, total);
+    printf("Free: %zu MB, Total: %zu MB\n", free / 1000 / 1000, total / 1000 / 1000);
+}
+
+}
\ No newline at end of file
diff --git a/src/cuda/DeviceInfo.h b/src/cuda/DeviceInfo.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a34824f38ecf5a7db035e87826b732325fdfddd
--- /dev/null
+++ b/src/cuda/DeviceInfo.h
@@ -0,0 +1,13 @@
+#ifndef CUDA_DEVICEINFO_H
+#define CUDA_DEVICEINFO_H
+
+namespace vf::cuda
+{
+
+void verifyAndSetDevice(int deviceId);
+
+void printCudaInformation(int deviceId);
+
+}
+
+#endif
diff --git a/src/gpu/GksGpu/CMakeLists.txt b/src/gpu/GksGpu/CMakeLists.txt
index da404e0209ed2c9f36ae323d2e6bd234fb6dfb96..5dbc533cc5f45c006c29a12242350f0433518bbf 100644
--- a/src/gpu/GksGpu/CMakeLists.txt
+++ b/src/gpu/GksGpu/CMakeLists.txt
@@ -1,3 +1,10 @@
 project(GksGpu LANGUAGES CUDA CXX)
 
-vf_add_library(PRIVATE_LINK basics GksMeshAdapter OpenMP::OpenMP_CXX MPI::MPI_CXX)
+vf_add_library(PRIVATE_LINK basics lbmCuda GksMeshAdapter OpenMP::OpenMP_CXX MPI::MPI_CXX)
+
+target_include_directories(GksGpu PRIVATE "${VF_THIRD_DIR}/cuda_samples/")
+
+if (NOT MSVC)
+    target_compile_options(GksGpu PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-fPIC>")
+endif()
+
diff --git a/src/gpu/GksGpu/DataBase/DataBase.cpp b/src/gpu/GksGpu/DataBase/DataBase.cpp
index a7319f049345bd6da76eeff29b347b0e45edcbf1..3c6ddb9a0337b90d889bfe12f0aaa3a509ef6aa0 100644
--- a/src/gpu/GksGpu/DataBase/DataBase.cpp
+++ b/src/gpu/GksGpu/DataBase/DataBase.cpp
@@ -1,28 +1,28 @@
 //=======================================================================================
-// ____          ____    __    ______     __________   __      __       __        __         
-// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
-//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
-//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
-//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
-//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
-//      \    \  |    |   ________________________________________________________________    
-//       \    \ |    |  |  ______________________________________________________________|   
-//        \    \|    |  |  |         __          __     __     __     ______      _______    
-//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
-//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
 //           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
 //
-//  This file is part of VirtualFluids. VirtualFluids is free software: you can 
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can
 //  redistribute it and/or modify it under the terms of the GNU General Public
-//  License as published by the Free Software Foundation, either version 3 of 
+//  License as published by the Free Software Foundation, either version 3 of
 //  the License, or (at your option) any later version.
-//  
-//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT 
-//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+//
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 //  for more details.
-//  
+//
 //  You should have received a copy of the GNU General Public License along
 //  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
 //
@@ -38,12 +38,16 @@
 #include <cuda_runtime.h>
 #include <helper_cuda.h>
 
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
+
 #include "DataBaseAllocator.h"
 #include "DataBaseStruct.h"
 
 #include "GksMeshAdapter/GksMeshAdapter.h"
 
-DataBase::DataBase( std::string type ) 
+DataBase::DataBase( std::string type )
         : myAllocator    ( DataBaseAllocator::create( type ) ),
           numberOfNodes      (0),
           numberOfCells      (0),
diff --git a/src/gpu/GksGpu/FlowStateData/FlowStateData.cuh b/src/gpu/GksGpu/FlowStateData/FlowStateData.cuh
index 1f3bc2252d9effda77333be97b21e8fb65ad4d6a..6b04b3108c186d9814a8ee6b6b11b437ccf217c3 100644
--- a/src/gpu/GksGpu/FlowStateData/FlowStateData.cuh
+++ b/src/gpu/GksGpu/FlowStateData/FlowStateData.cuh
@@ -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/>.
 //
@@ -41,8 +41,9 @@
 #endif
 
 #include "Core/DataTypes.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
 
+using namespace vf::lbm::constant;
 #include "Definitions/PassiveScalar.h"
 
 //////////////////////////////////////////////////////////////////////////
@@ -137,7 +138,7 @@ struct ConservedVariables
     {}
 
     //////////////////////////////////////////////////////////////////////////
-		  
+
     //! constructor that initializes the variables according to the arguments
     __host__ __device__ ConservedVariables(real rho
                                           ,real rhoU
diff --git a/src/gpu/GksMeshAdapter/GksMeshAdapter.cpp b/src/gpu/GksMeshAdapter/GksMeshAdapter.cpp
index 28a0b87d12e9de452a3a42b8ddfa0fe3e5add8e7..34b66440c564890ea9656aad043b9f666cd3a649 100644
--- a/src/gpu/GksMeshAdapter/GksMeshAdapter.cpp
+++ b/src/gpu/GksMeshAdapter/GksMeshAdapter.cpp
@@ -1,28 +1,28 @@
 //=======================================================================================
-// ____          ____    __    ______     __________   __      __       __        __         
-// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |        
-//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |        
-//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |        
-//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____    
-//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|   
-//      \    \  |    |   ________________________________________________________________    
-//       \    \ |    |  |  ______________________________________________________________|   
-//        \    \|    |  |  |         __          __     __     __     ______      _______    
-//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)   
-//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______    
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
 //           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
-//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/   
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
 //
-//  This file is part of VirtualFluids. VirtualFluids is free software: you can 
+//  This file is part of VirtualFluids. VirtualFluids is free software: you can
 //  redistribute it and/or modify it under the terms of the GNU General Public
-//  License as published by the Free Software Foundation, either version 3 of 
+//  License as published by the Free Software Foundation, either version 3 of
 //  the License, or (at your option) any later version.
-//  
-//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT 
-//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+//
+//  VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 //  for more details.
-//  
+//
 //  You should have received a copy of the GNU General Public License along
 //  with VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
 //
@@ -53,6 +53,10 @@
 #include "MeshCell.h"
 #include "MeshFace.h"
 
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
+
 using namespace vf::gpu;
 
 GksMeshAdapter::GksMeshAdapter(SPtr<MultipleGridBuilder> gridBuilder)
@@ -100,7 +104,7 @@ void GksMeshAdapter::inputGrid()
             }
         }
     }
-    
+
     //////////////////////////////////////////////////////////////////////////
     //
     //    S e t    M e s h    t o    G r i d    i n f o r m a t i o n
@@ -153,7 +157,7 @@ void GksMeshAdapter::findCellToCellConnectivity()
     Distribution dirs = DistributionHelper::getDistribution27();
 
     for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
-    
+
         MeshCell& cell = this->cells[ cellIdx ];
 
         real x, y, z;
@@ -169,8 +173,8 @@ void GksMeshAdapter::findCellToCellConnectivity()
             int ySign = dirs.directions[idx][1];
             int zSign = dirs.directions[idx][2];
 
-            uint neighborGridIdx = grids[cell.level]->transCoordToIndex( x + xSign * d, 
-                                                                         y + ySign * d, 
+            uint neighborGridIdx = grids[cell.level]->transCoordToIndex( x + xSign * d,
+                                                                         y + ySign * d,
                                                                          z + zSign * d );
 
             if( neighborGridIdx == INVALID_INDEX || this->gridToMesh[cell.level][neighborGridIdx] == INVALID_INDEX ){
@@ -203,7 +207,7 @@ void GksMeshAdapter::countCells()
 
         if( cell.level != level ) level++;
 
-        this->numberOfCellsPerLevel[ level ]++; 
+        this->numberOfCellsPerLevel[ level ]++;
 
         if( ! ( cell.isGhostCell || cell.isCoarseGhostCell() ) )
             this->numberOfBulkCellsPerLevel[ level ]++;
@@ -223,10 +227,10 @@ void GksMeshAdapter::partitionCells()
         std::iota( idxMap.begin(), idxMap.end(), 0 );
 
         // partition idxMap
-        std::stable_partition(  idxMap.begin() + this->startOfCellsPerLevel[level], 
-                                idxMap.begin() + this->startOfCellsPerLevel[level] 
-                                               + this->numberOfCellsPerLevel[level], 
-                                [this](int lhs){ 
+        std::stable_partition(  idxMap.begin() + this->startOfCellsPerLevel[level],
+                                idxMap.begin() + this->startOfCellsPerLevel[level]
+                                               + this->numberOfCellsPerLevel[level],
+                                [this](int lhs){
                                     return ! ( this->cells[ lhs ].isGhostCell || this->cells[ lhs ].isCoarseGhostCell() );
                                 }
                              );
@@ -239,10 +243,10 @@ void GksMeshAdapter::partitionCells()
         }
 
         // partition cell list
-        std::stable_partition(  this->cells.begin() + this->startOfCellsPerLevel[level], 
-                                this->cells.begin() + this->startOfCellsPerLevel[level] 
-                                                    + this->numberOfCellsPerLevel[level], 
-                                [this](MeshCell lhs){ 
+        std::stable_partition(  this->cells.begin() + this->startOfCellsPerLevel[level],
+                                this->cells.begin() + this->startOfCellsPerLevel[level]
+                                                    + this->numberOfCellsPerLevel[level],
+                                [this](MeshCell lhs){
                                     return ! ( lhs.isGhostCell || lhs.isCoarseGhostCell() );
                                 }
                              );
@@ -287,7 +291,7 @@ void GksMeshAdapter::generateNodes()
     Distribution dirs = DistributionHelper::getDistribution27();
 
     for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
-    
+
         MeshCell& cell = this->cells[ cellIdx ];
 
         //if( cell.type == STOPPER_SOLID ) continue;
@@ -340,9 +344,9 @@ void GksMeshAdapter::generateNodes()
 }
 
 void GksMeshAdapter::computeCellGeometry()
-{    
+{
     for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
-        
+
         MeshCell& cell = this->cells[ cellIdx ];
 
         Vec3 cellCenter;
@@ -366,7 +370,7 @@ void GksMeshAdapter::generateFaces()
     this->faces.reserve( 2 * this->cells.size() );
 
     for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
-    
+
         MeshCell& cell = this->cells[ cellIdx ];
 
         //if( cell.type == BC_SOLID || cell.type == STOPPER_SOLID ) continue;
@@ -435,7 +439,7 @@ void GksMeshAdapter::generateFaces()
             newFace.posCell = neighborCellIdx;
 
             //////////////////////////////////////////////////////////////////////////
-            
+
             Vec3 faceCenter;
 
             for( uint node = 0; node < 4; node++ ){
@@ -548,11 +552,11 @@ void GksMeshAdapter::sortFaces()
     for( uint level = 0; level < this->gridBuilder->getNumberOfLevels(); level++ )
     {
         auto bound =
-        std::stable_partition(  this->faces.begin() + this->startOfFacesPerLevelXYZ [3 * level], 
-                                this->faces.begin() + this->startOfFacesPerLevelXYZ [3 * level] 
-                                                    + this->numberOfFacesPerLevelXYZ[3 * level + 0] 
-                                                    + this->numberOfFacesPerLevelXYZ[3 * level + 1] 
-                                                    + this->numberOfFacesPerLevelXYZ[3 * level + 2], 
+        std::stable_partition(  this->faces.begin() + this->startOfFacesPerLevelXYZ [3 * level],
+                                this->faces.begin() + this->startOfFacesPerLevelXYZ [3 * level]
+                                                    + this->numberOfFacesPerLevelXYZ[3 * level + 0]
+                                                    + this->numberOfFacesPerLevelXYZ[3 * level + 1]
+                                                    + this->numberOfFacesPerLevelXYZ[3 * level + 2],
                                     [this](MeshFace& lhs)
                                     {
                                         for( uint neighborIndex = 0; neighborIndex < 6; neighborIndex++ )
@@ -609,7 +613,7 @@ void GksMeshAdapter::countFaces()
     this->startOfFacesPerLevelXYZ[0] = 0;
 
     for( uint level = 1; level < 3 * this->numberOfLevels; level++ ){
-        
+
         this->startOfFacesPerLevelXYZ[level] = this->startOfFacesPerLevelXYZ [level - 1]
                                              + this->numberOfFacesPerLevelXYZ[level - 1];
     }
@@ -658,7 +662,7 @@ void GksMeshAdapter::findPeriodicBoundaryNeighbors()
             uint neighborGridIdx = grid->transCoordToIndex( cell.cellCenter.x + delta.x,
                                                             cell.cellCenter.y + delta.y,
                                                             cell.cellCenter.z + delta.z );
-            
+
             if( neighborGridIdx == INVALID_INDEX ) throw std::runtime_error( std::string("No periodic cell found!") );
 
             uint neighborIdx = this->gridToMesh[ level ][ neighborGridIdx ];
@@ -676,7 +680,7 @@ void GksMeshAdapter::findPeriodicBoundaryNeighbors()
 
                 throw std::runtime_error( s.str() );
             }
-            
+
             this->periodicBoundaryNeighbors.push_back( {cellIdx, neighborIdx} );
         }
     }
diff --git a/src/gpu/VirtualFluids_GPU/CMakeLists.txt b/src/gpu/VirtualFluids_GPU/CMakeLists.txt
index 7b33ce5a1a28e5bba0454e5150b022306243c4aa..9df517caad38c8231a0e190f5f7342d8845e9ea6 100644
--- a/src/gpu/VirtualFluids_GPU/CMakeLists.txt
+++ b/src/gpu/VirtualFluids_GPU/CMakeLists.txt
@@ -5,7 +5,7 @@ if(MSVC)
     set(additional_libraries ws2_32 Traffic) # ws_32 throws an error on Phoenix
 endif()
 
-vf_add_library(PRIVATE_LINK ${additional_libraries} GridGenerator basics MPI::MPI_CXX)
+vf_add_library(PUBLIC_LINK basics lbmCuda PRIVATE_LINK ${additional_libraries} GridGenerator MPI::MPI_CXX vf_cuda)
 
 #SET(TPN_WIN32 "/EHsc")
 #https://stackoverflow.com/questions/6832666/lnk2019-when-including-asio-headers-solution-generated-with-cmake
diff --git a/src/gpu/VirtualFluids_GPU/GPU/AdvectionDiffusion27chim.cu b/src/gpu/VirtualFluids_GPU/GPU/AdvectionDiffusion27chim.cu
index 4a593c06dd7a71f33b29af9d138eec892a4538d2..ea4d643b397b6fc04bf973383cf4d5de341bdb89 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/AdvectionDiffusion27chim.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/AdvectionDiffusion27chim.cu
@@ -31,13 +31,16 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
 
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief forward chimera transformation \ref forwardChimera 
+//! \brief forward chimera transformation \ref forwardChimera
 //! - Chimera transform from distributions to central moments as defined in Eq. (43)-(45) in \ref
 //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
 inline __device__ void forwardChimera(real &mfa, real &mfb, real &mfc, real vv, real v2) {
@@ -50,7 +53,7 @@ inline __device__ void forwardChimera(real &mfa, real &mfb, real &mfc, real vv,
 
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief backward chimera transformation \ref backwardChimera 
+//! \brief backward chimera transformation \ref backwardChimera
 //! - Chimera transform from  central moments to distributions as defined in Eq. (88)-(96) in \ref
 //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
 inline __device__ void backwardChimera(real &mfa, real &mfb, real &mfc, real vv, real v2) {
@@ -86,9 +89,9 @@ extern "C" __global__ void Factorized_Central_Moments_Advection_Diffusion_Device
 	////////////////////////////////////////////////////////////////////////////////
 	//! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
 	//!
-	const unsigned  x = threadIdx.x; 
-	const unsigned  y = blockIdx.x;  
-	const unsigned  z = blockIdx.y;  
+	const unsigned  x = threadIdx.x;
+	const unsigned  y = blockIdx.x;
+	const unsigned  z = blockIdx.y;
 
 	const unsigned nx = blockDim.x;
 	const unsigned ny = gridDim.x;
@@ -227,7 +230,7 @@ extern "C" __global__ void Factorized_Central_Moments_Advection_Diffusion_Device
 			distAD.f[dirTSE ] = &distributionsAD[dirBNW *size_Mat];
 		}
 		////////////////////////////////////////////////////////////////////////////////
-		//! - Set neighbor indices (necessary for indirect addressing) 
+		//! - Set neighbor indices (necessary for indirect addressing)
 		uint kw   = neighborX[k];
 		uint ks   = neighborY[k];
 		uint kb   = neighborZ[k];
@@ -496,7 +499,7 @@ extern "C" __global__ void Factorized_Central_Moments_Advection_Diffusion_Device
 		backwardChimera(mfcca, mfccb, mfccc, vvz, vz2);
 
 		////////////////////////////////////////////////////////////////////////////////////
-		//! - Write distributions: style of reading and writing the distributions from/to 
+		//! - 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>
 		//!
diff --git a/src/gpu/VirtualFluids_GPU/GPU/BCsAdvectionDiffusion27.cu b/src/gpu/VirtualFluids_GPU/GPU/BCsAdvectionDiffusion27.cu
index 9a6075ab24e2f71b8bed53857c11444b0af29967..b1fb3456117f7dd65de5439fd6b987a7d984c92e 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/BCsAdvectionDiffusion27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/BCsAdvectionDiffusion27.cu
@@ -31,12 +31,14 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief forward chimera transformation \ref forwardInverseChimeraWithK 
+//! \brief forward chimera transformation \ref forwardInverseChimeraWithK
 //! Transformation from distributions to central moments according to Eq. (6)-(14) in \ref
 //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 //! Modified for lower round-off errors.
@@ -52,7 +54,7 @@ inline __device__ void forwardInverseChimeraWithKincompressible(real &mfa, real
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief backward chimera transformation \ref backwardInverseChimeraWithK 
+//! \brief backward chimera transformation \ref backwardInverseChimeraWithK
 //! Transformation from central moments to distributions according to Eq. (57)-(65) in \ref
 //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 //! Modified for lower round-off errors.
@@ -67,7 +69,7 @@ inline __device__ void backwardInverseChimeraWithKincompressible(real &mfa, real
 
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief forward chimera transformation \ref forwardChimera 
+//! \brief forward chimera transformation \ref forwardChimera
 //! - Chimera transform from distributions to central moments as defined in Eq. (43)-(45) in \ref
 //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
 inline __device__ void forwardChimera(real &mfa, real &mfb, real &mfc, real vv, real v2) {
@@ -80,7 +82,7 @@ inline __device__ void forwardChimera(real &mfa, real &mfb, real &mfc, real vv,
 
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief backward chimera transformation \ref backwardChimera 
+//! \brief backward chimera transformation \ref backwardChimera
 //! - Chimera transform from  central moments to distributions as defined in Eq. (88)-(96) in \ref
 //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
 inline __device__ void backwardChimera(real &mfa, real &mfb, real &mfc, real vv, real v2) {
@@ -244,9 +246,9 @@ extern "C" __global__ void AD_SlipVelDeviceComp(
         DAD.f[dirBNW ] = &distributionsAD[dirTSE  * size_Mat];
     }
     ////////////////////////////////////////////////////////////////////////////////
-    const unsigned  x = threadIdx.x;  // Globaler x-Index 
-    const unsigned  y = blockIdx.x;   // Globaler y-Index 
-    const unsigned  z = blockIdx.y;   // Globaler z-Index 
+    const unsigned  x = threadIdx.x;  // Globaler x-Index
+    const unsigned  y = blockIdx.x;   // Globaler y-Index
+    const unsigned  z = blockIdx.y;   // Globaler z-Index
 
     const unsigned nx = blockDim.x;
     const unsigned ny = gridDim.x;
@@ -462,7 +464,7 @@ extern "C" __global__ void AD_SlipVelDeviceComp(
             DAD.f[dirBNW ] = &distributionsAD[dirTSE  * size_Mat];
         }
         ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        real concentration = 
+        real concentration =
             f_TSE + f_TNW + f_TNE + f_TSW + f_BSE + f_BNW + f_BNE + f_BSW +
             f_BN + f_TS + f_TN + f_BS + f_BE + f_TW + f_TE + f_BW + f_SE + f_NW + f_NE + f_SW +
             f_T + f_B + f_N + f_S + f_E + f_W + ((D.f[dirREST])[kzero]);
diff --git a/src/gpu/VirtualFluids_GPU/GPU/CalcConc27.cu b/src/gpu/VirtualFluids_GPU/GPU/CalcConc27.cu
index 1418fac4bd632c6675a9f040f1723bf5fc5fd4d9..4067a702a6fdf76e073c1a8c26833d2e338bf227 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/CalcConc27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/CalcConc27.cu
@@ -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/>.
 //
@@ -31,12 +31,14 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
 
 ////////////////////////////////////////////////////////////////////////////////
-extern "C" __global__ void CalcConc27( 
+extern "C" __global__ void CalcConc27(
 	real* concentration,
 	uint* typeOfGridNode,
 	uint* neighborX,
@@ -52,9 +54,9 @@ extern "C" __global__ void CalcConc27(
    ////////////////////////////////////////////////////////////////////////////////
    //! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
    //!
-   const unsigned  x = threadIdx.x;  // Globaler x-Index 
-   const unsigned  y = blockIdx.x;   // Globaler y-Index 
-   const unsigned  z = blockIdx.y;   // Globaler z-Index 
+   const unsigned  x = threadIdx.x;  // Globaler x-Index
+   const unsigned  y = blockIdx.x;   // Globaler y-Index
+   const unsigned  z = blockIdx.y;   // Globaler z-Index
 
    const unsigned nx = blockDim.x;
    const unsigned ny = gridDim.x;
@@ -100,7 +102,7 @@ extern "C" __global__ void CalcConc27(
          distAD.f[dirBSW ] = &distributionsAD[dirBSW *size_Mat];
          distAD.f[dirBSE ] = &distributionsAD[dirBSE *size_Mat];
          distAD.f[dirBNW ] = &distributionsAD[dirBNW *size_Mat];
-      } 
+      }
       else
       {
          distAD.f[dirW   ] = &distributionsAD[dirE   *size_Mat];
@@ -132,7 +134,7 @@ extern "C" __global__ void CalcConc27(
          distAD.f[dirBNW ] = &distributionsAD[dirTSE *size_Mat];
       }
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set neighbor indices (necessary for indirect addressing)  
+	  //! - Set neighbor indices (necessary for indirect addressing)
 	  //!
 	  uint ke   = k;
       uint kw   = neighborX[k];
@@ -161,7 +163,7 @@ extern "C" __global__ void CalcConc27(
       uint ktne = k;
       uint kbsw = neighborZ[ksw];
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set local distributions  
+	  //! - Set local distributions
 	  //!
 	  real mfcbb = (distAD.f[dirE   ])[ke  ];
 	  real mfabb = (distAD.f[dirW   ])[kw  ];
@@ -194,11 +196,11 @@ extern "C" __global__ void CalcConc27(
 	  //! - Calculate concentration 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>
 	  //!
-	  concentration[k] = 
+	  concentration[k] =
 	   ((((mfccc + mfaaa) + (mfaca + mfcac)) + ((mfacc + mfcaa)   + (mfaac + mfcca))) +
       	(((mfbac + mfbca) + (mfbaa + mfbcc)) + ((mfabc + mfcba)   + (mfaba + mfcbc)) + ((mfacb + mfcab) + (mfaab + mfccb))) +
       	 ((mfabb + mfcbb) + (mfbab + mfbcb)  +  (mfbba + mfbbc))) +  mfbbb;
-      
+
    }
 }
 
diff --git a/src/gpu/VirtualFluids_GPU/GPU/CalcMac27.cu b/src/gpu/VirtualFluids_GPU/GPU/CalcMac27.cu
index f71c08bb49f2319bf95001df8441500348a939c6..8b8e66dd633418e21dd4157b0fea933fb0b5be49 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/CalcMac27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/CalcMac27.cu
@@ -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/>.
 //
@@ -31,12 +31,14 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
 
 ////////////////////////////////////////////////////////////////////////////////
-extern "C" __global__ void LBCalcMacCompSP27( 
+extern "C" __global__ void LBCalcMacCompSP27(
 	real* velocityX,
 	real* velocityY,
 	real* velocityZ,
@@ -56,9 +58,9 @@ extern "C" __global__ void LBCalcMacCompSP27(
    ////////////////////////////////////////////////////////////////////////////////
    //! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
    //!
-   const unsigned  x = threadIdx.x;  // Globaler x-Index 
-   const unsigned  y = blockIdx.x;   // Globaler y-Index 
-   const unsigned  z = blockIdx.y;   // Globaler z-Index 
+   const unsigned  x = threadIdx.x;  // Globaler x-Index
+   const unsigned  y = blockIdx.x;   // Globaler y-Index
+   const unsigned  z = blockIdx.y;   // Globaler z-Index
 
    const unsigned nx = blockDim.x;
    const unsigned ny = gridDim.x;
@@ -104,7 +106,7 @@ extern "C" __global__ void LBCalcMacCompSP27(
          dist.f[dirBSW ] = &distributions[dirBSW *size_Mat];
          dist.f[dirBSE ] = &distributions[dirBSE *size_Mat];
          dist.f[dirBNW ] = &distributions[dirBNW *size_Mat];
-      } 
+      }
       else
       {
          dist.f[dirW   ] = &distributions[dirE   *size_Mat];
@@ -136,7 +138,7 @@ extern "C" __global__ void LBCalcMacCompSP27(
          dist.f[dirBNW ] = &distributions[dirTSE *size_Mat];
       }
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set neighbor indices (necessary for indirect addressing)  
+	  //! - Set neighbor indices (necessary for indirect addressing)
 	  //!
 	  uint ke = k;
       uint kw   = neighborX[k];
@@ -165,7 +167,7 @@ extern "C" __global__ void LBCalcMacCompSP27(
       uint ktne = k;
       uint kbsw = neighborZ[ksw];
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set local distributions  
+	  //! - Set local distributions
 	  //!
 	  real mfcbb = (dist.f[dirE   ])[k   ];
 	  real mfabb = (dist.f[dirW   ])[kw  ];
@@ -195,7 +197,7 @@ extern "C" __global__ void LBCalcMacCompSP27(
 	  real mfcaa = (dist.f[dirBSE ])[kbs ];
 	  real mfaca = (dist.f[dirBNW ])[kbw ];
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set pressure, density and velocity to \f$ 1.0 \f$  
+	  //! - Set pressure, density and velocity to \f$ 1.0 \f$
 	  //!
 	  pressure[k]  = c0o1;
 	  rho[k]       = c0o1;
@@ -210,7 +212,7 @@ extern "C" __global__ void LBCalcMacCompSP27(
 	  real drho = ((((mfccc + mfaaa) + (mfaca + mfcac)) + ((mfacc + mfcaa) + (mfaac + mfcca))) +
       	(((mfbac + mfbca) + (mfbaa + mfbcc)) + ((mfabc + mfcba) + (mfaba + mfcbc)) + ((mfacb + mfcab) + (mfaab + mfccb))) +
       	((mfabb + mfcbb) + (mfbab + mfbcb) + (mfbba + mfbbc))) + mfbbb;
-      
+
       real rhoDev = c1o1 + drho;
       ////////////////////////////////////////////////////////////////////////////////////
       real vvx = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) +
@@ -222,17 +224,17 @@ extern "C" __global__ void LBCalcMacCompSP27(
       real vvz = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfacc - mfcaa) + (mfaac - mfcca))) +
       	(((mfbac - mfbca) + (mfbcc - mfbaa)) + ((mfabc - mfcba) + (mfcbc - mfaba))) +
       	(mfbbc - mfbba)) / rhoDev;
-      
+
       rho[k]        = drho;
       velocityX[k]  = vvx;
       velocityY[k]  = vvy;
       velocityZ[k]  = vvz;
-      
+
 	  //////////////////////////////////////////////////////////////////////////
 	  //! - Calculate pressure
 	  //!
 	  real OxxPyyPzz = c1o1;
-      pressure[k] =((dist.f[dirE   ])[ke  ]+ (dist.f[dirW   ])[kw  ]+ 
+      pressure[k] =((dist.f[dirE   ])[ke  ]+ (dist.f[dirW   ])[kw  ]+
                     (dist.f[dirN   ])[kn  ]+ (dist.f[dirS   ])[ks  ]+
                     (dist.f[dirT   ])[kt  ]+ (dist.f[dirB   ])[kb  ]+
                     c2o1*(
@@ -243,9 +245,9 @@ extern "C" __global__ void LBCalcMacCompSP27(
                     (dist.f[dirTN  ])[ktn ]+ (dist.f[dirBS  ])[kbs ]+
                     (dist.f[dirBN  ])[kbn ]+ (dist.f[dirTS  ])[kts ])+
                     c3o1*(
-                    (dist.f[dirTNE ])[ktne]+ (dist.f[dirTSW ])[ktsw]+ 
-                    (dist.f[dirTSE ])[ktse]+ (dist.f[dirTNW ])[ktnw]+ 
-                    (dist.f[dirBNE ])[kbne]+ (dist.f[dirBSW ])[kbsw]+ 
+                    (dist.f[dirTNE ])[ktne]+ (dist.f[dirTSW ])[ktsw]+
+                    (dist.f[dirTSE ])[ktse]+ (dist.f[dirTNW ])[ktnw]+
+                    (dist.f[dirBNE ])[kbne]+ (dist.f[dirBSW ])[kbsw]+
                     (dist.f[dirBSE ])[kbse]+ (dist.f[dirBNW ])[kbnw])-
                     rho[k]-(velocityX[k] * velocityX[k] + velocityY[k] * velocityY[k] + velocityZ[k] * velocityZ[k]) * (c1o1+rho[k])) * (c1o1 / OxxPyyPzz - c1o2) +rho[k];
    }
@@ -269,7 +271,7 @@ extern "C" __global__ void LBCalcMacCompSP27(
 
 
 ////////////////////////////////////////////////////////////////////////////////
-extern "C" __global__ void LBCalcMacADCompSP27( 
+extern "C" __global__ void LBCalcMacADCompSP27(
 	real* velocityX,
 	real* velocityY,
 	real* velocityZ,
@@ -291,9 +293,9 @@ extern "C" __global__ void LBCalcMacADCompSP27(
    ////////////////////////////////////////////////////////////////////////////////
    //! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
    //!
-   const unsigned  x = threadIdx.x;  // Globaler x-Index 
-   const unsigned  y = blockIdx.x;   // Globaler y-Index 
-   const unsigned  z = blockIdx.y;   // Globaler z-Index 
+   const unsigned  x = threadIdx.x;  // Globaler x-Index
+   const unsigned  y = blockIdx.x;   // Globaler y-Index
+   const unsigned  z = blockIdx.y;   // Globaler z-Index
 
    const unsigned nx = blockDim.x;
    const unsigned ny = gridDim.x;
@@ -339,7 +341,7 @@ extern "C" __global__ void LBCalcMacADCompSP27(
          dist.f[dirBSW ] = &distributions[dirBSW *size_Mat];
          dist.f[dirBSE ] = &distributions[dirBSE *size_Mat];
          dist.f[dirBNW ] = &distributions[dirBNW *size_Mat];
-      } 
+      }
       else
       {
          dist.f[dirW   ] = &distributions[dirE   *size_Mat];
@@ -433,7 +435,7 @@ extern "C" __global__ void LBCalcMacADCompSP27(
            distAD.f[dirTSE ] = &distributionsAD[dirBNW *size_Mat];
        }
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set neighbor indices (necessary for indirect addressing)  
+	  //! - Set neighbor indices (necessary for indirect addressing)
 	  //!
 	  uint ke = k;
       uint kw   = neighborX[k];
@@ -462,7 +464,7 @@ extern "C" __global__ void LBCalcMacADCompSP27(
       uint ktne = k;
       uint kbsw = neighborZ[ksw];
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set local distributions  
+	  //! - Set local distributions
 	  //!
 	  real mfcbb = (dist.f[dirE   ])[k   ];
 	  real mfabb = (dist.f[dirW   ])[kw  ];
@@ -522,7 +524,7 @@ extern "C" __global__ void LBCalcMacADCompSP27(
        real fcaa = (distAD.f[dirBSE ])[kbs];
        real faca = (distAD.f[dirBNW ])[kbw];
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set pressure, density and velocity to \f$ 1.0 \f$  
+	  //! - Set pressure, density and velocity to \f$ 1.0 \f$
 	  //!
 	  pressure[k]  = c0o1;
 	  rho[k]       = c0o1;
@@ -537,7 +539,7 @@ extern "C" __global__ void LBCalcMacADCompSP27(
 	  real drho = ((((mfccc + mfaaa) + (mfaca + mfcac)) + ((mfacc + mfcaa) + (mfaac + mfcca))) +
       	(((mfbac + mfbca) + (mfbaa + mfbcc)) + ((mfabc + mfcba) + (mfaba + mfcbc)) + ((mfacb + mfcab) + (mfaab + mfccb))) +
       	((mfabb + mfcbb) + (mfbab + mfbcb) + (mfbba + mfbbc))) + mfbbb;
-      
+
       real rhoDev = c1o1 + drho;
       ////////////////////////////////////////////////////////////////////////////////////
       real vvx = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) +
@@ -562,17 +564,17 @@ extern "C" __global__ void LBCalcMacADCompSP27(
        real fx = forces[0];
        real fy = forces[1];
        real fz = -rhoScalar*forces[2];
-      
+
       rho[k]        = drho;
       velocityX[k]  = vvx+fx*c1o2;
       velocityY[k]  = vvy+fy*c1o2;
       velocityZ[k]  = vvz+fz*c1o2;
-      
+
 	  //////////////////////////////////////////////////////////////////////////
 	  //! - Calculate pressure
 	  //!
 	  real OxxPyyPzz = c1o1;
-      pressure[k] =((dist.f[dirE   ])[ke  ]+ (dist.f[dirW   ])[kw  ]+ 
+      pressure[k] =((dist.f[dirE   ])[ke  ]+ (dist.f[dirW   ])[kw  ]+
                     (dist.f[dirN   ])[kn  ]+ (dist.f[dirS   ])[ks  ]+
                     (dist.f[dirT   ])[kt  ]+ (dist.f[dirB   ])[kb  ]+
                     c2o1*(
@@ -583,9 +585,9 @@ extern "C" __global__ void LBCalcMacADCompSP27(
                     (dist.f[dirTN  ])[ktn ]+ (dist.f[dirBS  ])[kbs ]+
                     (dist.f[dirBN  ])[kbn ]+ (dist.f[dirTS  ])[kts ])+
                     c3o1*(
-                    (dist.f[dirTNE ])[ktne]+ (dist.f[dirTSW ])[ktsw]+ 
-                    (dist.f[dirTSE ])[ktse]+ (dist.f[dirTNW ])[ktnw]+ 
-                    (dist.f[dirBNE ])[kbne]+ (dist.f[dirBSW ])[kbsw]+ 
+                    (dist.f[dirTNE ])[ktne]+ (dist.f[dirTSW ])[ktsw]+
+                    (dist.f[dirTSE ])[ktse]+ (dist.f[dirTNW ])[ktnw]+
+                    (dist.f[dirBNE ])[kbne]+ (dist.f[dirBSW ])[kbsw]+
                     (dist.f[dirBSE ])[kbse]+ (dist.f[dirBNW ])[kbnw])-
                     rho[k]-(velocityX[k] * velocityX[k] + velocityY[k] * velocityY[k] + velocityZ[k] * velocityZ[k]) * (c1o1+rho[k])) * (c1o1 / OxxPyyPzz - c1o2) +rho[k];
    }
diff --git a/src/gpu/VirtualFluids_GPU/GPU/Cumulant27chim.cu b/src/gpu/VirtualFluids_GPU/GPU/Cumulant27chim.cu
index ee9429304ee64e4ec840caababae9b94c2e9269f..a08da5ba3f08eecbd1b2c10ce902dc639e846716 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/Cumulant27chim.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/Cumulant27chim.cu
@@ -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/>.
 //
@@ -31,12 +31,14 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief forward chimera transformation \ref forwardInverseChimeraWithK 
+//! \brief forward chimera transformation \ref forwardInverseChimeraWithK
 //! Transformation from distributions to central moments according to Eq. (6)-(14) in \ref
 //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 //! Modified for lower round-off errors.
@@ -52,7 +54,7 @@ inline __device__ void forwardInverseChimeraWithK(real &mfa, real &mfb, real &mf
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief backward chimera transformation \ref backwardInverseChimeraWithK 
+//! \brief backward chimera transformation \ref backwardInverseChimeraWithK
 //! Transformation from central moments to distributions according to Eq. (57)-(65) in \ref
 //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 //! Modified for lower round-off errors.
@@ -65,7 +67,7 @@ inline __device__ void backwardInverseChimeraWithK(real &mfa, real &mfb, real &m
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief forward chimera transformation \ref forwardChimera 
+//! \brief forward chimera transformation \ref forwardChimera
 //! Transformation from distributions to central moments according to Eq. (6)-(14) in \ref
 //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 //! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations.
@@ -80,7 +82,7 @@ inline __device__ void forwardChimera(real &mfa, real &mfb, real &mfc, real vv,
 
 
 ////////////////////////////////////////////////////////////////////////////////
-//! \brief backward chimera transformation \ref backwardChimera 
+//! \brief backward chimera transformation \ref backwardChimera
 //! Transformation from central moments to distributions according to Eq. (57)-(65) in \ref
 //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 //! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations.
@@ -116,9 +118,9 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel(
 	////////////////////////////////////////////////////////////////////////////////
 	//! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
 	//!
-	const unsigned  x = threadIdx.x; 
-	const unsigned  y = blockIdx.x;  
-	const unsigned  z = blockIdx.y;  
+	const unsigned  x = threadIdx.x;
+	const unsigned  y = blockIdx.x;
+	const unsigned  z = blockIdx.y;
 
 	const unsigned nx = blockDim.x;
 	const unsigned ny = gridDim.x;
@@ -195,7 +197,7 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel(
 			dist.f[dirTSE ] = &distributions[dirBNW *size_Mat];
 		}
 		////////////////////////////////////////////////////////////////////////////////
-		//! - Set neighbor indices (necessary for indirect addressing) 
+		//! - Set neighbor indices (necessary for indirect addressing)
 		uint kw   = neighborX[k];
 		uint ks   = neighborY[k];
 		uint kb   = neighborZ[k];
@@ -245,15 +247,15 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel(
 		real rho = c1o1 + drho;
 		real OOrho = c1o1 / rho;
 
-		real vvx = 
+		real vvx =
 			((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) +
 			(((mfcba - mfabc) + (mfcbc - mfaba)) + ((mfcab - mfacb) + (mfccb - mfaab))) +
 			(mfcbb - mfabb)) * OOrho;
-		real vvy = 
+		real vvy =
 			((((mfccc - mfaaa) + (mfaca - mfcac)) + ((mfacc - mfcaa) + (mfcca - mfaac))) +
 			(((mfbca - mfbac) + (mfbcc - mfbaa)) + ((mfacb - mfcab) + (mfccb - mfaab))) +
 			(mfbcb - mfbab)) * OOrho;
-		real vvz = 
+		real vvz =
 			((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfacc - mfcaa) + (mfaac - mfcca))) +
 			(((mfbac - mfbca) + (mfbcc - mfbaa)) + ((mfabc - mfcba) + (mfcbc - mfaba))) +
 			(mfbbc - mfbba)) * OOrho;
@@ -262,8 +264,8 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel(
 		//! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa.2015.05.001 ]</b></a>
 		//!
 		real fx = forces[0];
-		real fy = forces[1]; 
-		real fz = forces[2]; 
+		real fy = forces[1];
+		real fz = forces[2];
 		vvx += fx*c1o2;
 		vvy += fy*c1o2;
 		vvz += fz*c1o2;
@@ -353,7 +355,7 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel(
 		real O6 = c1o1;
 
 		////////////////////////////////////////////////////////////////////////////////////
-		//! - A and B: parameters for fourth order convergence of the diffusion term according to Eq. (114) and (115) 
+		//! - A and B: parameters for fourth order convergence of the diffusion term according to Eq. (114) and (115)
 		//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 		//! with simplifications assuming \f$ \omega_2 = 1.0 \f$ (modify for different bulk viscosity).
 		//!
@@ -604,7 +606,7 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel(
 		backwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);
 
 		////////////////////////////////////////////////////////////////////////////////////
-		//! - Write distributions: style of reading and writing the distributions from/to 
+		//! - 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>
 		//!
@@ -687,9 +689,9 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel_AD(
 	////////////////////////////////////////////////////////////////////////////////
 	//! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
 	//!
-	const unsigned  x = threadIdx.x; 
-	const unsigned  y = blockIdx.x;  
-	const unsigned  z = blockIdx.y;  
+	const unsigned  x = threadIdx.x;
+	const unsigned  y = blockIdx.x;
+	const unsigned  z = blockIdx.y;
 
 	const unsigned nx = blockDim.x;
 	const unsigned ny = gridDim.x;
@@ -828,7 +830,7 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel_AD(
             distAD.f[dirTSE ] = &distributionsAD[dirBNW *size_Mat];
         }
 		////////////////////////////////////////////////////////////////////////////////
-		//! - Set neighbor indices (necessary for indirect addressing) 
+		//! - Set neighbor indices (necessary for indirect addressing)
 		uint kw   = neighborX[k];
 		uint ks   = neighborY[k];
 		uint kb   = neighborZ[k];
@@ -908,15 +910,15 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel_AD(
 		real rho = c1o1 + drho;
 		real OOrho = c1o1 / rho;
 
-		real vvx = 
+		real vvx =
 			((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) +
 			(((mfcba - mfabc) + (mfcbc - mfaba)) + ((mfcab - mfacb) + (mfccb - mfaab))) +
 			(mfcbb - mfabb)) * OOrho;
-		real vvy = 
+		real vvy =
 			((((mfccc - mfaaa) + (mfaca - mfcac)) + ((mfacc - mfcaa) + (mfcca - mfaac))) +
 			(((mfbca - mfbac) + (mfbcc - mfbaa)) + ((mfacb - mfcab) + (mfccb - mfaab))) +
 			(mfbcb - mfbab)) * OOrho;
-		real vvz = 
+		real vvz =
 			((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfacc - mfcaa) + (mfaac - mfcca))) +
 			(((mfbac - mfbca) + (mfbcc - mfbaa)) + ((mfabc - mfcba) + (mfcbc - mfaba))) +
 			(mfbbc - mfbba)) * OOrho;
@@ -1023,7 +1025,7 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel_AD(
 		real O6 = c1o1;
 
 		////////////////////////////////////////////////////////////////////////////////////
-		//! - A and B: parameters for fourth order convergence of the diffusion term according to Eq. (114) and (115) 
+		//! - A and B: parameters for fourth order convergence of the diffusion term according to Eq. (114) and (115)
 		//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
 		//! with simplifications assuming \f$ \omega_2 = 1.0 \f$ (modify for different bulk viscosity).
 		//!
@@ -1274,7 +1276,7 @@ extern "C" __global__ void Cumulant_K17_LBM_Device_Kernel_AD(
 		backwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);
 
 		////////////////////////////////////////////////////////////////////////////////////
-		//! - Write distributions: style of reading and writing the distributions from/to 
+		//! - 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>
 		//!
diff --git a/src/gpu/VirtualFluids_GPU/GPU/Init27.cu b/src/gpu/VirtualFluids_GPU/GPU/Init27.cu
index 65bda0bf8f6a254b9bf93607b590f1552c907019..08660a5c52fa0a8df4940f0ecb87696ba92a5c81 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/Init27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/Init27.cu
@@ -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/>.
 //
@@ -31,9 +31,11 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
 
 extern "C" __global__ void LBInit(
 	uint* neighborX,
@@ -54,9 +56,9 @@ extern "C" __global__ void LBInit(
 	////////////////////////////////////////////////////////////////////////////////
 	//! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
 	//!
-	const unsigned  x = threadIdx.x;  // Globaler x-Index 
-	const unsigned  y = blockIdx.x;   // Globaler y-Index 
-	const unsigned  z = blockIdx.y;   // Globaler z-Index 
+	const unsigned  x = threadIdx.x;  // Globaler x-Index
+	const unsigned  y = blockIdx.x;   // Globaler y-Index
+	const unsigned  z = blockIdx.y;   // Globaler z-Index
 
 	const unsigned nx = blockDim.x;
 	const unsigned ny = gridDim.x;
@@ -136,11 +138,11 @@ extern "C" __global__ void LBInit(
 		//! - Set local velocities and density
 		//!
 		real drho = rho[k];
-		real  vx1 = velocityX[k]; 
-		real  vx2 = velocityY[k]; 
-		real  vx3 = velocityZ[k]; 
+		real  vx1 = velocityX[k];
+		real  vx2 = velocityY[k];
+		real  vx3 = velocityZ[k];
 		//////////////////////////////////////////////////////////////////////////
-		//! - Set neighbor indices (necessary for indirect addressing)  
+		//! - Set neighbor indices (necessary for indirect addressing)
 		//!
 		uint kzero = k;
 		uint ke    = k;
diff --git a/src/gpu/VirtualFluids_GPU/GPU/InitAdvectionDiffusion27.cu b/src/gpu/VirtualFluids_GPU/GPU/InitAdvectionDiffusion27.cu
index bcfd1f4ed196bc658a6f5bcd13f1b1584ac4e004..d52d7f8e2b598d53c733dc6434d32be9c36512bf 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/InitAdvectionDiffusion27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/InitAdvectionDiffusion27.cu
@@ -31,9 +31,11 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
+
+using namespace vf::lbm::constant;
 
 extern "C" __global__ void InitAD(
 	uint* neighborX,
@@ -54,9 +56,9 @@ extern "C" __global__ void InitAD(
 	////////////////////////////////////////////////////////////////////////////////
 	//! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
 	//!
-	const unsigned  x = threadIdx.x;  // Globaler x-Index 
-	const unsigned  y = blockIdx.x;   // Globaler y-Index 
-	const unsigned  z = blockIdx.y;   // Globaler z-Index 
+	const unsigned  x = threadIdx.x;  // Globaler x-Index
+	const unsigned  y = blockIdx.x;   // Globaler y-Index
+	const unsigned  z = blockIdx.y;   // Globaler z-Index
 
 	const unsigned nx = blockDim.x;
 	const unsigned ny = gridDim.x;
@@ -136,11 +138,11 @@ extern "C" __global__ void InitAD(
 		//! - Set local velocities and concetration
 		//!
 		real conc = concentration[k];
-		real  vx1 = velocityX[k]; 
-		real  vx2 = velocityY[k]; 
-		real  vx3 = velocityZ[k]; 
+		real  vx1 = velocityX[k];
+		real  vx2 = velocityY[k];
+		real  vx3 = velocityZ[k];
 		//////////////////////////////////////////////////////////////////////////
-		//! - Set neighbor indices (necessary for indirect addressing)  
+		//! - Set neighbor indices (necessary for indirect addressing)
 		//!
 		uint kzero = k;
 		uint ke    = k;
diff --git a/src/gpu/VirtualFluids_GPU/GPU/VelocityBCs27.cu b/src/gpu/VirtualFluids_GPU/GPU/VelocityBCs27.cu
index 88a490feeb028022bde19ec9451cfa44c1e2458f..8bc893a1276d16046a8b673ec1ba674fcaf014dd 100644
--- a/src/gpu/VirtualFluids_GPU/GPU/VelocityBCs27.cu
+++ b/src/gpu/VirtualFluids_GPU/GPU/VelocityBCs27.cu
@@ -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/>.
 //
@@ -31,24 +31,25 @@
 //! \author Martin Schoenherr
 //=======================================================================================
 /* Device code */
-#include "LBM/LB.h" 
+#include "LBM/LB.h"
 #include "LBM/D3Q27.h"
-#include "Core/RealConstants.h"
+#include <lbm/constants/NumericConstants.h>
 
+using namespace vf::lbm::constant;
 //////////////////////////////////////////////////////////////////////////////
 extern "C" __global__ void QVelDevPlainBB27(
 	real* vx,
 	real* vy,
 	real* vz,
 	real* distributions,
-	int* k_Q, 
+	int* k_Q,
 	real* QQ,
 	uint sizeQ,
-	int kQ, 
+	int kQ,
 	uint* neighborX,
 	uint* neighborY,
 	uint* neighborZ,
-	uint size_Mat, 
+	uint size_Mat,
 	bool isEvenTimestep)
 {
 	//////////////////////////////////////////////////////////////////////////
@@ -57,9 +58,9 @@ extern "C" __global__ void QVelDevPlainBB27(
 	////////////////////////////////////////////////////////////////////////////////
 	//! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim.
 	//!
-	const unsigned  x = threadIdx.x;  // Globaler x-Index 
-   const unsigned  y = blockIdx.x;   // Globaler y-Index 
-   const unsigned  z = blockIdx.y;   // Globaler z-Index 
+	const unsigned  x = threadIdx.x;  // Globaler x-Index
+   const unsigned  y = blockIdx.x;   // Globaler y-Index
+   const unsigned  z = blockIdx.y;   // Globaler z-Index
 
    const unsigned nx = blockDim.x;
    const unsigned ny = gridDim.x;
@@ -104,7 +105,7 @@ extern "C" __global__ void QVelDevPlainBB27(
 		  dist.f[dirBSW ] = &distributions[dirBSW *size_Mat];
 		  dist.f[dirBSE ] = &distributions[dirBSE *size_Mat];
 		  dist.f[dirBNW ] = &distributions[dirBNW *size_Mat];
-	   } 
+	   }
 	   else
 	   {
 		  dist.f[dirW   ] = &distributions[dirE   *size_Mat];
@@ -146,11 +147,11 @@ extern "C" __global__ void QVelDevPlainBB27(
       ////////////////////////////////////////////////////////////////////////////////
 	  //! - Set local subgrid distances (q's)
 	  //!
-      real   *q_dirE,   *q_dirW,   *q_dirN,   *q_dirS,   *q_dirT,   *q_dirB, 
+      real   *q_dirE,   *q_dirW,   *q_dirN,   *q_dirS,   *q_dirT,   *q_dirB,
 			 *q_dirNE,  *q_dirSW,  *q_dirSE,  *q_dirNW,  *q_dirTE,  *q_dirBW,
 			 *q_dirBE,  *q_dirTW,  *q_dirTN,  *q_dirBS,  *q_dirBN,  *q_dirTS,
 			 *q_dirTNE, *q_dirTSW, *q_dirTSE, *q_dirTNW, *q_dirBNE, *q_dirBSW,
-			 *q_dirBSE, *q_dirBNW; 
+			 *q_dirBSE, *q_dirBNW;
       q_dirE   = &QQ[dirE   *sizeQ];
       q_dirW   = &QQ[dirW   *sizeQ];
       q_dirN   = &QQ[dirN   *sizeQ];
@@ -178,7 +179,7 @@ extern "C" __global__ void QVelDevPlainBB27(
       q_dirBSE = &QQ[dirBSE *sizeQ];
       q_dirBNW = &QQ[dirBNW *sizeQ];
       ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set neighbor indices (necessary for indirect addressing)  
+	  //! - Set neighbor indices (necessary for indirect addressing)
 	  //!
 	  uint KQK = k_Q[k];
       uint ke   = KQK;
@@ -208,9 +209,9 @@ extern "C" __global__ void QVelDevPlainBB27(
       uint ktne = KQK;
       uint kbsw = neighborZ[ksw];
       ////////////////////////////////////////////////////////////////////////////////
-     
+
       ////////////////////////////////////////////////////////////////////////////////
-	  //! - Set local distributions  
+	  //! - Set local distributions
 	  //!
 	  real f_W = (dist.f[dirE])[ke];
       real f_E    = (dist.f[dirW   ])[kw   ];
@@ -241,7 +242,7 @@ extern "C" __global__ void QVelDevPlainBB27(
 	  ////////////////////////////////////////////////////////////////////////////////
 
 	  ////////////////////////////////////////////////////////////////////////////////
-	  //! - change the pointer to write the results in the correct array  
+	  //! - change the pointer to write the results in the correct array
 	  //!
 	  if (!isEvenTimestep)
       {
@@ -272,7 +273,7 @@ extern "C" __global__ void QVelDevPlainBB27(
          dist.f[dirBSW ] = &distributions[dirBSW *size_Mat];
          dist.f[dirBSE ] = &distributions[dirBSE *size_Mat];
          dist.f[dirBNW ] = &distributions[dirBNW *size_Mat];
-      } 
+      }
       else
       {
          dist.f[dirW   ] = &distributions[dirE   *size_Mat];
@@ -306,10 +307,10 @@ extern "C" __global__ void QVelDevPlainBB27(
 	  ////////////////////////////////////////////////////////////////////////////////
 	  //! - rewrite distributions if there is a sub-grid distance (q) in same direction
 	  real q;
-      q = q_dirE[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirW  ])[kw  ]=f_E   + c4o9  * (-VeloX);	
-      q = q_dirW[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirE  ])[ke  ]=f_W   + c4o9  * ( VeloX);	
-      q = q_dirN[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirS  ])[ks  ]=f_N   + c4o9  * (-VeloY);	
-      q = q_dirS[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirN  ])[kn  ]=f_S   + c4o9  * ( VeloY);	
+      q = q_dirE[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirW  ])[kw  ]=f_E   + c4o9  * (-VeloX);
+      q = q_dirW[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirE  ])[ke  ]=f_W   + c4o9  * ( VeloX);
+      q = q_dirN[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirS  ])[ks  ]=f_N   + c4o9  * (-VeloY);
+      q = q_dirS[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirN  ])[kn  ]=f_S   + c4o9  * ( VeloY);
       q = q_dirT[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirB  ])[kb  ]=f_T   + c4o9  * (-VeloZ);
       q = q_dirB[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirT  ])[kt  ]=f_B   + c4o9  * ( VeloZ);
       q = q_dirNE[k];	if (q>=c0o1 && q<=c1o1)	(dist.f[dirSW ])[ksw ]=f_NE  + c1o9  * (-VeloX - VeloY);
diff --git a/src/lbm/BGK.cpp b/src/lbm/BGK.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fa3af6777a0492687768dd4945cbf1e9b186f514
--- /dev/null
+++ b/src/lbm/BGK.cpp
@@ -0,0 +1,140 @@
+#include "BGK.h"
+
+
+#include <basics/Core/DataTypes.h>
+#include <basics/Core/RealConstants.h>
+
+#include "constants/NumericConstants.h"
+#include "constants/D3Q27.h"
+
+#include "MacroscopicQuantities.h"
+
+namespace vf
+{
+namespace lbm
+{
+
+using namespace constant;
+
+
+
+__host__ __device__ void bgk(KernelParameter parameter)
+{
+    auto& distribution = parameter.distribution;
+    const auto omega = parameter.omega;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - 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>
+    //!
+    real mfcbb = distribution.f[dir::PZZ];
+    real mfabb = distribution.f[dir::MZZ];
+    real mfbcb = distribution.f[dir::ZPZ];
+    real mfbab = distribution.f[dir::ZMZ];
+    real mfbbc = distribution.f[dir::ZZP];
+    real mfbba = distribution.f[dir::ZZM];
+    real mfccb = distribution.f[dir::PPZ];
+    real mfaab = distribution.f[dir::MMZ];
+    real mfcab = distribution.f[dir::PMZ];
+    real mfacb = distribution.f[dir::MPZ];
+    real mfcbc = distribution.f[dir::PZP];
+    real mfaba = distribution.f[dir::MZM];
+    real mfcba = distribution.f[dir::PZM];
+    real mfabc = distribution.f[dir::MZP];
+    real mfbcc = distribution.f[dir::ZPP];
+    real mfbaa = distribution.f[dir::ZMM];
+    real mfbca = distribution.f[dir::ZPM];
+    real mfbac = distribution.f[dir::ZMP];
+    real mfccc = distribution.f[dir::PPP];
+    real mfacc = distribution.f[dir::MPP];
+    real mfcac = distribution.f[dir::PMP];
+    real mfaac = distribution.f[dir::MMP];
+    real mfcca = distribution.f[dir::PPM];
+    real mfaca = distribution.f[dir::MPM];
+    real mfcaa = distribution.f[dir::PMM];
+    real mfaaa = distribution.f[dir::MMM];
+    real mfbbb = distribution.f[dir::ZZZ];
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Acquire macroscopic quantities
+    const real drho = getDensity(distribution.f);
+    const real rho = c1o1 + drho;
+    const real OOrho = constant::c1o1 / (constant::c1o1 + drho);    
+
+    const real vvx = getIncompressibleVelocityX1(distribution.f) * OOrho;
+    const real vvy = getIncompressibleVelocityX2(distribution.f) * OOrho;
+    const real vvz = getIncompressibleVelocityX3(distribution.f) * OOrho;
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - BGK computation
+    const real cusq = c3o2*(vvx*vvx + vvy*vvy + vvz*vvz);
+
+    mfbbb = mfbbb  *(c1o1 + (-omega)) - (-omega)*   c8o27*  (drho - rho * cusq);
+    mfcbb = mfcbb  *(c1o1 + (-omega)) - (-omega)*   c2o27*  (drho + rho * (c3o1*(vvx)+c9o2*(vvx)*(vvx)-cusq));
+    mfabb = mfabb  *(c1o1 + (-omega)) - (-omega)*   c2o27*  (drho + rho * (c3o1*(-vvx) + c9o2*(-vvx)*(-vvx) - cusq));
+    mfbcb = mfbcb  *(c1o1 + (-omega)) - (-omega)*   c2o27*  (drho + rho * (c3o1*(vvy)+c9o2*(vvy)*(vvy)-cusq));
+    mfbab = mfbab  *(c1o1 + (-omega)) - (-omega)*   c2o27*  (drho + rho * (c3o1*(-vvy) + c9o2*(-vvy)*(-vvy) - cusq));
+    mfbbc = mfbbc  *(c1o1 + (-omega)) - (-omega)*   c2o27*  (drho + rho * (c3o1*(vvz)+c9o2*(vvz)*(vvz)-cusq));
+    mfbba = mfbba  *(c1o1 + (-omega)) - (-omega)*   c2o27*  (drho + rho * (c3o1*(-vvz) + c9o2*(-vvz)*(-vvz) - cusq));
+    mfccb = mfccb  *(c1o1 + (-omega)) - (-omega)*   c1o54*  (drho + rho * (c3o1*(vvx + vvy) + c9o2*(vvx + vvy)*(vvx + vvy) - cusq));
+    mfaab = mfaab  *(c1o1 + (-omega)) - (-omega)*   c1o54*  (drho + rho * (c3o1*(-vvx - vvy) + c9o2*(-vvx - vvy)*(-vvx - vvy) - cusq));
+    mfcab = mfcab  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(vvx - vvy) + c9o2*(vvx - vvy)*(vvx - vvy) - cusq));
+    mfacb = mfacb  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(-vvx + vvy) + c9o2*(-vvx + vvy)*(-vvx + vvy) - cusq));
+    mfcbc = mfcbc  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(vvx + vvz) + c9o2*(vvx + vvz)*(vvx + vvz) - cusq));
+    mfaba = mfaba  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(-vvx - vvz) + c9o2*(-vvx - vvz)*(-vvx - vvz) - cusq));
+    mfcba = mfcba  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(vvx - vvz) + c9o2*(vvx - vvz)*(vvx - vvz) - cusq));
+    mfabc = mfabc  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(-vvx + vvz) + c9o2*(-vvx + vvz)*(-vvx + vvz) - cusq));
+    mfbcc = mfbcc  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(vvy + vvz) + c9o2*(vvy + vvz)*(vvy + vvz) - cusq));
+    mfbaa = mfbaa  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(-vvy - vvz) + c9o2*(-vvy - vvz)*(-vvy - vvz) - cusq));
+    mfbca = mfbca  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(vvy - vvz) + c9o2*(vvy - vvz)*(vvy - vvz) - cusq));
+    mfbac = mfbac  *(c1o1 + (-omega)) - (-omega)*    c1o54* (drho + rho * (c3o1*(-vvy + vvz) + c9o2*(-vvy + vvz)*(-vvy + vvz) - cusq));
+    mfccc = mfccc  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(vvx + vvy + vvz) + c9o2*(vvx + vvy + vvz)*(vvx + vvy + vvz) - cusq));
+    mfaaa = mfaaa  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(-vvx - vvy - vvz) + c9o2*(-vvx - vvy - vvz)*(-vvx - vvy - vvz) - cusq));
+    mfcca = mfcca  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(vvx + vvy - vvz) + c9o2*(vvx + vvy - vvz)*(vvx + vvy - vvz) - cusq));
+    mfaac = mfaac  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(-vvx - vvy + vvz) + c9o2*(-vvx - vvy + vvz)*(-vvx - vvy + vvz) - cusq));
+    mfcac = mfcac  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(vvx - vvy + vvz) + c9o2*(vvx - vvy + vvz)*(vvx - vvy + vvz) - cusq));
+    mfaca = mfaca  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(-vvx + vvy - vvz) + c9o2*(-vvx + vvy - vvz)*(-vvx + vvy - vvz) - cusq));
+    mfcaa = mfcaa  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(vvx - vvy - vvz) + c9o2*(vvx - vvy - vvz)*(vvx - vvy - vvz) - cusq));
+    mfacc = mfacc  *(c1o1 + (-omega)) - (-omega)*    c1o216*(drho + rho * (c3o1*(-vvx + vvy + vvz) + c9o2*(-vvx + vvy + vvz)*(-vvx + vvy + vvz) - cusq));
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - 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>
+    //!
+    distribution.f[dir::MZZ] = mfcbb;
+    distribution.f[dir::PZZ] = mfabb;
+    distribution.f[dir::ZMZ] = mfbcb;
+    distribution.f[dir::ZPZ] = mfbab;
+    distribution.f[dir::ZZM] = mfbbc;
+    distribution.f[dir::ZZP] = mfbba;
+    distribution.f[dir::MMZ] = mfccb;
+    distribution.f[dir::PPZ] = mfaab;
+    distribution.f[dir::MPZ] = mfcab;
+    distribution.f[dir::PMZ] = mfacb;
+    distribution.f[dir::MZM] = mfcbc;
+    distribution.f[dir::PZP] = mfaba;
+    distribution.f[dir::MZP] = mfcba;
+    distribution.f[dir::PZM] = mfabc;
+    distribution.f[dir::ZMM] = mfbcc;
+    distribution.f[dir::ZPP] = mfbaa;
+    distribution.f[dir::ZMP] = mfbca;
+    distribution.f[dir::ZPM] = mfbac;
+    distribution.f[dir::MMM] = mfccc;
+    distribution.f[dir::PMM] = mfacc;
+    distribution.f[dir::MPM] = mfcac;
+    distribution.f[dir::PPM] = mfaac;
+    distribution.f[dir::MMP] = mfcca;
+    distribution.f[dir::PMP] = mfaca;
+    distribution.f[dir::MPP] = mfcaa;
+    distribution.f[dir::PPP] = mfaaa;
+    distribution.f[dir::ZZZ] = mfbbb;
+}
+
+
+}
+}
+
diff --git a/src/lbm/BGK.h b/src/lbm/BGK.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c82f5bd445ee008954add02fd0d6d6093364e90
--- /dev/null
+++ b/src/lbm/BGK.h
@@ -0,0 +1,24 @@
+#ifndef LBM_BGK_H
+#define LBM_BGK_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+#include <basics/Core/DataTypes.h>
+
+#include "KernelParameter.h"
+
+namespace vf
+{
+namespace lbm
+{
+
+__host__ __device__ void bgk(KernelParameter parameter);
+
+}
+}
+#endif
diff --git a/src/lbm/CMakeLists.txt b/src/lbm/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..afa90bdd3f95bb71cf7f1eda6407f9b38766072a
--- /dev/null
+++ b/src/lbm/CMakeLists.txt
@@ -0,0 +1,12 @@
+if(BUILD_VF_CPU)
+    project(lbm LANGUAGES CXX)
+
+    vf_add_library(NAME lbm PUBLIC_LINK basics)
+    target_link_libraries(lbm PRIVATE project_warnings)
+
+    vf_add_tests()
+endif()
+
+if(BUILD_VF_GPU OR BUILD_VF_GKS)
+    add_subdirectory(cuda)
+endif()
diff --git a/src/lbm/Chimera.h b/src/lbm/Chimera.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ffa0918aac4e6303efe4db82aa98ee645dc63e8
--- /dev/null
+++ b/src/lbm/Chimera.h
@@ -0,0 +1,121 @@
+#ifndef LBM_CHIMERA_H
+#define LBM_CHIMERA_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+#include <basics/Core/DataTypes.h>
+
+#include <lbm/constants/NumericConstants.h>
+
+namespace vf
+{
+namespace lbm
+{
+
+using namespace constant;
+
+////////////////////////////////////////////////////////////////////////////////
+//! \brief forward chimera transformation \ref forwardInverseChimeraWithK 
+//! Transformation from distributions to central moments according to Eq. (6)-(14) 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>
+//! Modified for lower round-off errors.
+////////////////////////////////////////////////////////////////////////////////
+inline __host__ __device__ void forwardInverseChimeraWithK(real &mfa, real &mfb, real &mfc, real vv,
+                                       real v2, real Kinverse, real K)
+{
+    const real m2 = mfa + mfc;
+    const real m1 = mfc - mfa;
+    real m0 = m2 + mfb;
+
+    mfa = m0;
+    m0 *= Kinverse;
+    m0 += c1o1;
+    mfb = (m1 * Kinverse - m0 * vv) * K;
+    mfc = ((m2 - c2o1 * m1 * vv) * Kinverse + v2 * m0) * K;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//! \brief backward chimera transformation \ref backwardInverseChimeraWithK
+//! Transformation from central moments to distributions according to Eq. (57)-(65) 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>
+//! ] Modified for lower round-off errors.
+////////////////////////////////////////////////////////////////////////////////
+inline __host__ __device__ void backwardInverseChimeraWithK(real &mfa, real &mfb, real &mfc, real vv,
+                                        real v2, real Kinverse, real K)
+{
+    const real m0 = (((mfc - mfb) * c1o2 + mfb * vv) * Kinverse + (mfa * Kinverse + c1o1) * (v2 - vv) * c1o2) * K;
+    const real m1 = (((mfa - mfc) - c2o1 * mfb * vv) * Kinverse + (mfa * Kinverse + c1o1) * (-v2)) * K;
+
+    mfc = (((mfc + mfb) * c1o2 + mfb * vv) * Kinverse + (mfa * Kinverse + c1o1) * (v2 + vv) * c1o2) * K;
+    mfa = m0;
+    mfb = m1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//! \brief forward chimera transformation \ref forwardChimera 
+//! Transformation from distributions to central moments according to Eq. (6)-(14) 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>
+//! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations.
+//! Modified for lower round-off errors.
+////////////////////////////////////////////////////////////////////////////////
+inline __host__ __device__ void forwardChimera(real &mfa, real &mfb, real &mfc, real vv, real v2)
+{
+    const real m1 = (mfa + mfc) + mfb;
+    const real m2 = mfc - mfa;
+
+    mfc = (mfc + mfa) + (v2 * m1 - c2o1 * vv * m2);
+    mfb = m2 - vv * m1;
+    mfa = m1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//! \brief backward chimera transformation \ref backwardChimera 
+//! Transformation from central moments to distributions according to Eq. (57)-(65) 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>
+//! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations.
+//! Modified for lower round-off errors.
+////////////////////////////////////////////////////////////////////////////////
+inline __host__ __device__ void backwardChimera(real &mfa, real &mfb, real &mfc, real vv, real v2)
+{
+    const real ma = (mfc + mfa * (v2 - vv)) * c1o2 + mfb * (vv - c1o2);
+    const real mb = ((mfa - mfc) - mfa * v2) - c2o1 * mfb * vv;
+
+    mfc = (mfc + mfa * (v2 + vv)) * c1o2 + mfb * (vv + c1o2);
+    mfb = mb;
+    mfa = ma;
+}
+
+
+inline __host__ __device__ void forwardChimeraWithK(real &mfa, real &mfb, real &mfc, real vv, real v2, real K) 
+{
+
+    const real m2 = mfa + mfc;
+    const real m1 = mfc - mfa;
+    const real m0 = m2 + mfb;
+    mfa = m0;
+    //m0     += K;
+    mfb = (m1 - K*vv) - m0 * vv;
+    mfc = ((m2 - c2o1*	m1 * vv) + v2*K) + v2 * m0;
+    //m0 += K;
+    //mfb = m1 - m0 * vv;
+    //mfc = m2 - two*	m1 * vv + v2 * m0;
+}
+
+
+inline __host__ __device__ void backwardChimeraWithK(real &mfa, real &mfb, real &mfc, real vv, real v2, real K) 
+{
+    const real  m0 = (mfc - mfb)* c1o2 + mfb * (vv)+(mfa + K) * (v2 - vv) * c1o2;
+    const real m1 = (mfa - mfc) - c2o1* mfb * vv + (mfa + K) * (-v2);
+    mfc = (mfc + mfb)* c1o2 + mfb * (vv)+(mfa + K) * (v2 + vv) * c1o2;
+    mfa = m0;
+    mfb = m1;
+}
+
+}
+}
+#endif
diff --git a/src/lbm/ChimeraTests.cpp b/src/lbm/ChimeraTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..01abbe82764c276f53a4cdd479d333536199c3a9
--- /dev/null
+++ b/src/lbm/ChimeraTests.cpp
@@ -0,0 +1,133 @@
+#include <gmock/gmock.h>
+
+#include "Chimera.h"
+
+#ifdef VF_DOUBLE_ACCURACY
+#define REAL_EQ(a) testing::DoubleEq(a)
+#else
+#define REAL_EQ(a) testing::FloatEq(a)
+#endif
+
+/*
+* InverseChimeraWithK
+*/
+TEST(ChimeraTest, forwardInverseChimeraWithK)
+{
+    real mfa = 1;
+    real mfb = 1;
+    real mfc = 1;
+
+    const real vv = 1.;
+    const real v2 = 1.;
+
+    const real K = 1.;
+    const real Kinverse = 1 / K;
+
+    vf::lbm::forwardInverseChimeraWithK(mfa, mfb, mfc, vv, v2, K, Kinverse);
+
+    EXPECT_THAT(mfa, REAL_EQ(3.));  // mfa + mfb + mfc
+    EXPECT_THAT(mfb, REAL_EQ(-4.)); // -(mfa + mfb + mfc + 1)
+    EXPECT_THAT(mfc, REAL_EQ(6.));  // (mfa + mfc) + (mfa + mfb + mfc + 1)
+}
+
+
+TEST(ChimeraTest, backwardInverseChimeraWithK)
+{
+    // starting with the result values from the test above.
+    real mfa = 3.;
+    real mfb = -4.;
+    real mfc = 6.;
+
+    const real vv = 1.;
+    const real v2 = 1.;
+
+    const real K = 1.;
+    const real Kinverse = 1 / K;
+
+    vf::lbm::backwardInverseChimeraWithK(mfa, mfb, mfc, vv, v2, K, Kinverse);
+
+    // resulting in the start values from the test above.
+    EXPECT_THAT(mfa, REAL_EQ(1.));
+    EXPECT_THAT(mfb, REAL_EQ(1.));
+    EXPECT_THAT(mfc, REAL_EQ(1.));
+}
+
+/*
+* Chimera
+*/
+TEST(ChimeraTest, forwardChimera)
+{
+    real mfa = 1;
+    real mfb = 1;
+    real mfc = 1;
+
+    const real vv = 1.;
+    const real v2 = 1.;
+
+    vf::lbm::forwardChimera(mfa, mfb, mfc, vv, v2);
+
+    EXPECT_THAT(mfa, REAL_EQ(3.));  // mfa + mfb + mfc
+    EXPECT_THAT(mfb, REAL_EQ(-3.)); // -(mfa + mfb + mfc)
+    EXPECT_THAT(mfc, REAL_EQ(5.));  // (mfa + mfc) + (mfa + mfb + mfc)
+}
+
+
+TEST(ChimeraTest, backwardChimera)
+{
+    // starting with the result values from the test above.
+    real mfa = 3.;
+    real mfb = -3.;
+    real mfc = 5.;
+
+    const real vv = 1.;
+    const real v2 = 1.;
+
+    vf::lbm::backwardChimera(mfa, mfb, mfc, vv, v2);
+
+    // resulting in the start values from the test above.
+    EXPECT_THAT(mfa, REAL_EQ(1.));
+    EXPECT_THAT(mfb, REAL_EQ(1.));
+    EXPECT_THAT(mfc, REAL_EQ(1.));
+}
+
+/*
+* ChimeraWithK
+*/
+TEST(ChimeraTest, forwardChimeraWithK)
+{
+    real mfa = 1;
+    real mfb = 1;
+    real mfc = 1;
+
+    const real vv = 1.;
+    const real v2 = 1.;
+
+    const real K = 1.;
+
+    vf::lbm::forwardChimeraWithK(mfa, mfb, mfc, vv, v2, K);
+
+    EXPECT_THAT(mfa, REAL_EQ(3.));  // mfa + mfb + mfc
+    EXPECT_THAT(mfb, REAL_EQ(-4.)); // -(mfa + mfb + mfc)
+    EXPECT_THAT(mfc, REAL_EQ(6.));  // (mfa + mfc) + (mfa + mfb + mfc)
+}
+
+
+TEST(ChimeraTest, backwardChimeraWithK)
+{
+    // starting with the result values from the test above.
+    real mfa = 3.;
+    real mfb = -4.;
+    real mfc = 6.;
+
+    const real vv = 1.;
+    const real v2 = 1.;
+
+    const real K = 1.;
+
+    vf::lbm::backwardChimeraWithK(mfa, mfb, mfc, vv, v2, K);
+
+    // resulting in the start values from the test above.
+    EXPECT_THAT(mfa, REAL_EQ(1.));
+    EXPECT_THAT(mfb, REAL_EQ(1.));
+    EXPECT_THAT(mfc, REAL_EQ(1.));
+}
diff --git a/src/lbm/CumulantChimera.cpp b/src/lbm/CumulantChimera.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..65dc9b1f82f409447fda54fc0bc5f460533aad1b
--- /dev/null
+++ b/src/lbm/CumulantChimera.cpp
@@ -0,0 +1,453 @@
+#include "CumulantChimera.h"
+
+#include <cmath>
+
+#include <basics/Core/DataTypes.h>
+#include <basics/Core/RealConstants.h>
+
+#include "constants/NumericConstants.h"
+#include "constants/D3Q27.h"
+
+#include "Chimera.h"
+#include "MacroscopicQuantities.h"
+
+namespace vf
+{
+namespace lbm
+{
+
+using namespace constant;
+
+
+////////////////////////////////////////////////////////////////////////////////////
+//! - Setting relaxation rates for non-hydrodynamic cumulants (default values). Variable names and equations    according to
+//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+//!  => [NAME IN PAPER]=[NAME IN CODE]=[DEFAULT VALUE].
+//!  - Trace of second order cumulants \f$ C_{200}+C_{020}+C_{002} \f$ used to adjust bulk  viscosity:\f$\omega_2=OxxPyyPzz=1.0 \f$.
+//!  - Third order cumulants \f$ C_{120}+C_{102}, C_{210}+C_{012}, C_{201}+C_{021} \f$: \f$ \omega_3=OxyyPxzz   \f$ set according to Eq. (111) with simplifications assuming \f$ \omega_2=1.0\f$.
+//!  - Third order cumulants \f$ C_{120}-C_{102}, C_{210}-C_{012}, C_{201}-C_{021} \f$: \f$ \omega_4 =  OxyyMxzz \f$ set according to Eq. (112) with simplifications assuming \f$ \omega_2 = 1.0\f$.
+//!  - Third order cumulants \f$ C_{111} \f$: \f$ \omega_5 = Oxyz \f$ set according to Eq. (113) with   simplifications assuming \f$ \omega_2 = 1.0\f$  (modify for different bulk viscosity).
+//!  - Fourth order cumulants \f$ C_{220}, C_{202}, C_{022}, C_{211}, C_{121}, C_{112} \f$: for simplification  all set to the same default value \f$ \omega_6=\omega_7=\omega_8=O4=1.0 \f$.
+//!  - Fifth order cumulants \f$ C_{221}, C_{212}, C_{122}\f$: \f$\omega_9=O5=1.0\f$.
+//!  - Sixth order cumulant \f$ C_{222}\f$: \f$\omega_{10}=O6=1.0\f$.
+//////////////////////////////////////////////////////////////////////////
+__host__ __device__ void setRelaxationRatesK17(real omega, real &OxxPyyPzz, real &OxyyPxzz, real &OxyyMxzz, real &Oxyz,
+                                               real &O4, real &O5, real &O6)
+{
+    OxxPyyPzz = c1o1;
+
+    OxyyPxzz = c8o1 * (-c2o1 + omega) * (c1o1 + c2o1 * omega) / (-c8o1 - c14o1 * omega + c7o1 * omega * omega);
+    OxyyMxzz = c8o1 * (-c2o1 + omega) * (-c7o1 + c4o1 * omega) / (c56o1 - c50o1 * omega + c9o1 * omega * omega);
+    Oxyz     = c24o1 * (-c2o1 + omega) * (-c2o1 - c7o1 * omega + c3o1 * omega * omega) /
+                (c48o1 + c152o1 * omega - c130o1 * omega * omega + c29o1 * omega * omega * omega);
+
+    O4 = c1o1;
+
+    O5 = c1o1;
+
+    O6 = c1o1;
+}
+
+
+__host__ __device__ void setRelaxationRatesK15(real omega, real &OxxPyyPzz, real &OxyyPxzz, real &OxyyMxzz, real &Oxyz,
+                                               real &O4, real &O5, real &O6)
+{
+    OxxPyyPzz = c1o1;
+
+    OxyyPxzz = c1o1;
+    OxyyMxzz = c1o1;
+    Oxyz     = c1o1;
+
+    O4 = c1o1;
+
+    O5 = c1o1;
+
+    O6 = c1o1;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//! Cumulant K17 Kernel is based on \ref
+//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a>
+//! and \ref
+//! <a href="https://doi.org/10.1016/j.jcp.2017.07.004"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.07.004 ]</b></a>
+//////////////////////////////////////////////////////////////////////////
+__host__ __device__ void cumulantChimera(KernelParameter parameter, RelaxationRatesFunctor setRelaxationRates)
+{
+    auto& distribution = parameter.distribution;
+    const auto omega = parameter.omega;
+    const auto* forces = parameter.forces;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - 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>
+    //!
+    real mfcbb = distribution.f[dir::PZZ];
+    real mfabb = distribution.f[dir::MZZ];
+    real mfbcb = distribution.f[dir::ZPZ];
+    real mfbab = distribution.f[dir::ZMZ];
+    real mfbbc = distribution.f[dir::ZZP];
+    real mfbba = distribution.f[dir::ZZM];
+    real mfccb = distribution.f[dir::PPZ];
+    real mfaab = distribution.f[dir::MMZ];
+    real mfcab = distribution.f[dir::PMZ];
+    real mfacb = distribution.f[dir::MPZ];
+    real mfcbc = distribution.f[dir::PZP];
+    real mfaba = distribution.f[dir::MZM];
+    real mfcba = distribution.f[dir::PZM];
+    real mfabc = distribution.f[dir::MZP];
+    real mfbcc = distribution.f[dir::ZPP];
+    real mfbaa = distribution.f[dir::ZMM];
+    real mfbca = distribution.f[dir::ZPM];
+    real mfbac = distribution.f[dir::ZMP];
+    real mfccc = distribution.f[dir::PPP];
+    real mfacc = distribution.f[dir::MPP];
+    real mfcac = distribution.f[dir::PMP];
+    real mfaac = distribution.f[dir::MMP];
+    real mfcca = distribution.f[dir::PPM];
+    real mfaca = distribution.f[dir::MPM];
+    real mfcaa = distribution.f[dir::PMM];
+    real mfaaa = distribution.f[dir::MMM];
+    real mfbbb = distribution.f[dir::ZZZ];
+
+
+    const real drho = getDensity(distribution.f);
+    const real OOrho = c1o1 / (c1o1 + drho);    
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Add half of the acceleration (body force) to the velocity as in Eq. (42) \ref
+    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa  2015.05.001 ]</b></a>
+    //!
+    const real vvx = getIncompressibleVelocityX1(distribution.f) * OOrho + forces[0] * c1o2;
+    const real vvy = getIncompressibleVelocityX2(distribution.f) * OOrho + forces[0] * c1o2;
+    const real vvz = getIncompressibleVelocityX3(distribution.f) * OOrho + forces[0] * c1o2;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // calculate the square of velocities for this lattice node
+    const real vx2 = vvx*vvx;
+    const real vy2 = vvy*vvy;
+    const real vz2 = vvz*vvz;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Chimera transform from well conditioned distributions to central moments as defined in Appendix J in \ref
+    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa  2015.05.001 ]</b></a>
+    //! see also Eq. (6)-(14) in \ref
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //!
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Z - Dir
+    vf::lbm::forwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36o1, c1o36);
+    vf::lbm::forwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::forwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36o1, c1o36);
+    vf::lbm::forwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::forwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2,  c9o4,  c4o9);
+    vf::lbm::forwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::forwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36o1, c1o36);
+    vf::lbm::forwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::forwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);   
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Y - Dir
+    vf::lbm::forwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2,  c6o1,  c1o6);
+    vf::lbm::forwardChimera(            mfaab, mfabb, mfacb, vvy, vy2);
+    vf::lbm::forwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18o1, c1o18);
+    vf::lbm::forwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2,  c3o2,  c2o3);
+    vf::lbm::forwardChimera(            mfbab, mfbbb, mfbcb, vvy, vy2);
+    vf::lbm::forwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2,  c9o2,  c2o9);
+    vf::lbm::forwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2,  c6o1,  c1o6);
+    vf::lbm::forwardChimera(            mfcab, mfcbb, mfccb, vvy, vy2);
+    vf::lbm::forwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18o1, c1o18);   
+    ////////////////////////////////////////////////////////////////////////////////////
+    // X - Dir
+    vf::lbm::forwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1o1, c1o1);
+    vf::lbm::forwardChimera(            mfaba, mfbba, mfcba, vvx, vx2);
+    vf::lbm::forwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3o1, c1o3);
+    vf::lbm::forwardChimera(            mfaab, mfbab, mfcab, vvx, vx2);
+    vf::lbm::forwardChimera(            mfabb, mfbbb, mfcbb, vvx, vx2);
+    vf::lbm::forwardChimera(            mfacb, mfbcb, mfccb, vvx, vx2);
+    vf::lbm::forwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3o1, c1o3);
+    vf::lbm::forwardChimera(            mfabc, mfbbc, mfcbc, vvx, vx2);
+    vf::lbm::forwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c3o1, c1o9); 
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Setting relaxation rates for non-hydrodynamic cumulants (default values). Variable names and equations
+    real OxxPyyPzz;
+    real OxyyPxzz;
+    real OxyyMxzz;
+    real Oxyz;
+    real O4;
+    real O5;
+    real O6;
+
+    setRelaxationRates(omega, OxxPyyPzz, OxyyPxzz, OxyyMxzz, Oxyz, O4, O5, O6);
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - A and B: parameters for fourth order convergence of the diffusion term according to Eq. (114) and (115) 
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //! with simplifications assuming \f$ \omega_2 = 1.0 \f$ (modify for different bulk viscosity).
+    //!
+    const real A = (c4o1 + c2o1*omega - c3o1*omega*omega) / (c2o1 - c7o1*omega + c5o1*omega*omega);
+    const real B = (c4o1 + c28o1*omega - c14o1*omega*omega) / (c6o1 - c21o1*omega + c15o1*omega*omega);   
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Compute cumulants from central moments according to Eq. (20)-(23) in
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //!
+    ////////////////////////////////////////////////////////////
+    //4.
+    real CUMcbb = mfcbb - ((mfcaa + c1o3) * mfabb + c2o1 * mfbba * mfbab) * OOrho;
+    real CUMbcb = mfbcb - ((mfaca + c1o3) * mfbab + c2o1 * mfbba * mfabb) * OOrho;
+    real CUMbbc = mfbbc - ((mfaac + c1o3) * mfbba + c2o1 * mfbab * mfabb) * OOrho;  
+    real CUMcca = mfcca - (((mfcaa * mfaca + c2o1 * mfbba * mfbba) + c1o3 * (mfcaa + mfaca)) * OOrho - c1o9*(drho   * OOrho));
+    real CUMcac = mfcac - (((mfcaa * mfaac + c2o1 * mfbab * mfbab) + c1o3 * (mfcaa + mfaac)) * OOrho - c1o9*(drho   * OOrho));
+    real CUMacc = mfacc - (((mfaac * mfaca + c2o1 * mfabb * mfabb) + c1o3 * (mfaac + mfaca)) * OOrho - c1o9*(drho   * OOrho));
+    ////////////////////////////////////////////////////////////
+    //5.
+    real CUMbcc = mfbcc - ((mfaac * mfbca + mfaca * mfbac + c4o1 * mfabb * mfbbb + c2o1 * (mfbab * mfacb + mfbba *  mfabc)) + c1o3 * (mfbca + mfbac)) * OOrho;
+    real CUMcbc = mfcbc - ((mfaac * mfcba + mfcaa * mfabc + c4o1 * mfbab * mfbbb + c2o1 * (mfabb * mfcab + mfbba *  mfbac)) + c1o3 * (mfcba + mfabc)) * OOrho;
+    real CUMccb = mfccb - ((mfcaa * mfacb + mfaca * mfcab + c4o1 * mfbba * mfbbb + c2o1 * (mfbab * mfbca + mfabb *  mfcba)) + c1o3 * (mfacb + mfcab)) * OOrho;
+    ////////////////////////////////////////////////////////////
+    //6.
+    real CUMccc = mfccc + ((-c4o1 *  mfbbb * mfbbb
+        - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+        - c4o1 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc)
+        - c2o1 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) * OOrho
+        + (c4o1 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+        + c2o1 * (mfcaa * mfaca * mfaac)
+        + c16o1 *  mfbba * mfbab * mfabb) * OOrho * OOrho
+        - c1o3 * (mfacc + mfcac + mfcca) * OOrho
+        - c1o9 * (mfcaa + mfaca + mfaac) * OOrho
+        + (c2o1 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+        + (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 *(mfaac + mfaca + mfcaa)) * OOrho * OOrho  * c2o3
+        + c1o27*((drho * drho - drho) * OOrho * OOrho));    
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Compute linear combinations of second and third order cumulants
+    //!
+    ////////////////////////////////////////////////////////////
+    //2.
+    real mxxPyyPzz = mfcaa + mfaca + mfaac;
+    real mxxMyy = mfcaa - mfaca;
+    real mxxMzz = mfcaa - mfaac;
+    ////////////////////////////////////////////////////////////
+    //3.
+    real mxxyPyzz = mfcba + mfabc;
+    real mxxyMyzz = mfcba - mfabc;  
+    real mxxzPyyz = mfcab + mfacb;
+    real mxxzMyyz = mfcab - mfacb;  
+    real mxyyPxzz = mfbca + mfbac;
+    real mxyyMxzz = mfbca - mfbac;  
+    ////////////////////////////////////////////////////////////////////////////////////
+    //incl. correction
+    ////////////////////////////////////////////////////////////
+    //! - Compute velocity  gradients from second order cumulants according to Eq. (27)-(32)
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //! Further explanations of the correction in viscosity in Appendix H of
+    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa  2015.05.001 ]</b></a>
+    //! Note that the division by rho is omitted here as we need rho times the gradients later.
+    //!
+    const real Dxy = -c3o1*omega*mfbba;
+    const real Dxz = -c3o1*omega*mfbab;
+    const real Dyz = -c3o1*omega*mfabb;
+    const real dxux = c1o2 * (-omega) *(mxxMyy + mxxMzz) + c1o2 *  OxxPyyPzz * (mfaaa - mxxPyyPzz);
+    const real dyuy = dxux + omega * c3o2 * mxxMyy;
+    const real dzuz = dxux + omega * c3o2 * mxxMzz;
+    ////////////////////////////////////////////////////////////
+    //! - Relaxation of second order cumulants with correction terms according to Eq. (33)-(35) in
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //!
+    mxxPyyPzz += OxxPyyPzz*(mfaaa - mxxPyyPzz) - c3o1 * (c1o1 - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2  * dzuz);
+    mxxMyy    += omega * (-mxxMyy) - c3o1 * (c1o1 + c1o2 * (-omega)) * (vx2 * dxux - vy2 * dyuy);
+    mxxMzz    += omega * (-mxxMzz) - c3o1 * (c1o1 + c1o2 * (-omega)) * (vx2 * dxux - vz2 * dzuz);   
+    ////////////////////////////////////////////////////////////////////////////////////
+    ////no correction
+    //mxxPyyPzz += OxxPyyPzz*(mfaaa - mxxPyyPzz);
+    //mxxMyy += -(-omega) * (-mxxMyy);
+    //mxxMzz += -(-omega) * (-mxxMzz);
+    //////////////////////////////////////////////////////////////////////////
+    mfabb += omega * (-mfabb);
+    mfbab += omega * (-mfbab);
+    mfbba += omega * (-mfbba);  
+    ////////////////////////////////////////////////////////////////////////////////////
+    //relax
+    //////////////////////////////////////////////////////////////////////////
+    // incl. limiter
+    //! Set relaxation limiters for third order cumulants to default value \f$ \lambda=0.001 \f$ according to section 6 in \ref
+    //! - Relaxation of third order cumulants including limiter according to Eq. (116)-(123)
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //!
+
+    const real qudricLimitP = c1o100;
+    const real qudricLimitM = c1o100;
+    const real qudricLimitD = c1o100;
+
+    real wadjust   = Oxyz + (c1o1 - Oxyz)*abs_internal(mfbbb) / (abs_internal(mfbbb) + qudricLimitD);
+    mfbbb    += wadjust * (-mfbbb);
+    wadjust   = OxyyPxzz + (c1o1 - OxyyPxzz)*abs_internal(mxxyPyzz) / (abs_internal(mxxyPyzz) + qudricLimitP);
+    mxxyPyzz += wadjust * (-mxxyPyzz);
+    wadjust   = OxyyMxzz + (c1o1 - OxyyMxzz)*abs_internal(mxxyMyzz) / (abs_internal(mxxyMyzz) + qudricLimitM);
+    mxxyMyzz += wadjust * (-mxxyMyzz);
+    wadjust   = OxyyPxzz + (c1o1 - OxyyPxzz)*abs_internal(mxxzPyyz) / (abs_internal(mxxzPyyz) + qudricLimitP);
+    mxxzPyyz += wadjust * (-mxxzPyyz);
+    wadjust   = OxyyMxzz + (c1o1 - OxyyMxzz)*abs_internal(mxxzMyyz) / (abs_internal(mxxzMyyz) + qudricLimitM);
+    mxxzMyyz += wadjust * (-mxxzMyyz);
+    wadjust   = OxyyPxzz + (c1o1 - OxyyPxzz)*abs_internal(mxyyPxzz) / (abs_internal(mxyyPxzz) + qudricLimitP);
+    mxyyPxzz += wadjust * (-mxyyPxzz);
+    wadjust   = OxyyMxzz + (c1o1 - OxyyMxzz)*abs_internal(mxyyMxzz) / (abs_internal(mxyyMxzz) + qudricLimitM);
+    mxyyMxzz += wadjust * (-mxyyMxzz);
+    //////////////////////////////////////////////////////////////////////////
+    // no limiter
+    //mfbbb += OxyyMxzz * (-mfbbb);
+    //mxxyPyzz += OxyyPxzz * (-mxxyPyzz);
+    //mxxyMyzz += OxyyMxzz * (-mxxyMyzz);
+    //mxxzPyyz += OxyyPxzz * (-mxxzPyyz);
+    //mxxzMyyz += OxyyMxzz * (-mxxzMyyz);
+    //mxyyPxzz += OxyyPxzz * (-mxyyPxzz);
+    //mxyyMxzz += OxyyMxzz * (-mxyyMxzz);   
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Compute inverse linear combinations of second and third order cumulants
+    //!
+    mfcaa = c1o3 * (mxxMyy + mxxMzz + mxxPyyPzz);
+    mfaca = c1o3 * (-c2o1*  mxxMyy + mxxMzz + mxxPyyPzz);
+    mfaac = c1o3 * (mxxMyy - c2o1* mxxMzz + mxxPyyPzz); 
+    mfcba = ( mxxyMyzz + mxxyPyzz) * c1o2;
+    mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2;
+    mfcab = ( mxxzMyyz + mxxzPyyz) * c1o2;
+    mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2;
+    mfbca = ( mxyyMxzz + mxyyPxzz) * c1o2;
+    mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2;
+    //////////////////////////////////////////////////////////////////////////  
+    //////////////////////////////////////////////////////////////////////////
+    //4.
+    // no limiter
+    //! - Relax fourth order cumulants to modified equilibrium for fourth order convergence of diffusion according  to Eq. (43)-(48)
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //!
+    CUMacc = -O4*(c1o1 / omega - c1o2) * (dyuy + dzuz) * c2o3 * A + (c1o1 - O4) * (CUMacc);
+    CUMcac = -O4*(c1o1 / omega - c1o2) * (dxux + dzuz) * c2o3 * A + (c1o1 - O4) * (CUMcac);
+    CUMcca = -O4*(c1o1 / omega - c1o2) * (dyuy + dxux) * c2o3 * A + (c1o1 - O4) * (CUMcca);
+    CUMbbc = -O4*(c1o1 / omega - c1o2) * Dxy           * c1o3 * B + (c1o1 - O4) * (CUMbbc);
+    CUMbcb = -O4*(c1o1 / omega - c1o2) * Dxz           * c1o3 * B + (c1o1 - O4) * (CUMbcb);
+    CUMcbb = -O4*(c1o1 / omega - c1o2) * Dyz           * c1o3 * B + (c1o1 - O4) * (CUMcbb); 
+    //////////////////////////////////////////////////////////////////////////
+    //5.
+    CUMbcc += O5 * (-CUMbcc);
+    CUMcbc += O5 * (-CUMcbc);
+    CUMccb += O5 * (-CUMccb);   
+    //////////////////////////////////////////////////////////////////////////
+    //6.
+    CUMccc += O6 * (-CUMccc);   
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Compute central moments from post collision cumulants according to Eq. (53)-(56) in
+    //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05  040 ]</b></a>
+    //! 
+    //////////////////////////////////////////////////////////////////////////
+    //4.
+    mfcbb = CUMcbb + c1o3*((c3o1*mfcaa + c1o1) * mfabb + c6o1 * mfbba * mfbab) * OOrho;
+    mfbcb = CUMbcb + c1o3*((c3o1*mfaca + c1o1) * mfbab + c6o1 * mfbba * mfabb) * OOrho;
+    mfbbc = CUMbbc + c1o3*((c3o1*mfaac + c1o1) * mfbba + c6o1 * mfbab * mfabb) * OOrho; 
+    mfcca = CUMcca + (((mfcaa * mfaca + c2o1 * mfbba * mfbba)*c9o1 + c3o1 * (mfcaa + mfaca)) * OOrho - (drho *  OOrho))*c1o9;
+    mfcac = CUMcac + (((mfcaa * mfaac + c2o1 * mfbab * mfbab)*c9o1 + c3o1 * (mfcaa + mfaac)) * OOrho - (drho *  OOrho))*c1o9;
+    mfacc = CUMacc + (((mfaac * mfaca + c2o1 * mfabb * mfabb)*c9o1 + c3o1 * (mfaac + mfaca)) * OOrho - (drho *  OOrho))*c1o9; 
+    //////////////////////////////////////////////////////////////////////////
+    //5.
+    mfbcc = CUMbcc + c1o3 *(c3o1*(mfaac * mfbca + mfaca * mfbac + c4o1 * mfabb * mfbbb + c2o1 * (mfbab * mfacb +    mfbba * mfabc)) + (mfbca + mfbac)) * OOrho;
+    mfcbc = CUMcbc + c1o3 *(c3o1*(mfaac * mfcba + mfcaa * mfabc + c4o1 * mfbab * mfbbb + c2o1 * (mfabb * mfcab +    mfbba * mfbac)) + (mfcba + mfabc)) * OOrho;
+    mfccb = CUMccb + c1o3 *(c3o1*(mfcaa * mfacb + mfaca * mfcab + c4o1 * mfbba * mfbbb + c2o1 * (mfbab * mfbca +    mfabb * mfcba)) + (mfacb + mfcab)) * OOrho; 
+    //////////////////////////////////////////////////////////////////////////
+    //6.
+    mfccc =	CUMccc - ((-c4o1 *  mfbbb * mfbbb
+            - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca)
+            - c4o1 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc)
+            - c2o1 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) * OOrho
+            + (c4o1 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac)
+                + c2o1 * (mfcaa * mfaca * mfaac)
+                + c16o1 *  mfbba * mfbab * mfabb) * OOrho * OOrho
+            - c1o3 * (mfacc + mfcac + mfcca) * OOrho
+            - c1o9 * (mfcaa + mfaca + mfaac) * OOrho
+            + (c2o1 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba)
+                + (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 *(mfaac + mfaca + mfcaa)) * OOrho * OOrho * c2o3
+            + c1o27*((drho * drho - drho) * OOrho * OOrho));    
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! -  Add acceleration (body force) to first order cumulants according to Eq. (85)-(87) in
+    //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), DOI:10.1016/j.camwa  2015.05.001 ]</b></a>
+    //!
+    mfbaa = -mfbaa;
+    mfaba = -mfaba;
+    mfaab = -mfaab; 
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - 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
+    vf::lbm::backwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1o1, c1o1);
+    vf::lbm::backwardChimera(            mfaba, mfbba, mfcba, vvx, vx2);
+    vf::lbm::backwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3o1, c1o3);
+    vf::lbm::backwardChimera(            mfaab, mfbab, mfcab, vvx, vx2);
+    vf::lbm::backwardChimera(            mfabb, mfbbb, mfcbb, vvx, vx2);
+    vf::lbm::backwardChimera(            mfacb, mfbcb, mfccb, vvx, vx2);
+    vf::lbm::backwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3o1, c1o3);
+    vf::lbm::backwardChimera(            mfabc, mfbbc, mfcbc, vvx, vx2);
+    vf::lbm::backwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c9o1, c1o9);    
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Y - Dir
+    vf::lbm::backwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2,  c6o1,  c1o6);
+    vf::lbm::backwardChimera(            mfaab, mfabb, mfacb, vvy, vy2);
+    vf::lbm::backwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18o1, c1o18);
+    vf::lbm::backwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2,  c3o2,  c2o3);
+    vf::lbm::backwardChimera(            mfbab, mfbbb, mfbcb, vvy, vy2);
+    vf::lbm::backwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2,  c9o2,  c2o9);
+    vf::lbm::backwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2,  c6o1,  c1o6);
+    vf::lbm::backwardChimera(            mfcab, mfcbb, mfccb, vvy, vy2);
+    vf::lbm::backwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18o1, c1o18);  
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Z - Dir
+    vf::lbm::backwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36o1, c1o36);
+    vf::lbm::backwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::backwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36o1, c1o36);
+    vf::lbm::backwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::backwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2,  c9o4,  c4o9);
+    vf::lbm::backwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::backwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36o1, c1o36);
+    vf::lbm::backwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2,  c9o1,  c1o9);
+    vf::lbm::backwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36o1, c1o36);
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //! - Write distributions: style of reading and writing the distributions from/to 
+    //! stored arrays dependent on timestep is based on the esoteric twist algorithm
+    //! <a href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), DOI:10.3390/computation5020019 ]</b></a>
+    //!
+    distribution.f[dir::MZZ] = mfcbb;
+    distribution.f[dir::PZZ] = mfabb;
+    distribution.f[dir::ZMZ] = mfbcb;
+    distribution.f[dir::ZPZ] = mfbab;
+    distribution.f[dir::ZZM] = mfbbc;
+    distribution.f[dir::ZZP] = mfbba;
+    distribution.f[dir::MMZ] = mfccb;
+    distribution.f[dir::PPZ] = mfaab;
+    distribution.f[dir::MPZ] = mfcab;
+    distribution.f[dir::PMZ] = mfacb;
+    distribution.f[dir::MZM] = mfcbc;
+    distribution.f[dir::PZP] = mfaba;
+    distribution.f[dir::MZP] = mfcba;
+    distribution.f[dir::PZM] = mfabc;
+    distribution.f[dir::ZMM] = mfbcc;
+    distribution.f[dir::ZPP] = mfbaa;
+    distribution.f[dir::ZMP] = mfbca;
+    distribution.f[dir::ZPM] = mfbac;
+    distribution.f[dir::MMM] = mfccc;
+    distribution.f[dir::PMM] = mfacc;
+    distribution.f[dir::MPM] = mfcac;
+    distribution.f[dir::PPM] = mfaac;
+    distribution.f[dir::MMP] = mfcca;
+    distribution.f[dir::PMP] = mfaca;
+    distribution.f[dir::MPP] = mfcaa;
+    distribution.f[dir::PPP] = mfaaa;
+    distribution.f[dir::ZZZ] = mfbbb;
+}
+
+
+}
+}
+
diff --git a/src/lbm/CumulantChimera.h b/src/lbm/CumulantChimera.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8740c7d3f5b988a6fdc5c3b16ab6a90e0a28b83
--- /dev/null
+++ b/src/lbm/CumulantChimera.h
@@ -0,0 +1,34 @@
+#ifndef LBM_CUMULANT_CHIMERA_H
+#define LBM_CUMULANT_CHIMERA_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+#include <basics/Core/DataTypes.h>
+
+#include "KernelParameter.h"
+
+namespace vf
+{
+namespace lbm
+{
+
+__host__ __device__ void setRelaxationRatesK17(real omega, real &OxxPyyPzz, real &OxyyPxzz, real &OxyyMxzz, real &Oxyz,
+                                               real &O4, real &O5, real &O6);
+
+__host__ __device__ void setRelaxationRatesK15(real omega, real &OxxPyyPzz, real &OxyyPxzz, real &OxyyMxzz, real &Oxyz,
+                                               real &O4, real &O5, real &O6);
+
+using RelaxationRatesFunctor = void(*)(real omega, real &OxxPyyPzz, real &OxyyPxzz, real &OxyyMxzz, real &Oxyz,
+                                       real &O4, real &O5, real &O6);
+
+
+__host__ __device__ void cumulantChimera(KernelParameter parameter, RelaxationRatesFunctor setRelaxationRates);
+
+}
+}
+#endif
diff --git a/src/lbm/KernelParameter.cpp b/src/lbm/KernelParameter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e039214d218ef19f35e8adf927f36d3a6f1aa355
--- /dev/null
+++ b/src/lbm/KernelParameter.cpp
@@ -0,0 +1,33 @@
+#include "KernelParameter.h"
+
+#include <cmath>
+
+#include "MacroscopicQuantities.h"
+
+
+namespace vf
+{
+namespace lbm
+{
+
+
+
+inline __host__ __device__ real Distribution27::getDensity_() const
+{
+    return getDensity(f);
+}
+
+
+
+__host__ __device__ real abs_internal(real value)
+{
+#ifdef __CUDA_ARCH__
+    return ::abs(value);
+#else
+    return std::abs(value);
+#endif
+}
+
+
+}
+}
diff --git a/src/lbm/KernelParameter.h b/src/lbm/KernelParameter.h
new file mode 100644
index 0000000000000000000000000000000000000000..95226628110637f3794c8a1f7e6f6c1f6dda937b
--- /dev/null
+++ b/src/lbm/KernelParameter.h
@@ -0,0 +1,43 @@
+#ifndef LBM_KERNEL_PARAMETER_H
+#define LBM_KERNEL_PARAMETER_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+#include <basics/Core/DataTypes.h>
+
+
+namespace vf
+{
+namespace lbm
+{
+
+struct Distribution27
+{
+    real f[27];
+
+    __host__ __device__ real getDensity_() const;
+};
+
+
+__host__ __device__ real abs_internal(real value);
+
+
+struct KernelParameter
+{
+    Distribution27& distribution;
+    real omega;
+    real* forces;
+};
+
+
+
+
+}
+}
+
+#endif
diff --git a/src/lbm/MacroscopicQuantities.h b/src/lbm/MacroscopicQuantities.h
new file mode 100644
index 0000000000000000000000000000000000000000..c37791294ff5b4edad21795f4ce0a32a18c5d236
--- /dev/null
+++ b/src/lbm/MacroscopicQuantities.h
@@ -0,0 +1,98 @@
+#ifndef LBM_CALCMAC_H
+#define LBM_CALCMAC_H
+
+#ifndef __host__
+#define __host__
+#endif
+#ifndef __device__
+#define __device__
+#endif
+
+#include <basics/Core/DataTypes.h>
+
+#include "constants/NumericConstants.h"
+#include "constants/D3Q27.h"
+
+namespace vf
+{
+namespace lbm
+{
+    
+////////////////////////////////////////////////////////////////////////////////////
+//! - 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>
+//!
+
+inline __host__ __device__ real getDensity(const real *const &f /*[27]*/)
+{
+    return ((f[dir::TNE] + f[dir::BSW]) + (f[dir::TSE] + f[dir::BNW])) + ((f[dir::BSE] + f[dir::TNW]) + (f[dir::TSW] + f[dir::BNE])) +
+           (((f[dir::NE] + f[dir::SW]) + (f[dir::SE] + f[dir::NW])) + ((f[dir::TE] + f[dir::BW]) + (f[dir::BE] + f[dir::TW])) +
+            ((f[dir::BN] + f[dir::TS]) + (f[dir::TN] + f[dir::BS]))) +
+           ((f[dir::E] + f[dir::W]) + (f[dir::N] + f[dir::S]) + (f[dir::T] + f[dir::B])) + f[dir::REST];
+}
+
+/*
+* Incompressible Macroscopic Quantities
+*/
+inline __host__ __device__ real getIncompressibleVelocityX1(const real *const &f /*[27]*/)
+{
+    return ((((f[dir::TNE] - f[dir::BSW]) + (f[dir::TSE] - f[dir::BNW])) + ((f[dir::BSE] - f[dir::TNW]) + (f[dir::BNE] - f[dir::TSW]))) +
+            (((f[dir::BE] - f[dir::TW]) + (f[dir::TE] - f[dir::BW])) + ((f[dir::SE] - f[dir::NW]) + (f[dir::NE] - f[dir::SW]))) + (f[dir::E] - f[dir::W]));
+}
+
+
+inline __host__ __device__ real getIncompressibleVelocityX2(const real *const &f /*[27]*/)
+{
+    return ((((f[dir::TNE] - f[dir::BSW]) + (f[dir::BNW] - f[dir::TSE])) + ((f[dir::TNW] - f[dir::BSE]) + (f[dir::BNE] - f[dir::TSW]))) +
+            (((f[dir::BN] - f[dir::TS]) + (f[dir::TN] - f[dir::BS])) + ((f[dir::NW] - f[dir::SE]) + (f[dir::NE] - f[dir::SW]))) + (f[dir::N] - f[dir::S]));
+}
+
+
+inline __host__ __device__ real getIncompressibleVelocityX3(const real *const &f /*[27]*/)
+{
+    return ((((f[dir::TNE] - f[dir::BSW]) + (f[dir::TSE] - f[dir::BNW])) + ((f[dir::TNW] - f[dir::BSE]) + (f[dir::TSW] - f[dir::BNE]))) +
+            (((f[dir::TS] - f[dir::BN]) + (f[dir::TN] - f[dir::BS])) + ((f[dir::TW] - f[dir::BE]) + (f[dir::TE] - f[dir::BW]))) + (f[dir::T] - f[dir::B]));
+}
+
+
+
+/*
+* Compressible Macroscopic Quantities
+*/
+inline __host__ __device__ real getCompressibleVelocityX1(const real *const &f27, const real& rho)
+{
+    return getIncompressibleVelocityX1(f27) / (rho + constant::c1o1);
+}
+
+
+inline __host__ __device__ real getCompressibleVelocityX2(const real *const &f27, const real& rho)
+{
+    return getIncompressibleVelocityX2(f27) / (rho + constant::c1o1);
+}
+
+
+inline __host__ __device__ real getCompressibleVelocityX3(const real *const &f27, const real& rho)
+{
+    return getIncompressibleVelocityX3(f27) / (rho + constant::c1o1);
+}
+
+/*
+* Pressure
+*/
+inline __host__ __device__ real getPressure(const real *const &f27, const real& rho, const real& vx, const real& vy, const real& vz)
+{
+    return (f27[dir::E] + f27[dir::W] + f27[dir::N] + f27[dir::S] + f27[dir::T] + f27[dir::B] + 
+    constant::c2o1 * (f27[dir::NE] + f27[dir::SW] + f27[dir::SE] + f27[dir::NW] + f27[dir::TE] + 
+                      f27[dir::BW] + f27[dir::BE] + f27[dir::TW] + f27[dir::TN] + f27[dir::BS] + 
+                      f27[dir::BN] + f27[dir::TS]) + 
+    constant::c3o1 * (f27[dir::TNE] + f27[dir::TSW] + f27[dir::TSE] + f27[dir::TNW] + 
+                      f27[dir::BNE] + f27[dir::BSW] + f27[dir::BSE] + f27[dir::BNW]) -
+    rho - (vx * vx + vy * vy + vz * vz) * (constant::c1o1 + rho)) * 
+    constant::c1o2 + rho; // times zero for incompressible case                 
+                          // Attention: op defined directly to op = 1 ; ^^^^(1.0/op-0.5)=0.5
+}
+
+}
+}
+
+#endif
diff --git a/src/lbm/MacroscopicQuantitiesTests.cpp b/src/lbm/MacroscopicQuantitiesTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..52f89943a3e6a99fcab13eba22de9959229a289d
--- /dev/null
+++ b/src/lbm/MacroscopicQuantitiesTests.cpp
@@ -0,0 +1,71 @@
+#include <gmock/gmock.h>
+
+#include "MacroscopicQuantities.h"
+#include "constants/D3Q27.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};
+
+using namespace vf::lbm;
+
+
+TEST(MacroscopicQuantitiesTest, check_density)
+{
+    const double density = getDensity(f);
+
+    const double expected_density = 27.;
+    ASSERT_THAT(density, testing::DoubleEq(expected_density));
+}
+
+TEST(MacroscopicQuantitiesTest, whenFsAreEqual_velocityInEachDirectionShouldBeZero)
+{
+    const double velocityX1 = getIncompressibleVelocityX1(f);
+    const double velocityX2 = getIncompressibleVelocityX2(f);
+    const double velocityX3 = getIncompressibleVelocityX3(f);
+
+    const double expected_velocity = 0.;
+    EXPECT_THAT(velocityX1, testing::DoubleEq(expected_velocity));
+    EXPECT_THAT(velocityX2, testing::DoubleEq(expected_velocity));
+    EXPECT_THAT(velocityX3, testing::DoubleEq(expected_velocity));
+}
+
+TEST(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Eis2_velocityInX1ShouldBeOne)
+{
+    f[dir::E] = 2.;
+
+    const double velocityX1 = getIncompressibleVelocityX1(f);
+    const double velocityX2 = getIncompressibleVelocityX2(f);
+    const double velocityX3 = getIncompressibleVelocityX3(f);
+
+    const double expected_velocity_x1 = 1.;
+    const double expected_velocity_x2 = 0.;
+    const double expected_velocity_x3 = 0.;
+
+    EXPECT_THAT(velocityX1, testing::DoubleEq(expected_velocity_x1));
+    EXPECT_THAT(velocityX2, testing::DoubleEq(expected_velocity_x2));
+    EXPECT_THAT(velocityX3, testing::DoubleEq(expected_velocity_x3));
+}
+
+TEST(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Nis2_velocityInX2ShouldBeOne)
+{
+    f[dir::N] = 2.;
+
+    const double velocity = getIncompressibleVelocityX2(f);
+
+    const double expected_velocity = 1.;
+    ASSERT_THAT(velocity, testing::DoubleEq(expected_velocity));
+}
+
+
+TEST(MacroscopicQuantitiesTest, givenAllFsAreOne_when_Tis2_velocityInX3ShouldBeOne)
+{
+    f[dir::T] = 2.;
+
+    const double velocity = getIncompressibleVelocityX3(f);
+
+    const double expected_velocity = 1.;
+    ASSERT_THAT(velocity, testing::DoubleEq(expected_velocity));
+}
diff --git a/src/lbm/constants/D3Q27.h b/src/lbm/constants/D3Q27.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b2cbfdd44e84af590fa2c2be4bf319cbfd4c815
--- /dev/null
+++ b/src/lbm/constants/D3Q27.h
@@ -0,0 +1,71 @@
+#ifndef LBM_D3Q27_H
+#define LBM_D3Q27_H
+
+namespace vf
+{
+namespace lbm
+{
+namespace dir
+{
+
+static constexpr int E    = 0;
+static constexpr int W    = 1;
+static constexpr int N    = 2;
+static constexpr int S    = 3;
+static constexpr int T    = 4;
+static constexpr int B    = 5;
+static constexpr int NE   = 6;
+static constexpr int SW   = 7;
+static constexpr int SE   = 8;
+static constexpr int NW   = 9;
+static constexpr int TE   = 10;
+static constexpr int BW   = 11;
+static constexpr int BE   = 12;
+static constexpr int TW   = 13;
+static constexpr int TN   = 14;
+static constexpr int BS   = 15;
+static constexpr int BN   = 16;
+static constexpr int TS   = 17;
+static constexpr int TNE  = 18;
+static constexpr int TNW  = 19;
+static constexpr int TSE  = 20;
+static constexpr int TSW  = 21;
+static constexpr int BNE  = 22;
+static constexpr int BNW  = 23;
+static constexpr int BSE  = 24;
+static constexpr int BSW  = 25;
+static constexpr int REST = 26;
+
+static constexpr int PZZ = 0;
+static constexpr int MZZ = 1;
+static constexpr int ZPZ = 2;
+static constexpr int ZMZ = 3;
+static constexpr int ZZP = 4;
+static constexpr int ZZM = 5;
+static constexpr int PPZ = 6;
+static constexpr int MMZ = 7;
+static constexpr int PMZ = 8;
+static constexpr int MPZ = 9;
+static constexpr int PZP = 10;
+static constexpr int MZM = 11;
+static constexpr int PZM = 12;
+static constexpr int MZP = 13;
+static constexpr int ZPP = 14;
+static constexpr int ZMM = 15;
+static constexpr int ZPM = 16;
+static constexpr int ZMP = 17;
+static constexpr int PPP = 18;
+static constexpr int MPP = 19;
+static constexpr int PMP = 20;
+static constexpr int MMP = 21;
+static constexpr int PPM = 22;
+static constexpr int MPM = 23;
+static constexpr int PMM = 24;
+static constexpr int MMM = 25;
+static constexpr int ZZZ = 26;
+
+}
+}
+}
+
+#endif
diff --git a/src/lbm/constants/NumericConstants.h b/src/lbm/constants/NumericConstants.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f023276e84fba064ec9ae6823a9a96f1631bfec
--- /dev/null
+++ b/src/lbm/constants/NumericConstants.h
@@ -0,0 +1,246 @@
+#ifndef REAL_CONSTANT_H
+#define REAL_CONSTANT_H
+
+
+namespace vf
+{
+namespace lbm 
+{
+namespace constant
+{
+
+#ifdef VF_DOUBLE_ACCURACY
+static constexpr double c1o2 = 0.5;
+static constexpr double c3o2 = 1.5;
+static constexpr double c1o3 = 0.333333333333333;
+static constexpr double c2o3 = 0.666666666666667;
+static constexpr double c1o4 = 0.25;
+static constexpr double c3o4 = 0.75;
+static constexpr double c1o6 = 0.166666666666667;
+static constexpr double c1o7 = 0.142857142857143;
+static constexpr double c1o8 = 0.125;
+static constexpr double c1o9 = 0.111111111111111;
+static constexpr double c2o9 = 0.222222222222222;
+static constexpr double c4o9 = 0.444444444444444;
+static constexpr double c1o10 = 0.1;
+static constexpr double c1o12 = 0.083333333333333;
+static constexpr double c1o16 = 0.0625;
+static constexpr double c3o16 = 0.1875;
+static constexpr double c9o16 = 0.5625;
+static constexpr double c1o18 = 0.055555555555556;
+static constexpr double c1o20 = 0.05;
+static constexpr double c19o20 = 0.95;
+static constexpr double c21o20 = 1.05;
+static constexpr double c1o24 = 0.041666666666667;
+static constexpr double c1o27 = 0.037037037037037;
+static constexpr double c3o32 = 0.09375;
+static constexpr double c4o32 = 0.125;
+static constexpr double c1o36 = 0.027777777777778;
+static constexpr double c1o48 = 0.020833333333333;
+static constexpr double c1o64 = 0.015625;
+static constexpr double c3o64 = 0.046875;
+static constexpr double c9o64 = 0.140625;
+static constexpr double c27o64 = 0.421875;
+static constexpr double c1o66 = 0.015151515151515;
+static constexpr double c1o72 = 0.013888888888889;
+static constexpr double c1o264 = 0.003787878787879;
+static constexpr double c8o27 = 0.296296296296296;
+static constexpr double c2o27 = 0.074074074074074;
+static constexpr double c1o54 = 0.018518518518519;
+static constexpr double c1o100 = 0.01;
+static constexpr double c99o100 = 0.99;
+static constexpr double c1o126 = 0.007936507936508;
+static constexpr double c1o216 = 0.004629629629630;
+static constexpr double c5o4 = 1.25;
+static constexpr double c9o4 = 2.25;
+static constexpr double c5o2 = 2.5;
+static constexpr double c9o2 = 4.5;
+
+static constexpr double c0o1 = 0.;
+static constexpr double c1o1 = 1.;
+static constexpr double c2o1 = 2.;
+static constexpr double c3o1 = 3.;
+static constexpr double c4o1 = 4.;
+static constexpr double c5o1 = 5.;
+static constexpr double c6o1 = 6.;
+static constexpr double c7o1 = 7.;
+static constexpr double c8o1 = 8.;
+static constexpr double c9o1 = 9.;
+static constexpr double c10o1 = 10.;
+static constexpr double c11o1 = 11.;
+static constexpr double c12o1 = 12.;
+static constexpr double c13o1 = 13.;
+static constexpr double c14o1 = 14.;
+static constexpr double c15o1 = 15.;
+static constexpr double c16o1 = 16.;
+static constexpr double c17o1 = 17.;
+static constexpr double c18o1 = 18.;
+static constexpr double c21o1 = 21.;
+static constexpr double c24o1 = 24.;
+static constexpr double c25o1 = 25.;
+static constexpr double c26o1 = 26.;
+static constexpr double c27o1 = 27.;
+static constexpr double c28o1 = 28.;
+static constexpr double c29o1 = 29.;
+static constexpr double c30o1 = 30.;
+static constexpr double c32o1 = 32.;
+static constexpr double c33o1 = 33.;
+static constexpr double c34o1 = 34.;
+static constexpr double c36o1 = 36.;
+static constexpr double c40o1 = 40.;
+static constexpr double c42o1 = 42.;
+static constexpr double c46o1 = 46.;
+static constexpr double c48o1 = 48.;
+static constexpr double c50o1 = 50.;
+static constexpr double c52o1 = 52.;
+static constexpr double c54o1 = 54.;
+static constexpr double c56o1 = 56.;
+static constexpr double c64o1 = 64.;
+static constexpr double c66o1 = 66.;
+static constexpr double c68o1 = 68.;
+static constexpr double c69o1 = 69.;
+static constexpr double c72o1 = 72.;
+static constexpr double c84o1 = 84.;
+static constexpr double c88o1 = 88.;
+static constexpr double c96o1 = 96.;
+static constexpr double c100o1 = 10.;
+static constexpr double c130o1 = 13.;
+static constexpr double c152o1 = 15.;
+static constexpr double c166o1 = 16.;
+static constexpr double c195o1 = 19.;
+static constexpr double c216o1 = 21.;
+static constexpr double c264o1 = 26.;
+static constexpr double c290o1 = 29.;
+static constexpr double c367o1 = 36.;
+
+static constexpr double Op0000002 = 0.0000002;
+static constexpr double c10eM30 = 1e-30;
+static constexpr double c10eM10 = 1e-10;
+static constexpr double smallSingle = 0.0000000002;
+
+static constexpr double cPi = 3.1415926535;
+static constexpr double c2Pi = 6.28318530717;
+static constexpr double cPio180 = 1.74532925199e-2;
+static constexpr double c180oPi = 57.2957795131;
+
+#else
+static constexpr float c1o2 = 0.5f;
+static constexpr float c3o2 = 1.5f;
+static constexpr float c1o3 = (1.0f / 3.0f);
+static constexpr float c2o3 = (2.0f / 3.0f);
+static constexpr float c1o4 = 0.25f;
+static constexpr float c3o4 = 0.75f;
+static constexpr float c1o6 = (1.0f / 6.0f);
+static constexpr float c1o7 = (1.0f / 7.0f);
+static constexpr float c1o8 = 0.125f;
+static constexpr float c1o9 = (1.0f / 9.0f);
+static constexpr float c2o9 = (2.0f / 9.0f);
+static constexpr float c4o9 = (4.0f / 9.0f);
+static constexpr float c1o10 = 0.1f;
+static constexpr float c1o12 = (1.0f / 12.0f);
+static constexpr float c1o16 = 0.0625f;
+static constexpr float c3o16 = 0.1875f;
+static constexpr float c9o16 = 0.5625f;
+static constexpr float c1o18 = (1.0f / 18.0f);
+static constexpr float c1o20 = 0.05f;
+static constexpr float c19o20 = 0.95f;
+static constexpr float c21o20 = 1.05f;
+static constexpr float c1o24 = (1.0f / 24.0f);
+static constexpr float c1o27 = (1.0f / 27.0f);
+static constexpr float c3o32 = 0.09375f;
+static constexpr float c4o32 = 0.125f;
+static constexpr float c1o36 = (1.0f / 36.0f);
+static constexpr float c1o48 = (1.0f / 48.0f);
+static constexpr float c1o64 = 0.015625f;
+static constexpr float c3o64 = 0.046875f;
+static constexpr float c9o64 = 0.140625f;
+static constexpr float c27o64 = 0.421875f;
+static constexpr float c1o66 = (1.0f / 66.0f);
+static constexpr float c1o72 = (1.0f / 72.0f);
+static constexpr float c1o264 = (1.0f / 264.0f);
+static constexpr float c8o27 = (8.0f / 27.0f);
+static constexpr float c2o27 = (2.0f / 27.0f);
+static constexpr float c1o54 = (1.0f / 54.0f);
+static constexpr float c1o100 = 0.01f;
+static constexpr float c99o100 = 0.99f;
+static constexpr float c1o126 = (1.0f / 126.0f);
+static constexpr float c1o216 = (1.0f / 216.0f);
+static constexpr float c5o4 = 1.25f;
+static constexpr float c9o4 = 2.25f;
+static constexpr float c5o2 = 2.5f;
+static constexpr float c9o2 = 4.5f;
+
+static constexpr float c0o1 = 0.f;
+static constexpr float c1o1 = 1.f;
+static constexpr float c2o1 = 2.f;
+static constexpr float c3o1 = 3.f;
+static constexpr float c4o1 = 4.f;
+static constexpr float c5o1 = 5.f;
+static constexpr float c6o1 = 6.f;
+static constexpr float c7o1 = 7.f;
+static constexpr float c8o1 = 8.f;
+static constexpr float c9o1 = 9.f;
+static constexpr float c10o1 = 10.f;
+static constexpr float c11o1 = 11.f;
+static constexpr float c12o1 = 12.f;
+static constexpr float c13o1 = 13.f;
+static constexpr float c14o1 = 14.f;
+static constexpr float c15o1 = 15.f;
+static constexpr float c16o1 = 16.f;
+static constexpr float c17o1 = 17.f;
+static constexpr float c18o1 = 18.f;
+static constexpr float c21o1 = 21.f;
+static constexpr float c24o1 = 24.f;
+static constexpr float c25o1 = 25.f;
+static constexpr float c26o1 = 26.f;
+static constexpr float c27o1 = 27.f;
+static constexpr float c28o1 = 28.f;
+static constexpr float c29o1 = 29.f;
+static constexpr float c30o1 = 30.f;
+static constexpr float c32o1 = 32.f;
+static constexpr float c33o1 = 33.f;
+static constexpr float c34o1 = 34.f;
+static constexpr float c36o1 = 36.f;
+static constexpr float c40o1 = 40.f;
+static constexpr float c42o1 = 42.f;
+static constexpr float c46o1 = 46.f;
+static constexpr float c48o1 = 48.f;
+static constexpr float c50o1 = 50.f;
+static constexpr float c52o1 = 52.f;
+static constexpr float c54o1 = 54.f;
+static constexpr float c56o1 = 56.f;
+static constexpr float c64o1 = 64.f;
+static constexpr float c66o1 = 66.f;
+static constexpr float c68o1 = 68.f;
+static constexpr float c69o1 = 69.f;
+static constexpr float c72o1 = 72.f;
+static constexpr float c84o1 = 84.f;
+static constexpr float c88o1 = 88.f;
+static constexpr float c96o1 = 96.f;
+static constexpr float c100o1 = 100.0f;
+static constexpr float c130o1 = 130.0f;
+static constexpr float c152o1 = 152.0f;
+static constexpr float c166o1 = 166.0f;
+static constexpr float c195o1 = 195.0f;
+static constexpr float c216o1 = 216.0f;
+static constexpr float c264o1 = 264.0f;
+static constexpr float c290o1 = 290.0f;
+static constexpr float c367o1 = 367.0f;
+
+static constexpr float Op0000002 = 0.0000002f;
+static constexpr float c10eM30 = 1e-30f;
+static constexpr float c10eM10 = 1e-10f;
+static constexpr float smallSingle = 0.0000000002f;
+
+static constexpr float cPi = 3.1415926535f;
+static constexpr double c2Pi = 6.2831853071f;
+static constexpr float cPio180 = 1.74532925199e-2f;
+static constexpr float c180oPi = 57.2957795131f;
+
+#endif
+
+}
+}
+}
+
+#endif
diff --git a/src/lbm/cuda/CMakeLists.txt b/src/lbm/cuda/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4142b7c3b1c46275c3257e3dfd657cc6b30c841d
--- /dev/null
+++ b/src/lbm/cuda/CMakeLists.txt
@@ -0,0 +1,12 @@
+project(lbmCuda LANGUAGES CUDA CXX)
+
+
+vf_add_library(NAME lbmCuda BUILDTYPE static PUBLIC_LINK basics FOLDER ../../lbm)
+
+
+set_target_properties(lbmCuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON POSITION_INDEPENDENT_CODE ON)
+
+
+set_source_files_properties(../KernelParameter.cpp PROPERTIES LANGUAGE CUDA)
+set_source_files_properties(../CumulantChimera.cpp PROPERTIES LANGUAGE CUDA)
+set_source_files_properties(../BGK.cpp PROPERTIES LANGUAGE CUDA)
diff --git a/src/logger/CMakeLists.txt b/src/logger/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..32cbdae2aaa40f11b12e1f3fe1629f47ba4ca195
--- /dev/null
+++ b/src/logger/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+vf_add_library(NAME logger PUBLIC_LINK spdlog PRIVATE_LINK project_warnings)
diff --git a/src/logger/Logger.cpp b/src/logger/Logger.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..708e359c8430380dd57c404ed9b3c41f53dcb714
--- /dev/null
+++ b/src/logger/Logger.cpp
@@ -0,0 +1,54 @@
+#include "Logger.h"
+
+#include <spdlog/spdlog.h>
+#include <spdlog/sinks/stdout_color_sinks.h>
+#include <spdlog/sinks/daily_file_sink.h>
+#include <spdlog/sinks/basic_file_sink.h>
+
+namespace vf::logging
+{
+
+    std::string Logger::logPath = {"logs/"};
+
+    void Logger::initalizeLogger() 
+    {
+        updateDefaultLogger();
+
+        // setting default log level to trace
+        // levels: trace < debug < info < warn < error < critical
+        spdlog::set_level(spdlog::level::trace);
+
+        // setting the log pattern
+        // formatting is documented here: https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
+        spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
+
+        // according to the flush policy https://github.com/gabime/spdlog/wiki/7.-Flush-policy
+        spdlog::flush_on(spdlog::level::info);
+    }
+
+
+    void Logger::changeLogPath(const std::string& path)
+    {
+        logPath = path;
+
+        updateDefaultLogger();
+    }
+
+
+    void Logger::updateDefaultLogger()
+    {
+        // initialize stdout sink with colored output
+        auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
+
+        // initialize daily file sink
+        // files will be written into "logs" folder relative to pwd. A new files is created at 0:00 o'clock.
+        auto daily_file_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>(logPath + "daily.txt", 0, 0);
+
+        // initialize last run file sink
+        auto last_run_file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(logPath + "last_run.txt", true);
+
+        // creating default logger with console and file sink
+        spdlog::set_default_logger(std::make_shared<spdlog::logger>("default", spdlog::sinks_init_list({console_sink, daily_file_sink, last_run_file_sink})));
+    }
+
+}
diff --git a/src/logger/Logger.h b/src/logger/Logger.h
new file mode 100644
index 0000000000000000000000000000000000000000..adb7796135a989843ef8de1f778c9901f3ad17c8
--- /dev/null
+++ b/src/logger/Logger.h
@@ -0,0 +1,73 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
+//
+//  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/>.
+//
+//! \author Soeren Peters
+//=======================================================================================
+#ifndef VF_LOGGER_H
+#define VF_LOGGER_H
+
+// VirtualFluids is using the spdlog logger https://github.com/gabime/spdlog
+#include <spdlog/spdlog.h>
+// To initialize spdlog initalizeLogger() must be called.
+// spdlog supports 5 log level, which can be changed at runtime e.g.:
+// spdlog::set_level(spdlog::level::debug)
+// 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
+// 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/
+// File path can be changed via changeLogPath()
+
+#define VF_LOG_TRACE(...) spdlog::trace(__VA_ARGS__)
+#define VF_LOG_DEBUG(...) spdlog::debug(__VA_ARGS__)
+#define VF_LOG_INFO(...) spdlog::info(__VA_ARGS__)
+#define VF_LOG_WARNING(...) spdlog::warn(__VA_ARGS__)
+#define VF_LOG_CRITICAL(...) spdlog::critical(__VA_ARGS__)
+
+
+namespace vf::logging
+{
+    class Logger
+    {
+    public:
+        // initalizing the above named logger
+        static void initalizeLogger();
+
+        // changing the path of the log files
+        static void changeLogPath(const std::string& path);
+
+    private:
+        static void updateDefaultLogger();
+
+        static std::string logPath;
+    };
+}
+
+#endif
diff --git a/src/mpi/CMakeLists.txt b/src/mpi/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..de1d58f5bd39e14742180b9cc6a77fb640d117f6
--- /dev/null
+++ b/src/mpi/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+vf_add_library(NAME mpi PUBLIC_LINK logger PRIVATE_LINK MPI::MPI_CXX basics)
diff --git a/src/cpu/VirtualFluidsCore/Parallel/Communicator.cpp b/src/mpi/Communicator.cpp
similarity index 91%
rename from src/cpu/VirtualFluidsCore/Parallel/Communicator.cpp
rename to src/mpi/Communicator.cpp
index b7ea54267edb7126573e512a7593e3f3f4312bd6..937f4d819f67804380d807bfe5ef6048ff507058 100644
--- a/src/cpu/VirtualFluidsCore/Parallel/Communicator.cpp
+++ b/src/mpi/Communicator.cpp
@@ -34,12 +34,17 @@
 #include "Communicator.h"
 #include <basics/utilities/UbException.h>
 
-SPtr<Communicator> Communicator::instance = SPtr<Communicator>();
+namespace vf::mpi 
+{
+std::mutex Communicator::instantiation_mutex = std::mutex();
+std::shared_ptr<Communicator> Communicator::instance = std::shared_ptr<Communicator>();
 //////////////////////////////////////////////////////////////////////////
-SPtr<Communicator> Communicator::getInstance()
+std::shared_ptr<Communicator> Communicator::getInstance()
 {
     if (!instance)
         UB_THROW(UbException(UB_EXARGS, "Communicator isn't initialized correctly! You can not create a new instance "
                                         "of abstract Communicator class!"));
     return instance;
 }
+
+}
diff --git a/src/mpi/Communicator.h b/src/mpi/Communicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..bcec064a23801c7b597d91deb601b44a1d9c7a71
--- /dev/null
+++ b/src/mpi/Communicator.h
@@ -0,0 +1,105 @@
+//=======================================================================================
+// ____          ____    __    ______     __________   __      __       __        __
+// \    \       |    |  |  |  |   _   \  |___    ___| |  |    |  |     /  \      |  |
+//  \    \      |    |  |  |  |  |_)   |     |  |     |  |    |  |    /    \     |  |
+//   \    \     |    |  |  |  |   _   /      |  |     |  |    |  |   /  /\  \    |  |
+//    \    \    |    |  |  |  |  | \  \      |  |     |   \__/   |  /  ____  \   |  |____
+//     \    \   |    |  |__|  |__|  \__\     |__|      \________/  /__/    \__\  |_______|
+//      \    \  |    |   ________________________________________________________________
+//       \    \ |    |  |  ______________________________________________________________|
+//        \    \|    |  |  |         __          __     __     __     ______      _______
+//         \         |  |  |_____   |  |        |  |   |  |   |  |   |   _  \    /  _____)
+//          \        |  |   _____|  |  |        |  |   |  |   |  |   |  | \  \   \_______
+//           \       |  |  |        |  |_____   |   \_/   |   |  |   |  |_/  /    _____  |
+//            \ _____|  |__|        |________|   \_______/    |__|   |______/    (_______/
+//
+//  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 Communicator.h
+//! \ingroup Parallel
+//! \author Konstantin Kutscher
+//=======================================================================================
+
+#ifndef MPI_COMMUNICATOR_H
+#define MPI_COMMUNICATOR_H
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <sstream>
+#include <mutex>
+
+
+namespace vf::mpi 
+{
+
+//! \brief An abstract class for communication between processes in parallel computation
+class Communicator
+{
+public:
+    Communicator(const Communicator&) = delete;
+    Communicator & operator=(const Communicator& rhs) = delete;
+    static std::shared_ptr<Communicator> getInstance();
+
+    virtual ~Communicator() = default;
+
+    virtual int getBundleID()                      = 0;
+    virtual int getNumberOfBundles()               = 0;
+    virtual int getProcessID()                     = 0;
+    virtual int getProcessID(int bundle, int rank) = 0;
+    virtual int getNumberOfProcesses()             = 0;
+    virtual bool isRoot()                          = 0;
+    virtual void *getNativeCommunicator()          = 0;
+
+    virtual void sendSerializedObject(std::stringstream &ss, int target)    = 0;
+    virtual void receiveSerializedObject(std::stringstream &ss, int source) = 0;
+
+    virtual int getRoot()                                = 0;
+    virtual int getBundleRoot()                          = 0;
+    virtual int getProcessRoot()                         = 0;
+    virtual int getNumberOfProcessesInBundle(int bundle) = 0;
+    virtual void barrier()                               = 0;
+    virtual void abort(int errorcode)                    = 0;
+
+    virtual std::vector<std::string> gather(const std::string &str)                         = 0;
+    virtual std::vector<int> gather(std::vector<int> &values)                               = 0;
+    virtual std::vector<float> gather(std::vector<float> &values)                           = 0;
+    virtual std::vector<double> gather(std::vector<double> &values)                         = 0;
+    virtual std::vector<unsigned long long> gather(std::vector<unsigned long long> &values) = 0;
+
+    virtual void allGather(std::vector<int> &svalues, std::vector<int> &rvalues)                               = 0;
+    virtual void allGather(std::vector<float> &svalues, std::vector<float> &rvalues)                           = 0;
+    virtual void allGather(std::vector<double> &svalues, std::vector<double> &rvalues)                         = 0;
+    virtual void allGather(std::vector<unsigned long long> &svalues, std::vector<unsigned long long> &rvalues) = 0;
+
+    virtual void broadcast(int &value)                    = 0;
+    virtual void broadcast(float &value)                  = 0;
+    virtual void broadcast(double &value)                 = 0;
+    virtual void broadcast(long int &value)               = 0;
+    virtual void broadcast(std::vector<int> &values)      = 0;
+    virtual void broadcast(std::vector<float> &values)    = 0;
+    virtual void broadcast(std::vector<double> &values)   = 0;
+    virtual void broadcast(std::vector<long int> &values) = 0;
+
+protected:
+    Communicator() = default;
+
+    static std::mutex instantiation_mutex;
+
+    static std::shared_ptr<Communicator> instance;
+};
+
+}
+
+#endif
diff --git a/src/mpi/MPICommunicator.cpp b/src/mpi/MPICommunicator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4e7a155ef3b78f7daa0a582f84f2ef8af83886c8
--- /dev/null
+++ b/src/mpi/MPICommunicator.cpp
@@ -0,0 +1,174 @@
+#if defined VF_MPI
+
+#include "MPICommunicator.h"
+#include <mpi.h>
+
+#include <sstream>
+using namespace std;
+
+namespace vf::mpi 
+{
+std::shared_ptr<Communicator> MPICommunicator::getInstance()
+{
+    std::lock_guard<std::mutex> myLock(instantiation_mutex);
+    if (!instance){
+        instance = std::shared_ptr<MPICommunicator>(new MPICommunicator);
+    }
+    return instance;
+}
+//////////////////////////////////////////////////////////////////////////
+MPICommunicator::MPICommunicator()
+{
+    // proof if MPI is initialized
+    int mpiInitialized = 0; // false
+    MPI_Initialized(&mpiInitialized);
+    if (!mpiInitialized) {
+        MPI_Init(NULL, NULL);
+        // MPI_Init_thread(NULL, NULL, MPI_THREAD_FUNNELED, NULL);
+    }
+    MPI_Comm_rank(MPI_COMM_WORLD, &PID);
+    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
+    // numprocs = 1000;
+    comm = MPI_COMM_WORLD;
+    root = 0;
+}
+//////////////////////////////////////////////////////////////////////////
+MPICommunicator::~MPICommunicator()
+{
+    // proof if MPI is finalized
+    int _mpiFinalized = 0; // false
+    MPI_Finalized(&_mpiFinalized);
+    if (!_mpiFinalized) {
+        MPI_Finalize();
+        // UBLOG(logINFO, "MPI_Finalize()");
+    }
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::abort(int errorcode) { MPI_Abort(comm, errorcode); }
+////////////////////////////////////////////////////////////////////////////
+vector<string> MPICommunicator::gather(const string &str)
+{
+    vector<string> parts;
+    vector<string> strings;
+    int scount;
+    vector<char> rbuf(1);
+    vector<int> rcounts(1);
+    MPI_Status status;
+
+    if (PID == root) {
+        rcounts.resize(numprocs - 1);
+        strings.push_back(str);
+
+        for (int i = 1; i < numprocs; i++) {
+            MPI_Recv(&rcounts[i - 1], 1, MPI_INT, i, 0, comm, &status);
+        }
+        for (int i = 1; i < numprocs; i++) {
+            rbuf.resize(rcounts[i - 1]);
+            MPI_Recv(&rbuf[0], rcounts[i - 1], MPI_CHAR, i, 0, comm, &status);
+            string s(&rbuf[0], rcounts[i - 1]);
+            if (s != "")
+                strings.push_back(s);
+        }
+    } else {
+        scount = (int)str.length();
+        MPI_Send(&scount, 1, MPI_INT, root, 0, comm);
+        MPI_Send((char *)str.c_str(), scount, MPI_CHAR, root, 0, comm);
+    }
+    return strings;
+}
+//////////////////////////////////////////////////////////////////////////
+vector<int> MPICommunicator::gather(vector<int> &values) { return gather<int>(values); }
+//////////////////////////////////////////////////////////////////////////
+vector<float> MPICommunicator::gather(vector<float> &values) { return gather<float>(values); }
+//////////////////////////////////////////////////////////////////////////
+vector<double> MPICommunicator::gather(vector<double> &values) { return gather<double>(values); }
+//////////////////////////////////////////////////////////////////////////
+std::vector<unsigned long long> MPICommunicator::gather(std::vector<unsigned long long> &values)
+{
+    return gather<unsigned long long>(values);
+}
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getProcessID() { return PID; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getProcessID(int /*bundle*/, int /*rank*/) { return PID; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getNumberOfProcesses() { return numprocs; }
+//////////////////////////////////////////////////////////////////////////
+void *MPICommunicator::getNativeCommunicator() { return &comm; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getBundleID() { return 0; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getNumberOfBundles() { return 1; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getRoot() { return root; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getBundleRoot() { return 0; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getProcessRoot() { return 0; }
+//////////////////////////////////////////////////////////////////////////
+int MPICommunicator::getNumberOfProcessesInBundle(int /*bundle*/) { return numprocs; }
+//////////////////////////////////////////////////////////////////////////
+bool MPICommunicator::isRoot() { return PID == root; }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::sendSerializedObject(std::stringstream &ss, int target)
+{
+    string str = ss.str();
+    int scount = static_cast<int>(str.length());
+    MPI_Send(&scount, 1, MPI_INT, target, 0, comm);
+    MPI_Send((char *)str.c_str(), scount, MPI_CHAR, target, 0, comm);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::receiveSerializedObject(std::stringstream &ss, int source)
+{
+    vector<char> rbuf;
+    int rcount;
+    MPI_Status status;
+    MPI_Recv(&rcount, 1, MPI_INT, source, 0, comm, &status);
+    rbuf.resize(rcount);
+    MPI_Recv(&rbuf[0], rcount, MPI_CHAR, source, 0, comm, &status);
+    ss.rdbuf()->pubsetbuf(&rbuf[0], rcount);
+    string str(&rbuf[0]);
+    ss.str(str);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::barrier() { MPI_Barrier(comm); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::allGather(std::vector<int> &svalues, std::vector<int> &rvalues)
+{
+    allGather<int>(svalues, rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::allGather(std::vector<float> &svalues, std::vector<float> &rvalues)
+{
+    allGather<float>(svalues, rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::allGather(std::vector<double> &svalues, std::vector<double> &rvalues)
+{
+    allGather<double>(svalues, rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::allGather(std::vector<unsigned long long> &svalues, std::vector<unsigned long long> &rvalues)
+{
+    allGather<unsigned long long>(svalues, rvalues);
+}
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(std::vector<int> &values) { broadcast<int>(values); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(std::vector<float> &values) { broadcast<float>(values); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(std::vector<double> &values) { broadcast<double>(values); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(std::vector<long int> &values) { broadcast<long int>(values); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(int &value) { broadcast<int>(value); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(float &value) { broadcast<float>(value); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(double &value) { broadcast<double>(value); }
+//////////////////////////////////////////////////////////////////////////
+void MPICommunicator::broadcast(long int &value) { broadcast<long int>(value); }
+
+}
+
+#endif
\ No newline at end of file
diff --git a/src/mpi/MPICommunicator.h b/src/mpi/MPICommunicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..96d7e3593acb6d94706c9842f176e96c7a0e8969
--- /dev/null
+++ b/src/mpi/MPICommunicator.h
@@ -0,0 +1,209 @@
+#if defined VF_MPI
+
+#ifndef MPI_MPICOMMUNICATOR_H
+#define MPI_MPICOMMUNICATOR_H
+
+#include "Communicator.h"
+#include <PointerDefinitions.h>
+#include <basics/utilities/UbException.h>
+#include <basics/utilities/UbLogger.h>
+#include <mpi.h>
+#include <string>
+#include <vector>
+
+namespace vf::mpi 
+{
+
+//! \brief A class uses MPI library to communication.
+//! \details Support MPI communication. Implements singleton pattern.
+//! \author K. Kutscher
+class MPICommunicator : public Communicator
+{
+public:
+    MPICommunicator(MPICommunicator const&) = delete;
+    MPICommunicator& operator=(MPICommunicator const&) = delete;
+
+    ~MPICommunicator() override;
+    static std::shared_ptr<Communicator> getInstance();
+    int getBundleID() override;
+    int getNumberOfBundles() override;
+    int getProcessID() override;
+    int getProcessID(int bundle, int rank) override;
+    int getNumberOfProcesses() override;
+    void *getNativeCommunicator() override;
+    int getRoot() override;
+    int getBundleRoot() override;
+    int getProcessRoot() override;
+    int getNumberOfProcessesInBundle(int bundle) override;
+    bool isRoot() override;
+    void abort(int errorcode) override;
+
+    void sendSerializedObject(std::stringstream &ss, int target) override;
+    void receiveSerializedObject(std::stringstream &ss, int source) override;
+
+    void barrier() override;
+
+    std::vector<std::string> gather(const std::string &str) override;
+    std::vector<int> gather(std::vector<int> &values) override;
+    std::vector<float> gather(std::vector<float> &values) override;
+    std::vector<double> gather(std::vector<double> &values) override;
+    std::vector<unsigned long long> gather(std::vector<unsigned long long> &values) override;
+
+    void allGather(std::vector<int> &svalues, std::vector<int> &rvalues) override;
+    void allGather(std::vector<float> &svalues, std::vector<float> &rvalues) override;
+    void allGather(std::vector<double> &svalues, std::vector<double> &rvalues) override;
+    void allGather(std::vector<unsigned long long> &svalues, std::vector<unsigned long long> &rvalues) override;
+
+    void broadcast(int &value) override;
+    void broadcast(float &value) override;
+    void broadcast(double &value) override;
+    void broadcast(long int &value) override;
+    void broadcast(std::vector<int> &values) override;
+    void broadcast(std::vector<float> &values) override;
+    void broadcast(std::vector<double> &values) override;
+    void broadcast(std::vector<long int> &values) override;
+
+    template <class T>
+    std::vector<T> gather(std::vector<T> &values);
+
+    template <class T>
+    void allGather(std::vector<T> &svalues, std::vector<T> &rvalues);
+
+    template <class T>
+    void broadcast(std::vector<T> &values);
+
+    template <class T>
+    void broadcast(T &value);
+
+private:
+    MPICommunicator();
+
+    int numprocs, PID;
+    MPI_Comm comm;
+    int root;
+};
+
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+std::vector<T> MPICommunicator::gather(std::vector<T> &values)
+{
+    MPI_Datatype mpiDataType;
+    if ((std::string) typeid(T).name() == (std::string) typeid(double).name())
+        mpiDataType = MPI_DOUBLE;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(float).name())
+        mpiDataType = MPI_FLOAT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(int).name())
+        mpiDataType = MPI_INT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(unsigned long long).name())
+        mpiDataType = MPI_UNSIGNED_LONG_LONG;
+    else
+        throw UbException(UB_EXARGS, "no MpiDataType for T" + (std::string) typeid(T).name());
+
+    int count = static_cast<int>(values.size());
+    std::vector<T> rvalues(1);
+
+    if (PID == root) {
+        rvalues.resize(numprocs * count);
+    }
+
+    MPI_Gather(&values[0], count, mpiDataType, &rvalues[0], count, mpiDataType, root, comm);
+
+    return rvalues;
+}
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void MPICommunicator::allGather(std::vector<T> &svalues, std::vector<T> &rvalues)
+{
+    MPI_Datatype mpiDataType;
+    if ((std::string) typeid(T).name() == (std::string) typeid(double).name())
+        mpiDataType = MPI_DOUBLE;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(float).name())
+        mpiDataType = MPI_FLOAT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(int).name())
+        mpiDataType = MPI_INT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(unsigned long long).name())
+        mpiDataType = MPI_UNSIGNED_LONG_LONG;
+    else
+        throw UbException(UB_EXARGS, "no MpiDataType for T" + (std::string) typeid(T).name());
+
+    int scount;
+    std::vector<int> displs, rcounts;
+
+    scount = (int)(svalues.size());
+
+    rcounts.resize(numprocs);
+    MPI_Allgather(&scount, 1, MPI_INT, &rcounts[0], 1, MPI_INT, comm);
+    displs.resize(numprocs);
+
+    displs[0] = 0;
+    for (int i = 1; i < numprocs; ++i) {
+        displs[i] = displs[i - 1] + rcounts[i - 1];
+    }
+
+    rvalues.resize(displs[numprocs - 1] + rcounts[numprocs - 1]);
+
+    if (rvalues.size() == 0) {
+        rvalues.resize(1);
+        rvalues[0] = 999;
+    }
+    if (scount == 0) {
+        svalues.resize(1);
+        svalues[0] = 999;
+    }
+
+    MPI_Allgatherv(&svalues[0], scount, mpiDataType, &rvalues[0], &rcounts[0], &displs[0], mpiDataType, comm);
+}
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void MPICommunicator::broadcast(std::vector<T> &values)
+{
+    MPI_Datatype mpiDataType;
+    if ((std::string) typeid(T).name() == (std::string) typeid(double).name())
+        mpiDataType = MPI_DOUBLE;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(float).name())
+        mpiDataType = MPI_FLOAT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(int).name())
+        mpiDataType = MPI_INT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(long int).name())
+        mpiDataType = MPI_LONG_INT;
+    else
+        throw UbException(UB_EXARGS, "no MpiDataType for T" + (std::string) typeid(T).name());
+
+    int rcount;
+    if (this->PID == this->root) {
+        rcount = (int)values.size();
+    }
+
+    MPI_Bcast(&rcount, 1, MPI_INT, this->root, comm);
+
+    if (this->PID != this->root) {
+        values.resize(rcount);
+    }
+
+    MPI_Bcast(&values[0], (int)values.size(), mpiDataType, this->root, comm);
+}
+//////////////////////////////////////////////////////////////////////////
+template <class T>
+void MPICommunicator::broadcast(T &value)
+{
+    MPI_Datatype mpiDataType;
+    if ((std::string) typeid(T).name() == (std::string) typeid(double).name())
+        mpiDataType = MPI_DOUBLE;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(float).name())
+        mpiDataType = MPI_FLOAT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(int).name())
+        mpiDataType = MPI_INT;
+    else if ((std::string) typeid(T).name() == (std::string) typeid(long int).name())
+        mpiDataType = MPI_LONG_INT;
+    else
+        throw UbException(UB_EXARGS, "no MpiDataType for T" + (std::string) typeid(T).name());
+
+    MPI_Bcast(&value, 1, mpiDataType, this->root, comm);
+}
+//////////////////////////////////////////////////////////////////////////
+
+#endif
+
+}
+
+#endif
diff --git a/src/cpu/VirtualFluidsCore/Parallel/NullCommunicator.cpp b/src/mpi/NullCommunicator.cpp
similarity index 65%
rename from src/cpu/VirtualFluidsCore/Parallel/NullCommunicator.cpp
rename to src/mpi/NullCommunicator.cpp
index 287bd564723928228ea7e0e32fb4a861d61d3816..0f407d0dccab79b551e8671bcaa150f6aab36789 100644
--- a/src/cpu/VirtualFluidsCore/Parallel/NullCommunicator.cpp
+++ b/src/mpi/NullCommunicator.cpp
@@ -33,23 +33,43 @@
 
 #include "NullCommunicator.h"
 
-NullCommunicator::NullCommunicator() = default;
+namespace vf::mpi 
+{
+
+// std::shared_ptr<Communicator> NullCommunicator::getInstance()
+// {
+//     std::lock_guard<std::mutex> myLock(instantiation_mutex);
+//     if (!instance){
+//         instance = std::shared_ptr<NullCommunicator>(new NullCommunicator);
+//     }
+//     return instance;
+// }
 //////////////////////////////////////////////////////////////////////////
-NullCommunicator::~NullCommunicator() = default;
+int NullCommunicator::getBundleID() { return 0; }
 //////////////////////////////////////////////////////////////////////////
-SPtr<Communicator> NullCommunicator::getInstance()
-{
-    if (!Communicator::instance)
-        Communicator::instance = SPtr<Communicator>(new NullCommunicator());
-    return Communicator::instance;
-}
+int NullCommunicator::getNumberOfBundles() { return 0; }
 //////////////////////////////////////////////////////////////////////////
 int NullCommunicator::getProcessID() { return 0; }
 //////////////////////////////////////////////////////////////////////////
-int NullCommunicator::getNumberOfProcesses() { return 1; }
+int NullCommunicator::getNumberOfProcesses() { return 0; }
 //////////////////////////////////////////////////////////////////////////
-bool NullCommunicator::isRoot() { return true; }
+void *NullCommunicator::getNativeCommunicator() { return NULL; }
 //////////////////////////////////////////////////////////////////////////
 int NullCommunicator::getRoot() { return 0; }
 //////////////////////////////////////////////////////////////////////////
+int NullCommunicator::getBundleRoot() { return 0; }
+//////////////////////////////////////////////////////////////////////////
 int NullCommunicator::getProcessRoot() { return 0; }
+//////////////////////////////////////////////////////////////////////////
+std::vector<std::string> NullCommunicator::gather(const std::string & /*str*/) { return std::vector<std::string>(); }
+//////////////////////////////////////////////////////////////////////////
+std::vector<double> NullCommunicator::gatherDoubles(std::vector<double> & /*values*/) { return std::vector<double>(); }
+//////////////////////////////////////////////////////////////////////////
+void NullCommunicator::allGatherInts(std::vector<int> &svalues, std::vector<int> &rvalues) {}
+//////////////////////////////////////////////////////////////////////////
+void NullCommunicator::sendSerializedObject(std::stringstream &ss, int target) {}
+//////////////////////////////////////////////////////////////////////////
+void NullCommunicator::receiveSerializedObject(std::stringstream &ss, int source) {}
+
+
+}
diff --git a/src/cpu/VirtualFluidsCore/Parallel/NullCommunicator.h b/src/mpi/NullCommunicator.h
similarity index 79%
rename from src/cpu/VirtualFluidsCore/Parallel/NullCommunicator.h
rename to src/mpi/NullCommunicator.h
index 6c0ed0927cc4d62237b6d8b6f2aafae28068d6cb..1a3ba3eac5c840d8e6e6c474d7dec9dfe6be6750 100644
--- a/src/cpu/VirtualFluidsCore/Parallel/NullCommunicator.h
+++ b/src/mpi/NullCommunicator.h
@@ -31,32 +31,37 @@
 //! \author Konstantin Kutscher
 //=======================================================================================
 
-#ifndef NullCommunicator_H
-#define NullCommunicator_H
+#ifndef MPI_NullCommunicator_H
+#define MPI_NullCommunicator_H
 
 #include "Communicator.h"
 
-#include <PointerDefinitions.h>
+namespace vf::mpi 
+{
 
 //! \brief A class implements Communicator for shared memory.
 //! \details NullCommunicator is only a place-holder. It is only one process in shared memory.
 class NullCommunicator : public Communicator
 {
-private:
-    NullCommunicator();
-    NullCommunicator(const NullCommunicator &) {}
-
 public:
-    ~NullCommunicator() override;
-    static SPtr<Communicator> getInstance();
+    // static std::shared_ptr<Communicator> getInstance();
+    int getBundleID() override;
+    int getNumberOfBundles() override;
     int getProcessID() override;
     int getNumberOfProcesses() override;
-    bool isRoot() override;
+    void *getNativeCommunicator() override;
     int getRoot() override;
+    int getBundleRoot() override;
     int getProcessRoot() override;
+    std::vector<std::string> gather(const std::string &str) override;
+    std::vector<double> gatherDoubles(std::vector<double> &values);
+    void allGatherInts(std::vector<int> &svalues, std::vector<int> &rvalues);
+    void sendSerializedObject(std::stringstream &ss, int target) override;
+    void receiveSerializedObject(std::stringstream &ss, int source) override;
 
-protected:
-private:
+    
 };
 
+}
+
 #endif