diff --git a/Processes/CMakeLists.txt b/Processes/CMakeLists.txt index 2835a7043cc80101ef22d1301af981b5735de6bb..6afe1cc51acdc689b97a90dec334d727b61c7f60 100644 --- a/Processes/CMakeLists.txt +++ b/Processes/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory (TrackingLine) add_subdirectory (HadronicElasticModel) add_subdirectory (EnergyLoss) add_subdirectory (UrQMD) +add_subdirectory (SwitchProcess) #add_custom_target(CORSIKAprocesses) add_library (CORSIKAprocesses INTERFACE) diff --git a/Processes/SwitchProcess/CMakeLists.txt b/Processes/SwitchProcess/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..0eb1418498c2c8a9771364c30592ec9303bcc6ef --- /dev/null +++ b/Processes/SwitchProcess/CMakeLists.txt @@ -0,0 +1,48 @@ +set ( + MODEL_HEADERS + SwitchProcess.h + ) + +set ( + MODEL_NAMESPACE + corsika/process/switch_process + ) + +add_library (ProcessSwitch INTERFACE) +CORSIKA_COPY_HEADERS_TO_NAMESPACE (ProcessSwitch ${MODEL_NAMESPACE} ${MODEL_HEADERS}) + +set_target_properties ( + ProcessStackInspector + PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 1 +# PUBLIC_HEADER "${MODEL_HEADERS}" + ) + +# target dependencies on other libraries (also the header onlys) +target_link_libraries ( + ProcessSwitch + INTERFACE + CORSIKAunits + CORSIKAprocesssequence + ) + +target_include_directories ( + ProcessSwitch + INTERFACE + $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include> + $<INSTALL_INTERFACE:include/include> + ) + +install (FILES ${MODEL_HEADERS} DESTINATION include/${MODEL_NAMESPACE}) + +# -------------------- +# code unit testing +#add_executable (testStackInspector testSwitchProcess.cc) + +#target_link_libraries ( +# testSwitchProcess +# ProcessSwitch +# CORSIKAthirdparty # for catch2 +# ) +#CORSIKA_ADD_TEST(testStackInspector) diff --git a/Processes/SwitchProcess/SwitchProcess.h b/Processes/SwitchProcess/SwitchProcess.h new file mode 100644 index 0000000000000000000000000000000000000000..85d614109ff3f83bd7d3151b71f0a604f4a6bcfc --- /dev/null +++ b/Processes/SwitchProcess/SwitchProcess.h @@ -0,0 +1,85 @@ +#ifndef _corsika_SwitchProcess_h +#define _corsika_SwitchProcess_h + +#include <corsika/process/InteractionProcess.h> +#include <corsika/process/ProcessSequence.h> +#include <corsika/setup/SetupStack.h> +#include <corsika/units/PhysicalUnits.h> + +namespace corsika::process::switch_process { + + /** + * This process provides an energy-based switch between two interaction processes P1 and + * P1. For energies below the threshold, P1 is invoked, otherwise P2. Both can be either + * single interaction processes or multiple ones combined in a ProcessSequence. A + * SwitchProcess itself will always be regarded as a ProcessSequence rather than an + * InteractionProcess when assembled into a greater ProcessSequence. + */ + + template <class TLowEProcess, class THighEProcess> + class SwitchProcess + : public InteractionProcess<SwitchProcess<TLowEProcess, THighEProcess>> { + TLowEProcess& fLowEProcess; + THighEProcess& fHighEProcess; + units::si::HEPEnergyType const fThresholdEnergy; + + public: + SwitchProcess(TLowEProcess& vLowEProcess, THighEProcess& vHighEProcess, + units::si::HEPEnergyType vThresholdEnergy) + : fLowEProcess(vLowEProcess) + , fHighEProcess(vHighEProcess) + , fThresholdEnergy(vThresholdEnergy) {} + + void Init() { + fLowEProcess.Init(); + fHighEProcess.Init(); + } + + template <typename TParticle> + units::si::GrammageType GetInteractionLength(TParticle& vParticle) { + if (vParticle.GetEnergy() < fThresholdEnergy) { + if constexpr (is_process_sequence_v<TLowEProcess>) { + return fLowEProcess.GetTotalInteractionLength(vParticle); + } else { + return fLowEProcess.GetInteractionLength(vParticle); + } + } else { + if constexpr (is_process_sequence_v<THighEProcess>) { + return fHighEProcess.GetTotalInteractionLength(vParticle); + } else { + return fHighEProcess.GetInteractionLength(vParticle); + } + } + } + + // required to conform to ProcessSequence interface. We cannot just + // implement DoInteraction() because we want to call SelectInteraction + // in case a member process is a ProcessSequence. + template <typename TParticle, typename TSecondaries> + EProcessReturn SelectInteraction( + TParticle& vP, TSecondaries& vS, + [[maybe_unused]] corsika::units::si::InverseGrammageType lambda_select, + corsika::units::si::InverseGrammageType& lambda_inv_count) { + + if (vP.GetEnergy() < fThresholdEnergy) { + if constexpr (is_process_sequence_v<TLowEProcess>) { + return fLowEProcess.SelectInteraction(vP, vS, lambda_select, lambda_inv_count); + } else { + return fLowEProcess.DoInteraction(vS); + } + } else { + if constexpr (is_process_sequence_v<THighEProcess>) { + return fHighEProcess.SelectInteraction(vP, vS, lambda_select, lambda_inv_count); + } else { + return fHighEProcess.DoInteraction(vS); + } + } + } + }; +} // namespace corsika::process::switch_process + +template <typename A, typename B> +struct corsika::process::is_process_sequence< + corsika::process::switch_process::SwitchProcess<A, B>> : std::true_type {}; + +#endif