diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3c90dae238aa7e57e02d1498681450af76cf6fd5..2ab53f79a493bf21105d41615ac99286c20baa9e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,6 +85,7 @@ endif ()
 # targets and settings needed to generate coverage reports
 if (CMAKE_BUILD_TYPE STREQUAL Coverage)
   find_package (Perl REQUIRED)
+
   set (GCOV gcov CACHE STRING "gcov executable" FORCE)
   set (LCOV_BIN_DIR "${PROJECT_SOURCE_DIR}/ThirdParty/lcov/bin")
   # collect coverage data
@@ -119,7 +120,6 @@ add_test (NAME clang_format COMMAND ./do-clang-format.sh check WORKING_DIRECTORY
 if (WITH_PYTHIA)
   find_package (Pythia8) # optional
 endif (WITH_PYTHIA)
-find_package (Eigen3 REQUIRED)
 
 # order of subdirectories
 add_subdirectory (ThirdParty)
@@ -134,3 +134,25 @@ add_subdirectory (Tools)
 if (WITH_COAST)
   add_subdirectory (COAST)
 endif ()
+
+# check for Eigen3: either use ThirdParty/eigen3 or system-level installation
+if (WITH_EIGEN3)
+  string (TOLOWER ${WITH_EIGEN3} WITH_EIGEN3_LOWER)
+  if (WITH_EIGEN3_LOWER EQUAL "system")
+    find_package (Eigen3 REQUIRED)
+  else ()
+    list (APPEND CMAKE_MODULE_PATH "${WITH_EIGEN3}/cmake")
+    set (EIGEN3_INCLUDE_DIR "${WITH_EIGEN3}" CACHE PATH "eigen3 directory") 
+    find_package (Eigen3 REQUIRED)
+  endif ()
+else (WITH_EIGEN3)
+  list (APPEND CMAKE_MODULE_PATH "${LOCAL_Eigen3_VERSION}/cmake")
+  set (EIGEN3_INCLUDE_DIR "${LOCAL_Eigen3_VERSION}" CACHE PATH "eigen3 directory")
+  find_package (Eigen3 REQUIRED)
+endif (WITH_EIGEN3)
+
+# some final info output
+message ("Use eigen3 version: ${EIGEN3_VERSION} from ${EIGEN3_INCLUDE_DIR}")
+
+include (FeatureSummary)
+feature_summary (WHAT ALL)
diff --git a/CMakeModules/CorsikaUtilities.cmake b/CMakeModules/CorsikaUtilities.cmake
index abe8e4a761cb30e0bbae0900258ab4817b22683d..090e26065dc987d602d28b246412574566e18ea2 100644
--- a/CMakeModules/CorsikaUtilities.cmake
+++ b/CMakeModules/CorsikaUtilities.cmake
@@ -126,30 +126,30 @@ endmacro(CORSIKA_ADD_FILES_ABSOLUTE)
 # TEMPORARY: All sanitizers are currently globally disabled by default, to enable them,
 # set CORSIKA_SANITIZERS_ENABLED to TRUE.
 function (CORSIKA_ADD_TEST)
-  cmake_parse_arguments(PARSE_ARGV 1 _ "" "SANITIZE" "SOURCES")
+  cmake_parse_arguments (PARSE_ARGV 1 _ "" "SANITIZE" "SOURCES")
 
-  set(name ${ARGV0})
+  set (name ${ARGV0})
 
   if (NOT __SOURCES)
-    set(sources ${name}.cc)
-  else()
-    set(sources ${__SOURCES})
-  endif()
+    set (sources ${name}.cc)
+  else ()
+    set (sources ${__SOURCES})
+  endif ()
 
   if (NOT __SANITIZE)
     set(sanitize "address,undefined")
-  else()
+  else ()
     set(sanitize ${__SANITIZE})
-  endif()
+  endif ()
 
-  add_executable(${name} ${sources})
-  target_compile_options(${name} PRIVATE -g) # do not skip asserts
+  add_executable (${name} ${sources})
+  target_compile_options (${name} PRIVATE -g) # do not skip asserts
   target_include_directories (${name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
   file (MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/test_outputs/)
   if (CORSIKA_SANITIZERS_ENABLED)
     # -O1 is suggested in clang docs to get reasonable performance
-    target_compile_options(${name} PRIVATE -O1 -fno-omit-frame-pointer -fsanitize=${sanitize} -fno-sanitize-recover=all)
-    set_target_properties(${name} PROPERTIES LINK_FLAGS "-fsanitize=${sanitize}")
-  endif()
+    target_compile_options (${name} PRIVATE -O1 -fno-omit-frame-pointer -fsanitize=${sanitize} -fno-sanitize-recover=all)
+    set_target_properties (${name} PROPERTIES LINK_FLAGS "-fsanitize=${sanitize}")
+  endif ()
   add_test (NAME ${name} COMMAND ${name} -o ${PROJECT_BINARY_DIR}/test_outputs/junit-${name}.xml -s -r junit)
 endfunction (CORSIKA_ADD_TEST)
diff --git a/CMakeModules/FindPythia8.cmake b/CMakeModules/FindPythia8.cmake
index 57aea3d0bb86f4a90a17e36cb0e18da5561ba309..324e6b9ab6d74bfccc7df8113107be878acb3443 100644
--- a/CMakeModules/FindPythia8.cmake
+++ b/CMakeModules/FindPythia8.cmake
@@ -21,7 +21,7 @@ function (_PYTHIA8_CONFIG_ option variable type doc)
   if (NOT ${_local_res_} EQUAL 0)
     message ("Error in running ${PYTHIA8_CONFIG} ${option}")
   else ()
-    set(${variable} "${_local_out_}" CACHE ${type} ${doc})
+    set (${variable} "${_local_out_}" CACHE ${type} ${doc})
   endif ()
 endfunction (_PYTHIA8_CONFIG_)
   
@@ -39,7 +39,7 @@ endfunction (_PYTHIA8_CONFIG_)
 # PYTHIA8_VERSION       version of Pythia8 if found
 #
 
-set(_SEARCH_PYTHIA8_
+set (_SEARCH_PYTHIA8_
   ${PROJECT_BINARY_DIR}/ThirdParty/pythia8-install
   ${PYTHIA8}
   $ENV{PYTHIA8}
@@ -51,23 +51,23 @@ set(_SEARCH_PYTHIA8_
   $ENV{PYTHIA8_ROOT}
   /opt/pythia8)
 
-find_program(PYTHIA8_CONFIG
+find_program (PYTHIA8_CONFIG
   NAME pythia8-config
   PATHS ${_SEARCH_PYTHIA8_}
   PATH_SUFFIXES "/bin"
   DOC "The location of the pythia8-config script")
 
 if (PYTHIA8_CONFIG)
-  set(HAVE_PYTHIA8 1 CACHE BOOL "presence of pythia8, found via pythia8-config")
+  set (HAVE_PYTHIA8 1 CACHE BOOL "presence of pythia8, found via pythia8-config")
 
-  _PYTHIA8_CONFIG_("--prefix" PYTHIA8_PREFIX PATH "location of pythia8 installation")
-  _PYTHIA8_CONFIG_("--includedir" PYTHIA8_INCLUDE_DIR PATH "pythia8 include directory")
-  _PYTHIA8_CONFIG_("--libs" PYTHIA8_LIBRARY STRING "the pythia8 libs")
-  _PYTHIA8_CONFIG_("--datadir" PYTHIA8_DATA_DIR PATH "the pythia8 data dir")
-  _PYTHIA8_CONFIG_("--cxxflags" PYTHIA8_CXXFLAGS STRING "the pythia8 cxxflags")
+  _PYTHIA8_CONFIG_ ("--prefix" PYTHIA8_PREFIX PATH "location of pythia8 installation")
+  _PYTHIA8_CONFIG_ ("--includedir" PYTHIA8_INCLUDE_DIR PATH "pythia8 include directory")
+  _PYTHIA8_CONFIG_ ("--libs" PYTHIA8_LIBRARY STRING "the pythia8 libs")
+  _PYTHIA8_CONFIG_ ("--datadir" PYTHIA8_DATA_DIR PATH "the pythia8 data dir")
+  _PYTHIA8_CONFIG_ ("--cxxflags" PYTHIA8_CXXFLAGS STRING "the pythia8 cxxflags")
 endif ()
 
 # standard cmake infrastructure:
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Pythia8 DEFAULT_MSG PYTHIA8_PREFIX PYTHIA8_INCLUDE_DIR PYTHIA8_LIBRARY)
-mark_as_advanced(PYTHIA8_DATA_DIR PYTHIA8_CXXFLAGS PYTHIA8_INCLUDE_DIR PYTHIA8_LIBRARY)
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (Pythia8 DEFAULT_MSG PYTHIA8_PREFIX PYTHIA8_INCLUDE_DIR PYTHIA8_LIBRARY)
+mark_as_advanced (PYTHIA8_DATA_DIR PYTHIA8_CXXFLAGS PYTHIA8_INCLUDE_DIR PYTHIA8_LIBRARY)
diff --git a/Framework/Geometry/CMakeLists.txt b/Framework/Geometry/CMakeLists.txt
index c8e80d31ca74928744bd4113dda7e5771bea734b..39d4fb9844230b0aec94dcc207caadc285dc5b20 100644
--- a/Framework/Geometry/CMakeLists.txt
+++ b/Framework/Geometry/CMakeLists.txt
@@ -46,8 +46,7 @@ target_link_libraries (
 target_include_directories (
   CORSIKAgeometry
   SYSTEM
-  PUBLIC    ${EIGEN3_INCLUDE_DIR}
-  INTERFACE ${EIGEN3_INCLUDE_DIR}
+  PUBLIC ${EIGEN3_INCLUDE_DIR}
   )
 
 target_include_directories (
diff --git a/ThirdParty/.gitignore b/ThirdParty/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b4bac0ecf395dd655e583e048902f92da63774ce
--- /dev/null
+++ b/ThirdParty/.gitignore
@@ -0,0 +1,2 @@
+eigen-eigen-b3f3d4950030/
+
diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt
index 4eb0c17439854330bd88ee7c3589ca2c0cddf07d..f33a2f516deba04e8dee556b0e18c28cabe69f2c 100644
--- a/ThirdParty/CMakeLists.txt
+++ b/ThirdParty/CMakeLists.txt
@@ -9,4 +9,18 @@ target_include_directories (CORSIKAthirdparty SYSTEM
 
 install (DIRECTORY phys DESTINATION include/ThirdParty/)
 install (DIRECTORY catch2 DESTINATION include/ThirdParty/)
-install (DIRECTORY boost DESTINATION include/ThirdParty/boost/)
\ No newline at end of file
+install (DIRECTORY boost DESTINATION include/ThirdParty/boost/)
+
+if (NOT WITH_EIGEN3)
+  set (_LOCAL_Eigen3_VERSION "eigen-eigen-b3f3d4950030")
+  if ("${CMAKE_CURRENT_SOURCE_DIR}/${_LOCAL_Eigen3_VERSION}.tar.bz2"
+      IS_NEWER_THAN
+      "${CMAKE_CURRENT_SOURCE_DIR}/${_LOCAL_Eigen3_VERSION}")
+    message ("Unpacking ThirdParty/eigen3")
+    execute_process (
+      COMMAND ${CMAKE_COMMAND} -E tar xjf ${_LOCAL_Eigen3_VERSION}.tar.bz2
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+      )
+  endif ()
+  set (LOCAL_Eigen3_VERSION ${CMAKE_CURRENT_SOURCE_DIR}/eigen-eigen-b3f3d4950030 PARENT_SCOPE)
+endif (NOT WITH_EIGEN3)
diff --git a/ThirdParty/eigen-eigen-b3f3d4950030.tar b/ThirdParty/eigen-eigen-b3f3d4950030.tar
deleted file mode 100644
index 4c050d1cc7e51abd98fc0c03b81b350c87b2b5f3..0000000000000000000000000000000000000000
Binary files a/ThirdParty/eigen-eigen-b3f3d4950030.tar and /dev/null differ
diff --git a/ThirdParty/eigen-eigen-b3f3d4950030.tar.bz2 b/ThirdParty/eigen-eigen-b3f3d4950030.tar.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..f7571b34f31468787f82a953029475b9896796a4
Binary files /dev/null and b/ThirdParty/eigen-eigen-b3f3d4950030.tar.bz2 differ
diff --git a/ThirdParty/pythia8235.tgz b/ThirdParty/pythia8235.tar.bz2
similarity index 63%
rename from ThirdParty/pythia8235.tgz
rename to ThirdParty/pythia8235.tar.bz2
index 552398c41da544421f187f0a5cf78f3739a1ee1d..ec450fc8bfde5e06b10d2353774d48413f6ac1f7 100644
Binary files a/ThirdParty/pythia8235.tgz and b/ThirdParty/pythia8235.tar.bz2 differ