IAP GITLAB

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AirShowerPhysics/corsika
  • rulrich/corsika
  • AAAlvesJr/corsika
  • Andre/corsika
  • arrabito/corsika
  • Nikos/corsika
  • olheiser73/corsika
  • AirShowerPhysics/papers/corsika
  • pranav/corsika
9 results
Show changes
Showing
with 2006 additions and 30 deletions
#
# (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
#
# See file AUTHORS for a list of contributors.
#
# This software is distributed under the terms of the 3-clause BSD license.
# See file LICENSE for a full version of the license.
#
# - find Conex
#
# This module defines
# CONEX_PREFIX
# CONEX_INCLUDE_DIR
# CONEX_LIBRARY
set (SEARCH_conex_
${WITH_CONEX}
${CONEXROOT}
${CONEX_ROOT}
$ENV{CONEXROOT}
$ENV{CONEX_ROOT}
)
find_path (CONEX_PREFIX
NAMES lib/${CMAKE_SYSTEM_NAME}
PATHS ${SEARCH_conex_}
DOC "The CONEX root directory"
NO_DEFAULT_PATH
)
find_path (CONEX_INCLUDE_DIR
NAMES ConexDynamicInterface.h
PATHS ${CONEX_PREFIX}
PATH_SUFFIXES src
DOC "The CONEX include directory"
)
find_library (CONEX_LIBRARY
NAMES libCONEXdynamic.a
PATHS ${CONEX_PREFIX}
PATH_SUFFIXES lib/${CMAKE_SYSTEM_NAME}
DOC "The CONEX library"
)
# standard cmake infrastructure:
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (CONEX
"Did not find system-level CONEX."
CONEX_INCLUDE_DIR CONEX_LIBRARY CONEX_PREFIX)
mark_as_advanced (CONEX_INCLUDE_DIR CONEX_LIBRARY CONEX_PREFIX)
#
# (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
#
# See file AUTHORS for a list of contributors.
#
# This software is distributed under the terms of the 3-clause BSD license.
# See file LICENSE for a full version of the license.
#
add_library (PhysUnits INTERFACE)
target_compile_options (PhysUnits
INTERFACE
-I${CMAKE_SOURCE_DIR}/externals/phys_units
)
set (PhysUnits_FOUND True)
#
# (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
#
# See file AUTHORS for a list of contributors.
#
# This software is distributed under the terms of the 3-clause BSD license.
# See file LICENSE for a full version of the license.
#
#################################################
#
# run pythia8-config and interpret result
#
function (_Pythia8_CONFIG_ option variable type doc)
execute_process (COMMAND ${Pythia8_CONFIG} ${option}
OUTPUT_VARIABLE _local_out_
RESULT_VARIABLE _local_res_)
string (REGEX REPLACE "\n$" "" _local_out_ "${_local_out_}")
if (NOT ${_local_res_} EQUAL 0)
message ("Error in running ${Pythia8_CONFIG} ${option}")
else ()
set (${variable} "${_local_out_}" CACHE ${type} ${doc})
endif ()
endfunction (_Pythia8_CONFIG_)
#################################################
#
# take directory and assume standard install layout
#
function (_Pythia8_LAYOUT_ dir variable type doc)
set (${variable} "${dir}" CACHE ${type} ${doc})
endfunction (_Pythia8_LAYOUT_)
#################################################
#
# Searched Pythia8 on system. Expect pythia8-config in PATH, or typical installation location
#
# This module defines
# HAVE_Pythia8
# Pythia8_INCLUDE_DIR where to locate Pythia.h file
# Pythia8_LIBRARY where to find the libpythia8 library
# Pythia8_LIBRARIES (not cached) the libraries to link against to use Pythia8
# Pythia8_VERSION version of Pythia8 if found
#
set (_SEARCH_Pythia8_
${PROJECT_BINARY_DIR}/ThirdParty/pythia8-install
${PYTHIA8}
$ENV{PYTHIA8}
${PYTHIA8DIR}
$ENV{PYTHIA8DIR}
${PYTHIA8_ROOT}
$ENV{PYTHIA8_ROOT}
${PYTHIA8_DIR}
$ENV{PYTHIA8_DIR}
${Pythia8_DIR}
$ENV{Pythia8_DIR}
/opt/pythia8
)
find_file (Pythia8_Pythia_h_LOC
NAME Pythia.h
PATHS ${_SEARCH_Pythia8_}
PATH_SUFFIXES include/Pythia8
DOC "The location of the Pythia8/Pythia.h script"
REQUIRED)
if ("${Pythia8_Pythia_h_LOC}" STREQUAL "Pythia8_Pythia_h_LOC-NOTFOUND")
message (FATAL_ERROR "Did not find SYSTEM-level Pythia8 in: \"${_SEARCH_Pythia8_}\"")
endif ()
string (REPLACE "/include/Pythia8/Pythia.h" "" Pythia8_DIR ${Pythia8_Pythia_h_LOC})
set (Pythia8_CONFIG ${Pythia8_DIR}/bin/pythia-config)
if (Pythia8_CONFIG)
set (HAVE_Pythia8 1 CACHE BOOL "presence of pythia8, found via pythia8-config")
# pythia-config is not relocatable
#_Pythia8_CONFIG_ ("--prefix" Pythia8_PREFIX PATH "location of pythia8 installation")
#_Pythia8_CONFIG_ ("--includedir" Pythia8_INCLUDE_DIR PATH "pythia8 include directory")
#_Pythia8_CONFIG_ ("--libdir" Pythia8_LIBRARY STRING "the pythia8 libs")
#_Pythia8_CONFIG_ ("--datadir" Pythia8_DATA_DIR PATH "the pythia8 data dir")
_Pythia8_LAYOUT_ ("${Pythia8_DIR}" Pythia8_PREFIX PATH "location of pythia8 installation")
_Pythia8_LAYOUT_ ("${Pythia8_DIR}/include" Pythia8_INCLUDE_DIR PATH "pythia8 include directory")
_Pythia8_LAYOUT_ ("${Pythia8_DIR}/lib" Pythia8_LIBRARY STRING "the pythia8 libs")
_Pythia8_LAYOUT_ ("${Pythia8_DIR}/share/Pythia8/xmldoc" Pythia8_DATA_DIR PATH "the pythia8 data dir")
# read the config string
file (READ "${Pythia8_INCLUDE_DIR}/Pythia8/Pythia.h" Pythia8_TMP_PYTHIA_H)
string (REGEX MATCH "#define PYTHIA_VERSION_INTEGER ([0-9]*)" _ ${Pythia8_TMP_PYTHIA_H})
set (Pythia8_VERSION ${CMAKE_MATCH_1})
message (STATUS "Found Pythia8 version: ${Pythia8_VERSION}")
endif ()
# standard cmake infrastructure:
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (Pythia8 REQUIRED_VARS Pythia8_PREFIX Pythia8_INCLUDE_DIR Pythia8_LIBRARY VERSION_VAR Pythia8_VERSION)
mark_as_advanced (Pythia8_DATA_DIR Pythia8_INCLUDE_DIR Pythia8_LIBRARY)
#
# (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
#
# See file AUTHORS for a list of contributors.
#
# This software is distributed under the terms of the 3-clause BSD license.
# See file LICENSE for a full version of the license.
#
# Look for an executable called sphinx-build
find_program (SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include (FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args (Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
#
# (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
#
# See file AUTHORS for a list of contributors.
#
# This software is distributed under the terms of the 3-clause BSD license.
# See file LICENSE for a full version of the license.
#
set (CORSIKA8_VERSION @c8_version@)
@PACKAGE_INIT@
#+++++++++++++++++++++++++++++
# Setup hardware and infrastructure dependent defines and other setting
#
include (${CMAKE_CURRENT_LIST_DIR}/corsikaDefines.cmake)
#+++++++++++++++++++++++++++
# Options
#
option (WITH_HISTORY "Flag to switch on/off HISTORY" ON)
#++++++++++++++++++++++++++++
# General config and flags
#
set (CMAKE_CXX_STANDARD @CMAKE_CXX_STANDARD@)
set (CMAKE_CXX_EXTENSIONS @CMAKE_CXX_EXTENSIONS@)
set (COMPILE_OPTIONS @COMPILE_OPTIONS@)
set (CMAKE_VERBOSE_MAKEFILE @CMAKE_VERBOSE_MAKEFILE@)
#+++++++++++++++++++++++++++++
# external dependencies
# same list as top-level CML.txt, except for Catch2 (not needed here)
#
find_package(Boost COMPONENTS filesystem REQUIRED)
find_package(CLI11 REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(spdlog REQUIRED)
find_package(yaml-cpp REQUIRED)
find_package(Arrow REQUIRED)
find_package(PROPOSAL REQUIRED)
#+++++++++++++++++++++++++++++
# Import Pythia8
# since we always import pythia (ExternalProject_Add) we have to
# import here, too.
#
add_library (C8::ext::pythia8 STATIC IMPORTED GLOBAL)
set_target_properties (
C8::ext::pythia8 PROPERTIES
IMPORTED_LOCATION @Pythia8_LIBDIR@/libpythia8.a
IMPORTED_LINK_INTERFACE_LIBRARIES dl
INTERFACE_INCLUDE_DIRECTORIES @Pythia8_INCDIR@
)
set (Pythia8_FOUND @Pythia8_FOUND@)
message (STATUS "Pythia8 at: @Pythia8_PREFIX@")
#+++++++++++++++++++++++++++++
# Import TAUOLA
# since we always import TAUOLA (ExternalProject_Add) we have to
# import here, too.
#
add_library (C8::ext::tauola::CxxInterface STATIC IMPORTED GLOBAL)
add_library (C8::ext::tauola::Fortran STATIC IMPORTED GLOBAL)
add_library(C8::ext::tauola INTERFACE IMPORTED)
set_property(TARGET C8::ext::tauola
PROPERTY
INTERFACE_LINK_LIBRARIES
C8::ext::tauola::CxxInterface
C8::ext::tauola::Fortran)
set_target_properties (
C8::ext::tauola::CxxInterface PROPERTIES
IMPORTED_LOCATION @TAUOLA_LIBDIR@/libTauolaCxxInterface.a
IMPORTED_LINK_INTERFACE_LIBRARIES dl
INTERFACE_INCLUDE_DIRECTORIES @TAUOLA_INCDIR@
)
set_target_properties (
C8::ext::tauola::Fortran PROPERTIES
IMPORTED_LOCATION @TAUOLA_LIBDIR@/libTauolaFortran.a
IMPORTED_LINK_INTERFACE_LIBRARIES dl
INTERFACE_INCLUDE_DIRECTORIES @TAUOLA_INCDIR@
)
set (TAUOLA_FOUND @TAUOLA_FOUND@)
message (STATUS "TAUOLA at: @TAUOLA_PREFIX@")
#++++++++++++++++++++++++++++++
# import CORSIKA8
#
include ("${CMAKE_CURRENT_LIST_DIR}/corsikaTargets.cmake")
check_required_components (corsika)
#+++++++++++++++++++++++++++++++
# add further definitions / options
#
if (WITH_HISTORY)
set_property (
TARGET CORSIKA8::CORSIKA8
APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS "WITH_HISTORY"
)
endif (WITH_HISTORY)
#+++++++++++++++++++++++++++++++
#
# final summary output
#
include (FeatureSummary)
add_feature_info (HISTORY WITH_HISTORY "Full information on cascade history for particles.")
feature_summary (WHAT ALL)
#
# (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
#
# See file AUTHORS for a list of contributors.
#
# This software is distributed under the terms of the 3-clause BSD license.
# See file LICENSE for a full version of the license.
#
#+++++++++++++++++++++++++++++
# as long as there still are modules using it:
#
enable_language (Fortran)
set (CMAKE_Fortran_FLAGS "-std=legacy -Wfunction-elimination")
#+++++++++++++++++++++++++++++
# Build types settings
#
# setup coverage build type
set (CMAKE_CXX_FLAGS_COVERAGE "-g --coverage")
set (CMAKE_EXE_LINKER_FLAGS_COVERAGE "--coverage")
set (CMAKE_SHARED_LINKER_FLAGS_COVERAGE "--coverage")
# set a flag to inform code that we are in debug mode
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_C8_DEBUG_")
#+++++++++++++++++++++++++++++
# Build type selection
#
# Set the possible values of build type for cmake-gui and command line check
set (ALLOWED_BUILD_TYPES Debug Release MinSizeRel RelWithDebInfo Coverage)
set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${ALLOWED_BUILD_TYPES})
set (DEFAULT_BUILD_TYPE "Release")
if (EXISTS "${CMAKE_SOURCE_DIR}/.git")
set (DEFAULT_BUILD_TYPE "Debug")
endif ()
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message (STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as no other was specified.")
set (CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE
STRING "Choose the type of build." FORCE)
else (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
# Ignore capitalization when build type is selected manually and check for valid setting
string (TOLOWER ${CMAKE_BUILD_TYPE} SELECTED_LOWER)
string (TOLOWER "${ALLOWED_BUILD_TYPES}" BUILD_TYPES_LOWER)
if (NOT SELECTED_LOWER IN_LIST BUILD_TYPES_LOWER)
message (FATAL_ERROR "Unknown build type: ${CMAKE_BUILD_TYPE} [allowed: ${ALLOWED_BUILD_TYPES}]")
endif ()
message (STATUS "Build type is: ${CMAKE_BUILD_TYPE}")
endif (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
#
# Floating point exception support - select implementation to use
#
include (CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX ("fenv.h" HAS_FEENABLEEXCEPT)
if (HAS_FEENABLEEXCEPT) # FLOATING_POINT_ENVIRONMENT
set (CORSIKA_HAS_FEENABLEEXCEPT 1)
set_property (DIRECTORY ${CMAKE_HOME_DIRECTORY} APPEND PROPERTY COMPILE_DEFINITIONS "CORSIKA_HAS_FEENABLEEXCEPT")
endif ()
#
# General OS Detection
#
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set (CORSIKA_OS_WINDOWS TRUE)
set (CORSIKA_OS "Windows")
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set (CORSIKA_OS_LINUX TRUE)
set (CORSIKA_OS "Linux")
# check for RedHat/CentOS compiler from the software collections (scl)
string (FIND ${CMAKE_CXX_COMPILER} "/opt/rh/devtoolset-" index)
if (${index} EQUAL 0)
set (CORSIKA_SCL_CXX TRUE)
endif ()
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set (CORSIKA_OS_MAC TRUE)
set (CORSIKA_OS "Mac")
endif ()
#
# (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
#
# See file AUTHORS for a list of contributors.
#
# This software is distributed under the terms of the 3-clause BSD license.
# See file LICENSE for a full version of the license.
#
#################################################
#
# central macro to register unit tests in cmake
#
# 1) Simple use:
# Pass the name of the test.cc file as the first
# argument, without the ".cc" extention.
#
# Example: CORSIKA_ADD_TEST (testSomething)
#
# This generates target testSomething from file testSomething.cc.
#
# 2) Customize sources:
# If 1) doesn't work, use the SOURCES keyword to explicitly
# specify the sources.
#
# Example: CORSIKA_ADD_TEST (testSomething
# SOURCES source1.cc source2.cc someheader.h)
#
# 3) Customize sanitizers:
# You can override which sanitizers are compiled into the
# test, but only do this if the defaults do not work.
#
# Example: CORSIKA_ADD_TEST (testSomething SANITIZE undefined)
#
# Only uses the sanitizer for undefined behavior.
#
# In all cases, you can further customize the target with
# target_link_libraries(testSomething ...) and so on.
#
# 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 C8_ADD_TEST "" "SANITIZE" "SOURCES")
set (name ${ARGV0})
if (NOT C8_ADD_TEST_SOURCES)
set (sources ${name}.cc)
else ()
set (sources ${C8_ADD_TEST_SOURCES})
endif ()
if (NOT C8_ADD_TEST_SANITIZE)
set(sanitize "address,undefined")
else ()
set(sanitize ${C8_ADD_TEST_SANITIZE})
endif ()
find_package(Catch2 REQUIRED)
add_executable (${name} ${sources})
target_link_libraries (${name} CORSIKA8 Catch2::Catch2WithMain CorsikaTestingCommon)
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 ()
add_test (NAME ${name} COMMAND ${name} -o ${PROJECT_BINARY_DIR}/test_outputs/junit-${name}.xml -s -r junit)
endfunction (CORSIKA_ADD_TEST)
#!/bin/bash
function show_usage(){
printf "\n\nUsage:"
printf "$0 options [parameters]\n"
printf "\n"
printf "Options:\n"
printf "\n -s or --source-directory:\n Corsika 8 download directory, which contains the 'conanfile.py' recipe. Default is the current directory."
printf "\n -d or --debug:\n Specify 'Debug' as build type for the installed dependences. This should be matched when building CORSIKA 8."
printf "\n -r or --release:\n Specify 'Release' as build type for the installed dependences. This should be matched when building CORSIKA 8."
printf "\n -rd or --release-with-debug:\n Specify 'RelWithDebInfo' as build type for the installed dependences. This should be matched when building CORSIKA 8."
printf "\n\nExample: ./conan-install.sh --source-directory /some_path/corsika --debug"
printf "\n -h or --help:\n Prints this message.\n"
exit 0
}
echo "|---------------------------------------------------|"
echo "|-----------------[ CORSIKA 8 ]---------------------|"
echo "|-----[ CONAN2 DEPENDENCIES INSTALL SCRIPT ]------- |"
echo "|---------------------------------------------------|"
echo "|-------------------- BEGIN ------------------------| "
echo " "
SOURCE=${BASH_SOURCE[0]}
while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
SOURCE=$(readlink "$SOURCE")
[[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
SCRIPT_DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
BUILD_TYPE="RelWithDebInfo"
CORSIKA_DIR=${CURRENT_DIR}
CORSIKA_DIR_INFORMED=${CURRENT_DIR}
CONAN2_OUTPUT_FOLDER_NAME="conan_cmake"
printf "[ conan-install | info > This script is located at the directory: ${SCRIPT_DIR}\n"
if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]];then
show_usage
fi
while [ ! -z "$1" ]; do
case "$1" in
--source-directory|-s)
shift
CORSIKA_DIR=$(readlink -e ${1})
CORSIKA_DIR_INFORMED=${1}
;;
--debug|-d)
#shift
BUILD_TYPE="Debug"
;;
--release|-r)
#shift
BUILD_TYPE="Release"
;;
--release-with-debug|-rd)
#shift
BUILD_TYPE="RelWithDebInfo"
;;
--help|-h)
#shift
show_usage
;;
*)
show_usage
;;
esac
if [ $# -gt 0 ]; then
shift
fi
done
if [[ ${#CORSIKA_DIR} -eq 0 ]]; then
printf "[ conan-install | warning > Output folder for cmake scripts generated by conan2 not found.\n"
printf "[ conan-install | warning > Directory '${CORSIKA_DIR_INFORMED}' does not exist.\n"
exit 1
fi
if [ -d "${CORSIKA_DIR}/${CONAN2_OUTPUT_FOLDER_NAME}" ]; then
printf "[ conan-install | info > Output folder for cmake scripts generated by conan2 is: ${CORSIKA_DIR}/${CONAN2_OUTPUT_FOLDER_NAME}\n"
else
printf "[ conan-install | warning > Output folder for cmake scripts generated by conan2 not found.\n"
printf "[ conan-install | warning > Creating directory ${CORSIKA_DIR}/${CONAN2_OUTPUT_FOLDER_NAME}.\n"
mkdir -p "${CORSIKA_DIR}/${CONAN2_OUTPUT_FOLDER_NAME}"
fi
if [ -f "${CORSIKA_DIR}/conanfile.py" ]; then
printf "[ conan-install | info > conan2 recipe: ${CORSIKA_DIR}/conanfile.py\n"
else
printf "[ conan-install | warning > conan2 recipe not found.\n"
printf "[ conan-install | warning > File '${CORSIKA_DIR}/conanfile.py' does not exist.\n"
exit 1
fi
# Conan2 variabes
CONAN2_HOME=$(readlink -e `conan config home`)
CONAN2_PROFILE_NAME="corsika8"
printf "[ conan-install | info > conan2 home: ${CONAN2_HOME}\n"
# Conan2 commands
CONAN2_DEFAULT_PROFILE_COMMAND="conan profile detect --force"
CONAN2_PROFILE_COMMAND="conan profile detect --name ${CONAN2_PROFILE_NAME} --force"
CONAN2_INSTALL_COMMAND="conan install ${CORSIKA_DIR} --output-folder=${CORSIKA_DIR}/${CONAN2_OUTPUT_FOLDER_NAME} --build=missing --settings=build_type=${BUILD_TYPE} --profile=${CONAN2_PROFILE_NAME}"
CONAN2_SHOW_PROFLE_COMMAND="conan profile show -pr ${CONAN2_PROFILE_NAME}"
printf "[ conan-install | info > Creating default profile...\n\n"
eval $CONAN2_DEFAULT_PROFILE_COMMAND
if [ ! $? -eq 0 ]; then
printf "[ conan-install | error > Exit code 126 (Command invoked cannot execute):\n ${CONAN2_DEFAULT_PROFILE_COMMAND}.\n"
exit 126
fi
printf "[ conan-install | info > Creating '${CONAN2_PROFILE_NAME}' profile...\n\n"
eval $CONAN2_PROFILE_COMMAND
if [ ! $? -eq 0 ]; then
printf "[ conan-install | error > Exit code 126 (Command invoked cannot execute):\n ${CONAN2_PROFILE_COMMAND}.\n"
exit 126
fi
printf "\n\n[ conan-install | info > Editing '${CONAN2_PROFILE_NAME}' profile\n"
#========== cppstd setting ============
STD_NUMBER=`grep -n -m 1 "compiler.cppstd=" ${CONAN2_HOME}/profiles/${CONAN2_PROFILE_NAME} | cut -d: -f1`
SED_STD_COMMAND="sed -i '${STD_NUMBER}s/.*/compiler.cppstd=gnu17/' ${CONAN2_HOME}/profiles/${CONAN2_PROFILE_NAME}"
eval $SED_STD_COMMAND
if [ ! $? -eq 0 ]; then
printf "[ conan-install | error > Exit code 126 (Command invoked cannot execute):\n ${SED_STD_COMMAND}\n"
exit 126
fi
#========== libcxx setting ============
CXX_NUMBER=`grep -n -m 1 "compiler.libcxx=" ${CONAN2_HOME}/profiles/${CONAN2_PROFILE_NAME} | cut -d: -f1`
SED_CXX_COMMAND="sed -i '${CXX_NUMBER}s/.*/compiler.libcxx=libstdc++11/' ${CONAN2_HOME}/profiles/${CONAN2_PROFILE_NAME}"
eval $SED_CXX_COMMAND
if [ ! $? -eq 0 ]; then
printf "[ conan-install | error > Exit code 126 (Command invoked cannot execute):\n ${SED_CXX_COMMAND}\n"
exit 126
fi
eval $CONAN2_SHOW_PROFLE_COMMAND
if [ ! $? -eq 0 ]; then
printf "[ conan-install | error > Exit code 126 (Command invoked cannot execute):\n ${CONAN2_SHOW_PROFLE_COMMAND}\n"
exit 126
fi
printf "[ conan-install | info > ${CONAN2_INSTALL_COMMAND}\n"
eval ${CONAN2_INSTALL_COMMAND}
if [ ! $? -eq 0 ]; then
printf "[ conan-install | error > Exit code 126 (Command invoked cannot execute):\n ${CONAN2_INSTALL_COMMAND}\n"
exit 126
fi
CORSIKA_CMAKE_SCRIPT="#!/bin/bash
function show_usage(){
printf \"\n\nUsage:\"
printf \"\$0 options [parameters]\n\"
printf \"\n\"
printf \"Options:\n\"
printf \"\n -c or --cmake-flags:\n Additional flags and settings to cmake base command. Default is empty string.\"
printf \"\n\nExample: ./corsika-cmake.sh --cmake-flags '-DUSE_Pythia8_C8=C8' \"
printf \"\n\nNote: the source directory (the one containing CMakeLists.txt), CMAKE_BUILD_TYPE, CMAKE_POLICY_DEFAULT_CMP0091 and CMAKE_TOOLCHAIN_FILE are already set. Do not repeat them.\"
printf \"\n -h or --help:\n Prints this message.\n\"
exit 0
}
echo \"|---------------------------------------------------|\"
echo \"|-----------------[ CORSIKA 8 ]---------------------|\"
echo \"|----------[ CMAKE CONFIGURATION SCRIPT ]---------- |\"
echo \"|---------------------------------------------------|\"
echo \"|-------------------- BEGIN ------------------------|\"
CMAKE_BASE_SETTINGS=\"cmake -S ${CORSIKA_DIR} -D CONAN_CMAKE_DIR=${CORSIKA_DIR}/${CONAN2_OUTPUT_FOLDER_NAME} -D CMAKE_TOOLCHAIN_FILE=${CORSIKA_DIR}/${CONAN2_OUTPUT_FOLDER_NAME}/conan_toolchain.cmake -D CMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=${BUILD_TYPE}\"
CMAKE_ADDITIONAL_SETTINGS=\"\"
if [[ \"\$1\" == \"--help\" ]] || [[ \"\$1\" == \"-h\" ]];then
show_usage
fi
while [ ! -z \"\$1\" ]; do
case \"\$1\" in
--cmake-flags|-c)
shift
CMAKE_ADDITIONAL_SETTINGS=\${1}
;;
--help|-h)
#shift
show_usage
;;
*)
show_usage
;;
esac
if [ \$# -gt 0 ]; then
shift
fi
done
printf \"[corsika-cmake | info > Issuing CMake command :\n\"
printf '[corsika-cmake | info > \e[1;36m%s\e[0m\n\n\n' \"\${CMAKE_BASE_SETTINGS} \${CMAKE_ADDITIONAL_SETTINGS}\"
eval \"\${CMAKE_BASE_SETTINGS} \${CMAKE_ADDITIONAL_SETTINGS}\"
if [ ! \$? -eq 0 ]; then
printf \"[ corsika | error > Project configuration (CMake) failed. \n\"
exit 1
fi
echo \"|---------------------------------------------------|\"
echo \"|-----------------[ CORSIKA 8 ]---------------------|\"
echo \"|----------[ CMAKE CONFIGURATION SCRIPT ]---------- |\"
echo \"|---------------------------------------------------|\"
echo \"|-------------------- END --------------------------|\"
"
printf "%s" "${CORSIKA_CMAKE_SCRIPT}" > ${SCRIPT_DIR}/corsika-cmake.sh
chmod +x ${SCRIPT_DIR}/corsika-cmake.sh
printf "\n\n[ conan-install | info > Copy and paste the commands below in the corsika-build directory:\n\n"
printf '\e[1;36m%s\e[0m\n' "> ${SCRIPT_DIR}/corsika-cmake.sh "
printf '\e[1;36m%s\e[0m\n' "> make -j8"
echo " "
echo "|---------------------------------------------------|"
echo "|-----------------[ CORSIKA 8 ]---------------------|"
echo "|-----[ CONAN2 DEPENDENCIES INSTALL SCRIPT ]------- |"
echo "|---------------------------------------------------|"
echo "|-------------------- END --------------------------| "
echo " "
exit 0
from conan import ConanFile
from conan.tools.cmake import cmake_layout,CMakeToolchain, CMakeDeps
class Pkg(ConanFile):
generators = "CMakeDeps", #"CMakeToolchain",
settings = "os", "arch", "compiler", "build_type"
default_options = {
'readline*:shared': 'True',
'arrow*:shared': 'False',
'arrow*:parquet': 'True',
'arrow*:fPIC': 'False',
'arrow*:with_re2': 'True',
'arrow*:with_protobuf': 'False',
'arrow*:with_openssl': 'False',
'arrow*:with_gflags': 'False',
'arrow*:with_glog': 'False',
'arrow*:with_grpc': 'False',
'arrow*:with_utf8proc': 'False',
'arrow*:with_zstd': 'False',
'arrow*:with_bz2': 'False',
'arrow*:with_lz4': 'True',
'arrow*:with_thrift': 'True',
'arrow*:with_boost': 'True',
'boost*:without_container': 'True',
'boost*:without_context': 'True',
'boost*:without_contract': 'True',
'boost*:without_coroutine': 'True',
'boost*:without_date_time': 'True',
'boost*:without_fiber': 'True',
'boost*:without_filesystem': 'False',
'boost*:without_graph': 'True',
'boost*:without_graph_parallel': 'True',
'boost*:without_iostreams': 'False',
'boost*:without_json': 'True',
'boost*:without_locale': 'True',
'boost*:without_log': 'True',
'boost*:without_math': 'False',
'boost*:without_mpi': 'True',
'boost*:without_nowide': 'True',
'boost*:without_program_options': 'True',
'boost*:without_python': 'True',
'boost*:without_serialization': 'False',
'boost*:without_stacktrace': 'True',
'boost*:without_system': 'False',
'boost*:without_test': 'True',
'boost*:without_thread': 'True',
'boost*:without_timer': 'True',
'boost*:without_type_erasure': 'True',
'boost*:without_wave': 'True'
}
def configure(self):
self.options['arrow'].with_boost = True
self.options['arrow'].parquet = True
self.options['arrow'].with_thrift = True
def requirements(self):
self.requires("spdlog/1.14.1", force=True)
self.requires("catch2/3.6.0")
self.requires("bzip2/1.0.8")
self.requires("boost/1.85.0", force=True)
self.requires("eigen/3.4.0")
self.requires("zlib/1.3.1")
self.requires("yaml-cpp/0.8.0")
self.requires("cli11/1.9.1")
self.requires("arrow/16.1.0")
self.requires("proposal/7.6.2")
def build_requirements(self):
self.tool_requires("readline/8.0")
self.tool_requires("bison/[>1.0]")
def generate(self):
tc = CMakeToolchain(self)
tc.absolute_paths = True
tc.generate()
/**
@mainpage CORSIKA air shower simulations framework
Documentation and reference guide for the CORSIKA8 (CORSIKA version 8)
software framework for air shower simulations. CORSIKA8 is developed
at <a
href="https://gitlab.ikp.kit.edu/AirShowerPhysics">https://gitlab.ikp.kit.edu</a>. If
you got the code from somewhere else, consider to switch to the
official development repository. If you want to report bugs, or want
to suggest features or future development, please submit an "issue" on
this gitlab server.
CORSIKA is the most comprehensive framework for simulating particle
cascades in astrophysical environments, for example extensive air
showers. The impact of stochastic and continuous processes on the
cascade development is simulated. To boost computational efficiency
different techniques are provided, like thinning or cascade equations.
The software makes extensive use of static design patterns and
compiler optimization. Thus, the most fundamental configuration
decision of the user must be performed at compile time. At runtime
only spcific parameters can still be changed.
When you contribute to CORSIKA, follow the guidlines outlined here:
<a
href="https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/wikis/home">Development
wiki text</a>
*/
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
// Another possibility:
// https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Execute-Around_Pointer
// for a more global approach
//
// In this case here only a single function is measured via member function pointer.
#pragma once
#include <chrono>
#include <utility>
namespace corsika {
// Common
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...), typename TTimer>
inline ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr, TTimer>::ClassTimer(TClass& obj)
: ClassTimerImpl<TClass, TTimer>(obj) {}
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...), typename TTimer>
inline TRet ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr, TTimer>::call(
TArgs... args) {
this->start_ = ClassTimerImpl<TClass, TTimer>::clock_type::now();
auto tmp = (this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
this->timeDiff_ = std::chrono::duration_cast<
typename ClassTimerImpl<TClass, TTimer>::duration_type>(
ClassTimerImpl<TClass, TTimer>::clock_type::now() - this->start_);
return tmp;
}
// Specialisation 1
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...),
typename TTimer>
inline ClassTimer<void (TClass::*)(TArgs...), TFuncPtr, TTimer>::ClassTimer(TClass& obj)
: ClassTimerImpl<TClass, TTimer>(obj) {}
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...),
typename TTimer>
inline void ClassTimer<void (TClass::*)(TArgs...), TFuncPtr, TTimer>::call(
TArgs... args) {
this->start_ = ClassTimerImpl<TClass, TTimer>::clock_type::now();
(this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
this->timeDiff_ = std::chrono::duration_cast<
typename ClassTimerImpl<TClass, TTimer>::duration_type>(
ClassTimerImpl<TClass, TTimer>::clock_type::now() - this->start_);
return;
}
/// Specialisation 2
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...) const, typename TTimer>
inline ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::ClassTimer(
TClass& obj)
: ClassTimerImpl<TClass, TTimer>(obj) {}
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...) const, typename TTimer>
inline TRet ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::call(
TArgs... args) {
this->start_ = ClassTimerImpl<TClass, TTimer>::clock_type::now();
auto tmp = (this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
this->timeDiff_ = std::chrono::duration_cast<
typename ClassTimerImpl<TClass, TTimer>::duration_type>(
ClassTimerImpl<TClass, TTimer>::clock_type::now() - this->start_);
return tmp;
}
/// Specialisation 3
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const,
typename TTimer>
inline ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::ClassTimer(
TClass& obj)
: ClassTimerImpl<TClass, TTimer>(obj) {}
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const,
typename TTimer>
inline void ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::call(
TArgs... args) {
this->start_ = ClassTimerImpl<TClass, TTimer>::clock_type::now();
(this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
this->timeDiff_ = std::chrono::duration_cast<
typename ClassTimerImpl<TClass, TTimer>::duration_type>(
ClassTimerImpl<TClass, TTimer>::clock_type::now() - this->start_);
return;
}
} // namespace corsika
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <chrono>
#include <utility>
namespace corsika {
template <typename TFunc, typename TTime>
inline FunctionTimer<TFunc, TTime>::FunctionTimer(TFunc f)
: function_(f) {}
template <typename TFunc, typename TTime>
template <typename... TArgs>
inline auto FunctionTimer<TFunc, TTime>::operator()(TArgs&&... args)
-> std::invoke_result_t<TFunc, TArgs...> {
this->startTimer();
auto tmp = function_(std::forward<TArgs>(args)...);
this->stopTimer();
return tmp;
}
} // namespace corsika
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/core/Step.hpp>
#include <corsika/framework/process/ProcessReturn.hpp>
#include <corsika/framework/process/ContinuousProcessStepLength.hpp>
#include <corsika/framework/process/ContinuousProcessIndex.hpp>
#include <corsika/framework/random/ExponentialDistribution.hpp>
#include <corsika/framework/random/RNGManager.hpp>
#include <corsika/framework/random/UniformRealDistribution.hpp>
#include <corsika/framework/stack/SecondaryView.hpp>
#include <corsika/framework/utility/COMBoost.hpp>
#include <corsika/media/Environment.hpp>
#include <corsika/media/NuclearComposition.hpp>
#include <cassert>
#include <cmath>
#include <iostream>
#include <limits>
#include <type_traits>
namespace corsika {
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline Cascade<TTracking, TProcessList, TOutput, TStack>::Cascade(
Environment<medium_interface_type> const& env, TTracking& tr, TProcessList& pl,
TOutput& out, TStack& stack)
: environment_(env)
, tracking_(tr)
, sequence_(pl)
, output_(out)
, stack_(stack)
, forceInteraction_(false)
, forceDecay_(false) {
CORSIKA_LOG_INFO(c8_ascii_);
CORSIKA_LOG_INFO("This is CORSIKA {}.{}.{}.{}", CORSIKA_RELEASE_NUMBER,
CORSIKA_MAJOR_NUMBER, CORSIKA_MINOR_NUMBER, CORSIKA_PATCH_NUMBER);
CORSIKA_LOG_INFO(
"The C8 author list can be found at: "
"https://gitlab.iap.kit.edu/AirShowerPhysics/corsika/-/wikis/"
"Current-CORSIKA-8-author-list");
CORSIKA_LOG_INFO("Tracking algorithm: {} (version {})", TTracking::getName(),
TTracking::getVersion());
if constexpr (stack_view_type::has_event) {
CORSIKA_LOG_INFO("Stack - with full cascade HISTORY.");
}
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline void Cascade<TTracking, TProcessList, TOutput, TStack>::run() {
// trigger the start of the outputs for this shower
output_.startOfShower();
setNodes(); // put each particle on stack in correct environment volume
while (!stack_.isEmpty()) {
sequence_.initCascadeEquations();
while (!stack_.isEmpty()) {
CORSIKA_LOG_TRACE("Stack: {}", stack_.asString());
count_++;
auto pNext = stack_.getNextParticle();
CORSIKA_LOG_TRACE(
"============== next particle : count={}, pid={}"
", stack entries={}"
", stack deleted={}",
count_, pNext.getPID(), stack_.getEntries(), stack_.getErased());
step(pNext);
sequence_.doStack(stack_);
}
// do cascade equations, which can put new particles on Stack,
// thus, the double loop
sequence_.doCascadeEquations(stack_);
}
// indicate end of shower
output_.endOfShower();
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline void Cascade<TTracking, TProcessList, TOutput, TStack>::forceInteraction() {
forceInteraction_ = true;
if (forceDecay_) {
CORSIKA_LOG_ERROR("Cannot set forceInteraction when forceDecay is already set");
throw std::runtime_error(
"Cannot set forceInteraction when forceDecay is already set");
}
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline void Cascade<TTracking, TProcessList, TOutput, TStack>::forceDecay() {
forceDecay_ = true;
if (forceInteraction_) {
CORSIKA_LOG_ERROR("Cannot set forceDecay when forceInteraction is already set");
throw std::runtime_error(
"Cannot set forceDecay when forceInteraction is already set");
}
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline void Cascade<TTracking, TProcessList, TOutput, TStack>::step(
particle_type& particle) {
// determine the volume where the particle is (last) known to be
auto const* currentLogicalNode = particle.getNode();
// assert that particle stays outside void Universe if it has no
// model properties set
assert((currentLogicalNode != &*environment_.getUniverse() ||
environment_.getUniverse()->hasModelProperties()) &&
"FATAL: The environment model has no valid properties set!");
NuclearComposition const& composition =
currentLogicalNode->getModelProperties().getNuclearComposition();
// determine projectile
HEPEnergyType const Elab = particle.getEnergy();
FourMomentum const projectileP4{Elab, particle.getMomentum()};
// determine combined full inelastic cross section of the particles in the material
auto const targetMomentum = MomentumVector{
particle.getMomentum().getCoordinateSystem(), {0_GeV, 0_GeV, 0_GeV}};
auto const xs_function = [&](Code const targetId) -> CrossSectionType {
FourMomentum const targetP4{get_mass(targetId), targetMomentum};
return sequence_.getCrossSection(particle, targetId, targetP4);
};
CrossSectionType const total_cx_pre = composition.getWeightedSum(xs_function);
if (forceInteraction_) {
CORSIKA_LOG_TRACE("forced interaction!");
forceInteraction_ = false; // just one (first) interaction
stack_view_type secondaries(particle);
interaction(secondaries, projectileP4, composition, total_cx_pre);
sequence_.doSecondaries(secondaries);
particle.erase(); // primary particle is done
return;
}
if (forceDecay_) {
CORSIKA_LOG_TRACE("forced decay!");
forceDecay_ = false; // just one decay
stack_view_type secondaries(particle);
decay(secondaries, sequence_.getInverseLifetime(particle));
if (secondaries.getSize() == 1 && secondaries.getProjectile().getPID() ==
secondaries.getNextParticle().getPID()) {
throw std::runtime_error(
fmt::format("Particle {} decays into itself!",
get_name(secondaries.getProjectile().getPID())));
}
sequence_.doSecondaries(secondaries);
particle.erase(); // primary particle is done
return;
}
// calculate interaction length in medium
GrammageType const total_lambda =
(composition.getAverageMassNumber() * constants::u) / total_cx_pre;
// sample random exponential step length in grammage
ExponentialDistribution expDist{total_lambda};
GrammageType const next_interact = expDist(rng_);
CORSIKA_LOG_DEBUG("total_lambda={} g/cm2, next_interact={} g/cm2",
double(total_lambda / 1_g * 1_cm * 1_cm),
double(next_interact / 1_g * 1_cm * 1_cm));
// determine combined total inverse decay time
InverseTimeType const total_inv_lifetime_pre = sequence_.getInverseLifetime(particle);
// sample random exponential decay time
ExponentialDistribution expDistDecay(1 / total_inv_lifetime_pre);
TimeType const next_decay = expDistDecay(rng_);
CORSIKA_LOG_DEBUG("total_lifetime={} ns, next_decay={} ns",
(1 / total_inv_lifetime_pre) / 1_ns, next_decay / 1_ns);
// convert next_decay from time to length [m]
LengthType const distance_decay = next_decay * particle.getMomentum().getNorm() /
particle.getEnergy() * constants::c;
// determine geometric tracking
auto [track, nextVol] = tracking_.getTrack(particle);
auto geomMaxLength = track.getLength(1);
// convert next_step from grammage to length
LengthType const distance_interact =
currentLogicalNode->getModelProperties().getArclengthFromGrammage(track,
next_interact);
// determine the maximum geometric step length
ContinuousProcessStepLength const continuousMaxStep =
sequence_.getMaxStepLength(particle, track);
LengthType const continuous_max_dist = continuousMaxStep;
// take minimum of geometry, interaction, decay for next step
LengthType const min_discrete = std::min(distance_interact, distance_decay);
LengthType const min_non_continuous = std::min(min_discrete, geomMaxLength);
LengthType const min_distance = std::min(min_non_continuous, continuous_max_dist);
bool const isContinuous = continuous_max_dist < min_non_continuous;
// inform ContinuousProcesses (if applicable) that it is responsible for step-limit
// this would become simpler if we follow the idea of Max to enumerate ALL types of
// processes. Then non-continuous are included and no further logic is needed to
// distinguish between continuous and non-continuous limit.
auto const limitingId = isContinuous ? continuousMaxStep : ContinuousProcessIndex{};
// // the current step IS limited by a known continuous process
CORSIKA_LOG_DEBUG(
"transport particle by : {} m "
"Medium transition after: {} m "
"Decay after: {} m "
"Interaction after: {} m "
"Continuous limit: {} m ",
min_distance / 1_m, geomMaxLength / 1_m, distance_decay / 1_m,
distance_interact / 1_m, continuous_max_dist / 1_m);
// move particle along the trajectory to new position
// also update momentum/direction/time
track.setLength(min_distance);
Step step{particle, track};
// apply all continuous processes on particle + track
if (sequence_.doContinuous(step, limitingId) == ProcessReturn::ParticleAbsorbed) {
CORSIKA_LOG_DEBUG("Cascade: delete absorbed particle PID={} E={} GeV",
particle.getPID(), particle.getEnergy() / 1_GeV);
if (particle.isErased()) {
CORSIKA_LOG_WARN(
"Particle marked as Absorbed in doContinuous, but prematurely erased. This "
"may be bug. Check.");
} else {
particle.erase();
}
return; // particle is gone -> return
}
particle.setTime(step.getTimePost());
particle.setPosition(step.getPositionPost());
particle.setDirection(step.getDirectionPost());
particle.setKineticEnergy(step.getEkinPost());
if (isContinuous) {
return; // there is nothing further, step is finished
}
CORSIKA_LOG_DEBUG("discrete process before geometric limit ? {}",
((min_distance < geomMaxLength) ? "yes" : "no"));
if (geomMaxLength < min_discrete) {
// geometric / tracking limit
if (nextVol != currentLogicalNode) {
// boundary crossing, step is limited by volume boundary
CORSIKA_LOG_DEBUG("volume boundary crossing to {}", fmt::ptr(nextVol));
if (nextVol == environment_.getUniverse().get()) {
CORSIKA_LOG_DEBUG(
"particle left physics world, is now in unknown space -> delete");
particle.erase();
}
particle.setNode(nextVol);
/*
doBoundary may delete the particle (or not)
caveat: any changes to particle, or even the production
of new secondaries is currently not passed to ParticleCut,
thus, particles outside the desired phase space may be produced.
\todo: this must be fixed.
*/
sequence_.doBoundaryCrossing(particle, *currentLogicalNode, *nextVol);
return; // step finished
}
CORSIKA_LOG_DEBUG("step limit reached (e.g. deflection). nothing further happens.");
// final sanity check, no actions
{
auto const* numericalNodeAfterStep =
environment_.getUniverse()->getContainingNode(particle.getPosition());
CORSIKA_LOG_TRACE(
"Geometry check: numericalNodeAfterStep={} currentLogicalNode={}",
fmt::ptr(numericalNodeAfterStep), fmt::ptr(currentLogicalNode));
if (numericalNodeAfterStep != currentLogicalNode) {
CORSIKA_LOG_DEBUG(
"expect to be in node currentLogicalNode={} but are in "
"numericalNodeAfterStep={}. Continue, but without guarantee.",
fmt::ptr(currentLogicalNode), fmt::ptr(numericalNodeAfterStep));
}
}
// we did not cross any volume boundary
// step length limit
return;
}
// interaction or decay to happen in this step
// the outcome of decay or interaction MAY be a) new particles in
// secondaries, b) the projectile particle deleted (or
// changed)
stack_view_type secondaries{particle};
/*
Create SecondaryView object on Stack. The data container
remains untouched and identical, and 'projectile' is identical
to 'particle' above this line. However,
projectile.addSecondaries populate the SecondaryView, which can
then be used afterwards for further processing. Thus: it is
important to use projectile/view (and not particle) for Interaction,
and Decay!
*/
FourMomentum const projectileP4Post{particle.getEnergy(), particle.getMomentum()};
bool eraseParticle =
false; // only erase original particle if it decayed or interacted
if (distance_interact < distance_decay) {
eraseParticle = isInteracted(
interaction(secondaries, projectileP4Post, composition, total_cx_pre));
} else {
[[maybe_unused]] auto projectile = secondaries.getProjectile();
if (decay(secondaries, total_inv_lifetime_pre) == ProcessReturn::Decayed) {
eraseParticle = true;
if (secondaries.getSize() == 1 &&
projectile.getPID() == secondaries.getNextParticle().getPID()) {
throw std::runtime_error(fmt::format("Particle {} decays into itself!",
get_name(projectile.getPID())));
}
}
}
if (eraseParticle) {
// doSecondaries() makes sense only if there was an actual event
sequence_.doSecondaries(secondaries);
particle.erase();
}
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline ProcessReturn Cascade<TTracking, TProcessList, TOutput, TStack>::decay(
stack_view_type& view, InverseTimeType initial_inv_decay_time) {
CORSIKA_LOG_DEBUG("decay");
// one option is that decay_time is now larger (less
// probability for decay) than it was before the step, thus,
// no decay might actually occur and is allowed
UniformRealDistribution<InverseTimeType> uniDist(initial_inv_decay_time);
const auto sample_process = uniDist(rng_);
auto const returnCode = sequence_.selectDecay(view, sample_process);
if (returnCode != ProcessReturn::Decayed) {
CORSIKA_LOG_ERROR("Particle {} did not decay!",
get_name(view.getProjectile().getPID()));
}
setEventType(view, history::EventType::Decay);
return returnCode;
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline ProcessReturn Cascade<TTracking, TProcessList, TOutput, TStack>::interaction(
stack_view_type& view, FourMomentum const& projectileP4,
NuclearComposition const& composition,
CrossSectionType const initial_cross_section) {
CORSIKA_LOG_DEBUG("collide");
// one option is that cross section is now smaller (less
// probability for collision) than it was before the step, thus,
// no interaction might actually occur and is allowed
UniformRealDistribution<CrossSectionType> uniDist(initial_cross_section);
CrossSectionType const sample_process_by_cx = uniDist(rng_);
auto const returnCode = sequence_.selectInteraction(view, projectileP4, composition,
rng_, sample_process_by_cx);
if (returnCode != ProcessReturn::Interacted) {
CORSIKA_LOG_DEBUG("Particle did not interact!");
}
setEventType(view, history::EventType::Interaction);
return returnCode;
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline void Cascade<TTracking, TProcessList, TOutput, TStack>::setNodes() {
std::for_each(stack_.begin(), stack_.end(), [&](auto& p) {
auto const* numericalNode =
environment_.getUniverse()->getContainingNode(p.getPosition());
p.setNode(numericalNode);
});
}
template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
inline void Cascade<TTracking, TProcessList, TOutput, TStack>::setEventType(
stack_view_type& view, [[maybe_unused]] history::EventType eventType) {
if constexpr (stack_view_type::has_event) {
for (auto&& sec : view) { sec.getEvent()->setEventType(eventType); }
}
}
} // namespace corsika
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <spdlog/fmt/ostr.h> // will output whenerver a streaming operator is found
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
namespace corsika {
// many of these free functions are special to the logging
// infrastructure so we hide them in the corsika::logging namespace.
namespace logging {
/*
* The default pattern for CORSIKA8 loggers.
*/
inline auto set_default_level(level::level_enum const minlevel) -> void {
spdlog::set_level(minlevel);
}
template <typename TLogger>
inline auto add_source_info(TLogger& logger) -> void {
logger->set_pattern(source_pattern);
}
template <typename TLogger>
inline auto reset_pattern(TLogger& logger) -> void {
logger->set_pattern(default_pattern);
}
} // namespace logging
inline std::shared_ptr<spdlog::logger> create_logger(std::string const& name,
bool const defaultlog) {
// create the logger
// this is currently a colorized multi-threading safe logger
auto logger = spdlog::stdout_color_mt(name);
// set the default C8 format
#if (!defined(_GLIBCXX_USE_CXX11_ABI) || _GLIBCXX_USE_CXX11_ABI == 1)
logger->set_pattern(default_pattern);
#else
// special case: gcc from the software collections devtoolset
std::string dp(default_pattern);
logger->set_pattern(dp);
#endif
// if defaultlog is True, we set this as the default spdlog logger.
if (defaultlog) { spdlog::set_default_logger(logger); }
return logger;
}
inline std::shared_ptr<spdlog::logger> get_logger(std::string const& name,
bool const defaultlog) {
// attempt to get the logger from the registry
auto logger = spdlog::get(name);
// weg found the logger, so just return it
if (logger) {
return logger;
} else { // logger was not found so create it
return create_logger(name, defaultlog);
}
}
} // namespace corsika
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <cmath>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/core/Logging.hpp>
namespace corsika {
inline HEPEnergyType get_kinetic_energy_propagation_threshold(Code const code) {
if (is_nucleus(code)) return particle::detail::threshold_nuclei;
return particle::detail::propagation_thresholds[static_cast<CodeIntType>(code)];
}
inline void set_kinetic_energy_propagation_threshold(Code const code,
HEPEnergyType const val) {
if (is_nucleus(code))
particle::detail::threshold_nuclei = val;
else
particle::detail::propagation_thresholds[static_cast<CodeIntType>(code)] = val;
}
inline HEPMassType constexpr get_mass(Code const code) {
if (is_nucleus(code)) { return get_nucleus_mass(code); }
return particle::detail::masses[static_cast<CodeIntType>(code)];
}
inline HEPEnergyType get_energy_production_threshold(Code const p) {
return particle::detail::production_thresholds[static_cast<CodeIntType>(p)];
}
inline void set_energy_production_threshold(Code const p, HEPEnergyType const val) {
particle::detail::production_thresholds[static_cast<CodeIntType>(p)] = val;
}
inline bool constexpr is_charged(Code const c) { return get_charge_number(c) != 0; }
inline bool constexpr is_nucleus(Code const code) { return code >= Code::Nucleus; }
inline Code constexpr get_nucleus_code(size_t const A,
size_t const Z) { // 10LZZZAAAI
if (Z > A) { throw std::runtime_error("Z cannot be larger than A in nucleus."); }
return static_cast<Code>(static_cast<CodeIntType>(Code::Nucleus) + Z * 10000 +
A * 10);
}
inline size_t constexpr get_nucleus_Z(Code const code) {
return (static_cast<CodeIntType>(code) % static_cast<CodeIntType>(Code::Nucleus)) /
10000;
}
inline size_t constexpr get_nucleus_A(Code const code) {
return (static_cast<CodeIntType>(code) % 10000) / 10;
}
inline PDGCode constexpr get_PDG(Code const code) {
if (code < Code::Nucleus) {
return particle::detail::pdg_codes[static_cast<CodeIntType>(code)];
}
size_t const Z = get_nucleus_Z(code);
size_t const A = get_nucleus_A(code);
return static_cast<PDGCode>(static_cast<CodeIntType>(Code::Nucleus) + Z * 10000 +
A * 10); // 10LZZZAAAI
}
inline PDGCode constexpr get_PDG(unsigned int const A, unsigned int const Z) {
return PDGCode(1000000000 + Z * 10000 + A * 10);
}
inline int16_t constexpr get_charge_number(Code const code) {
if (is_nucleus(code)) return get_nucleus_Z(code);
return particle::detail::electric_charges[static_cast<CodeIntType>(code)];
}
inline ElectricChargeType constexpr get_charge(Code const code) {
if (code == Code::Nucleus)
throw std::runtime_error("charge of particle::Nucleus undefined");
return get_charge_number(code) * constants::e;
}
inline std::string_view constexpr get_name(Code const code) {
if (is_nucleus(code)) { return "nucleus"; }
return particle::detail::names[static_cast<CodeIntType>(code)];
}
inline std::string get_name(Code code, full_name) {
if (is_nucleus(code)) {
return fmt::format("nucleus ({},{})", get_nucleus_A(code), get_nucleus_Z(code));
}
return std::string{get_name(code)};
}
inline TimeType constexpr get_lifetime(Code const p) {
return particle::detail::lifetime[static_cast<CodeIntType>(p)] * second;
}
inline bool constexpr is_hadron(Code const code) {
if (is_nucleus(code)) return true;
return particle::detail::isHadron[static_cast<CodeIntType>(code)];
}
inline bool constexpr is_em(Code const c) {
return c == Code::Electron || c == Code::Positron || c == Code::Photon;
}
inline bool constexpr is_muon(Code const c) {
return c == Code::MuPlus || c == Code::MuMinus;
}
inline bool constexpr is_neutrino(Code const c) {
return c == Code::NuE || c == Code::NuMu || c == Code::NuTau || c == Code::NuEBar ||
c == Code::NuMuBar || c == Code::NuTauBar;
}
inline std::ostream& operator<<(std::ostream& stream, corsika::Code const code) {
return stream << get_name(code);
}
inline Code convert_from_PDG(PDGCode const p) {
static_assert(particle::detail::conversionArray.size() % 2 == 1);
// this will fail, for the strange case where the maxPDG is negative...
int constexpr maxPDG{(particle::detail::conversionArray.size() - 1) >> 1};
auto const k = static_cast<PDGCodeIntType>(p);
if (std::abs(k) <= maxPDG) {
return particle::detail::conversionArray[k + maxPDG];
} else {
if (1000000000 <= k && k <= 1009999990) { // nucleus (no L or I)
int const Z = (k - 1000000000) / 10000;
int const A = (k - 1000000000 - 10000 * Z) / 10;
return get_nucleus_code(A, Z);
}
return particle::detail::conversionMap.at(p);
}
}
inline HEPMassType constexpr get_nucleus_mass(Code const code) {
unsigned int const A = get_nucleus_A(code);
unsigned int const Z = get_nucleus_Z(code);
return get_nucleus_mass(A, Z);
}
inline HEPMassType constexpr get_nucleus_mass(unsigned int const A,
unsigned int const Z) {
return get_mass(Code::Proton) * Z + (A - Z) * get_mass(Code::Neutron);
}
inline std::string get_nucleus_name(Code const code) {
size_t const A = get_nucleus_A(code);
size_t const Z = get_nucleus_Z(code);
return fmt::format("Nucleus_A{}_Z{}", A, Z);
}
inline std::initializer_list<Code> constexpr get_all_particles() {
return particle::detail::all_particles;
}
} // namespace corsika
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <fmt/format.h>
#include <corsika/framework/core/ParticleProperties.hpp>
#include <boost/filesystem/path.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <Eigen/Dense>
//-----------------------------------
// STD
//-----------------------------------
namespace std {
auto inline format_as(std::_Put_time<char> const& arg) {
std::ostringstream os;
os << arg;
return os.str();
}
} // namespace std
//-----------------------------------
// CORSIKA
//-----------------------------------
namespace corsika {
// formatters for particle codes declared on ParticleProperties.hpp
auto inline format_as(Code code) { return get_name(code); }
auto inline format_as(PDGCode code) { return fmt::underlying(code); }
template <typename Type>
auto inline format_as(Type const& arg) {
std::ostringstream os;
os << arg;
return os.str();
}
} // namespace corsika
//-----------------------------------
// boost::filesystem
//-----------------------------------
namespace boost::filesystem {
auto inline format_as(path const& fname) { return fname.string().c_str(); }
} // namespace boost::filesystem
//-----------------------------------
// phys::units
//-----------------------------------
namespace phys::units {
template <typename Dimensions>
auto inline format_as(phys::units::quantity<Dimensions> const& arg) {
return io::to_string(arg);
}
} // namespace phys::units
//----------------------------------
// Eigen
//----------------------------------
namespace Eigen {
template <typename Scalar, int M, int N>
auto inline format_as(Matrix<Scalar, M, N> const& arg) {
std::ostringstream os;
os << arg;
return os.str();
}
template <typename Matrix1, typename Matrix2>
auto inline format_as(Product<Matrix1, Matrix2> const& arg) {
std::ostringstream os;
os << arg;
return os.str();
}
} // namespace Eigen
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <corsika/framework/geometry/CoordinateSystem.hpp>
#include <corsika/framework/geometry/QuantityVector.hpp>
namespace corsika {
template <typename TDimension>
inline CoordinateSystemPtr BaseVector<TDimension>::getCoordinateSystem() const {
return cs_;
}
template <typename TDimension>
inline QuantityVector<TDimension> const& BaseVector<TDimension>::getQuantityVector()
const {
return quantityVector_;
}
template <typename TDimension>
inline QuantityVector<TDimension>& BaseVector<TDimension>::getQuantityVector() {
return quantityVector_;
}
} // namespace corsika
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
namespace corsika {
inline Box::Box(CoordinateSystemPtr cs, LengthType const x, LengthType const y,
LengthType const z)
: center_(Point(cs, {0_m, 0_m, 0_m}))
, cs_(cs)
, x_(x)
, y_(y)
, z_(z) {}
inline Box::Box(CoordinateSystemPtr cs, LengthType const side)
: center_(Point(cs, {0_m, 0_m, 0_m}))
, cs_(cs)
, x_(side / 2)
, y_(side / 2)
, z_(side / 2) {}
inline bool Box::contains(Point const& p) const {
if ((abs(p.getX(cs_)) < x_) && (abs(p.getY(cs_)) < y_) && (abs(p.getZ(cs_)) < z_))
return true;
else
return false;
}
inline std::string Box::asString() const {
std::ostringstream txt;
txt << "center=" << center_ << ", x-axis=" << DirectionVector{cs_, {1, 0, 0}}
<< ", y-axis: " << DirectionVector{cs_, {0, 1, 0}}
<< ", z-axis: " << DirectionVector{cs_, {0, 0, 1}};
return txt.str();
}
template <typename TDim>
inline void Box::rotate(QuantityVector<TDim> const& axis, double const angle) {
cs_ = make_rotation(cs_, axis, angle);
}
} // namespace corsika
\ No newline at end of file
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <corsika/framework/geometry/RootCoordinateSystem.hpp>
#include <corsika/framework/geometry/QuantityVector.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <Eigen/Dense>
#include <memory>
#include <stdexcept>
namespace corsika {
inline CoordinateSystemPtr CoordinateSystem::getReferenceCS() const {
return referenceCS_;
}
inline EigenTransform const& CoordinateSystem::getTransform() const { return transf_; }
inline bool CoordinateSystem::operator==(CoordinateSystem const& cs) const {
return referenceCS_ == cs.referenceCS_ && transf_.matrix() == cs.transf_.matrix();
}
inline bool CoordinateSystem::operator!=(CoordinateSystem const& cs) const {
return !(cs == *this);
}
/// find transformation between two CS, using most optimal common base
inline EigenTransform get_transformation(CoordinateSystem const& pFrom,
CoordinateSystem const& pTo) {
CoordinateSystem const* a{&pFrom};
CoordinateSystem const* b{&pTo};
while (a != b && b) {
// traverse pFrom
a = &pFrom;
while (a != b && a) { a = a->getReferenceCS().get(); }
if (a == b) break;
b = b->getReferenceCS().get();
}
if (a != b || a == nullptr) {
throw std::runtime_error("no connection between coordinate systems found!");
}
CoordinateSystem const* commonBase = a;
CoordinateSystem const* p = &pFrom;
EigenTransform t = EigenTransform::Identity();
while ((*p) != (*commonBase)) {
t = p->getTransform() * t;
p = p->getReferenceCS().get();
}
p = &pTo;
while (*p != *commonBase) {
t = t * p->getTransform().inverse(Eigen::TransformTraits::Isometry);
p = p->getReferenceCS().get();
}
return t;
}
inline CoordinateSystemPtr make_translation(CoordinateSystemPtr const& cs,
QuantityVector<length_d> const& vector) {
EigenTransform const translation{EigenTranslation(vector.getEigenVector())};
return CoordinateSystemPtr{new CoordinateSystem(cs, translation)};
}
template <typename TDim>
inline CoordinateSystemPtr make_rotationToZ(CoordinateSystemPtr const& cs,
Vector<TDim> const& vVec) {
auto const vVecComp = vVec.getComponents(cs);
if (vVecComp.getX().magnitude() == 0 && vVecComp.getY().magnitude() == 0 &&
vVecComp.getZ().magnitude() == 0) {
return cs;
}
auto const a = vVecComp.normalized().getEigenVector();
auto const a1 = a(0), a2 = a(1), a3 = a(2);
Eigen::Matrix3d A, B;
if (a3 > 0) {
auto const c = 1 / (1 + a3);
A << 1, 0, a1, // comment to prevent clang-format
0, 1, a2, // .
-a1, -a2, 1; // .
B << -a1 * a1 * c, -a1 * a2 * c, 0, // .
-a1 * a2 * c, -a2 * a2 * c, 0, // .
0, 0, -(a1 * a1 + a2 * a2) * c; // .
} else {
auto const c = 1 / (1 - a3);
A << 1, 0, a1, // .
0, -1, a2, // .
a1, -a2, -1; // .
B << -a1 * a1 * c, +a1 * a2 * c, 0, // .
-a1 * a2 * c, +a2 * a2 * c, 0, // .
0, 0, (a1 * a1 + a2 * a2) * c; // .
}
return CoordinateSystemPtr{new CoordinateSystem{cs, EigenTransform{A + B}}};
}
template <typename TDim>
inline CoordinateSystemPtr make_rotation(CoordinateSystemPtr const& cs,
QuantityVector<TDim> const& axis,
double const angle) {
if (axis.getEigenVector().isZero()) {
throw std::runtime_error("null-vector given as axis parameter");
}
EigenTransform const rotation{
Eigen::AngleAxisd(angle, axis.getEigenVector().normalized())};
return CoordinateSystemPtr{new CoordinateSystem{cs, rotation}};
}
template <typename TDim>
inline CoordinateSystemPtr make_translationAndRotation(
CoordinateSystemPtr const& cs, QuantityVector<length_d> const& translation,
QuantityVector<TDim> const& axis, double const angle) {
if (axis.getEigenVector().isZero()) {
throw std::runtime_error("null-vector given as axis parameter");
}
EigenTransform const transf{
Eigen::AngleAxisd(angle, axis.getEigenVector().normalized()) *
EigenTranslation(translation.getEigenVector())};
return CoordinateSystemPtr{new CoordinateSystem{cs, transf}};
}
} // namespace corsika
/*
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the 3-clause BSD license.
* See file LICENSE for a full version of the license.
*/
#pragma once
#include <type_traits>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/geometry/Vector.hpp>
namespace corsika {
template <typename TTimeType, typename TSpaceVecType>
inline TTimeType FourVector<TTimeType, TSpaceVecType>::getTimeLikeComponent() const {
return timeLike_;
}
template <typename TTimeType, typename TSpaceVecType>
inline TSpaceVecType& FourVector<TTimeType, TSpaceVecType>::getSpaceLikeComponents() {
return spaceLike_;
}
template <typename TTimeType, typename TSpaceVecType>
inline TSpaceVecType const&
FourVector<TTimeType, TSpaceVecType>::getSpaceLikeComponents() const {
return spaceLike_;
}
template <typename TTimeType, typename TSpaceVecType>
inline typename FourVector<TTimeType, TSpaceVecType>::norm_square_type
FourVector<TTimeType, TSpaceVecType>::getNormSqr() const {
return getTimeSquared() - spaceLike_.getSquaredNorm();
}
template <typename TTimeType, typename TSpaceVecType>
inline typename FourVector<TTimeType, TSpaceVecType>::norm_type
FourVector<TTimeType, TSpaceVecType>::getNorm() const {
return sqrt(abs(getNormSqr()));
}
template <typename TTimeType, typename TSpaceVecType>
inline bool FourVector<TTimeType, TSpaceVecType>::isTimelike() const {
return getTimeSquared() < spaceLike_.getSquaredNorm();
}
template <typename TTimeType, typename TSpaceVecType>
inline bool FourVector<TTimeType, TSpaceVecType>::isSpacelike() const {
return getTimeSquared() > spaceLike_.getSquaredNorm();
}
template <typename TTimeType, typename TSpaceVecType>
inline FourVector<TTimeType, TSpaceVecType>& FourVector<TTimeType, TSpaceVecType>::
operator+=(FourVector const& b) {
timeLike_ += b.timeLike_;
spaceLike_ += b.spaceLike_;
return *this;
}
template <typename TTimeType, typename TSpaceVecType>
inline FourVector<TTimeType, TSpaceVecType>& FourVector<TTimeType, TSpaceVecType>::
operator-=(FourVector const& b) {
timeLike_ -= b.timeLike_;
spaceLike_ -= b.spaceLike_;
return *this;
}
template <typename TTimeType, typename TSpaceVecType>
inline FourVector<TTimeType, TSpaceVecType>& FourVector<TTimeType, TSpaceVecType>::
operator*=(double const b) {
timeLike_ *= b;
spaceLike_ *= b;
return *this;
}
template <typename TTimeType, typename TSpaceVecType>
inline FourVector<TTimeType, TSpaceVecType>& FourVector<TTimeType, TSpaceVecType>::
operator/=(double const b) {
timeLike_ /= b;
spaceLike_.getComponents() /= b;
return *this;
}
template <typename TTimeType, typename TSpaceVecType>
inline FourVector<TTimeType, TSpaceVecType>& FourVector<TTimeType, TSpaceVecType>::
operator/(double const b) {
*this /= b;
return *this;
}
template <typename TTimeType, typename TSpaceVecType>
inline typename FourVector<TTimeType, TSpaceVecType>::norm_type
FourVector<TTimeType, TSpaceVecType>::operator*(FourVector const& b) {
if constexpr (std::is_same<time_type, decltype(std::declval<space_type>() / meter *
second)>::value)
return timeLike_ * b.timeLike_ * constants::cSquared - spaceLike_.norm();
else
return timeLike_ * timeLike_ - spaceLike_.norm();
}
template <typename TTimeType, typename TSpaceVecType>
inline typename FourVector<TTimeType, TSpaceVecType>::norm_square_type
FourVector<TTimeType, TSpaceVecType>::getTimeSquared() const {
if constexpr (std::is_same<time_type, decltype(std::declval<space_type>() / meter *
second)>::value)
return timeLike_ * timeLike_ * constants::cSquared;
else
return timeLike_ * timeLike_;
}
template <typename TTimeType, typename TSpaceVecType>
inline std::ostream& operator<<(
std::ostream& os, corsika::FourVector<TTimeType, TSpaceVecType> const qv) {
os << '(' << qv.timeLike_ << ", " << qv.spaceLike_ << ") ";
return os;
}
} // namespace corsika