IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 4257da6c authored by ralfulrich's avatar ralfulrich
Browse files

migrated framework/process

parent 3ebf404d
No related branches found
No related tags found
No related merge requests found
Showing
with 423 additions and 341 deletions
...@@ -26,233 +26,239 @@ ...@@ -26,233 +26,239 @@
namespace corsika { namespace corsika {
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename Particle, typename VTNType> template <typename Particle, typename VTNType>
EProcessReturn ProcessSequence<T1, T2>::DoBoundaryCrossing(Particle& p, EProcessReturn ProcessSequence<TProcess1, TProcess2>::doBoundaryCrossing(Particle& particle,
VTNType const& from, VTNType const& from,
VTNType const& to) { VTNType const& to) {
EProcessReturn ret = EProcessReturn::eOk; EProcessReturn ret = EProcessReturn::eOk;
if constexpr (std::is_base_of<BoundaryCrossingProcess<T1type>, T1type>::value || if constexpr (std::is_base_of_v<BoundaryCrossingProcess<process1_type>,
process1_type> ||
t1ProcSeq) { t1ProcSeq) {
ret |= A.DoBoundaryCrossing(p, from, to); ret |= A_.doBoundaryCrossing(particle, from, to);
} }
if constexpr (std::is_base_of<BoundaryCrossingProcess<T2type>, T2type>::value || if constexpr (std::is_base_of_v<BoundaryCrossingProcess<process2_type>,
process2_type> ||
t2ProcSeq) { t2ProcSeq) {
ret |= B.DoBoundaryCrossing(p, from, to); ret |= B_.doBoundaryCrossing(particle, from, to);
} }
return ret; return ret;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TParticle, typename TTrack> template <typename TParticle, typename TTrack>
EProcessReturn ProcessSequence<T1, T2>::DoContinuous(TParticle& vP, TTrack& vT) { EProcessReturn ProcessSequence<TProcess1, TProcess2>::doContinuous(TParticle& particle, TTrack& vT) {
EProcessReturn ret = EProcessReturn::eOk; EProcessReturn ret = EProcessReturn::eOk;
if constexpr (std::is_base_of<ContinuousProcess<T1type>, T1type>::value || if constexpr (std::is_base_of_v<ContinuousProcess<process1_type>, process1_type> ||
t1ProcSeq) { t1ProcSeq) {
ret |= A_.doContinuous(particle, vT);
ret |= A.DoContinuous(vP, vT);
} }
if constexpr (std::is_base_of<ContinuousProcess<T2type>, T2type>::value || if constexpr (std::is_base_of_v<ContinuousProcess<process2_type>, process2_type> ||
t2ProcSeq) { t2ProcSeq) {
ret |= B.DoContinuous(vP, vT); if (!isAbsorbed(ret)) { ret |= B_.doContinuous(particle, vT); }
} }
return ret; return ret;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TSecondaries> template <typename TSecondaries>
EProcessReturn ProcessSequence<T1, T2>::DoSecondaries(TSecondaries& vS) { void ProcessSequence<TProcess1, TProcess2>::doSecondaries(TSecondaries& vS) {
EProcessReturn ret = EProcessReturn::eOk; if constexpr (std::is_base_of_v<SecondariesProcess<process1_type>, process1_type> ||
if constexpr (std::is_base_of<SecondariesProcess<T1type>, T1type>::value ||
t1ProcSeq) { t1ProcSeq) {
ret |= A.DoSecondaries(vS); A_.doSecondaries(vS);
} }
if constexpr (std::is_base_of<SecondariesProcess<T2type>, T2type>::value || if constexpr (std::is_base_of_v<SecondariesProcess<process2_type>, process2_type> ||
t2ProcSeq) { t2ProcSeq) {
ret |= B.DoSecondaries(vS); B_.doSecondaries(vS);
} }
return ret;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
bool ProcessSequence<T1, T2>::CheckStep() { bool ProcessSequence<TProcess1, TProcess2>::checkStep() {
bool ret = false; bool ret = false;
if constexpr (std::is_base_of<StackProcess<T1type>, T1type>::value || t1ProcSeq) { if constexpr (std::is_base_of_v<StackProcess<process1_type>, process1_type> ||
ret |= A.CheckStep(); (t1ProcSeq && !t1SwitchProcSeq)) {
ret |= A_.checkStep();
} }
if constexpr (std::is_base_of<StackProcess<T2type>, T2type>::value || t2ProcSeq) { if constexpr (std::is_base_of_v<StackProcess<process2_type>, process2_type> ||
ret |= B.CheckStep(); (t2ProcSeq && !t2SwitchProcSeq)) {
ret |= B_.checkStep();
} }
return ret; return ret;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TStack> template <typename TStack>
EProcessReturn ProcessSequence<T1, T2>::DoStack(TStack& vS) { void ProcessSequence<TProcess1, TProcess2>::doStack(TStack& stack) {
EProcessReturn ret = EProcessReturn::eOk; if constexpr (std::is_base_of_v<StackProcess<process1_type>, process1_type> ||
if constexpr (std::is_base_of<StackProcess<T1type>, T1type>::value || t1ProcSeq) { (t1ProcSeq && !t1SwitchProcSeq)) {
if (A.CheckStep()) { ret |= A.DoStack(vS); } if (A_.checkStep()) { A_.doStack(stack); }
} }
if constexpr (std::is_base_of<StackProcess<T2type>, T2type>::value || t2ProcSeq) { if constexpr (std::is_base_of_v<StackProcess<process2_type>, process2_type> ||
if (B.CheckStep()) { ret |= B.DoStack(vS); } (t2ProcSeq && !t2SwitchProcSeq)) {
if (B_.checkStep()) { B_.doStack(stack); }
} }
return ret;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TParticle, typename TTrack> template <typename TParticle, typename TTrack>
LengthType ProcessSequence<T1, T2>::MaxStepLength(TParticle& vP, TTrack& vTrack) { LengthType ProcessSequence<TProcess1, TProcess2>::maxStepLength(TParticle& particle, TTrack& vTrack) {
LengthType max_length = // if no other process in the sequence implements it LengthType max_length = // if no other process in the sequence implements it
std::numeric_limits<double>::infinity() * meter; std::numeric_limits<double>::infinity() * meter;
if constexpr (std::is_base_of<ContinuousProcess<T1type>, T1type>::value || if constexpr (std::is_base_of_v<ContinuousProcess<process1_type>, process1_type> ||
t1ProcSeq) { t1ProcSeq) {
LengthType const len = A.MaxStepLength(vP, vTrack); LengthType const len = A_.maxStepLength(particle, vTrack);
max_length = std::min(max_length, len); max_length = std::min(max_length, len);
} }
if constexpr (std::is_base_of<ContinuousProcess<T2type>, T2type>::value || if constexpr (std::is_base_of_v<ContinuousProcess<process2_type>, process2_type> ||
t2ProcSeq) { t2ProcSeq) {
LengthType const len = B.MaxStepLength(vP, vTrack); LengthType const len = B_.maxStepLength(particle, vTrack);
max_length = std::min(max_length, len); max_length = std::min(max_length, len);
} }
return max_length; return max_length;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TParticle>
GrammageType ProcessSequence<T1, T2>::GetTotalInteractionLength(TParticle& vP) {
return 1. / GetInverseInteractionLength(vP);
}
template <typename T1, typename T2>
template <typename TParticle> template <typename TParticle>
InverseGrammageType ProcessSequence<T1, T2>::GetTotalInverseInteractionLength( InverseGrammageType ProcessSequence<TProcess1, TProcess2>::getInverseInteractionLength(
TParticle& vP) { TParticle&& particle) {
return GetInverseInteractionLength(vP);
}
template <typename T1, typename T2> InverseGrammageType tot = 0 * meter * meter / gram; // default value
template <typename TParticle>
InverseGrammageType ProcessSequence<T1, T2>::GetInverseInteractionLength(
TParticle& vP) {
InverseGrammageType tot = 0 * meter * meter / gram;
if constexpr (std::is_base_of<InteractionProcess<T1type>, T1type>::value || if constexpr (std::is_base_of_v<InteractionProcess<process1_type>, process1_type> ||
t1ProcSeq || t1SwitchProc) { t1ProcSeq) {
tot += A.GetInverseInteractionLength(vP); tot += A_.getInverseInteractionLength(particle);
} }
if constexpr (std::is_base_of<InteractionProcess<T2type>, T2type>::value || if constexpr (std::is_base_of_v<InteractionProcess<process2_type>, process2_type> ||
t2ProcSeq || t2SwitchProc) { t2ProcSeq) {
tot += B.GetInverseInteractionLength(vP); tot += B_.getInverseInteractionLength(particle);
} }
return tot; return tot;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TParticle, typename TSecondaries> template <typename TSecondaryView>
EProcessReturn ProcessSequence<T1, T2>::SelectInteraction( inline EProcessReturn ProcessSequence<TProcess1, TProcess2>::selectInteraction(
TParticle& vP, TSecondaries& vS, [[maybe_unused]] InverseGrammageType lambda_select, TSecondaryView& view, [[maybe_unused]] InverseGrammageType lambda_inv_select,
InverseGrammageType& lambda_inv_count) { [[maybe_unused]] InverseGrammageType lambda_inv_sum) {
if constexpr (t1ProcSeq || t1SwitchProc) { // TODO: add check for lambda_inv_select>lambda_inv_tot
if constexpr (t1ProcSeq) {
// if A is a process sequence --> check inside // if A is a process sequence --> check inside
const EProcessReturn ret = EProcessReturn const ret =
A.SelectInteraction(vP, vS, lambda_select, lambda_inv_count); A_.selectInteraction(view, lambda_inv_select, lambda_inv_sum);
// if A did succeed, stop routine // if A_ did succeed, stop routine. Not checking other static branch B_.
if (ret != EProcessReturn::eOk) { return ret; } if (ret != EProcessReturn::eOk) { return ret; }
} else if constexpr (std::is_base_of<InteractionProcess<T1type>, T1type>::value) { } else if constexpr (std::is_base_of_v<InteractionProcess<process1_type>,
process1_type>) {
// if this is not a ContinuousProcess --> evaluate probability // if this is not a ContinuousProcess --> evaluate probability
lambda_inv_count += A.GetInverseInteractionLength(vP); auto const particle = view.parent();
lambda_inv_sum += A_.getInverseInteractionLength(particle);
// check if we should execute THIS process and then EXIT // check if we should execute THIS process and then EXIT
if (lambda_select < lambda_inv_count) { if (lambda_inv_select < lambda_inv_sum) {
A.DoInteraction(vS); A_.doInteraction(view);
return EProcessReturn::eInteracted; return EProcessReturn::eInteracted;
} }
} // end branch A } // end branch A_
if constexpr (t2ProcSeq || t2SwitchProc) { if constexpr (t2ProcSeq) {
// if A is a process sequence --> check inside // if B_ is a process sequence --> check inside
const EProcessReturn ret = return B_.selectInteraction(view, lambda_inv_select, lambda_inv_sum);
B.SelectInteraction(vP, vS, lambda_select, lambda_inv_count); } else if constexpr (std::is_base_of_v<InteractionProcess<process2_type>,
// if A did succeed, stop routine process2_type>) {
if (ret != EProcessReturn::eOk) { return ret; }
} else if constexpr (std::is_base_of<InteractionProcess<T2type>, T2type>::value) {
// if this is not a ContinuousProcess --> evaluate probability // if this is not a ContinuousProcess --> evaluate probability
lambda_inv_count += B.GetInverseInteractionLength(vP); lambda_inv_sum += B_.getInverseInteractionLength(view.parent());
// check if we should execute THIS process and then EXIT // check if we should execute THIS process and then EXIT
if (lambda_select < lambda_inv_count) { if (lambda_inv_select < lambda_inv_sum) {
B.DoInteraction(vS); B_.doInteraction(view);
return EProcessReturn::eInteracted; return EProcessReturn::eInteracted;
} }
} // end branch A } // end branch B_
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TParticle>
TimeType ProcessSequence<T1, T2>::GetTotalLifetime(TParticle& p) {
return 1. / GetInverseLifetime(p);
}
template <typename T1, typename T2>
template <typename TParticle> template <typename TParticle>
InverseTimeType ProcessSequence<T1, T2>::GetTotalInverseLifetime(TParticle& p) { inline InverseTimeType ProcessSequence<TProcess1, TProcess2>::getInverseLifetime(
return GetInverseLifetime(p); TParticle&& particle) {
}
template <typename T1, typename T2> InverseTimeType tot = 0 / second; // default value
template <typename TParticle>
InverseTimeType ProcessSequence<T1, T2>::GetInverseLifetime(TParticle& p) {
InverseTimeType tot = 0 / second;
if constexpr (std::is_base_of<DecayProcess<T1type>, T1type>::value || t1ProcSeq) { if constexpr (std::is_base_of_v<DecayProcess<process1_type>, process1_type> ||
tot += A.GetInverseLifetime(p); t1ProcSeq) {
tot += A_.getInverseLifetime(particle);
} }
if constexpr (std::is_base_of<DecayProcess<T2type>, T2type>::value || t2ProcSeq) { if constexpr (std::is_base_of_v<DecayProcess<process2_type>, process2_type> ||
tot += B.GetInverseLifetime(p); t2ProcSeq) {
tot += B_.getInverseLifetime(particle);
} }
return tot; return tot;
} }
template <typename T1, typename T2> template <typename TProcess1, typename TProcess2>
template <typename TParticle, typename TSecondaries> // select decay process
EProcessReturn ProcessSequence<T1, T2>::SelectDecay( template <typename TSecondaryView>
TParticle& vP, TSecondaries& vS, [[maybe_unused]] InverseTimeType decay_select, inline EProcessReturn ProcessSequence<TProcess1, TProcess2>::selectDecay(
InverseTimeType& decay_inv_count) { TSecondaryView& view, [[maybe_unused]] InverseTimeType decay_inv_select,
[[maybe_unused]] InverseTimeType decay_inv_sum) {
// TODO: add check for decay_inv_select>decay_inv_tot
if constexpr (t1ProcSeq) { if constexpr (t1ProcSeq) {
// if A is a process sequence --> check inside // if A_ is a process sequence --> check inside
const EProcessReturn ret = A.SelectDecay(vP, vS, decay_select, decay_inv_count); EProcessReturn const ret = A_.selectDecay(view, decay_inv_select, decay_inv_sum);
// if A did succeed, stop routine // if A_ did succeed, stop routine here (not checking other static branch B_)
if (ret != EProcessReturn::eOk) { return ret; } if (ret != EProcessReturn::eOk) { return ret; }
} else if constexpr (std::is_base_of<DecayProcess<T1type>, T1type>::value) { } else if constexpr (std::is_base_of_v<DecayProcess<process1_type>, process1_type>) {
// if this is not a ContinuousProcess --> evaluate probability // if this is not a ContinuousProcess --> evaluate probability
decay_inv_count += A.GetInverseLifetime(vP); decay_inv_sum += A_.getInverseLifetime(view.parent());
// check if we should execute THIS process and then EXIT // check if we should execute THIS process and then EXIT
if (decay_select < decay_inv_count) { // more pedagogical: rndm_select < if (decay_inv_select < decay_inv_sum) { // more pedagogical: rndm_select <
// decay_inv_count / decay_inv_tot // decay_inv_sum / decay_inv_tot
A.DoDecay(vS); A_.doDecay(view);
return EProcessReturn::eDecayed; return EProcessReturn::eDecayed;
} }
} // end branch A } // end branch A_
if constexpr (t2ProcSeq) { if constexpr (t2ProcSeq) {
// if A is a process sequence --> check inside // if B_ is a process sequence --> check inside
const EProcessReturn ret = B.SelectDecay(vP, vS, decay_select, decay_inv_count); return B_.selectDecay(view, decay_inv_select, decay_inv_sum);
// if A did succeed, stop routine } else if constexpr (std::is_base_of_v<DecayProcess<process2_type>, process2_type>) {
if (ret != EProcessReturn::eOk) { return ret; }
} else if constexpr (std::is_base_of<DecayProcess<T2type>, T2type>::value) {
// if this is not a ContinuousProcess --> evaluate probability // if this is not a ContinuousProcess --> evaluate probability
decay_inv_count += B.GetInverseLifetime(vP); decay_inv_sum += B_.getInverseLifetime(view.parent());
// check if we should execute THIS process and then EXIT // check if we should execute THIS process and then EXIT
if (decay_select < decay_inv_count) { if (decay_inv_select < decay_inv_sum) {
B.DoDecay(vS); B_.doDecay(view);
return EProcessReturn::eDecayed; return EProcessReturn::eDecayed;
} }
} // end branch B } // end branch B_
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
/**
* traits marker to identify objects containing any StackProcesses
**/
namespace detail {
// need helper alias to achieve this:
template <typename TProcess1, typename TProcess2,
typename = typename std::enable_if_t<
contains_stack_process_v<TProcess1> ||
std::is_base_of_v<StackProcess<typename std::decay_t<TProcess1>>,
typename std::decay_t<TProcess1>> ||
contains_stack_process_v<TProcess2> ||
std::is_base_of_v<StackProcess<typename std::decay_t<TProcess2>>,
typename std::decay_t<TProcess2>>,
int>>
using enable_if_stack = ProcessSequence<TProcess1, TProcess2>;
} // namespace detail
template <typename TProcess1, typename TProcess2>
struct contains_stack_process<detail::enable_if_stack<TProcess1, TProcess2>>
: std::true_type {};
} // namespace corsika } // namespace corsika
...@@ -8,9 +8,6 @@ n/* ...@@ -8,9 +8,6 @@ n/*
#pragma once #pragma once
#include <corsika/framework/process/ProcessReturn.hpp> // for convenience
#include <type_traits>
namespace corsika { namespace corsika {
class TDerived; // fwd decl class TDerived; // fwd decl
...@@ -23,11 +20,14 @@ namespace corsika { ...@@ -23,11 +20,14 @@ namespace corsika {
are of type BaseProcess<T> are of type BaseProcess<T>
\todo rename BaseProcess into just Process \todo rename BaseProcess into just Process
\todo rename _BaseProcess, or find better alternative in
./Processes/AnalyticProcessors/ExecTime.h, see e.g. how this is done in
ProcessSequence.hpp/make_sequence
*/ */
class _BaseProcess {}; class _BaseProcess {};
template <typename TDerived> template <typename TDerived>
class BaseProcess : _BaseProcess { struct BaseProcess : _BaseProcess {
protected: protected:
friend TDerived; friend TDerived;
...@@ -35,16 +35,12 @@ namespace corsika { ...@@ -35,16 +35,12 @@ namespace corsika {
// derived classes to be created, not // derived classes to be created, not
// BaseProcess itself // BaseProcess itself
TDerived& GetRef() { return static_cast<TDerived&>(*this); } TDerived& ref() { return static_cast<TDerived&>(*this); }
const TDerived& GetRef() const { return static_cast<const TDerived&>(*this); } const TDerived& ref() const { return static_cast<const TDerived&>(*this); }
public: public:
// Base processor type for use in other template classes // Base processor type for use in other template classes
using TProcessType = TDerived; using TProcessType = TDerived;
}; };
// overwrite the default trait class, to mark BaseProcess<T> as useful process
template <class T>
std::true_type is_process_impl(const BaseProcess<T>* impl);
} // namespace corsika } // namespace corsika
...@@ -13,15 +13,8 @@ n/* ...@@ -13,15 +13,8 @@ n/*
namespace corsika { namespace corsika {
template <typename TDerived>
struct BoundaryCrossingProcess {
auto& GetRef() { return static_cast<TDerived&>(*this); }
auto const& GetRef() const { return static_cast<const TDerived&>(*this); }
template <typename TDerived> template <typename TDerived>
class BoundaryCrossingProcess : public BaseProcess<TDerived> { class BoundaryCrossingProcess : public BaseProcess<TDerived> {
private:
protected:
public: public:
/** /**
* This method is called when a particle crosses the boundary between the nodes * This method is called when a particle crosses the boundary between the nodes
...@@ -32,7 +25,4 @@ namespace corsika { ...@@ -32,7 +25,4 @@ namespace corsika {
TVolumeNode const& to); TVolumeNode const& to);
}; };
template <class T>
std::true_type is_process_impl(BoundaryCrossingProcess<T> const* impl);
} // namespace corsika } // namespace corsika
...@@ -8,8 +8,8 @@ n/* ...@@ -8,8 +8,8 @@ n/*
#pragma once #pragma once
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/process/BaseProcess.hpp>
#include <corsika/framework/process/ProcessReturn.hpp> // for convenience #include <corsika/framework/process/ProcessReturn.hpp>
namespace corsika { namespace corsika {
...@@ -30,15 +30,11 @@ namespace corsika { ...@@ -30,15 +30,11 @@ namespace corsika {
// here starts the interface part // here starts the interface part
// -> enforce TDerived to implement DoContinuous... // -> enforce TDerived to implement DoContinuous...
template <typename TParticle, typename TTrack> template <typename TParticle, typename TTrack>
EProcessReturn DoContinuous(TParticle&, TTrack const&) const; EProcessReturn doContinuous(TParticle&, TTrack const&) const;
// -> enforce derived to implement MaxStepLength... // -> enforce TDerived to implement MaxStepLength...
template <typename Particle, typename Track> template <typename TParticle, typename TTrack>
LengthType MaxStepLength(Particle const& p, Track const& track) const; units::si::LengthType maxStepLength(TParticle const& p, TTrack const& track) const;
}; };
// overwrite the default trait class, to mark BaseProcess<T> as useful process
template <class T>
std::true_type is_process_impl(const ContinuousProcess<T>* impl);
} // namespace corsika } // namespace corsika
...@@ -8,10 +8,8 @@ n/* ...@@ -8,10 +8,8 @@ n/*
#pragma once #pragma once
#include <type_traits> #include <corsika/framework/process/BaseProcess.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/process/ProcessReturn.hpp>
namespace corsika { namespace corsika {
...@@ -27,25 +25,19 @@ namespace corsika { ...@@ -27,25 +25,19 @@ namespace corsika {
template <typename TDerived> template <typename TDerived>
struct DecayProcess : BaseProcess<TDerived> { struct DecayProcess : BaseProcess<TDerived> {
public: public:
using BaseProcess<TDerived>::GetRef; using BaseProcess<TDerived>::ref;
/// here starts the interface-definition part /// here starts the interface-definition part
// -> enforce TDerived to implement DoDecay... // -> enforce TDerived to implement DoDecay...
template <typename TParticle> template <typename TParticle>
EProcessReturn DoDecay(TParticle&); EProcessReturn doDecay(TParticle&);
template <typename Particle> template <typename TParticle>
TimeType GetLifetime(Particle& p); TimeType getLifetime(TParticle const&);
template <typename Particle> template <typename TParticle>
InverseTimeType GetInverseLifetime(Particle& vP) { InverseTimeType getInverseLifetime(TParticle const& particle) {
return 1. / GetRef().GetLifetime(vP); return 1. / ref().getLifetime(particle);
} }
/* template <typename TParticle>
corsika::units::si::InverseTimeType GetInverseInteractionLength(TParticle&& particle)
{ auto p = std::move(particle); return 1. / GetRef().GetLifetime(p);
}*/
};
} // namespace corsika } // namespace corsika
...@@ -8,10 +8,8 @@ n/* ...@@ -8,10 +8,8 @@ n/*
#pragma once #pragma once
#include <type_traits> #include <corsika/framework/process/BaseProcess.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/process/ProcessReturn.hpp>
namespace corsika { namespace corsika {
...@@ -27,24 +25,21 @@ namespace corsika { ...@@ -27,24 +25,21 @@ namespace corsika {
template <typename TDerived> template <typename TDerived>
class InteractionProcess : public BaseProcess<TDerived> { class InteractionProcess : public BaseProcess<TDerived> {
public: public:
using BaseProcess<TDerived>::GetRef; using BaseProcess<TDerived>::ref;
/// here starts the interface-definition part /// here starts the interface-definition part
// -> enforce TDerived to implement DoInteraction... // -> enforce TDerived to implement DoInteraction...
template <typename TParticle> template <typename TParticle>
EProcessReturn DoInteraction(TParticle&); EProcessReturn doInteraction(TParticle&);
template <typename TParticle> template <typename TParticle>
GrammageType GetInteractionLength(TParticle& p); corsika::units::si::GrammageType getInteractionLength(TParticle const&);
template <typename TParticle> template <typename TParticle>
InverseGrammageType GetInverseInteractionLength(TParticle& p) { corsika::units::si::InverseGrammageType getInverseInteractionLength(
return 1. / GetRef().GetInteractionLength(p); TParticle const& particle) {
return 1. / ref().getInteractionLength(particle);
} }
}; };
// overwrite the default trait class, to mark BaseProcess<T> as useful process
template <class T>
std::true_type is_process_impl(const InteractionProcess<T>* impl);
} // namespace corsika } // namespace corsika
...@@ -39,4 +39,20 @@ namespace corsika { ...@@ -39,4 +39,20 @@ namespace corsika {
return (static_cast<int>(a) & static_cast<int>(b)) != 0; return (static_cast<int>(a) & static_cast<int>(b)) != 0;
} }
inline bool isOk(const EProcessReturn a) {
return static_cast<int>(a & EProcessReturn::eOk);
}
inline bool isAbsorbed(const EProcessReturn a) {
return static_cast<int>(a & EProcessReturn::eParticleAbsorbed);
}
inline bool isDecayed(const EProcessReturn a) {
return static_cast<int>(a & EProcessReturn::eDecayed);
}
inline bool isInteracted(const EProcessReturn a) {
return static_cast<int>(a & EProcessReturn::eInteracted);
}
} // namespace corsika } // namespace corsika
...@@ -8,9 +8,8 @@ n/* ...@@ -8,9 +8,8 @@ n/*
#pragma once #pragma once
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/process/BaseProcess.hpp> #include <corsika/framework/process/BaseProcess.hpp>
#include <corsika/framework/process/ProcessTraits.hpp>
#include <corsika/framework/process/BoundaryCrossingProcess.hpp> #include <corsika/framework/process/BoundaryCrossingProcess.hpp>
#include <corsika/framework/process/ContinuousProcess.hpp> #include <corsika/framework/process/ContinuousProcess.hpp>
#include <corsika/framework/process/DecayProcess.hpp> #include <corsika/framework/process/DecayProcess.hpp>
...@@ -18,15 +17,13 @@ n/* ...@@ -18,15 +17,13 @@ n/*
#include <corsika/framework/process/ProcessReturn.hpp> #include <corsika/framework/process/ProcessReturn.hpp>
#include <corsika/framework/process/SecondariesProcess.hpp> #include <corsika/framework/process/SecondariesProcess.hpp>
#include <corsika/framework/process/StackProcess.hpp> #include <corsika/framework/process/StackProcess.hpp>
#include <corsika/framework/process/NullModel.hpp>
#include <cmath> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <limits>
#include <type_traits>
namespace corsika { namespace corsika {
/** /**
* FIXME *
\class ProcessSequence \class ProcessSequence
A compile time static list of processes. The compiler will A compile time static list of processes. The compiler will
...@@ -38,26 +35,26 @@ namespace corsika { ...@@ -38,26 +35,26 @@ namespace corsika {
they are just classes. This allows us to handle both, rvalue as they are just classes. This allows us to handle both, rvalue as
well as lvalue Processes in the ProcessSequence. well as lvalue Processes in the ProcessSequence.
\comment Using CRTP pattern, The sequence, and the processes use CRTP.
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
*/ */
template <typename TProcess1, typename TProcess2 = NullModel> template <typename TProcess1, typename TProcess2 = NullModel>
class ProcessSequence : public BaseProcess<ProcessSequence<TProcess1, TProcess2>> { class ProcessSequence : public BaseProcess<ProcessSequence<TProcess1, TProcess2>> {
using TProcess1type = typename std::decay_t<TProcess1>; using process1_type = typename std::decay_t<TProcess1>;
using TProcess2type = typename std::decay_t<TProcess2>; using process2_type = typename std::decay_t<TProcess2>;
static bool constexpr t1ProcSeq = is_process_sequence_v<TProcess1type>; static bool constexpr t1ProcSeq = is_process_sequence_v<process1_type>;
static bool constexpr t2ProcSeq = is_process_sequence_v<TProcess2type>; static bool constexpr t2ProcSeq = is_process_sequence_v<process2_type>;
static bool constexpr t1SwitchProcSeq = is_switch_process_sequence_v<TProcess1type>; static bool constexpr t1SwitchProcSeq = is_switch_process_sequence_v<process1_type>;
static bool constexpr t2SwitchProcSeq = is_switch_process_sequence_v<TProcess2type>; static bool constexpr t2SwitchProcSeq = is_switch_process_sequence_v<process2_type>;
// make sure only BaseProcess types TProcess1/2 are passed // make sure only BaseProcess types TProcess1/2 are passed
static_assert(std::is_base_of_v<BaseProcess<TProcess1type>, TProcess1type>, static_assert(std::is_base_of_v<BaseProcess<process1_type>, process1_type>,
"can only use process derived from BaseProcess in " "can only use process derived from BaseProcess in "
"ProcessSequence, for Process 1"); "ProcessSequence, for Process 1");
static_assert(std::is_base_of_v<BaseProcess<TProcess2type>, TProcess2type>, static_assert(std::is_base_of_v<BaseProcess<process2_type>, process2_type>,
"can only use process derived from BaseProcess in " "can only use process derived from BaseProcess in "
"ProcessSequence, for Process 2"); "ProcessSequence, for Process 2");
...@@ -69,18 +66,15 @@ namespace corsika { ...@@ -69,18 +66,15 @@ namespace corsika {
: A_(in_A) : A_(in_A)
, B_(in_B) {} , B_(in_B) {}
// example for a trait-based call: template <typename TParticle, typename TVTNType>
// void Hello() const { detail::CallHello<T1,T2>::Call(A, B); } EProcessReturn doBoundaryCrossing(TParticle& particle, TVTNType const& from,
TVTNType const& to);
template <typename Particle, typename VTNType>
EProcessReturn DoBoundaryCrossing(Particle& p, VTNType const& from,
VTNType const& to);
template <typename TParticle, typename TTrack> template <typename TParticle, typename TTrack>
EProcessReturn DoContinuous(TParticle& vP, TTrack& vT); inline EProcessReturn doContinuous(TParticle& particle, TTrack& vT);
template <typename TSecondaries> template <typename TSecondaries>
EProcessReturn DoSecondaries(TSecondaries& vS); inline void doSecondaries(TSecondaries& vS);
/** /**
The processes of type StackProcess do have an internal counter, The processes of type StackProcess do have an internal counter,
...@@ -90,53 +84,48 @@ namespace corsika { ...@@ -90,53 +84,48 @@ namespace corsika {
tested if either A_ or B_ are StackProcess and if they are due tested if either A_ or B_ are StackProcess and if they are due
for execution. for execution.
*/ */
bool CheckStep(); inline bool checkStep();
/** /**
Execute the StackProcess-es in the ProcessSequence Execute the StackProcess-es in the ProcessSequence
*/ */
template <typename TStack> template <typename TStack>
EProcessReturn DoStack(TStack& vS); inline void doStack(TStack& stack);
template <typename TParticle, typename TTrack> template <typename TParticle, typename TTrack>
LengthType MaxStepLength(TParticle& vP, TTrack& vTrack); inline LengthType maxStepLength(TParticle& particle, TTrack& vTrack);
template <typename TParticle>
GrammageType GetTotalInteractionLength(TParticle& vP);
template <typename TParticle> template <typename TParticle>
inline InverseGrammageType GetTotalInverseInteractionLength(TParticle& vP); inline GrammageType getInteractionLength(TParticle&& particle) {
return 1. / getInverseInteractionLength(particle);
}
template <typename TParticle> template <typename TParticle>
inline InverseGrammageType GetInverseInteractionLength(TParticle& vP); inline InverseGrammageType getInverseInteractionLength(TParticle&& particle);
template <typename TParticle, typename TSecondaries> template <typename TSecondaryView>
EProcessReturn SelectInteraction(TParticle& vP, TSecondaries& vS, inline EProcessReturn selectInteraction(
[[maybe_unused]] InverseGrammageType lambda_select, TSecondaryView& view, [[maybe_unused]] InverseGrammageType lambda_inv_select,
InverseGrammageType& lambda_inv_count); [[maybe_unused]] InverseGrammageType lambda_inv_sum =
InverseGrammageType::zero());
template <typename TParticle>
TimeType GetTotalLifetime(TParticle& p);
template <typename TParticle> template <typename TParticle>
InverseTimeType GetTotalInverseLifetime(TParticle& p); inline TimeType getLifetime(TParticle& particle) {
return 1. / getInverseLifetime(particle);
}
template <typename TParticle> template <typename TParticle>
InverseTimeType GetInverseLifetime(TParticle& p); inline InverseTimeType getInverseLifetime(TParticle&& particle);
// select decay process // select decay process
template <typename TParticle, typename TSecondaries> template <typename TSecondaryView>
EProcessReturn SelectDecay(TParticle& vP, TSecondaries& vS, inline EProcessReturn selectDecay(
[[maybe_unused]] InverseTimeType decay_select, TSecondaryView& view, [[maybe_unused]] InverseTimeType decay_inv_select,
InverseTimeType& decay_inv_count); [[maybe_unused]] InverseTimeType decay_inv_sum = InverseTimeType::zero());
void Init() {
A.Init();
B.Init();
}
}; };
/** /**
* \function sequence * \function make_sequence
* *
* to construct ProcessSequences in a flexible and dynamic way the * to construct ProcessSequences in a flexible and dynamic way the
* `sequence` factory functions are provided * `sequence` factory functions are provided
...@@ -159,15 +148,55 @@ namespace corsika { ...@@ -159,15 +148,55 @@ namespace corsika {
inline typename std::enable_if_t< inline typename std::enable_if_t<
std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess1>>, std::is_base_of_v<BaseProcess<typename std::decay_t<TProcess1>>,
typename std::decay_t<TProcess1>>, typename std::decay_t<TProcess1>>,
ProcessSequence<TProcess1, decltype(sequence(std::declval<TProcesses>()...))>> ProcessSequence<TProcess1, decltype(make_sequence(std::declval<TProcesses>()...))>>
sequence(TProcess1&& vA, TProcesses&&... vBs) { make_sequence(TProcess1&& vA, TProcesses&&... vBs) {
return ProcessSequence<TProcess1, decltype(sequence(std::declval<TProcesses>()...))>( return ProcessSequence<TProcess1,
vA, sequence(std::forward<TProcesses>(vBs)...)); decltype(make_sequence(std::declval<TProcesses>()...))>(
vA, make_sequence(std::forward<TProcesses>(vBs)...));
} }
/// marker to identify objectas ProcessSequence template <typename TProcess1, typename TProcess2>
template <typename A, typename B> inline typename std::enable_if_t<
struct is_process_sequence<corsika::ProcessSequence<A, B>> : std::true_type {}; 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) {
return ProcessSequence<TProcess1, TProcess2>(vA, vB);
}
/**
* \ function make_sequence
*
* also allow a single Process in ProcessSequence, accompany by
* `NullModel`
**/
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>>
make_sequence(TProcess&& vA) {
return ProcessSequence<TProcess, NullModel>(vA, NullModel());
}
/**
* \class is_process_sequence
*
* traits marker to identify objectas ProcessSequence
**/
template <typename TProcess1, typename TProcess2>
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_process_sequence() {}
};
} // namespace corsika } // namespace corsika
......
n/*
* (c) Copyright 2020 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
#define FORCE_SIGNATURE(nameTrait, nameMethod, signatureMethod) \
template <typename U> \
class nameTrait { \
private: \
template <typename T, T> \
struct helper; \
template <typename T> \
static std::uint8_t check(helper<signatureMethod, &nameMethod>*); \
template <typename T> \
static std::uint16_t check(...); \
\
public: \
static constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
}
// FORCE_SIGNATURE(thisMustBeDefined, T::thisMustBeDefined, int(*)(void));
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#pragma once #pragma once
#include <corsika/framework/process/BaseProcess.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/process/ProcessReturn.hpp>
namespace corsika { namespace corsika {
...@@ -28,11 +28,7 @@ namespace corsika { ...@@ -28,11 +28,7 @@ namespace corsika {
/// here starts the interface-definition part /// here starts the interface-definition part
// -> enforce TDerived to implement DoSecondaries... // -> enforce TDerived to implement DoSecondaries...
template <typename TSecondaries> template <typename TSecondaries>
inline void DoSecondaries(TSecondaries&); inline void doSecondaries(TSecondaries&);
}; };
// overwrite the default trait class, to mark BaseProcess<T> as useful process
template <class T>
std::true_type is_process_impl(const SecondariesProcess<T>* impl);
} // namespace corsika } // namespace corsika
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#pragma once #pragma once
#include <corsika/framework/process/BaseProcess.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/process/ProcessReturn.hpp> // for convenience
namespace corsika { namespace corsika {
...@@ -29,15 +29,15 @@ namespace corsika { ...@@ -29,15 +29,15 @@ namespace corsika {
public: public:
StackProcess() = delete; StackProcess() = delete;
StackProcess(const unsigned int nStep) StackProcess(const unsigned int nStep)
: fNStep(nStep) {} : nStep_(nStep) {}
/// here starts the interface-definition part /// here starts the interface-definition part
// -> enforce TDerived to implement DoStack... // -> enforce TDerived to implement DoStack...
template <typename TStack> template <typename TStack>
inline void DoStack(TStack&); inline void doStack(TStack&);
int GetStep() const { return fIStep; } int getStep() const { return iStep_; }
bool CheckStep() { return !((++fIStep) % fNStep); } bool checkStep() { return !((++iStep_) % nStep_); }
private: private:
/** /**
...@@ -46,13 +46,9 @@ namespace corsika { ...@@ -46,13 +46,9 @@ namespace corsika {
"fIStep modulo fNStep" "fIStep modulo fNStep"
@{ @{
*/ */
unsigned int fNStep = 0; unsigned int nStep_ = 0;
unsigned long int fIStep = 0; unsigned long int iStep_ = 0;
//! @} //! @}
}; };
// overwrite the default trait class, to mark BaseProcess<T> as useful process
template <class T>
std::true_type is_process_impl(const StackProcess<T>* impl);
} // namespace corsika } // namespace corsika
...@@ -12,7 +12,8 @@ set (test_framework_sources ...@@ -12,7 +12,8 @@ set (test_framework_sources
testLogging.cpp testLogging.cpp
TestMain.cpp TestMain.cpp
testParticles.cpp testParticles.cpp
#testProcessSequence.cpp #FIXME: reenable this testNullModel.cpp
testProcessSequence.cpp
testRandom.cpp testRandom.cpp
testSecondaryView.cpp testSecondaryView.cpp
testStackInterface.cpp testStackInterface.cpp
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#include <corsika/framework/core/Cascade.hpp> #include <corsika/framework/core/Cascade.hpp>
#include <corsika/framework/sequence/ProcessSequence.hpp> #include <corsika/framework/sequence/ProcessSequence.hpp>
#include <corsika/process/NullModel.hpp> #include <corsika/framework/sequence/NullModel.hpp>
#include <corsika/process/StackInspector.hpp> #include <corsika/modules/StackInspector.hpp>
#include <corsika/process/TrackingLine.hpp> #include <corsika/modules/TrackingLine.hpp>
#include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/core/ParticleProperties.hpp>
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
*/ */
#include <corsika/framework/process/ProcessSequence.hpp> #include <corsika/framework/process/ProcessSequence.hpp>
#include <corsika/framework/process/SwitchProcessSequence.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <catch2/catch.hpp> #include <catch2/catch.hpp>
...@@ -15,8 +17,6 @@ ...@@ -15,8 +17,6 @@
#include <iostream> #include <iostream>
#include <typeinfo> #include <typeinfo>
using namespace corsika;
using namespace corsika::units::si;
using namespace corsika; using namespace corsika;
using namespace std; using namespace std;
...@@ -41,7 +41,7 @@ public: ...@@ -41,7 +41,7 @@ public:
} }
template <typename D, typename T> template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const { inline EProcessReturn doContinuous(D& d, T&) const {
cout << "ContinuousProcess1::DoContinuous" << endl; cout << "ContinuousProcess1::DoContinuous" << endl;
checkCont |= 1; checkCont |= 1;
for (int i = 0; i < nData; ++i) d.data_[i] += 0.933; for (int i = 0; i < nData; ++i) d.data_[i] += 0.933;
...@@ -60,7 +60,7 @@ public: ...@@ -60,7 +60,7 @@ public:
} }
template <typename D, typename T> template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const { inline EProcessReturn doContinuous(D& d, T&) const {
cout << "ContinuousProcess2::DoContinuous" << endl; cout << "ContinuousProcess2::DoContinuous" << endl;
checkCont |= 2; checkCont |= 2;
for (int i = 0; i < nData; ++i) d.data_[i] += 0.111; for (int i = 0; i < nData; ++i) d.data_[i] += 0.111;
...@@ -79,7 +79,7 @@ public: ...@@ -79,7 +79,7 @@ public:
} }
template <typename D, typename T> template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const { inline EProcessReturn doContinuous(D& d, T&) const {
cout << "ContinuousProcess3::DoContinuous" << endl; cout << "ContinuousProcess3::DoContinuous" << endl;
checkCont |= 4; checkCont |= 4;
for (int i = 0; i < nData; ++i) d.data_[i] += 0.333; for (int i = 0; i < nData; ++i) d.data_[i] += 0.333;
...@@ -96,11 +96,17 @@ public: ...@@ -96,11 +96,17 @@ public:
} }
template <typename TView> template <typename TView>
inline EProcessReturn DoInteraction(TView& v) const { inline EProcessReturn doInteraction(TView& v) const {
checkInteract |= 1; checkInteract |= 1;
for (int i = 0; i < nData; ++i) v.parent().data_[i] += 1 + i; for (int i = 0; i < nData; ++i) v.parent().data_[i] += 1 + i;
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
template <typename TParticle>
GrammageType getInteractionLength(TParticle&) const {
return 10_g / square(1_cm);
}
private: private:
[[maybe_unused]] int fV; [[maybe_unused]] int fV;
}; };
...@@ -116,14 +122,14 @@ public: ...@@ -116,14 +122,14 @@ public:
} }
template <typename TView> template <typename TView>
inline EProcessReturn DoInteraction(TView& v) const { inline EProcessReturn doInteraction(TView& v) const {
checkInteract |= 2; checkInteract |= 2;
for (int i = 0; i < nData; ++i) v.parent().data_[i] /= 1.1; for (int i = 0; i < nData; ++i) v.parent().data_[i] /= 1.1;
cout << "Process2::DoInteraction" << endl; cout << "Process2::DoInteraction" << endl;
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
template <typename Particle> template <typename Particle>
GrammageType GetInteractionLength(Particle&) const { GrammageType getInteractionLength(Particle&) const {
cout << "Process2::GetInteractionLength" << endl; cout << "Process2::GetInteractionLength" << endl;
return 20_g / (1_cm * 1_cm); return 20_g / (1_cm * 1_cm);
} }
...@@ -140,14 +146,14 @@ public: ...@@ -140,14 +146,14 @@ public:
} }
template <typename TView> template <typename TView>
inline EProcessReturn DoInteraction(TView& v) const { inline EProcessReturn doInteraction(TView& v) const {
checkInteract |= 4; checkInteract |= 4;
for (int i = 0; i < nData; ++i) v.parent().data_[i] *= 1.01; for (int i = 0; i < nData; ++i) v.parent().data_[i] *= 1.01;
cout << "Process3::DoInteraction" << endl; cout << "Process3::DoInteraction" << endl;
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
template <typename Particle> template <typename Particle>
GrammageType GetInteractionLength(Particle&) const { GrammageType getInteractionLength(Particle&) const {
cout << "Process3::GetInteractionLength" << endl; cout << "Process3::GetInteractionLength" << endl;
return 30_g / (1_cm * 1_cm); return 30_g / (1_cm * 1_cm);
} }
...@@ -164,34 +170,31 @@ public: ...@@ -164,34 +170,31 @@ public:
} }
template <typename D, typename T> template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const { inline EProcessReturn doContinuous(D& d, T&) const {
std::cout << "Base::DoContinuous" << std::endl; std::cout << "Base::DoContinuous" << std::endl;
checkCont |= 8; checkCont |= 8;
for (int i = 0; i < nData; ++i) { d.data_[i] /= 1.2; } for (int i = 0; i < nData; ++i) { d.data_[i] /= 1.2; }
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
template <typename TView> template <typename TView>
EProcessReturn DoInteraction(TView&) const { EProcessReturn doInteraction(TView&) const {
checkInteract |= 8; checkInteract |= 8;
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
}; };
class Decay1 : public DecayProcess<Decay1> { class Decay1 : public DecayProcess<Decay1> {
[[maybe_unused]] int fV = 0;
public:
Decay1(const int) { Decay1(const int) {
cout << "Decay1()" << endl; cout << "Decay1()" << endl;
globalCount++; globalCount++;
} }
template <typename Particle> template <typename Particle>
TimeType GetLifetime(Particle&) const { TimeType getLifetime(Particle&) const {
return 1_s; return 1_s;
} }
template <typename TView> template <typename TView>
EProcessReturn DoDecay(TView&) const { EProcessReturn doDecay(TView&) const {
checkDecay |= 1; checkDecay |= 1;
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
...@@ -206,11 +209,11 @@ public: ...@@ -206,11 +209,11 @@ public:
} }
template <typename Particle> template <typename Particle>
TimeType GetLifetime(Particle&) const { TimeType getLifetime(Particle&) const {
return 2_s; return 2_s;
} }
template <typename TView> template <typename TView>
EProcessReturn DoDecay(TView&) const { EProcessReturn doDecay(TView&) const {
checkDecay |= 2; checkDecay |= 2;
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
...@@ -223,11 +226,11 @@ public: ...@@ -223,11 +226,11 @@ public:
Stack1(const int n) Stack1(const int n)
: StackProcess(n) {} : StackProcess(n) {}
template <typename TStack> template <typename TStack>
EProcessReturn DoStack(TStack&) { EProcessReturn doStack(TStack&) {
fCount++; fCount++;
return EProcessReturn::eOk; return EProcessReturn::eOk;
} }
int GetCount() const { return fCount; } int getCount() const { return fCount; }
}; };
struct DummyStack {}; struct DummyStack {};
...@@ -256,16 +259,16 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { ...@@ -256,16 +259,16 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
Process4 m4(3); Process4 m4(3);
CHECK(globalCount == 4); CHECK(globalCount == 4);
auto sequence1 = process::sequence(m1, m2, m3, m4); auto sequence1 = make_sequence(m1, m2, m3, m4);
CHECK(is_process_sequence_v<decltype(sequence1)> == true); CHECK(is_process_sequence_v<decltype(sequence1)> == true);
CHECK(is_process_sequence_v<decltype(m2)> == false); CHECK(is_process_sequence_v<decltype(m2)> == false);
CHECK(is_switch_process_sequence_v<decltype(sequence1)> == false); CHECK(is_switch_process_sequence_v<decltype(sequence1)> == false);
CHECK(is_switch_process_sequence_v<decltype(m2)> == false); CHECK(is_switch_process_sequence_v<decltype(m2)> == false);
auto sequence2 = process::sequence(m1, m2, m3); auto sequence2 = make_sequence(m1, m2, m3);
CHECK(is_process_sequence_v<decltype(sequence2)> == true); CHECK(is_process_sequence_v<decltype(sequence2)> == true);
auto sequence3 = process::sequence(m4); auto sequence3 = make_sequence(m4);
CHECK(is_process_sequence_v<decltype(sequence3)> == true); CHECK(is_process_sequence_v<decltype(sequence3)> == true);
} }
...@@ -277,9 +280,9 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { ...@@ -277,9 +280,9 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
DummyData particle; DummyData particle;
auto sequence2 = sequence(cp1, m2, m3); auto sequence2 = make_sequence(cp1, m2, m3);
GrammageType const tot = sequence2.GetInteractionLength(particle); GrammageType const tot = sequence2.getInteractionLength(particle);
InverseGrammageType const tot_inv = sequence2.GetInverseInteractionLength(particle); InverseGrammageType const tot_inv = sequence2.getInverseInteractionLength(particle);
cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl; cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;
CHECK(tot / 1_g * square(1_cm) == 12); CHECK(tot / 1_g * square(1_cm) == 12);
...@@ -296,9 +299,9 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { ...@@ -296,9 +299,9 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
DummyData particle; DummyData particle;
auto sequence2 = sequence(cp1, m2, m3, d3); auto sequence2 = make_sequence(cp1, m2, m3, d3);
TimeType const tot = sequence2.GetLifetime(particle); TimeType const tot = sequence2.getLifetime(particle);
InverseTimeType const tot_inv = sequence2.GetInverseLifetime(particle); InverseTimeType const tot_inv = sequence2.getInverseLifetime(particle);
cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl; cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;
CHECK(tot / 1_s == 1); CHECK(tot / 1_s == 1);
...@@ -313,7 +316,7 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { ...@@ -313,7 +316,7 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
Process2 m2(2); // /= 1.1 Process2 m2(2); // /= 1.1
Process3 m3(3); // *= 1.01 Process3 m3(3); // *= 1.01
auto sequence2 = sequence(cp1, m2, m3, cp2); auto sequence2 = make_sequence(cp1, m2, m3, cp2);
DummyData particle; DummyData particle;
DummyTrajectory track; DummyTrajectory track;
...@@ -329,7 +332,7 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { ...@@ -329,7 +332,7 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
cout << "Running loop with n=" << nLoop << endl; cout << "Running loop with n=" << nLoop << endl;
for (int iLoop = 0; iLoop < nLoop; ++iLoop) { for (int iLoop = 0; iLoop < nLoop; ++iLoop) {
for (int i = 0; i < nData; ++i) { test_data[i] += 0.933 + 0.111; } for (int i = 0; i < nData; ++i) { test_data[i] += 0.933 + 0.111; }
sequence2.DoContinuous(particle, track); sequence2.doContinuous(particle, track);
} }
for (int i = 0; i < nData; i++) { for (int i = 0; i < nData; i++) {
cout << "data_[" << i << "]=" << particle.data_[i] << endl; cout << "data_[" << i << "]=" << particle.data_[i] << endl;
...@@ -344,20 +347,20 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { ...@@ -344,20 +347,20 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
Stack1 s1(1); Stack1 s1(1);
Stack1 s2(2); Stack1 s2(2);
auto sequence = process::sequence(s1, s2); auto sequence1 = make_sequence(s1, s2);
DummyStack stack; DummyStack stack;
const int nLoop = 20; const int nLoop = 20;
for (int i = 0; i < nLoop; ++i) { sequence.DoStack(stack); } for (int i = 0; i < nLoop; ++i) { sequence1.doStack(stack); }
CHECK(s1.GetCount() == 20); CHECK(s1.getCount() == 20);
CHECK(s2.GetCount() == 10); CHECK(s2.getCount() == 10);
ContinuousProcess2 cp2(1); // += 0.111 ContinuousProcess2 cp2(1); // += 0.111
Process2 m2(2); // /= 1.1 Process2 m2(2); // /= 1.1
auto sequence2 = process::sequence(cp2, m2); auto sequence2 = make_sequence(cp2, m2);
auto sequence3 = process::sequence(cp2, m2, s1); auto sequence3 = make_sequence(cp2, m2, s1);
CHECK(is_process_sequence_v<decltype(sequence2)> == true); CHECK(is_process_sequence_v<decltype(sequence2)> == true);
CHECK(is_process_sequence_v<decltype(sequence3)> == true); CHECK(is_process_sequence_v<decltype(sequence3)> == true);
...@@ -366,14 +369,106 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { ...@@ -366,14 +369,106 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
} }
} }
/* TEST_CASE("Switch Process Sequence", "[Process Sequence]") {
Note: there is a fine-grained dedicated test-suite for SwitchProcess
in Processes/SwitchProcess/testSwtichProcess SECTION("Check construction") {
*/
/* struct TestSelect {
TEST_CASE("SwitchProcess") { SwitchResult operator()(const DummyData& p) const {
Process1 p1(0); std::cout << "TestSelect data=" << p.data_[0] << std::endl;
Process2 p2(0); if (p.data_[0] > 0) return SwitchResult::First;
switch_process::SwitchProcess s(p1, p2, 10_GeV); return SwitchResult::Second;
REQUIRE(is_switch_process_v<decltype(s)>); }
}*/ };
TestSelect select1;
auto sequence1 = make_sequence(Process1(0), ContinuousProcess2(0), Decay1(0));
auto sequence2 = make_sequence(ContinuousProcess3(0), Process2(0), Decay2(0));
auto sequence3 = make_sequence(ContinuousProcess1(0), Process3(0),
SwitchProcessSequence(sequence1, sequence2, select1));
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 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(
SwitchProcessSequence(sequence1, sequence2, select1))> == true);
DummyData particle;
DummyTrajectory track;
DummyView view(particle);
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = 100; // data positive
sequence3.doContinuous(particle, track);
CHECK(checkInteract == 0);
CHECK(checkDecay == 0);
CHECK(checkCont == 0b011);
CHECK(checkSec == 0);
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = -100; // data negative
sequence_alt.doContinuous(particle, track);
CHECK(checkInteract == 0);
CHECK(checkDecay == 0);
CHECK(checkCont == 0b101);
CHECK(checkSec == 0);
// 1/(30g/cm2) is Process3
InverseGrammageType lambda_select = .9 / 30. * square(1_cm) / 1_g;
InverseTimeType time_select = 0.1 / second;
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = 100; // data positive
sequence3.selectInteraction(view, lambda_select);
sequence3.selectDecay(view, time_select);
CHECK(checkInteract == 0b100); // this is Process3
CHECK(checkDecay == 0b001); // this is Decay1
CHECK(checkCont == 0);
CHECK(checkSec == 0);
lambda_select = 1.01 / 30. * square(1_cm) / 1_g;
checkInteract = 0;
sequence3.selectInteraction(view, lambda_select);
CHECK(checkInteract == 0b001); // this is Process1
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = -100; // data negative
sequence3.selectInteraction(view, lambda_select);
sequence3.selectDecay(view, time_select);
CHECK(checkInteract == 0b010); // this is Process2
CHECK(checkDecay == 0b010); // this is Decay2
CHECK(checkCont == 0);
CHECK(checkSec == 0);
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = -100; // data negative
sequence3.doSecondaries(view);
Stack1 stack(0);
sequence3.doStack(stack);
CHECK(checkInteract == 0);
CHECK(checkDecay == 0);
CHECK(checkCont == 0);
CHECK(checkSec == 0);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment