From a8cf60a9f138030348917c1e52a217e5aaae4cb2 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Mon, 18 Jan 2021 17:25:48 +0100 Subject: [PATCH] almost works, only switch-pro-seq not --- corsika/detail/framework/core/Cascade.inl | 10 +- corsika/detail/framework/geometry/Plane.inl | 8 + corsika/detail/framework/geometry/Point.inl | 6 + .../framework/geometry/QuantityVector.inl | 2 +- corsika/detail/framework/geometry/Vector.inl | 8 + .../framework/process/ProcessSequence.inl | 144 ++++--- .../process/SwitchProcessSequence.inl | 125 +++--- .../detail/modules/LongitudinalProfile.inl | 2 +- corsika/detail/modules/ObservationPlane.inl | 73 ++-- corsika/detail/modules/ParticleCut.inl | 2 +- corsika/detail/modules/TrackWriter.inl | 3 +- .../modules/energy_loss/BetheBlochPDG.inl | 4 +- .../modules/proposal/ContinuousProcess.inl | 2 +- .../modules/tracking/TrackingStraight.inl | 2 + corsika/framework/geometry/Plane.hpp | 4 + corsika/framework/geometry/QuantityVector.hpp | 4 +- corsika/framework/process/BaseProcess.hpp | 4 + .../framework/process/ContinuousProcess.hpp | 41 +- .../process/ContinuousProcessIndex.hpp | 26 ++ .../process/ContinuousProcessStepLength.hpp | 43 ++ corsika/framework/process/ProcessSequence.hpp | 99 +++-- corsika/framework/process/ProcessTraits.hpp | 63 +-- .../process/SwitchProcessSequence.hpp | 69 +++- corsika/modules/LongitudinalProfile.hpp | 4 +- corsika/modules/ParticleCut.hpp | 6 +- corsika/modules/TrackWriter.hpp | 2 +- corsika/modules/energy_loss/BetheBlochPDG.hpp | 12 +- .../modules/proposal/ContinuousProcess.hpp | 5 +- examples/staticsequence_example.cpp | 10 +- examples/vertical_EAS.cpp | 6 +- modules/conex | 2 +- modules/data | 2 +- tests/framework/testProcessSequence.cpp | 385 ++++++++++++++---- tests/modules/testObservationPlane.cpp | 56 ++- tests/modules/testParticleCut.cpp | 1 + 35 files changed, 895 insertions(+), 340 deletions(-) create mode 100644 corsika/framework/process/ContinuousProcessIndex.hpp create mode 100644 corsika/framework/process/ContinuousProcessStepLength.hpp diff --git a/corsika/detail/framework/core/Cascade.inl b/corsika/detail/framework/core/Cascade.inl index 8cd5b2e39..0e9161259 100644 --- a/corsika/detail/framework/core/Cascade.inl +++ b/corsika/detail/framework/core/Cascade.inl @@ -10,6 +10,8 @@ #include <corsika/framework/core/PhysicalUnits.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> @@ -118,7 +120,10 @@ namespace corsika { next_interact); // determine the maximum geometric step length - LengthType const continuous_max_dist = sequence_.getMaxStepLength(vParticle, step); + ContinuousProcessStepLength const continuousMaxStep = + sequence_.getMaxStepLength(vParticle, step); + LengthType const continuous_max_dist = continuousMaxStep; + ContinuousProcessIndex const limitingId = continuousMaxStep; // take minimum of geometry, interaction, decay for next step auto const min_distance = @@ -142,7 +147,8 @@ namespace corsika { vParticle.setTime(vParticle.getTime() + step.getDuration()); // apply all continuous processes on particle + track - if (sequence_.doContinuous(vParticle, step) == ProcessReturn::ParticleAbsorbed) { + if (sequence_.doContinuous(vParticle, step, limitingId) == + ProcessReturn::ParticleAbsorbed) { CORSIKA_LOG_DEBUG("Cascade: delete absorbed particle PID={} E={} GeV", vParticle.getPID(), vParticle.getEnergy() / 1_GeV); if (!vParticle.isErased()) vParticle.erase(); diff --git a/corsika/detail/framework/geometry/Plane.inl b/corsika/detail/framework/geometry/Plane.inl index e158e04d3..d32167cf1 100644 --- a/corsika/detail/framework/geometry/Plane.inl +++ b/corsika/detail/framework/geometry/Plane.inl @@ -12,6 +12,8 @@ #include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/Vector.hpp> +#include <sstream> + namespace corsika { inline bool Plane::isAbove(Point const& vP) const { @@ -26,4 +28,10 @@ namespace corsika { inline Plane::DimLessVec const& Plane::getNormal() const { return normal_; } + inline std::string Plane::asString() const { + std::ostringstream txt; + txt << "center=" << center_ << ", normal=" << normal_; + return txt.str(); + } + } // namespace corsika diff --git a/corsika/detail/framework/geometry/Point.inl b/corsika/detail/framework/geometry/Point.inl index 6c550c1ce..e424812f0 100644 --- a/corsika/detail/framework/geometry/Point.inl +++ b/corsika/detail/framework/geometry/Point.inl @@ -95,4 +95,10 @@ namespace corsika { return Vector<length_d>(cs, getCoordinates() - pB.getCoordinates(cs)); } + inline std::ostream& operator<<(std::ostream& os, corsika::Point const& p) { + auto const& qv = p.getCoordinates(); + os << qv << " m"; + return os; + } + } // namespace corsika diff --git a/corsika/detail/framework/geometry/QuantityVector.inl b/corsika/detail/framework/geometry/QuantityVector.inl index 9df35aab4..6ba02e4f8 100644 --- a/corsika/detail/framework/geometry/QuantityVector.inl +++ b/corsika/detail/framework/geometry/QuantityVector.inl @@ -145,7 +145,7 @@ namespace corsika { template <typename TDimension> inline std::ostream& operator<<(std::ostream& os, - corsika::QuantityVector<TDimension> const qv) { + corsika::QuantityVector<TDimension> const& qv) { using quantity_type = phys::units::quantity<TDimension, double>; os << '(' << qv.eigenVector_(0) << ' ' << qv.eigenVector_(1) << ' ' diff --git a/corsika/detail/framework/geometry/Vector.inl b/corsika/detail/framework/geometry/Vector.inl index cbfd597b3..2ecc82e65 100644 --- a/corsika/detail/framework/geometry/Vector.inl +++ b/corsika/detail/framework/geometry/Vector.inl @@ -228,4 +228,12 @@ namespace corsika { bareResult); } + template <typename TDimension> + inline std::ostream& operator<<(std::ostream& os, + corsika::Vector<TDimension> const& v) { + auto const& qv = v.getComponents(); + os << qv; + return os; + } + } // namespace corsika diff --git a/corsika/detail/framework/process/ProcessSequence.inl b/corsika/detail/framework/process/ProcessSequence.inl index 2ca682b4a..19056ad6c 100644 --- a/corsika/detail/framework/process/ProcessSequence.inl +++ b/corsika/detail/framework/process/ProcessSequence.inl @@ -12,6 +12,8 @@ #include <corsika/framework/process/BaseProcess.hpp> #include <corsika/framework/process/BoundaryCrossingProcess.hpp> #include <corsika/framework/process/ContinuousProcess.hpp> +#include <corsika/framework/process/ContinuousProcessStepLength.hpp> +#include <corsika/framework/process/ContinuousProcessIndex.hpp> #include <corsika/framework/process/DecayProcess.hpp> #include <corsika/framework/process/InteractionProcess.hpp> #include <corsika/framework/process/ProcessReturn.hpp> @@ -24,11 +26,14 @@ namespace corsika { - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TParticle> - ProcessReturn ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::doBoundaryCrossing( - TParticle& particle, typename TParticle::node_type const& from, - typename TParticle::node_type const& to) { + ProcessReturn ProcessSequence< + TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::doBoundaryCrossing(TParticle& particle, + typename TParticle::node_type const& from, + typename TParticle::node_type const& to) { ProcessReturn ret = ProcessReturn::Ok; if constexpr (std::is_base_of_v<BoundaryCrossingProcess<process1_type>, @@ -46,25 +51,38 @@ namespace corsika { return ret; } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TParticle, typename TTrack> - ProcessReturn ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::doContinuous(TParticle& particle, - TTrack& vT) { + ProcessReturn + ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>:: + doContinuous(TParticle& particle, TTrack& vT, + [[maybe_unused]] ContinuousProcessIndex const limitId) { ProcessReturn ret = ProcessReturn::Ok; - if constexpr (std::is_base_of_v<ContinuousProcess<process1_type>, process1_type> || - t1ProcSeq) { - ret |= A_.doContinuous(particle, vT); + if constexpr (t1ProcSeq) { + ret |= A_.doContinuous(particle, vT, limitId); + } else if constexpr (is_continuous_process_v<process1_type>) { + ret |= + A_.doContinuous(particle, vT, limitId == ContinuousProcessIndex(IndexProcess1)); } - if constexpr (std::is_base_of_v<ContinuousProcess<process2_type>, process2_type> || - t2ProcSeq) { - if (!isAbsorbed(ret)) { ret |= B_.doContinuous(particle, vT); } + + if constexpr (t2ProcSeq) { + if (!isAbsorbed(ret)) { ret |= B_.doContinuous(particle, vT, limitId); } + } else if constexpr (is_continuous_process_v<process2_type>) { + if (!isAbsorbed(ret)) { + ret |= B_.doContinuous(particle, vT, + limitId == ContinuousProcessIndex(IndexProcess2)); + } } + return ret; } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TSecondaries> - void ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::doSecondaries(TSecondaries& vS) { + void ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::doSecondaries(TSecondaries& vS) { if constexpr (std::is_base_of_v<SecondariesProcess<process1_type>, process1_type> || t1ProcSeq) { A_.doSecondaries(vS); @@ -75,8 +93,10 @@ namespace corsika { } } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> - bool ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::checkStep() { + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> + bool ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::checkStep() { bool ret = false; if constexpr (std::is_base_of_v<StackProcess<process1_type>, process1_type> || (t1ProcSeq && !t1SwitchProcSeq)) { @@ -89,9 +109,11 @@ namespace corsika { return ret; } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TStack> - void ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::doStack(TStack& stack) { + void ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::doStack(TStack& stack) { if constexpr (std::is_base_of_v<StackProcess<process1_type>, process1_type> || (t1ProcSeq && !t1SwitchProcSeq)) { if (A_.checkStep()) { A_.doStack(stack); } @@ -102,30 +124,52 @@ namespace corsika { } } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + /** + * Calculate the maximum allowed length of the next tracking step, based on all + * ContinuousProcess-es + * + * The maximum allowed step length is the minimum of the allowed track lenght over all + * ContinuousProcess-es in the ProcessSequence. + * + * \return: ContinuousProcessStepLength which contains the step length itself in + * LengthType, and a unique identifier of the related ContinuousProcess. + **/ + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TParticle, typename TTrack> - LengthType ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::getMaxStepLength(TParticle& particle, - TTrack& vTrack) { - LengthType max_length = // if no other process in the sequence implements it - std::numeric_limits<double>::infinity() * meter; + ContinuousProcessStepLength + ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::getMaxStepLength(TParticle& particle, TTrack& vTrack) { + // if no other process in the sequence implements it + ContinuousProcessStepLength max_length(std::numeric_limits<double>::infinity() * + meter); - if constexpr (std::is_base_of_v<ContinuousProcess<process1_type>, process1_type> || - t1ProcSeq) { - LengthType const len = A_.getMaxStepLength(particle, vTrack); - max_length = std::min(max_length, len); + if constexpr (t1ProcSeq) { + ContinuousProcessStepLength const step = A_.getMaxStepLength(particle, vTrack); + max_length = std::min(max_length, step); + } else if constexpr (is_continuous_process_v<process1_type>) { + ContinuousProcessStepLength const step(A_.getMaxStepLength(particle, vTrack), + ContinuousProcessIndex(IndexProcess1)); + max_length = std::min(max_length, step); } - if constexpr (std::is_base_of_v<ContinuousProcess<process2_type>, process2_type> || - t2ProcSeq) { - LengthType const len = B_.getMaxStepLength(particle, vTrack); - max_length = std::min(max_length, len); + // return ContinuousProcessStepLength(std::min(max_length, len), IndexProcess1); + if constexpr (t2ProcSeq) { + ContinuousProcessStepLength const step = B_.getMaxStepLength(particle, vTrack); + max_length = std::min(max_length, step); + } else if constexpr (is_continuous_process_v<process2_type>) { + ContinuousProcessStepLength const step(B_.getMaxStepLength(particle, vTrack), + ContinuousProcessIndex(IndexProcess2)); + max_length = std::min(max_length, step); } return max_length; } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TParticle> - InverseGrammageType ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::getInverseInteractionLength( - TParticle&& particle) { + InverseGrammageType + ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::getInverseInteractionLength(TParticle&& particle) { InverseGrammageType tot = 0 * meter * meter / gram; // default value @@ -140,11 +184,14 @@ namespace corsika { return tot; } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TSecondaryView> - inline ProcessReturn ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::selectInteraction( - TSecondaryView& view, [[maybe_unused]] InverseGrammageType lambda_inv_select, - [[maybe_unused]] InverseGrammageType lambda_inv_sum) { + inline ProcessReturn + ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>:: + selectInteraction(TSecondaryView& view, + [[maybe_unused]] InverseGrammageType lambda_inv_select, + [[maybe_unused]] InverseGrammageType lambda_inv_sum) { // TODO: add check for lambda_inv_select>lambda_inv_tot @@ -182,10 +229,12 @@ namespace corsika { return ProcessReturn::Ok; } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> template <typename TParticle> - inline InverseTimeType ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::getInverseLifetime( - TParticle&& particle) { + inline InverseTimeType + ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::getInverseLifetime(TParticle&& particle) { InverseTimeType tot = 0 / second; // default value @@ -200,12 +249,15 @@ namespace corsika { return tot; } - template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, int IndexStart, int IndexProcess1, + int IndexProcess2> // select decay process template <typename TSecondaryView> - inline ProcessReturn ProcessSequence<TProcess1, TProcess2, IndexStart, IndexProcess1, IndexProcess2>::selectDecay( - TSecondaryView& view, [[maybe_unused]] InverseTimeType decay_inv_select, - [[maybe_unused]] InverseTimeType decay_inv_sum) { + inline ProcessReturn ProcessSequence< + TProcess1, TProcess2, IndexStart, IndexProcess1, + IndexProcess2>::selectDecay(TSecondaryView& view, + [[maybe_unused]] InverseTimeType decay_inv_select, + [[maybe_unused]] InverseTimeType decay_inv_sum) { // TODO: add check for decay_inv_select>decay_inv_tot diff --git a/corsika/detail/framework/process/SwitchProcessSequence.inl b/corsika/detail/framework/process/SwitchProcessSequence.inl index 413caae4a..2eadc8782 100644 --- a/corsika/detail/framework/process/SwitchProcessSequence.inl +++ b/corsika/detail/framework/process/SwitchProcessSequence.inl @@ -12,6 +12,8 @@ #include <corsika/framework/process/ProcessTraits.hpp> #include <corsika/framework/process/BoundaryCrossingProcess.hpp> #include <corsika/framework/process/ContinuousProcess.hpp> +#include <corsika/framework/process/ContinuousProcessStepLength.hpp> +#include <corsika/framework/process/ContinuousProcessIndex.hpp> #include <corsika/framework/process/DecayProcess.hpp> #include <corsika/framework/process/InteractionProcess.hpp> #include <corsika/framework/process/ProcessReturn.hpp> @@ -25,11 +27,14 @@ namespace corsika { - template <typename TProcess1, typename TProcess2, typename TSelect, - int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> template <typename TParticle, typename TVTNType> - ProcessReturn SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, IndexProcess2>::doBoundaryCrossing( - TParticle& particle, TVTNType const& from, TVTNType const& to) { + ProcessReturn + SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, + IndexProcess2>::doBoundaryCrossing(TParticle& particle, + TVTNType const& from, + TVTNType const& to) { switch (select_(particle)) { case SwitchResult::First: { if constexpr (std::is_base_of_v<BoundaryCrossingProcess<process1_type>, @@ -51,24 +56,27 @@ namespace corsika { return ProcessReturn::Ok; } - template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> template <typename TParticle, typename TTrack> - inline ProcessReturn SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, IndexProcess2>::doContinuous( - TParticle& particle, TTrack& vT) { + inline ProcessReturn SwitchProcessSequence< + TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, + IndexProcess2>::doContinuous(TParticle& particle, TTrack& vT, + ContinuousProcessIndex const idLimit) { switch (select_(particle)) { case SwitchResult::First: { - if constexpr (std::is_base_of_v<ContinuousProcess<process1_type>, - process1_type> || - t1ProcSeq) { - return A_.doContinuous(particle, vT); + if constexpr (t1ProcSeq) { return A_.doContinuous(particle, vT, idLimit); } + if constexpr (is_continuous_process_v<process1_type>) { + return A_.doContinuous(particle, vT, + idLimit == ContinuousProcessIndex(IndexProcess1)); } break; } case SwitchResult::Second: { - if constexpr (std::is_base_of_v<ContinuousProcess<process2_type>, - process2_type> || - t2ProcSeq) { - return B_.doContinuous(particle, vT); + if constexpr (t2ProcSeq) { return B_.doContinuous(particle, vT, idLimit); } + if constexpr (is_continuous_process_v<process2_type>) { + return B_.doContinuous(particle, vT, + idLimit == ContinuousProcessIndex(IndexProcess2)); } break; } @@ -76,10 +84,12 @@ namespace corsika { return ProcessReturn::Ok; } - template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> template <typename TSecondaries> - inline void SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, IndexProcess2>::doSecondaries( - TSecondaries& vS) { + inline void + SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, + IndexProcess2>::doSecondaries(TSecondaries& vS) { const auto& particle = vS.parent(); switch (select_(particle)) { case SwitchResult::First: { @@ -101,39 +111,42 @@ namespace corsika { } } - template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> template <typename TParticle, typename TTrack> - inline LengthType SwitchProcessSequence<TProcess1, TProcess2, - TSelect, IndexStart, IndexProcess1, IndexProcess2>::getMaxStepLength(TParticle& particle, - TTrack& vTrack) { + inline ContinuousProcessStepLength + SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, + IndexProcess2>::getMaxStepLength(TParticle& particle, + TTrack& vTrack) { switch (select_(particle)) { case SwitchResult::First: { - if constexpr (std::is_base_of_v<ContinuousProcess<process1_type>, - process1_type> || - t1ProcSeq) { - return A_.getMaxStepLength(particle, vTrack); + if constexpr (t1ProcSeq) { return A_.getMaxStepLength(particle, vTrack); } + if constexpr (is_continuous_process_v<process1_type>) { + return ContinuousProcessStepLength(A_.getMaxStepLength(particle, vTrack), + ContinuousProcessIndex(IndexProcess1)); } break; } case SwitchResult::Second: { - if constexpr (std::is_base_of_v<ContinuousProcess<process2_type>, - process2_type> || - t2ProcSeq) { - return B_.getMaxStepLength(particle, vTrack); + if constexpr (t2ProcSeq) { return B_.getMaxStepLength(particle, vTrack); } + if constexpr (is_continuous_process_v<process2_type>) { + return ContinuousProcessStepLength(B_.getMaxStepLength(particle, vTrack), + ContinuousProcessIndex(IndexProcess2)); } break; } } // if no other process in the sequence implements it - return std::numeric_limits<double>::infinity() * meter; + return ContinuousProcessStepLength(std::numeric_limits<double>::infinity() * meter); } - template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> template <typename TParticle> - inline InverseGrammageType - SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, IndexProcess2>::getInverseInteractionLength( - TParticle&& particle) { + inline InverseGrammageType SwitchProcessSequence< + TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, + IndexProcess2>::getInverseInteractionLength(TParticle&& particle) { switch (select_(particle)) { case SwitchResult::First: { @@ -156,12 +169,14 @@ namespace corsika { return 0 * meter * meter / gram; // default value } - template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> template <typename TSecondaryView> - inline ProcessReturn - SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, IndexProcess2>::selectInteraction( - TSecondaryView& view, [[maybe_unused]] InverseGrammageType lambda_inv_select, - [[maybe_unused]] InverseGrammageType lambda_inv_sum) { + inline ProcessReturn SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, + IndexProcess1, IndexProcess2>:: + selectInteraction(TSecondaryView& view, + [[maybe_unused]] InverseGrammageType lambda_inv_select, + [[maybe_unused]] InverseGrammageType lambda_inv_sum) { switch (select_(view.parent())) { case SwitchResult::First: { if constexpr (t1ProcSeq) { @@ -204,11 +219,12 @@ namespace corsika { return ProcessReturn::Ok; } - template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> template <typename TParticle> inline InverseTimeType - SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, IndexProcess2>::getInverseLifetime( - TParticle&& particle) { + SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, + IndexProcess2>::getInverseLifetime(TParticle&& particle) { switch (select_(particle)) { case SwitchResult::First: { @@ -230,12 +246,15 @@ namespace corsika { return 0 / second; // default value } - template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, int IndexProcess1, int IndexProcess2> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart, + int IndexProcess1, int IndexProcess2> // select decay process template <typename TSecondaryView> - inline ProcessReturn SwitchProcessSequence<TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, IndexProcess2>::selectDecay( - TSecondaryView& view, [[maybe_unused]] InverseTimeType decay_inv_select, - [[maybe_unused]] InverseTimeType decay_inv_sum) { + inline ProcessReturn SwitchProcessSequence< + TProcess1, TProcess2, TSelect, IndexStart, IndexProcess1, + IndexProcess2>::selectDecay(TSecondaryView& view, + [[maybe_unused]] InverseTimeType decay_inv_select, + [[maybe_unused]] InverseTimeType decay_inv_sum) { switch (select_(view.parent())) { case SwitchResult::First: { if constexpr (t1ProcSeq) { @@ -278,11 +297,23 @@ namespace corsika { return ProcessReturn::Ok; } + /* + /// traits marker to identify objectas ProcessSequence + template <typename TProcess1, typename TProcess2, typename TSelect> + struct is_process_sequence<ProcessSequence<typename std::decay_t<TProcess1>, + typename std::decay_t<TProcess2>, + typename std::decay_t<TSelect>>> + : std::true_type {}; + */ /// traits marker to identify objectas ProcessSequence template <typename TProcess1, typename TProcess2, typename TSelect> struct is_process_sequence<SwitchProcessSequence<TProcess1, TProcess2, TSelect>> : std::true_type {}; + template <typename TProcess1, typename TProcess2, typename TSelect> + struct is_process_sequence<SwitchProcessSequence<TProcess1, TProcess2, TSelect>&> + : std::true_type {}; + /// traits marker to identify objectas SwitchProcessSequence template <typename TProcess1, typename TProcess2, typename TSelect> struct is_switch_process_sequence<SwitchProcessSequence<TProcess1, TProcess2, TSelect>> diff --git a/corsika/detail/modules/LongitudinalProfile.inl b/corsika/detail/modules/LongitudinalProfile.inl index d18813c26..df6bb471d 100644 --- a/corsika/detail/modules/LongitudinalProfile.inl +++ b/corsika/detail/modules/LongitudinalProfile.inl @@ -27,7 +27,7 @@ namespace corsika { template <typename TParticle, typename TTrack> ProcessReturn LongitudinalProfile::doContinuous(TParticle const& vP, - TTrack const& vTrack) { + TTrack const& vTrack, bool const) { auto const pid = vP.getPID(); GrammageType const grammageStart = shower_axis_.getProjectedX(vTrack.getPosition(0)); diff --git a/corsika/detail/modules/ObservationPlane.inl b/corsika/detail/modules/ObservationPlane.inl index 526fb273a..74c29b336 100644 --- a/corsika/detail/modules/ObservationPlane.inl +++ b/corsika/detail/modules/ObservationPlane.inl @@ -28,34 +28,30 @@ namespace corsika { } ProcessReturn ObservationPlane::doContinuous( - corsika::setup::Stack::particle_type& particle, - corsika::setup::Trajectory& trajectory, + corsika::setup::Stack::particle_type& particle, corsika::setup::Trajectory&, bool const stepLimit) { - auto const* volumeNode = particle.getNode(); - - if (!stepLimit) { - return ProcessReturn::Ok; - } - - HEPEnergyType const energy = particle.getEnergy(); - TimeType const timeOfIntersection = particle.getTime(); - Point const pointOfIntersection = particle.getPosition(); - Vector const displacement = pointOfIntersection - plane_.getCenter(); - - outputStream_ << static_cast<int>(get_PDG(particle.getPID())) << ' ' << energy / 1_eV - << ' ' << displacement.dot(xAxis_) / 1_m << ' ' - << displacement.dot(yAxis_) / 1_m - << (pointOfIntersection - plane_.getCenter()).getNorm() / 1_m - << '\n'; - - if (deleteOnHit_) { - count_ground_++; - energy_ground_ += energy; - particle.erase(); - return ProcessReturn::ParticleAbsorbed; - } else { - return ProcessReturn::Ok; + /* + The current step did not yet reach the ObservationPlane, do nothing now and wait: + */ + if (!stepLimit) { return ProcessReturn::Ok; } + + HEPEnergyType const energy = particle.getEnergy(); + Point const pointOfIntersection = particle.getPosition(); + Vector const displacement = pointOfIntersection - plane_.getCenter(); + + outputStream_ << static_cast<int>(get_PDG(particle.getPID())) << ' ' << energy / 1_eV + << ' ' << displacement.dot(xAxis_) / 1_m << ' ' + << displacement.dot(yAxis_) / 1_m + << (pointOfIntersection - plane_.getCenter()).getNorm() / 1_m << '\n'; + + if (deleteOnHit_) { + count_ground_++; + energy_ground_ += energy; + particle.erase(); + return ProcessReturn::ParticleAbsorbed; + } else { + return ProcessReturn::Ok; } } @@ -66,18 +62,22 @@ namespace corsika { auto const& volumeNode = particle.getNode(); typedef typename std::remove_const_t< - std::remove_reference_t<decltype(volumeNode->getModelProperties())>> - medium_type; - - Intersections const intersection = setup::Tracking::intersect<corsika::setup::Stack::particle_type, medium_type>(particle, plane_, - volumeNode->getModelProperties()); + std::remove_reference_t<decltype(volumeNode->getModelProperties())>> + medium_type; + Intersections const intersection = + setup::Tracking::intersect<corsika::setup::Stack::particle_type, medium_type>( + particle, plane_, volumeNode->getModelProperties()); TimeType const timeOfIntersection = intersection.getEntry(); - - if (timeOfIntersection < TimeType::zero()) { + + CORSIKA_LOG_TRACE("particle={}, pos={}, dir={}, plane={}, timeOfIntersection={}", + particle.asString(), particle.getPosition(), + particle.getDirection(), plane_.asString(), timeOfIntersection); + + if (timeOfIntersection < TimeType::zero()) { return std::numeric_limits<double>::infinity() * 1_m; - } + } if (timeOfIntersection > trajectory.getDuration()) { return std::numeric_limits<double>::infinity() * 1_m; } @@ -85,9 +85,8 @@ namespace corsika { double const fractionOfIntersection = timeOfIntersection / trajectory.getDuration(); auto const pointOfIntersection = trajectory.getPosition(fractionOfIntersection); - auto dist = (trajectory.getPosition(0) - pointOfIntersection).getNorm() * 1.001; // make max. step length a bit longer, to assure crossing - CORSIKA_LOG_TRACE("ObservationPlane: getMaxStepLength l={} m", - dist / 1_m); + auto dist = (trajectory.getPosition(0) - pointOfIntersection).getNorm(); + CORSIKA_LOG_TRACE("ObservationPlane: getMaxStepLength l={} m", dist / 1_m); return dist; } diff --git a/corsika/detail/modules/ParticleCut.inl b/corsika/detail/modules/ParticleCut.inl index 7a22b4d71..3fd882225 100644 --- a/corsika/detail/modules/ParticleCut.inl +++ b/corsika/detail/modules/ParticleCut.inl @@ -145,7 +145,7 @@ namespace corsika { } ProcessReturn ParticleCut::doContinuous(corsika::setup::Stack::particle_type& particle, - corsika::setup::Trajectory const&) { + corsika::setup::Trajectory const&, bool const) { CORSIKA_LOG_TRACE("ParticleCut::DoContinuous"); if (checkCutParticle(particle)) { CORSIKA_LOG_TRACE("removing during continuous"); diff --git a/corsika/detail/modules/TrackWriter.inl b/corsika/detail/modules/TrackWriter.inl index 27b47cf65..c6f72edf4 100644 --- a/corsika/detail/modules/TrackWriter.inl +++ b/corsika/detail/modules/TrackWriter.inl @@ -31,7 +31,8 @@ namespace corsika { } template <typename TParticle, typename TTrack> - ProcessReturn TrackWriter::doContinuous(const TParticle& vP, const TTrack& vT) { + ProcessReturn TrackWriter::doContinuous(const TParticle& vP, const TTrack& vT, + bool const) { auto const start = vT.getPosition(0).getCoordinates(); auto const delta = vT.getPosition(1).getCoordinates() - start; auto const pdg = static_cast<int>(get_PDG(vP.getPID())); diff --git a/corsika/detail/modules/energy_loss/BetheBlochPDG.inl b/corsika/detail/modules/energy_loss/BetheBlochPDG.inl index 89fe81c7b..cbabb0892 100644 --- a/corsika/detail/modules/energy_loss/BetheBlochPDG.inl +++ b/corsika/detail/modules/energy_loss/BetheBlochPDG.inl @@ -140,7 +140,7 @@ namespace corsika { } ProcessReturn BetheBlochPDG::doContinuous(setup::Stack::particle_type& p, - setup::Trajectory const& t) { + setup::Trajectory const& t, bool const) { if (p.getChargeNumber() == 0) return ProcessReturn::Ok; GrammageType const dX = @@ -174,7 +174,7 @@ namespace corsika { // slightly smaller than emCut since, either this Step is limited // by energy_lim, then the particle is stopped in a very short // range (before doing anythin else) and is then removed - // instantly. The exact position where it reaches emCut is not + // instantly. The exact 3D position where it reaches emCut is not very // important, the important fact is that its E_kin is zero // afterwards. // diff --git a/corsika/detail/modules/proposal/ContinuousProcess.inl b/corsika/detail/modules/proposal/ContinuousProcess.inl index 8bfbd705b..26f604c99 100644 --- a/corsika/detail/modules/proposal/ContinuousProcess.inl +++ b/corsika/detail/modules/proposal/ContinuousProcess.inl @@ -88,7 +88,7 @@ namespace corsika::proposal { template <> ProcessReturn ContinuousProcess::doContinuous(setup::Stack::particle_type& vP, - setup::Trajectory const& vT) { + setup::Trajectory const& vT, bool const) { if (!canInteract(vP.getPID())) return ProcessReturn::Ok; if (vT.getLength() == 0_m) return ProcessReturn::Ok; diff --git a/corsika/detail/modules/tracking/TrackingStraight.inl b/corsika/detail/modules/tracking/TrackingStraight.inl index 2c284b4d0..5869601a5 100644 --- a/corsika/detail/modules/tracking/TrackingStraight.inl +++ b/corsika/detail/modules/tracking/TrackingStraight.inl @@ -92,6 +92,8 @@ namespace corsika::tracking_line { auto const n = plane.getNormal(); auto const c = n.dot(velocity); + CORSIKA_LOG_TRACE("c={}, delta={}, momentum={}", c, delta, particle.getMomentum()); + return Intersections(c.magnitude() == 0 ? std::numeric_limits<TimeType::value_type>::infinity() * 1_s : n.dot(delta) / c); diff --git a/corsika/framework/geometry/Plane.hpp b/corsika/framework/geometry/Plane.hpp index 9b2eacade..7218e6b35 100644 --- a/corsika/framework/geometry/Plane.hpp +++ b/corsika/framework/geometry/Plane.hpp @@ -12,6 +12,8 @@ #include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/Vector.hpp> +#include <string> + namespace corsika { class Plane { @@ -32,6 +34,8 @@ namespace corsika { DimLessVec const& getNormal() const; + std::string asString() const; + public: Point const center_; DimLessVec const normal_; diff --git a/corsika/framework/geometry/QuantityVector.hpp b/corsika/framework/geometry/QuantityVector.hpp index 235237afe..eb6c2f11e 100644 --- a/corsika/framework/geometry/QuantityVector.hpp +++ b/corsika/framework/geometry/QuantityVector.hpp @@ -101,7 +101,7 @@ namespace corsika { template <typename T> friend class corsika::Vector; template <typename TDim> - friend std::ostream& operator<<(std::ostream& os, QuantityVector<TDim> qv); + friend std::ostream& operator<<(std::ostream& os, QuantityVector<TDim> const& qv); protected: Eigen::Vector3d @@ -114,7 +114,7 @@ namespace corsika { template <typename TDimension> inline std::ostream& operator<<(std::ostream& os, - corsika::QuantityVector<TDimension> const qv); + corsika::QuantityVector<TDimension> const& qv); } // namespace corsika diff --git a/corsika/framework/process/BaseProcess.hpp b/corsika/framework/process/BaseProcess.hpp index e91651d12..55572291c 100644 --- a/corsika/framework/process/BaseProcess.hpp +++ b/corsika/framework/process/BaseProcess.hpp @@ -8,6 +8,10 @@ #pragma once +//#include <corsika/framework/process/ProcessTraits.hpp> + +#include <type_traits> + namespace corsika { class TDerived; // fwd decl diff --git a/corsika/framework/process/ContinuousProcess.hpp b/corsika/framework/process/ContinuousProcess.hpp index 065d4c234..521cb0ee2 100644 --- a/corsika/framework/process/ContinuousProcess.hpp +++ b/corsika/framework/process/ContinuousProcess.hpp @@ -8,6 +8,7 @@ #pragma once +#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/process/BaseProcess.hpp> #include <corsika/framework/process/ProcessReturn.hpp> #include <corsika/framework/process/ProcessTraits.hpp> @@ -29,11 +30,23 @@ namespace corsika { protected: public: // here starts the interface part - // -> enforce TDerived to implement DoContinuous... + /** + * Applies the effects of this ContinuousProcess on a Particle on a Track. + * + * Note, the stepLimit is a flag, if this particular process was responsible for the + * track-length limit. This can be used by the process to trigger activity. + * + * \todo -> enforce TDerived to implement doContinuous... + **/ template <typename TParticle, typename TTrack> ProcessReturn doContinuous(TParticle&, TTrack const&, bool const stepLimit) const; - // -> enforce TDerived to implement MaxStepLength... + /** + * Calculates/returns a possible step length limitation of this continuousprocess. + * + * + * \todo -> enforce TDerived to implement getMaxStepLength... + **/ template <typename TParticle, typename TTrack> LengthType getMaxStepLength(TParticle const& p, TTrack const& track) const; }; @@ -41,12 +54,20 @@ namespace corsika { /** * ProcessTraits specialization **/ - /* - template <typename TProcess, int N> - struct count_continuous<TProcess, N, - typename std::enable_if_t<std::is_base_of_v<ContinuousProcess<typename std::decay_t<TProcess>>, - typename std::decay_t<TProcess>>>> { - enum { count = N+1 }; - }; - */ + template <typename TProcess> + struct is_continuous_process< + TProcess, std::enable_if_t< + std::is_base_of_v<ContinuousProcess<typename std::decay_t<TProcess>>, + typename std::decay_t<TProcess>>>> + : std::true_type {}; + + template <typename TProcess, int N> + struct count_continuous<TProcess, N, + typename std::enable_if_t<is_continuous_process_v<TProcess>>> { + // std::is_base_of_v< + // ContinuousProcess<typename std::decay_t<TProcess>>, + // typename std::decay_t<TProcess>>>> { + enum { count = N + 1 }; + }; + } // namespace corsika diff --git a/corsika/framework/process/ContinuousProcessIndex.hpp b/corsika/framework/process/ContinuousProcessIndex.hpp new file mode 100644 index 000000000..4cba88fde --- /dev/null +++ b/corsika/framework/process/ContinuousProcessIndex.hpp @@ -0,0 +1,26 @@ +/* + * (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#pragma once + +namespace corsika { + + class ContinuousProcessIndex { + public: + ContinuousProcessIndex(int const id) + : id_(id) {} + void setIndex(int const id) { id_ = id; } + int getIndex() const { return id_; } + bool operator==(ContinuousProcessIndex const v) const { return id_ == v.id_; } + bool operator!=(ContinuousProcessIndex const v) const { return id_ != v.id_; } + + private: + int id_; + }; + +} // namespace corsika diff --git a/corsika/framework/process/ContinuousProcessStepLength.hpp b/corsika/framework/process/ContinuousProcessStepLength.hpp new file mode 100644 index 000000000..32b921857 --- /dev/null +++ b/corsika/framework/process/ContinuousProcessStepLength.hpp @@ -0,0 +1,43 @@ +/* + * (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#pragma once + +#include <corsika/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/process/ContinuousProcessIndex.hpp> + +namespace corsika { + + /** + * To store step length in LengthType and unique index in ProcessSequence of shortest + * step ContinuousProcess. + * + **/ + + class ContinuousProcessStepLength { + public: + ContinuousProcessStepLength(LengthType const step) + : step_(step) + , id_(0) {} + ContinuousProcessStepLength(LengthType const step, ContinuousProcessIndex const id) + : step_(step) + , id_(id) {} + void setLength(LengthType const step) { step_ = step; } + LengthType getLength() const { return step_; } + void setIndex(ContinuousProcessIndex const id) { id_ = id; } + ContinuousProcessIndex getIndex() const { return id_; } + operator ContinuousProcessIndex() const { return id_; } + operator LengthType() const { return step_; } + bool operator<(ContinuousProcessStepLength const& r) const { return step_ < r.step_; } + + private: + LengthType step_; + ContinuousProcessIndex id_; + }; + +} // namespace corsika diff --git a/corsika/framework/process/ProcessSequence.hpp b/corsika/framework/process/ProcessSequence.hpp index 594a6637b..d344673c6 100644 --- a/corsika/framework/process/ProcessSequence.hpp +++ b/corsika/framework/process/ProcessSequence.hpp @@ -16,6 +16,8 @@ #include <corsika/framework/process/ProcessTraits.hpp> #include <corsika/framework/process/BoundaryCrossingProcess.hpp> #include <corsika/framework/process/ContinuousProcess.hpp> +#include <corsika/framework/process/ContinuousProcessIndex.hpp> +#include <corsika/framework/process/ContinuousProcessStepLength.hpp> #include <corsika/framework/process/DecayProcess.hpp> #include <corsika/framework/process/InteractionProcess.hpp> #include <corsika/framework/process/ProcessReturn.hpp> @@ -26,6 +28,28 @@ namespace corsika { + /* + template <typename TProcess1, typename TProcess2 = NullModel, int IndexStart = 0, + int IndexProcess1 = count_continuous<TProcess1>::count, + int IndexProcess2 = + count_continuous<TProcess1, count_continuous<TProcess2>::count>::count> + class ProcessSequence; + */ + + /** + * traits class to count ContinuousProcess-es, specialized for ProcessSequence-es + **/ + // template <typename TProcess1, typename TProcess2, int N> + // struct count_continuous<ProcessSequence<TProcess1, TProcess2>, N> { + // enum { count = N + ProcessSequence<TProcess1,TProcess2>::nContinuous }; + //}; + + template <typename TProcess, int N> + struct count_continuous<TProcess, N, + typename std::enable_if_t<is_process_sequence_v<TProcess>>> { + enum { count = N + std::decay_t<TProcess>::nContinuous }; + }; + /** * * Definition of a static process list/sequence @@ -39,14 +63,23 @@ namespace corsika { * they are just classes. This allows us to handle both, rvalue as * well as lvalue Processes in the ProcessSequence. * - * (The sequence, and the processes use the CRTP, curiously recurring template pattern). + * (The sequence, and the processes use the CRTP, curiously recurring template + * pattern). * + * Template parameters: + * - TProcess1 is of type BaseProcess, either a dedicatd process, or a ProcessSequence + * - TProcess2 is of type BaseProcess, either a dedicatd process, or a ProcessSequence + * - IndexStart, IndexProcess1, IndexProcess2 are to count and index each + *ContinuousProcess in the entire process-chain **/ - template <typename TProcess1, typename TProcess2 = NullModel, - int IndexStart = 0, - int IndexProcess1 = count_continuous<TProcess1>::count, - int IndexProcess2 = count_continuous<TProcess1, count_continuous<TProcess2>::count>::count> + template <typename TProcess1, typename TProcess2 = NullModel, int IndexStart = 0, + int IndexProcess1 = count_continuous< + TProcess1, count_continuous<TProcess2, IndexStart>::count>::count, + int IndexProcess2 = count_continuous<TProcess2, IndexStart>::count> + // template <typename TProcess1, typename TProcess2, int IndexStart, int + // IndexProcess1, + // int IndexProcess2> class ProcessSequence : public BaseProcess<ProcessSequence<TProcess1, TProcess2>> { using process1_type = typename std::decay_t<TProcess1>; @@ -59,15 +92,18 @@ namespace corsika { static bool constexpr t2SwitchProcSeq = is_switch_process_sequence_v<process2_type>; // make sure only BaseProcess types TProcess1/2 are passed - static_assert(std::is_base_of_v<BaseProcess<process1_type>, process1_type>, + static_assert(is_base_process_v<process1_type>, "can only use process derived from BaseProcess in " "ProcessSequence, for Process 1"); - static_assert(std::is_base_of_v<BaseProcess<process2_type>, process2_type>, + static_assert(is_base_process_v<process2_type>, "can only use process derived from BaseProcess in " "ProcessSequence, for Process 2"); public: - enum { nContinuous = IndexProcess2 }; // static counter to index continuous processes + /** + * static counter to uniquely index (count) all ContinuousProcess in sequence. + **/ + enum { nContinuous = IndexProcess1 }; // resource management ProcessSequence() = delete; // only initialized objects @@ -96,7 +132,8 @@ namespace corsika { typename TParticle::node_type const& to); template <typename TParticle, typename TTrack> - inline ProcessReturn doContinuous(TParticle& particle, TTrack& vT); + inline ProcessReturn doContinuous(TParticle& particle, TTrack& vT, + ContinuousProcessIndex const limitID); template <typename TSecondaries> inline void doSecondaries(TSecondaries& vS); @@ -117,9 +154,19 @@ namespace corsika { template <typename TStack> inline void doStack(TStack& stack); + /** + * Determines the step-length limitation caused by ContinuousProcess-es in this + ProcessSequence. + * + * Returns a ContinuousProcessStepLength object, which contains both: the actual + * length (LengthType) as well as the index of the ContinuousProcess inside the + * ProcessSequence (for identification). + + **/ + template <typename TParticle, typename TTrack> - inline LengthType getMaxStepLength(TParticle& particle, TTrack& vTrack); - //inline std::pair<LengthType,int> getMaxStepLength(TParticle& particle, TTrack& vTrack); + inline ContinuousProcessStepLength getMaxStepLength(TParticle& particle, + TTrack& vTrack); template <typename TParticle> inline GrammageType getInteractionLength(TParticle&& particle) { @@ -152,7 +199,6 @@ namespace corsika { private: TProcess1 A_; /// process/list A, this is a reference, if possible TProcess2 B_; /// process/list B, this is a reference, if possible - }; /** @@ -176,12 +222,12 @@ namespace corsika { * * \param vA needs to derive from BaseProcess or ProcessSequence * \param vB paramter-pack, needs to derive BaseProcess or ProcessSequence + * **/ template <typename... TProcesses, typename TProcess1> inline typename std::enable_if_t< - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess1>>, - typename std::decay_t<TProcess1>>, + is_base_process_v<typename std::decay_t<TProcess1>>, ProcessSequence<TProcess1, decltype(make_sequence(std::declval<TProcesses>()...))>> make_sequence(TProcess1&& vA, TProcesses&&... vBs) { return ProcessSequence<TProcess1, @@ -198,13 +244,11 @@ namespace corsika { * \param vB needs to derive BaseProcess or ProcessSequence **/ template <typename TProcess1, typename TProcess2> - inline typename std::enable_if_t< - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess1>>, - typename std::decay_t<TProcess1>> && - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess2>>, - typename std::decay_t<TProcess2>>, - ProcessSequence<TProcess1, TProcess2>> - make_sequence(TProcess1&& vA, TProcess2&& vB) { + inline + typename std::enable_if_t<is_base_process_v<typename std::decay_t<TProcess1>> && + is_base_process_v<typename std::decay_t<TProcess2>>, + ProcessSequence<TProcess1, TProcess2>> + make_sequence(TProcess1&& vA, TProcess2&& vB) { return ProcessSequence<TProcess1, TProcess2>(vA, vB); } @@ -217,10 +261,8 @@ namespace corsika { * \param vA needs to derive from BaseProcess or ProcessSequence **/ template <typename TProcess> - inline typename std::enable_if_t< - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess>>, - typename std::decay_t<TProcess>>, - ProcessSequence<TProcess, NullModel>> + inline typename std::enable_if_t<is_base_process_v<typename std::decay_t<TProcess>>, + ProcessSequence<TProcess, NullModel>> make_sequence(TProcess&& vA) { return ProcessSequence<TProcess, NullModel>(vA, NullModel()); } @@ -232,15 +274,10 @@ namespace corsika { struct is_process_sequence<ProcessSequence<TProcess1, TProcess2>> : std::true_type { // only switch on for BaseProcesses template <typename std::enable_if_t< - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess1>>, - typename std::decay_t<TProcess1>> && - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess2>>, - typename std::decay_t<TProcess2>>, - int>> + is_base_process_v<TProcess1> && is_base_process_v<TProcess2>, int>> is_process_sequence() {} }; - } // namespace corsika #include <corsika/detail/framework/process/ProcessSequence.inl> diff --git a/corsika/framework/process/ProcessTraits.hpp b/corsika/framework/process/ProcessTraits.hpp index 0eb5e7aae..104a40711 100644 --- a/corsika/framework/process/ProcessTraits.hpp +++ b/corsika/framework/process/ProcessTraits.hpp @@ -12,12 +12,40 @@ * \file ProcessTraits.hpp */ -#include <corsika/framework/process/ProcessTraits.hpp> +//#include <corsika/framework/process/BaseProcess.hpp> +//#include <corsika/framework/process/ProcessSequence.hpp> +//#include <corsika/framework/process/SwitchProcessSequence.hpp> +//#include <corsika/framework/process/ContinuousProcess.hpp> #include <type_traits> namespace corsika { + /** + * A traits marker to identify BaseProcess + */ + template <typename TProcess, typename Enable = void> + struct is_base_process : std::false_type {}; + + template <typename TProcess> + bool constexpr is_base_process_v = is_base_process<TProcess>::value; + + template <typename TProcess> + struct is_base_process< + TProcess, + std::enable_if_t<std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess>>, + typename std::decay_t<TProcess>>>> + : std::true_type {}; + + /** + * A traits marker to identify ContinuousProcess + */ + template <typename TProcess, typename Enable = void> + struct is_continuous_process : std::false_type {}; + + template <typename TProcess> + bool constexpr is_continuous_process_v = is_continuous_process<TProcess>::value; + /** * A traits marker to track which BaseProcess is also a ProcessSequence **/ @@ -47,34 +75,11 @@ namespace corsika { bool constexpr contains_stack_process_v = contains_stack_process<TClass>::value; /** - * traits class to count ContinuousProcess-es - **/ - template <typename TProcess, int N=0, typename Enable=void> - struct count_continuous { - enum { count = N }; - }; - - - /** - * traits class to count ContinuousProcess-es - **/ - template <typename TProcessSequence, int N> - struct count_continuous<TProcessSequence, N, - typename std::enable_if_t<is_process_sequence_v<TProcessSequence>>> { - enum { count = N+TProcessSequence::nContinuous }; - }; - - /** - * traits class to count ContinuousProcess-es + * traits class to count ContinuousProcess-es, general version **/ - - template <typename TSwitchProcessSequence, int N> - struct count_continuous<TSwitchProcessSequence, N, - typename std::enable_if_t<is_switch_process_sequence_v<TSwitchProcessSequence>>> { - enum { count = N+TSwitchProcessSequence::nContinuous }; - }; - - - + template <typename TProcess, int N = 0, typename Enable = void> + struct count_continuous { + enum { count = N }; + }; } // namespace corsika diff --git a/corsika/framework/process/SwitchProcessSequence.hpp b/corsika/framework/process/SwitchProcessSequence.hpp index 95f21a60d..df951154a 100644 --- a/corsika/framework/process/SwitchProcessSequence.hpp +++ b/corsika/framework/process/SwitchProcessSequence.hpp @@ -16,6 +16,7 @@ #include <corsika/framework/process/ProcessTraits.hpp> #include <corsika/framework/process/BoundaryCrossingProcess.hpp> #include <corsika/framework/process/ContinuousProcess.hpp> +#include <corsika/framework/process/ContinuousProcessIndex.hpp> #include <corsika/framework/process/DecayProcess.hpp> #include <corsika/framework/process/InteractionProcess.hpp> #include <corsika/framework/process/ProcessReturn.hpp> @@ -29,6 +30,32 @@ namespace corsika { + /* + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart = 0, + int IndexProcess1 = count_continuous<TProcess1>::count, + int IndexProcess2 = count_continuous<TProcess2>::count> + class SwitchProcessSequence; + */ + + /** + * traits class to count ContinuousProcess-es, specialized for ProcessSequence-es + **/ + + /* template <typename TProcess1, typename TProcess2, typename TSelect, int N> + struct count_continuous<SwitchProcessSequence<TProcess1, TProcess2, TSelect>, N> { + enum { + count = N + SwitchProcessSequence<TProcess1, TProcess2, TSelect>::nContinuous + }; + };*/ + + /* + template <typename TSProcess, int N> + struct count_continuous< + TSProcess, N, typename std::enable_if_t<is_switch_process_sequence_v<TSProcess>>> { + enum { count = N + TSProcess::nContinuous }; + }; + */ + /** * enum for the process switch selection: identify if First or * Second process branch should be used. @@ -57,13 +84,19 @@ namespace corsika { since this makes no sense. The StackProcess acts on an entire particle stack and not on indiviidual particles. + Template parameters: + - TProcess1 is of type BaseProcess, either a dedicatd process, or a ProcessSequence + - TProcess2 is of type BaseProcess, either a dedicatd process, or a ProcessSequence + - IndexStart, IndexProcess1, IndexProcess2 are to count and index each + ContinuousProcess in the entire process-chain + + See also class \sa ProcessSequence **/ - template <typename TProcess1, typename TProcess2, typename TSelect, - int IndexStart = 0, - int IndexProcess1 = count_continuous<TProcess1>::count, - int IndexProcess2 = count_continuous<TProcess1, count_continuous<TProcess2>::count>::count> + template <typename TProcess1, typename TProcess2, typename TSelect, int IndexStart = 0, + int IndexProcess1 = count_continuous<TProcess1, IndexStart>::count, + int IndexProcess2 = count_continuous<TProcess2, IndexProcess1>::count> class SwitchProcessSequence : public BaseProcess<SwitchProcessSequence<TProcess1, TProcess2, TSelect>> { @@ -74,10 +107,10 @@ namespace corsika { static bool constexpr t2ProcSeq = is_process_sequence_v<process2_type>; // make sure only BaseProcess types TProcess1/2 are passed - static_assert(std::is_base_of_v<BaseProcess<process1_type>, process1_type>, + static_assert(is_base_process_v<process1_type>, "can only use process derived from BaseProcess in " "SwitchProcessSequence, for Process 1"); - static_assert(std::is_base_of_v<BaseProcess<process2_type>, process2_type>, + static_assert(is_base_process_v<process2_type>, "can only use process derived from BaseProcess in " "SwitchProcessSequence, for Process 2"); @@ -97,7 +130,10 @@ namespace corsika { "ProcessSequence 2"); public: - enum { nContinuous = IndexProcess1+IndexProcess2 }; // static counter to index continuous processes + /** + * static counter to uniquely index (count) all ContinuousProcess in switch sequence. + **/ + enum { nContinuous = IndexProcess2 }; // resource management SwitchProcessSequence() = delete; // only initialized objects @@ -127,13 +163,15 @@ namespace corsika { TVTNType const& to); template <typename TParticle, typename TTrack> - inline ProcessReturn doContinuous(TParticle& particle, TTrack& vT); + inline ProcessReturn doContinuous(TParticle& particle, TTrack& vT, + ContinuousProcessIndex const limitId); template <typename TSecondaries> inline void doSecondaries(TSecondaries& vS); template <typename TParticle, typename TTrack> - inline LengthType getMaxStepLength(TParticle& particle, TTrack& vTrack); + inline ContinuousProcessStepLength getMaxStepLength(TParticle& particle, + TTrack& vTrack); template <typename TParticle> inline GrammageType getInteractionLength(TParticle&& particle) { @@ -183,17 +221,14 @@ namespace corsika { **/ template <typename TProcess1, typename TProcess2, typename TSelect> - inline typename std::enable_if_t< - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess1>>, - typename std::decay_t<TProcess1>> && - std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess2>>, - typename std::decay_t<TProcess2>>, - SwitchProcessSequence<TProcess1, TProcess2, TSelect>> - make_select(TProcess1&& vA, TProcess2&& vB, TSelect selector) { + inline + typename std::enable_if_t<is_base_process_v<typename std::decay_t<TProcess1>> && + is_base_process_v<typename std::decay_t<TProcess2>>, + SwitchProcessSequence<TProcess1, TProcess2, TSelect>> + make_select(TProcess1&& vA, TProcess2&& vB, TSelect selector) { return SwitchProcessSequence<TProcess1, TProcess2, TSelect>(vA, vB, selector); } - } // namespace corsika #include <corsika/detail/framework/process/SwitchProcessSequence.inl> diff --git a/corsika/modules/LongitudinalProfile.hpp b/corsika/modules/LongitudinalProfile.hpp index baaa50468..b06e2ef85 100644 --- a/corsika/modules/LongitudinalProfile.hpp +++ b/corsika/modules/LongitudinalProfile.hpp @@ -41,7 +41,9 @@ namespace corsika { GrammageType dX = 10_g / square(1_cm)); // profile binning); template <typename TParticle, typename TTrack> - ProcessReturn doContinuous(TParticle const&, TTrack const&); + ProcessReturn doContinuous( + TParticle const&, TTrack const&, + bool const flagLimit = false); // not needed for LongitudinalProfile template <typename TParticle, typename TTrack> LengthType getMaxStepLength(TParticle const&, TTrack const&) { diff --git a/corsika/modules/ParticleCut.hpp b/corsika/modules/ParticleCut.hpp index 1678c528e..9842dd034 100644 --- a/corsika/modules/ParticleCut.hpp +++ b/corsika/modules/ParticleCut.hpp @@ -50,8 +50,10 @@ namespace corsika { bool const em, bool const inv); void doSecondaries(corsika::setup::StackView&); - ProcessReturn doContinuous(corsika::setup::Stack::particle_type& vParticle, - corsika::setup::Trajectory const& vTrajectory); + ProcessReturn doContinuous( + corsika::setup::Stack::particle_type& vParticle, + corsika::setup::Trajectory const& vTrajectory, + const bool limitFlag = false); // this is not used for ParticleCut LengthType getMaxStepLength(corsika::setup::Stack::particle_type const&, corsika::setup::Trajectory const&) { return meter * std::numeric_limits<double>::infinity(); diff --git a/corsika/modules/TrackWriter.hpp b/corsika/modules/TrackWriter.hpp index c437bc7d1..5bf9856b3 100644 --- a/corsika/modules/TrackWriter.hpp +++ b/corsika/modules/TrackWriter.hpp @@ -22,7 +22,7 @@ namespace corsika { TrackWriter(std::string const& filename); template <typename TParticle, typename TTrack> - ProcessReturn doContinuous(TParticle const&, TTrack const&); + ProcessReturn doContinuous(TParticle const&, TTrack const&, bool const limitFlag); template <typename TParticle, typename TTrack> LengthType getMaxStepLength(TParticle const&, TTrack const&); diff --git a/corsika/modules/energy_loss/BetheBlochPDG.hpp b/corsika/modules/energy_loss/BetheBlochPDG.hpp index f8e875937..582a0c4e0 100644 --- a/corsika/modules/energy_loss/BetheBlochPDG.hpp +++ b/corsika/modules/energy_loss/BetheBlochPDG.hpp @@ -43,7 +43,17 @@ namespace corsika { public: BetheBlochPDG(ShowerAxis const& showerAxis); - ProcessReturn doContinuous(setup::Stack::particle_type&, setup::Trajectory const&); + /** clang-format-off + * Interface function of ContinuousProcess. + * + * \param particle The particle to process in its current state + * \param track The trajectory in space of this particle, on which doContinuous should + * act + * \param limitFlag flag to identify, if BetheBlochPDG::getMaxStepLength is the + * globally limiting factor (or not) + clang-format-on **/ + ProcessReturn doContinuous(setup::Stack::particle_type& particle, + setup::Trajectory const& track, bool const limitFlag); LengthType getMaxStepLength(setup::Stack::particle_type const&, setup::Trajectory const&) const; //! limited by the energy threshold! By default the limit is the particle diff --git a/corsika/modules/proposal/ContinuousProcess.hpp b/corsika/modules/proposal/ContinuousProcess.hpp index 3b8976f3a..0efbf12ec 100644 --- a/corsika/modules/proposal/ContinuousProcess.hpp +++ b/corsika/modules/proposal/ContinuousProcess.hpp @@ -67,8 +67,11 @@ namespace corsika::proposal { //! If the particle if below the given energy threshold where it will be //! considered stochastically, it will be absorbed. //! + //! \param limitFlag is true, if the track was actually limited by + //! proposal::ContinuousProcess::getMaxStepLength + //! template <typename TParticle, typename TTrack> - ProcessReturn doContinuous(TParticle&, TTrack const&); + ProcessReturn doContinuous(TParticle&, TTrack const& track, bool const limitFlag); //! //! Calculates maximal step length of process. diff --git a/examples/staticsequence_example.cpp b/examples/staticsequence_example.cpp index d7b9e06b5..3f6c5aff7 100644 --- a/examples/staticsequence_example.cpp +++ b/examples/staticsequence_example.cpp @@ -24,7 +24,7 @@ class Process1 : public ContinuousProcess<Process1> { public: Process1() {} template <typename D, typename T> - ProcessReturn doContinuous(D& d, T&) const { + ProcessReturn doContinuous(D& d, T&, bool const) const { for (int i = 0; i < nData; ++i) d.p[i] += 1; return ProcessReturn::Ok; } @@ -35,7 +35,7 @@ public: Process2() {} template <typename D, typename T> - inline ProcessReturn doContinuous(D& d, T&) const { + inline ProcessReturn doContinuous(D& d, T&, bool const) const { for (int i = 0; i < nData; ++i) d.p[i] -= 0.1 * i; return ProcessReturn::Ok; } @@ -46,7 +46,7 @@ public: Process3() {} template <typename D, typename T> - inline ProcessReturn doContinuous(D&, T&) const { + inline ProcessReturn doContinuous(D&, T&, bool const) const { return ProcessReturn::Ok; } }; @@ -56,7 +56,7 @@ public: Process4(const double v) : fV(v) {} template <typename D, typename T> - inline ProcessReturn doContinuous(D& d, T&) const { + inline ProcessReturn doContinuous(D& d, T&, bool const) const { for (int i = 0; i < nData; ++i) d.p[i] *= fV; return ProcessReturn::Ok; } @@ -90,7 +90,7 @@ void modular() { const int nEv = 10; for (int iEv = 0; iEv < nEv; ++iEv) { - sequence.doContinuous(particle, track); + sequence.doContinuous(particle, track, ContinuousProcessIndex(0)); for (int i = 0; i < nData; ++i) { check[i] += 1. - 0.1 * i; check[i] *= 1.5; diff --git a/examples/vertical_EAS.cpp b/examples/vertical_EAS.cpp index 4ebffab2e..a661ca3ed 100644 --- a/examples/vertical_EAS.cpp +++ b/examples/vertical_EAS.cpp @@ -254,9 +254,9 @@ int main(int argc, char** argv) { auto hadronSequence = make_select( urqmdCounted, make_sequence(sibyllNucCounted, sibyllCounted), EnergySwitch(55_GeV)); auto decaySequence = make_sequence(decayPythia, decaySibyll); - auto sequence = make_sequence(stackInspect, hadronSequence, reset_particle_mass, - decaySequence, em_continuous, cut, - trackWriter, observationLevel, longprof); + auto sequence = + make_sequence(stackInspect, hadronSequence, reset_particle_mass, decaySequence, + em_continuous, cut, trackWriter, observationLevel, longprof); // define air shower object, run simulation setup::Tracking tracking; diff --git a/modules/conex b/modules/conex index 73e3d1fa8..180215204 160000 --- a/modules/conex +++ b/modules/conex @@ -1 +1 @@ -Subproject commit 73e3d1fa850d2d3602a15b3b948ac1789fbc968d +Subproject commit 180215204035fa17c5f6cacb42588dca85d171ca diff --git a/modules/data b/modules/data index afe83dc19..fb7577314 160000 --- a/modules/data +++ b/modules/data @@ -1 +1 @@ -Subproject commit afe83dc19c1464deb176f38c3ddab80a64e081f4 +Subproject commit fb7577314e5e3c837fa5a3006dc4f3c0146cabf7 diff --git a/tests/framework/testProcessSequence.cpp b/tests/framework/testProcessSequence.cpp index 4dd0efc8b..5ae3239e4 100644 --- a/tests/framework/testProcessSequence.cpp +++ b/tests/framework/testProcessSequence.cpp @@ -10,6 +10,7 @@ #include <corsika/framework/process/SwitchProcessSequence.hpp> #include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/process/ProcessTraits.hpp> +#include <corsika/framework/process/ContinuousProcessStepLength.hpp> #include <catch2/catch.hpp> @@ -18,10 +19,12 @@ #include <iostream> #include <typeinfo> +#include <boost/type_index.hpp> + using namespace corsika; using namespace std; -static const int nData = 10; +static int const nData = 10; int globalCount = 0; // simple counter @@ -32,68 +35,110 @@ int checkCont = 0; // use this as a bit field class ContinuousProcess1 : public ContinuousProcess<ContinuousProcess1> { public: - ContinuousProcess1(const int v) - : v_(v) { + ContinuousProcess1(int const v, LengthType const step) + : v_(v) + , step_(step) { cout << "globalCount: " << globalCount << ", v_: " << v_ << std::endl; globalCount++; } + void setStep(LengthType const v) { step_ = v; } + template <typename D, typename T> - inline ProcessReturn doContinuous(D& d, T&) const { + inline ProcessReturn doContinuous(D& d, T&, bool const flag) const { + flag_ = flag; cout << "ContinuousProcess1::DoContinuous" << endl; checkCont |= 1; for (int i = 0; i < nData; ++i) d.data_[i] += 0.933; return ProcessReturn::Ok; } + template <typename TParticle, typename TTrack> + inline LengthType getMaxStepLength(TParticle&, TTrack&) { + return step_; + } + + bool getFlag() const { return flag_; } + void resetFlag() { flag_ = false; } + private: int v_ = 0; + LengthType step_ = 0_m; + mutable bool flag_ = false; }; class ContinuousProcess2 : public ContinuousProcess<ContinuousProcess2> { public: - ContinuousProcess2(const int v) - : v_(v) { + ContinuousProcess2(int const v, LengthType const step) + : v_(v) + , step_(step) { cout << "globalCount: " << globalCount << ", v_: " << v_ << std::endl; globalCount++; } + void setStep(LengthType const v) { step_ = v; } + template <typename D, typename T> - inline ProcessReturn doContinuous(D& d, T&) const { + inline ProcessReturn doContinuous(D& d, T&, bool const flag) const { + flag_ = flag; cout << "ContinuousProcess2::DoContinuous" << endl; checkCont |= 2; for (int i = 0; i < nData; ++i) d.data_[i] += 0.111; return ProcessReturn::Ok; } + template <typename TParticle, typename TTrack> + inline LengthType getMaxStepLength(TParticle&, TTrack&) { + return step_; + } + + bool getFlag() const { return flag_; } + void resetFlag() { flag_ = false; } + private: int v_ = 0; + LengthType step_ = 0_m; + mutable bool flag_ = false; }; class ContinuousProcess3 : public ContinuousProcess<ContinuousProcess3> { public: - ContinuousProcess3(const int v) - : v_(v) { + ContinuousProcess3(int const v, LengthType const step) + : v_(v) + , step_(step) { cout << "globalCount: " << globalCount << ", v_: " << v_ << std::endl; globalCount++; } + void setStep(LengthType const v) { step_ = v; } + template <typename D, typename T> - inline ProcessReturn doContinuous(D& d, T&) const { + inline ProcessReturn doContinuous(D& d, T&, bool const flag) const { + flag_ = flag; cout << "ContinuousProcess3::DoContinuous" << endl; checkCont |= 4; for (int i = 0; i < nData; ++i) d.data_[i] += 0.333; return ProcessReturn::Ok; } + template <typename TParticle, typename TTrack> + inline LengthType getMaxStepLength(TParticle&, TTrack&) { + return step_; + } + + bool getFlag() const { return flag_; } + void resetFlag() { flag_ = false; } + private: int v_ = 0; + LengthType step_ = 0_m; + mutable bool flag_ = false; }; class Process1 : public InteractionProcess<Process1> { public: - Process1(const int v) + Process1(int const v) : v_(v) { cout << "globalCount: " << globalCount << ", v_: " << v_ << std::endl; globalCount++; @@ -116,7 +161,7 @@ private: class Process2 : public InteractionProcess<Process2> { public: - Process2(const int v) + Process2(int const v) : v_(v) { cout << "globalCount: " << globalCount << ", v_: " << v_ << std::endl; globalCount++; @@ -140,7 +185,7 @@ private: class Process3 : public InteractionProcess<Process3> { public: - Process3(const int v) + Process3(int const v) : v_(v) { cout << "globalCount: " << globalCount << ", v_: " << v_ << std::endl; globalCount++; @@ -164,14 +209,14 @@ private: class Process4 : public BaseProcess<Process4> { public: - Process4(const int v) + Process4(int const v) : v_(v) { cout << "globalCount: " << globalCount << ", v_: " << v_ << std::endl; globalCount++; } template <typename D, typename T> - inline ProcessReturn doContinuous(D& d, T&) const { + inline ProcessReturn doContinuous(D& d, T&, bool const) const { std::cout << "Base::doContinuous" << std::endl; checkCont |= 8; for (int i = 0; i < nData; ++i) { d.data_[i] /= 1.2; } @@ -188,7 +233,7 @@ private: class Decay1 : public DecayProcess<Decay1> { public: - Decay1(const int) { + Decay1(int const) { cout << "Decay1()" << endl; globalCount++; } @@ -205,7 +250,7 @@ public: class Decay2 : public DecayProcess<Decay2> { public: - Decay2(const int) { + Decay2(int const) { cout << "Decay2()" << endl; globalCount++; } @@ -222,7 +267,7 @@ public: class Stack1 : public StackProcess<Stack1> { public: - Stack1(const int n) + Stack1(int const n) : StackProcess(n) {} template <typename TStack> ProcessReturn doStack(TStack&) { @@ -235,12 +280,16 @@ private: int count_ = 0; }; +// The stack is non-existent for this example struct DummyStack {}; +// our data object (particle) is a simple arrary of doubles struct DummyData { double data_[nData] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; }; +// there is no real trajectory/track struct DummyTrajectory {}; - +// since there is no stack, there is also no view. This is a simplistic dummy object +// sufficient here. struct DummyView { DummyView(DummyData& p) : p_(p) {} @@ -253,6 +302,18 @@ TEST_CASE("Process Sequence General", "ProcessSequence") { logging::set_level(logging::level::info); corsika_logger->set_pattern("[%n:%^%-8l%$]: %v"); + SECTION("BaseProcess") { + + Process1 m1(0); + const Process4 m4(3); + + CHECK(is_base_process_v<Process1>); + CHECK_FALSE(is_base_process_v<DummyData>); + CHECK(is_base_process_v<decltype(m4)>); + CHECK(is_base_process_v<decltype(Decay1(1))>); + CHECK(is_base_process_v<decltype(ContinuousProcess3{3, 3_m})>); + } + SECTION("Check construction") { globalCount = 0; Process1 m1(0); @@ -265,10 +326,15 @@ TEST_CASE("Process Sequence General", "ProcessSequence") { CHECK(globalCount == 4); auto sequence1 = make_sequence(m1, m2, m3, m4); - CHECK(is_process_sequence_v<decltype(sequence1)> == true); - CHECK(is_process_sequence_v<decltype(m2)> == false); - CHECK(is_switch_process_sequence_v<decltype(sequence1)> == false); - CHECK(is_switch_process_sequence_v<decltype(m2)> == false); + CHECK(is_base_process_v<decltype(sequence1)>); + CHECK(is_base_process_v<decltype(m2)>); + CHECK(is_process_sequence_v<decltype(sequence1)>); + CHECK_FALSE(is_process_sequence_v<decltype(m2)>); + CHECK_FALSE(is_switch_process_sequence_v<decltype(sequence1)>); + CHECK_FALSE(is_switch_process_sequence_v<decltype(m2)>); + + CHECK_FALSE(is_process_sequence_v<decltype(Decay1(7))>); + CHECK_FALSE(is_switch_process_sequence_v<decltype(Decay1(7))>); auto sequence2 = make_sequence(m1, m2, m3); CHECK(is_process_sequence_v<decltype(sequence2)> == true); @@ -279,7 +345,7 @@ TEST_CASE("Process Sequence General", "ProcessSequence") { SECTION("interaction length") { globalCount = 0; - ContinuousProcess1 cp1(0); + ContinuousProcess1 cp1(0, 1_m); Process2 m2(1); Process3 m3(2); @@ -297,7 +363,7 @@ TEST_CASE("Process Sequence General", "ProcessSequence") { SECTION("lifetime") { globalCount = 0; - ContinuousProcess1 cp1(0); + ContinuousProcess1 cp1(0, 1_m); Process2 m2(1); Process3 m3(2); Decay1 d3(3); @@ -314,30 +380,61 @@ TEST_CASE("Process Sequence General", "ProcessSequence") { globalCount = 0; } - SECTION("sectionTwo") { + SECTION("ContinousProcess") { globalCount = 0; - ContinuousProcess1 cp1(0); // += 0.933 - ContinuousProcess2 cp2(1); // += 0.111 - Process2 m2(2); // /= 1.1 - Process3 m3(3); // *= 1.01 + ContinuousProcess1 cp1(0, 1_m); // += 0.933 + ContinuousProcess2 cp2(1, 1.1_m); // += 0.111 + Process2 m2(2); // /= 1.1 + Process3 m3(3); // *= 1.01 auto sequence2 = make_sequence(cp1, m2, m3, cp2); + std::cout << boost::typeindex::type_id<decltype(sequence2)>().pretty_name() + << std::endl; + DummyData particle; DummyTrajectory track; + cp1.resetFlag(); + cp2.resetFlag(); + + ContinuousProcessStepLength const step1 = sequence2.getMaxStepLength(particle, track); + CHECK(LengthType(step1) == 1_m); + sequence2.doContinuous(particle, track, step1); + CHECK(cp1.getFlag()); + CHECK_FALSE(cp2.getFlag()); + CORSIKA_LOG_INFO("step1, l={}, i={}", LengthType(step1), + ContinuousProcessIndex(step1).getIndex()); + + cp1.resetFlag(); + cp2.resetFlag(); + + cp1.setStep(10_m); + ContinuousProcessStepLength const step2 = sequence2.getMaxStepLength(particle, track); + CHECK(LengthType(step2) == 1.1_m); + CHECK(ContinuousProcessIndex(step1) != ContinuousProcessIndex(step2)); + sequence2.doContinuous(particle, track, step2); + CHECK_FALSE(cp1.getFlag()); + CHECK(cp2.getFlag()); + CORSIKA_LOG_INFO("step2, l={}, i={}", LengthType(step2), + ContinuousProcessIndex(step2).getIndex()); + cout << "-->init sequence2" << endl; globalCount = 0; - cout << "-->docont" << endl; + cout << "-->docontinuous" << endl; // validation data double test_data[nData] = {0}; - const int nLoop = 5; + // reset + particle = DummyData(); + track = DummyTrajectory(); + + int const nLoop = 5; cout << "Running loop with n=" << nLoop << endl; for (int iLoop = 0; iLoop < nLoop; ++iLoop) { for (int i = 0; i < nData; ++i) { test_data[i] += 0.933 + 0.111; } - sequence2.doContinuous(particle, track); + sequence2.doContinuous(particle, track, ContinuousProcessIndex(1)); } for (int i = 0; i < nData; i++) { cout << "data_[" << i << "]=" << particle.data_[i] << endl; @@ -356,14 +453,14 @@ TEST_CASE("Process Sequence General", "ProcessSequence") { DummyStack stack; - const int nLoop = 20; + int const nLoop = 20; for (int i = 0; i < nLoop; ++i) { sequence1.doStack(stack); } CHECK(s1.getCount() == 20); CHECK(s2.getCount() == 10); - ContinuousProcess2 cp2(1); // += 0.111 - Process2 m2(2); // /= 1.1 + ContinuousProcess2 cp2(1, 2_m); // += 0.111 + Process2 m2(2); // /= 1.1 auto sequence2 = make_sequence(cp2, m2); auto sequence3 = make_sequence(cp2, m2, s1); @@ -379,34 +476,59 @@ TEST_CASE("Switch Process Sequence", "ProcessSequence") { logging::set_level(logging::level::info); corsika_logger->set_pattern("[%n:%^%-8l%$]: %v"); + /** + * In this example switching is done only by "data_[0]>0", where + * data in an arrray of doubles, DummyData. + */ + + struct SwitchSelect { + SwitchResult operator()(DummyData const& p) const { + if (p.data_[0] > 0) return SwitchResult::First; + return SwitchResult::Second; + } + }; + SwitchSelect select1; + + auto cp1 = ContinuousProcess1(0, 1_m); + auto cp2 = ContinuousProcess2(0, 2_m); + auto cp3 = ContinuousProcess3(0, 3_m); + + auto sequence1 = make_sequence(Process1(0), cp2, Decay1(0)); + auto sequence2 = make_sequence(cp3, Process2(0), Decay2(0)); + + auto sequence3 = make_sequence(cp1, Process3(0), + SwitchProcessSequence(sequence1, sequence2, select1)); + SECTION("Check construction") { - struct TestSelect { - SwitchResult operator()(const DummyData& p) const { - std::cout << "TestSelect data=" << p.data_[0] << std::endl; - if (p.data_[0] > 0) return SwitchResult::First; - return SwitchResult::Second; - } - }; - TestSelect select1; + auto sequence_alt = + make_sequence(cp1, Process3(0), + make_select(make_sequence(Process1(0), cp2, Decay1(0)), + make_sequence(cp3, Process2(0), Decay2(0)), select1)); - auto sequence1 = make_sequence(Process1(0), ContinuousProcess2(0), Decay1(0)); - auto sequence2 = make_sequence(ContinuousProcess3(0), Process2(0), Decay2(0)); + auto switch_seq = SwitchProcessSequence(sequence1, sequence2, select1); + CHECK(is_process_sequence_v<decltype(switch_seq)>); + CHECK(is_switch_process_sequence_v<decltype(switch_seq)>); + // CHECK(is_switch_process_sequence_v<decltype(&switch_seq)>); + CHECK(is_switch_process_sequence_v<decltype( + SwitchProcessSequence(sequence1, sequence2, select1))>); - auto sequence3 = make_sequence(ContinuousProcess1(0), Process3(0), - SwitchProcessSequence(sequence1, sequence2, select1)); + CHECK(is_process_sequence_v<decltype(sequence3)>); + CHECK_FALSE(is_switch_process_sequence_v<decltype(sequence3)>); - auto sequence_alt = make_sequence( - ContinuousProcess1(0), Process3(0), - make_select(make_sequence(Process1(0), ContinuousProcess2(0), Decay1(0)), - make_sequence(ContinuousProcess3(0), Process2(0), Decay2(0)), - select1)); + CHECK(is_process_sequence_v<decltype( + SwitchProcessSequence(sequence1, sequence2, select1))>); + CHECK(is_switch_process_sequence_v<decltype( + SwitchProcessSequence(sequence1, sequence2, select1))>); // check that same process sequence can be build in different ways CHECK(typeid(sequence3) == typeid(sequence_alt)); - CHECK(is_process_sequence_v<decltype(sequence3)> == true); + CHECK(is_process_sequence_v<decltype(sequence3)>); CHECK(is_process_sequence_v<decltype( - SwitchProcessSequence(sequence1, sequence2, select1))> == true); + SwitchProcessSequence(sequence1, sequence2, select1))>); + } + + SECTION("Check interfaces") { DummyData particle; DummyTrajectory track; @@ -417,7 +539,7 @@ TEST_CASE("Switch Process Sequence", "ProcessSequence") { checkSec = 0; checkCont = 0; particle.data_[0] = 100; // data positive - sequence3.doContinuous(particle, track); + sequence3.doContinuous(particle, track, ContinuousProcessIndex(1)); CHECK(checkInteract == 0); CHECK(checkDecay == 0); CHECK(checkCont == 0b011); @@ -428,7 +550,7 @@ TEST_CASE("Switch Process Sequence", "ProcessSequence") { checkSec = 0; checkCont = 0; particle.data_[0] = -100; // data negative - sequence_alt.doContinuous(particle, track); + sequence3.doContinuous(particle, track, ContinuousProcessIndex(1)); CHECK(checkInteract == 0); CHECK(checkDecay == 0); CHECK(checkCont == 0b101); @@ -479,6 +601,95 @@ TEST_CASE("Switch Process Sequence", "ProcessSequence") { CHECK(checkCont == 0); CHECK(checkSec == 0); } + + SECTION("Check ContinuousProcesses in SwitchProcessSequence") { + + DummyData particle; + DummyTrajectory track; + + particle.data_[0] = + 100; // data positive, selects particular branch on SwitchProcessSequence + + cp1.setStep(10_m); + cp2.setStep(15_m); + cp3.setStep(100_m); + + cp1.resetFlag(); + cp2.resetFlag(); + cp3.resetFlag(); + + ContinuousProcessStepLength const step1 = sequence3.getMaxStepLength(particle, track); + CHECK(LengthType(step1) == 10_m); + sequence3.doContinuous(particle, track, step1); + CHECK(cp1.getFlag()); + CHECK_FALSE(cp2.getFlag()); + CHECK_FALSE(cp3.getFlag()); + CORSIKA_LOG_INFO("step1, l={}, i={}", LengthType(step1), + ContinuousProcessIndex(step1).getIndex()); + + particle.data_[0] = + 100; // data positive, selects particular branch on SwitchProcessSequence + + cp1.setStep(50_m); + cp2.setStep(15_m); + cp3.setStep(100_m); + + cp1.resetFlag(); + cp2.resetFlag(); + cp3.resetFlag(); + + ContinuousProcessStepLength const step2 = sequence3.getMaxStepLength(particle, track); + CHECK(LengthType(step2) == 15_m); + sequence3.doContinuous(particle, track, step2); + CHECK_FALSE(cp1.getFlag()); + CHECK(cp2.getFlag()); + CHECK_FALSE(cp3.getFlag()); + CORSIKA_LOG_INFO("step2, len_cont={}, indexLimit={} type={}", LengthType(step2), + ContinuousProcessIndex(step2).getIndex(), + boost::typeindex::type_id<decltype(sequence3)>().pretty_name()); + + particle.data_[0] = + -100; // data positive, selects particular branch on SwitchProcessSequence + + cp1.setStep(11_m); + cp2.setStep(15_m); + cp3.setStep(100_m); + + cp1.resetFlag(); + cp2.resetFlag(); + cp3.resetFlag(); + + ContinuousProcessStepLength const step3 = sequence3.getMaxStepLength(particle, track); + CHECK(LengthType(step3) == 11_m); + sequence3.doContinuous(particle, track, step3); + CHECK(cp1.getFlag()); + CHECK_FALSE(cp2.getFlag()); + CHECK_FALSE(cp3.getFlag()); + CORSIKA_LOG_INFO("step3, len_cont={}, indexLimit={} type={}", LengthType(step3), + ContinuousProcessIndex(step3).getIndex(), + boost::typeindex::type_id<decltype(sequence3)>().pretty_name()); + + particle.data_[0] = + -100; // data positive, selects particular branch on SwitchProcessSequence + + cp1.setStep(11_m); + cp2.setStep(15_m); + cp3.setStep(2_m); + + cp1.resetFlag(); + cp2.resetFlag(); + cp3.resetFlag(); + + ContinuousProcessStepLength const step4 = sequence3.getMaxStepLength(particle, track); + CHECK(LengthType(step4) == 2_m); + sequence3.doContinuous(particle, track, step4); + CHECK_FALSE(cp1.getFlag()); + CHECK_FALSE(cp2.getFlag()); + CHECK(cp3.getFlag()); + CORSIKA_LOG_INFO("step4, len_cont={}, indexLimit={} type={}", LengthType(step4), + ContinuousProcessIndex(step4).getIndex(), + boost::typeindex::type_id<decltype(sequence3)>().pretty_name()); + } } TEST_CASE("Continuous Process Indexing", "ProcessSequence") { @@ -486,16 +697,24 @@ TEST_CASE("Continuous Process Indexing", "ProcessSequence") { logging::set_level(logging::level::info); corsika_logger->set_pattern("[%n:%^%-8l%$]: %v"); - SECTION("Counting") { + SECTION("Indexing") { int const n0 = count_continuous<Decay2>::count; int const n1 = count_continuous<ContinuousProcess3>::count; - int const n2 = count_continuous<ContinuousProcess2, count_continuous<ContinuousProcess3>::count>::count; - int const n1_b = count_continuous<Process2, count_continuous<ContinuousProcess3>::count>::count; - int const n1_c = count_continuous<ContinuousProcess3, count_continuous<Process2>::count>::count; - int const n12 = count_continuous<ContinuousProcess2, count_continuous<ContinuousProcess3, 10>::count>::count; - int const n11_b = count_continuous<Process1, count_continuous<ContinuousProcess3, 10>::count>::count; - int const n11_c = count_continuous<ContinuousProcess3, count_continuous<Process1, 10>::count>::count; + int const n2 = count_continuous<ContinuousProcess2, + count_continuous<ContinuousProcess3>::count>::count; + int const n1_b = + count_continuous<Process2, count_continuous<ContinuousProcess3>::count>::count; + int const n1_c = + count_continuous<ContinuousProcess3, count_continuous<Process2>::count>::count; + int const n12 = + count_continuous<ContinuousProcess2, + count_continuous<ContinuousProcess3, 10>::count>::count; + int const n11_b = + count_continuous<Process1, + count_continuous<ContinuousProcess3, 10>::count>::count; + int const n11_c = count_continuous<ContinuousProcess3, + count_continuous<Process1, 10>::count>::count; CHECK(n0 == 0); CHECK(n1 == 1); @@ -506,30 +725,44 @@ TEST_CASE("Continuous Process Indexing", "ProcessSequence") { CHECK(n11_c == 11); CHECK(n12 == 12); + std::cout << count_continuous<ContinuousProcess3>::count << std::endl; + std::cout << count_continuous<Process3>::count << std::endl; - struct TestSelect { - SwitchResult operator()(const DummyData& p) const { - std::cout << "TestSelect data=" << p.data_[0] << std::endl; + struct SwitchSelect { + SwitchResult operator()(DummyData const& p) const { + std::cout << "SwitchSelect data=" << p.data_[0] << std::endl; if (p.data_[0] > 0) return SwitchResult::First; return SwitchResult::Second; } }; - TestSelect select1; - auto sequence1 = make_sequence(Process1(0), ContinuousProcess2(0), Decay1(0)); - auto sequence2 = make_sequence(ContinuousProcess3(0), Process2(0), Decay2(0)); + auto sequence1 = make_sequence(Process1(0), ContinuousProcess2(0, 2_m), Decay1(0)); + auto sequence2 = make_sequence(ContinuousProcess3(0, 3_m), Process2(0), Decay2(0), + ContinuousProcess1(0, 1_m)); + SwitchSelect select1; auto switch_seq = SwitchProcessSequence(sequence1, sequence2, select1); - auto sequence3 = make_sequence(ContinuousProcess1(0), Process3(0), - switch_seq); + auto sequence3 = make_sequence(ContinuousProcess1(0, 1_m), Process3(0), switch_seq); + auto sequence4 = make_sequence(ContinuousProcess1(0, 1_m), Process3(0), + SwitchProcessSequence(sequence1, sequence2, select1)); + int const switch_seq_n = count_continuous<decltype(switch_seq)>::count; + int const sequence3_n = count_continuous<decltype(sequence3)>::count; CHECK(decltype(sequence1)::nContinuous == 1); CHECK(count_continuous<decltype(sequence1)>::count == 1); - CHECK(count_continuous<decltype(sequence2)>::count == 1); - CHECK(count_continuous<decltype(switch_seq)>::count == 2); - CHECK(count_continuous<decltype(sequence3)>::count == 3); - + CHECK(count_continuous<decltype(sequence2)>::count == 2); + CHECK(switch_seq_n == 3); + CHECK(sequence3_n == 4); + CHECK(count_continuous<decltype(sequence4)>::count == 4); + + std::cout << "switch_seq " + << boost::typeindex::type_id<decltype(switch_seq)>().pretty_name() + << std::endl; + + std::cout << "sequence3 " + << boost::typeindex::type_id<decltype(sequence3)>().pretty_name() + << std::endl; } } diff --git a/tests/modules/testObservationPlane.cpp b/tests/modules/testObservationPlane.cpp index 9b9be4656..90a12288b 100644 --- a/tests/modules/testObservationPlane.cpp +++ b/tests/modules/testObservationPlane.cpp @@ -23,10 +23,10 @@ using namespace corsika; -TEST_CASE("ContinuousProcess interface", "[proccesses][observation_plane]") { +TEST_CASE("ObservationPlane", "[proccesses][observation_plane]") { - logging::set_level(logging::level::info); - corsika_logger->set_pattern("[%n:%^%-8l%$] custom pattern: %v"); + logging::set_level(logging::level::trace); + corsika_logger->set_pattern("[%n:%^%-8l%$]: %v"); auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Oxygen); auto const& cs = *csPtr; @@ -34,48 +34,64 @@ TEST_CASE("ContinuousProcess interface", "[proccesses][observation_plane]") { [[maybe_unused]] auto const& node_dummy = nodePtr; /* - Test with downward going 1_GeV neutrino, starting at 0,1_m,10m + Test with 1_GeV neutrino, starting at 0,0,0 travelling into +x direction (see + setup_stack). - ObservationPlane has origin at 0,0,0 + ObservationPlane has origin at 10,0,0 and a normal in x-direction */ auto [stack, viewPtr] = setup::testing::setup_stack(Code::NuE, 0, 0, 1_GeV, nodePtr, cs); [[maybe_unused]] setup::StackView& view = *viewPtr; auto particle = stack->getNextParticle(); + // dummy track. Not used for calculation! Point const start(cs, {0_m, 1_m, 10_m}); VelocityVector vec(cs, 0_m / second, 0_m / second, -constants::c); Line line(start, vec); - - setup::Trajectory track = + setup::Trajectory no_used_track = setup::testing::make_track<setup::Trajectory>(line, 12_m / constants::c); - particle.setPosition(Point(cs, {1_m, 1_m, 10_m})); // moving already along -z - SECTION("horizontal plane") { - Plane const obsPlane(Point(cs, {0_m, 0_m, 0_m}), DirectionVector(cs, {0., 0., 1.})); - ObservationPlane obs(obsPlane, DirectionVector(cs, {1., 0., 0.}), "particles.dat", + Plane const obsPlane(Point(cs, {10_m, 0_m, 0_m}), DirectionVector(cs, {1., 0., 0.})); + ObservationPlane obs(obsPlane, DirectionVector(cs, {0., 1., 0.}), "particles.dat", true); - LengthType const length = obs.getMaxStepLength(particle, track); - ProcessReturn const ret = obs.doContinuous(particle, track); + LengthType const length = obs.getMaxStepLength(particle, no_used_track); + ProcessReturn const ret = obs.doContinuous(particle, no_used_track, true); CHECK(length / 10_m == Approx(1).margin(1e-4)); CHECK(ret == ProcessReturn::ParticleAbsorbed); } - SECTION("inclined plane") {} - SECTION("transparent plane") { - Plane const obsPlane(Point(cs, {0_m, 0_m, 0_m}), DirectionVector(cs, {0., 0., 1.})); - ObservationPlane obs(obsPlane, DirectionVector(cs, {1., 0., 0.}), "particles.dat", + Plane const obsPlane(Point(cs, {1_m, 0_m, 0_m}), DirectionVector(cs, {1., 0., 0.})); + ObservationPlane obs(obsPlane, DirectionVector(cs, {0., 0., 1.}), "particles.dat", false); - LengthType const length = obs.getMaxStepLength(particle, track); - ProcessReturn const ret = obs.doContinuous(particle, track); + LengthType const length = obs.getMaxStepLength(particle, no_used_track); + ProcessReturn const ret = obs.doContinuous(particle, no_used_track, true); - CHECK(length / 10_m == Approx(1).margin(1e-4)); + CHECK(length / 1_m == Approx(1).margin(1e-4)); CHECK(ret == ProcessReturn::Ok); } + + SECTION("inclined plane, inclined particle") { + + MomentumVector const pnew = MomentumVector(cs, {1_GeV, 0.5_GeV, -0.4_GeV}); + HEPEnergyType const enew = sqrt(pnew.dot(pnew)); + particle.setMomentum(pnew); + particle.setEnergy(enew); + + Plane const obsPlane(Point(cs, {10_m, 5_m, 5_m}), + DirectionVector(cs, {1, 0.1, -0.05})); + ObservationPlane obs(obsPlane, DirectionVector(cs, {0., 1., 0.}), "particles.dat", + true); + + LengthType const length = obs.getMaxStepLength(particle, no_used_track); + ProcessReturn const ret = obs.doContinuous(particle, no_used_track, true); + + CHECK(length / 10_m == Approx(1.1375).margin(1e-4)); + CHECK(ret == ProcessReturn::ParticleAbsorbed); + } } diff --git a/tests/modules/testParticleCut.cpp b/tests/modules/testParticleCut.cpp index 0dede160e..ef12f58e8 100644 --- a/tests/modules/testParticleCut.cpp +++ b/tests/modules/testParticleCut.cpp @@ -14,6 +14,7 @@ #include <corsika/framework/geometry/Vector.hpp> #include <corsika/framework/utility/CorsikaFenv.hpp> #include <corsika/media/Environment.hpp> +#include <corsika/framework/process/ContinuousProcessIndex.hpp> #include <SetupTestStack.hpp> #include <SetupTestTrajectory.hpp> -- GitLab