Physics modules and processes¶
-
group
Processes
Physics processes in CORSIKA 8 are clustered in ProcessSequence and SwitchProcessSequence containers.
The former is a mere (ordered) collection, while the latter has the option to switch between two alternative ProcessSequences.
Depending on the type of data to act on and on the allowed actions of processes there are several interface options:
And all processes (including ProcessSequence and SwitchProcessSequence) are derived from BaseProcess.
Processes of any type (e.g. p1, p2, p3,…) can be assembled into a ProcessSequence using the
make_sequence
factory function.auto sequence1 = make_sequence(p1, p2, p3); auto sequence2 = make_sequence(p4, p5, p6, p7); auto sequence3 = make_sequence(sequence1, sequemce2, p8, p9);
Note, if the order of processes matters, the order of occurence in the ProcessSequence determines the executiion order.
SecondariesProcess alyways act on new secondaries produced (i.e. in InteractionProcess and DecayProcess) in the scope of their ProcessSequence. For example if i1 and i2 are InteractionProcesses and s1 is a SecondariesProcess, then
auto sequence = make_sequence(i1, make_sequence(i2, s1))
will result in s1 acting only on the particles produced by i2 and not by i1. This can be very useful, e.g. to fine tune thinning.
A special type of ProcessSequence is SwitchProcessSequence, which has two branches and a functor that can select between these two branches.
auto sequence = make_switch(sequence1, sequence2, selector);
where the only requirement to
selector
is that it provides aSwitchResult operator()(Particle const& particle) const
method. Thus, based on the dynamic properties ofparticle
the functor can make its decision. This is clearly important for switching between low-energy and high-energy models, but not limited to this. The selection can even be done with a lambda function.-
template<typename
TDerived
>
structcorsika
::
BaseProcess
: public corsika::_BaseProcess¶ - #include <BaseProcess.hpp>
Each process in C8 must derive from BaseProcess.
The structural base type of a process object in a ProcessSequence. Both, the ProcessSequence and all its elements are of type BaseProcess
- Todo:
rename BaseProcess into just Process
rename _BaseProcess, or find better alternative in FIXME ./Processes/AnalyticProcessors/ExecTime.h, see e.g. how this is done in ProcessSequence.hpp/make_sequence
Subclassed by corsika::BoundaryCrossingProcess< TDerived >, corsika::ContinuousProcess< TDerived >, corsika::DecayProcess< TDerived >, corsika::InteractionProcess< TDerived >, corsika::SecondariesProcess< TDerived >, corsika::StackProcess< TDerived >
Public Static Functions
-
static inline unsigned int constexpr
getNumberOfProcesses
()¶ Default number of processes is just one, obviously.
-
template<typename
TDerived
>
classBoundaryCrossingProcess
: public corsika::BaseProcess<TDerived>¶ - #include <BoundaryCrossingProcess.hpp>
Processes acting on the particles traversion from one volume into another volume.
Create a new BoundaryCrossingProcess, e.g. for XYModel, via
class XYModel : public BoundaryCrossingProcess<XYModel> {};
and provide the necessary interface method:
template <typename TParticle> ProcessReturn XYModel::doBoundaryCrossing(TParticle& Particle, typename TParticle::node_type const& from, typename TParticle::node_type const& to);
where Particle is the object to read particle data from a Stack. The volume the particle is originating from is
from
, the volume where it goes to isto
.
-
template<typename
TDerived
>
classContinuousProcess
: public corsika::BaseProcess<TDerived>¶ - #include <ContinuousProcess.hpp>
Processes with continuous effects along a particle Trajectory.
Create a new ContinuousProcess, e.g. for XYModel, via
class XYModel : public ContinuousProcess<XYModel> {};
and provide two necessary interface methods:
template <typename TParticle, typename TTrack> LengthType getMaxStepLength(TParticle const& p, TTrack const& track) const;
which allows any ContinuousProcess to tell to CORSIKA a maximum allowed step length. Such step-length limitation, if it turns out to be smaller/sooner than any other limit (decay length, interaction length, other continuous processes, geometry, etc.) will lead to a limited step length.
template <typename TParticle, typename TTrack> ProcessReturn doContinuous(TParticle& p, TTrack const& t, bool const stepLimit) const;
which applied any continuous effects on Particle p along Trajectory t. The particle in all typical scenarios will be altered by a doContinuous. The flag stepLimit will be true if the preious evaluation of getMaxStepLength resulted in this particular ContinuousProcess to be responsible for the step length limit on the current track t. This information can be expoited and avoid e.g. any uncessary calculations.
Particle and Track are the valid classes to access particles and track (Trajectory) data on the Stack. Those two methods do not need to be templated, they could use the types e.g. corsika::setup::Stack::particle_type but by the cost of loosing all flexibility otherwise provided.
-
class
ContinuousProcessIndex
¶ - #include <ContinuousProcessIndex.hpp>
To index individual processes (continuous processes) inside a ProcessSequence.
-
class
ContinuousProcessStepLength
¶ - #include <ContinuousProcessStepLength.hpp>
To store step length in LengthType and unique index in ProcessSequence of shortest step ContinuousProcess.
-
template<typename
TDerived
>
structDecayProcess
: public corsika::BaseProcess<TDerived>¶ - #include <DecayProcess.hpp>
Process decribing the decay of particles.
Create a new DecayProcess, e.g. for XYModel, via
class XYModel : public DecayProcess<XYModel> {};
and provide the two necessary interface methods
template <typename TSecondaryView> void XYModel::doDecay(TSecondaryView&); template <typename TParticle> TimeType getLifetime(TParticle const&)
Where, of course, SecondaryView and Particle are the valid classes to access particles on the Stack. Those two methods do not need to be templated, they could use the types e.g. corsika::setup::Stack::particle_type but by the cost of loosing all flexibility otherwise provided.
SecondaryView allows to retrieve the properties of the projectile particles, AND to store new particles (secondaries) which then subsequently can be processes by SecondariesProcess. This is how the output of decays can be studied right away.
-
template<class
TCountedProcess
>
classcorsika
::
InteractionCounter
: public corsika::InteractionProcess<InteractionCounter<TCountedProcess>>¶ - #include <InteractionCounter.hpp>
Wrapper around an InteractionProcess that fills histograms of the number of calls to
doInteraction()
binned in projectile energy (both in lab and center-of-mass frame) and speciesUse by wrapping a normal InteractionProcess
InteractionProcess collision1; InteractionClounter<collision1> counted_collision1;
Public Functions
-
template<typename
TSecondaryView
>
voiddoInteraction
(TSecondaryView &view)¶ wrapper around internall process doInteraction
-
template<typename
TParticle
>
GrammageTypegetInteractionLength
(TParticle const &particle) const¶ ! returns internal process getInteractionLength
-
InteractionHistogram const &
getHistogram
() const¶ returns the filles histograms
- Return
InteractionHistogram, which contains the histogram data
-
template<typename
-
class
corsika
::
InteractionHistogram
¶ - #include <InteractionHistogram.hpp>
Class that creates and stores histograms of collisions \(dN/dE_{lab}\), \(dN/d\sqrt{s}\) which is used by class InteractionCounter.
Histograms are of type boost::histogram
Public Functions
-
void
fill
(Code projectile_id, HEPEnergyType lab_energy, HEPEnergyType mass_target, int A = 0, int Z = 0)¶ fill both CMS and lab histograms at the same time
- Parameters
projectile_id
: corsika::Code of particlelab_energy
: Energy in lab. framemass_target
: Mass of target particleA
: if projectile_id is corsika::Nucleus : Mass of nucleusZ
: if projectile_id is corsika::Nucleus : Charge of nucleus
-
inline hist_type const &
CMSHist
() const¶ return histogram in c.m.s. frame
-
inline hist_type const &
labHist
() const¶ return histogram in laboratory frame
-
void
-
template<typename
TDerived
>
classInteractionProcess
: public corsika::BaseProcess<TDerived>¶ - #include <InteractionProcess.hpp>
Process describing the interaction of particles.
Create a new InteractionProcess, e.g. for XYModel, via
class XYModel : public InteractionProcess<XYModel> {};
and provide the two necessary interface methods
template <typename TSecondaryView> void XYModel::doInteraction(TSecondaryView&); template <typename TParticle> GrammageType XYModel::getInteractionLength(TParticle const&)
Where, of course, SecondaryView and Particle are the valid classes to access particles on the Stack. Those two methods do not need to be templated, they could use the types e.g. corsika::setup::Stack::particle_type but by the cost of loosing all flexibility otherwise provided.
SecondaryView allows to retrieve the properties of the projectile particles, AND to store new particles (secondaries) which then subsequently can be processes by SecondariesProcess. This is how the output of interactions can be studied right away.
-
class
corsika
::
NullModel
¶ - #include <NullModel.hpp>
Process that does nothing.
It is not even derived from BaseProcess
Public Static Functions
-
static inline unsigned int constexpr
getNumberOfProcesses
()¶ Default number of processes is just one, obviously.
-
static inline unsigned int constexpr
-
template<typename
TDerived
>
classSecondariesProcess
: public corsika::BaseProcess<TDerived>¶ - #include <SecondariesProcess.hpp>
Processes acting on the secondaries produced by other processes.
Create a new SecondariesProcess, e.g. for XYModel, via
class XYModel : public SecondariesProcess<XYModel> {};
and provide the necessary interface method:
template <typename TStackView> void doSecondaries(TStackView& StackView);
where StackView is an object that can store secondaries on a stack and also iterate over these secondaries.
-
template<typename
TDerived
>
classcorsika
::
StackProcess
: public corsika::BaseProcess<TDerived>¶ - #include <StackProcess.hpp>
Process to act on the entire particle stack.
Create a new StackProcess, e.g. for XYModel, via
class XYModel : public StackProcess<XYModel> {};
and provide the necessary interface method
template <typename TStack> void XYModel::doStack(TStack&);
Where, of course, Stack is the valid class to access particles on the Stack. This methods does not need to be templated, they could use the types e.g. corsika::setup::Stack directly but by the cost of loosing all flexibility otherwise provided.
A StackProcess has only one constructor
StackProcess::StackProcess(unsigned int const nStep)
where nStep is the number of steps of the cascade stepping after which the stack process should be run. Good values are on the order of 1000, which will not compromise run time in the end, but provide all the benefits of the StackProcess.The number of “steps” during the cascade processing after
which this StackProcess is going to be executed.
The logic is “iStep_ modulo nStep_”
Public Functions
-
inline int
getStep
() const¶ return the current Cascade step counter
-
inline bool
checkStep
()¶ check if current step is where StackProcess should be executed, this also increases the internal step counter implicitly
-
inline int
-
template<typename
TProcess1
, typenameTProcess2
, typenameTSelect
, intIndexFirstProcess
= 0, intIndexOfProcess1
= count_processes<TProcess1, IndexFirstProcess>::count, intIndexOfProcess2
= count_processes<TProcess2, IndexOfProcess1>::count>
classcorsika
::
SwitchProcessSequence
: public corsika::BaseProcess<SwitchProcessSequence<TProcess1, TProcess2, TSelect>>¶ - #include <SwitchProcessSequence.hpp>
Class to switch between two process branches.
A compile-time static list of processes that uses an internal TSelect class to switch between different versions of processes (or process sequence).
TProcess1 and TProcess2 must be derived from BaseProcess and are both references if possible (lvalue), otherwise (rvalue) they are just classes. This allows us to handle both, rvalue as well as lvalue Processes in the SwitchProcessSequence.
TSelect has to implement a
operator()(const Particle&)
and has to return either SwitchResult::First or SwitchResult::Second. Note: TSelect may absolutely also use random numbers to sample between its results. This can be used to achieve arbitrarily smooth transition or mixtures of processes.Warning: do not put StackProcess into a SwitchProcessSequence since this makes no sense. The StackProcess acts on an entire particle stack and not on indiviidual particles.
Template parameters:
See also class
ProcessSequence.- Template Parameters
TProcess1
: is of type BaseProcess, either a dedicatd process, or a ProcessSequenceTProcess2
: is of type BaseProcess, either a dedicatd process, or a ProcessSequenceTSelect
: selector functor/functionIndexFirstProcess
: to count and index each Process in the entire process-chainIndexOfProcess1
: index of TProcess1 (counting of Process)IndexOfProcess2
: index of TProcess2 (counting of Process)
Public Functions
-
inline
SwitchProcessSequence
(TProcess1 in_A, TProcess2 in_B, TSelect sel)¶ Only valid user constructor will create fully initialized object.
SwitchProcessSequence supports and encourages move semantics. You can use object, l-value references or r-value references to construct sequences.
- Parameters
in_A
: process branch Ain_A
: process branch Bsel
: functor to switch between branch A and B
Public Static Functions
-
static inline unsigned int constexpr
getNumberOfProcesses
()¶ static counter to uniquely index (count) all ContinuousProcess in switch sequence.
-
template<typename
TProcess1
, typenameTProcess2
= NullModel, intProcessIndexOffset
= 0, intIndexOfProcess1
= count_processes<TProcess1, count_processes<TProcess2, ProcessIndexOffset>::count>::count, intIndexOfProcess2
= count_processes<TProcess2, ProcessIndexOffset>::count>
classcorsika
::
ProcessSequence
: public corsika::BaseProcess<ProcessSequence<TProcess1, TProcess2>>¶ - #include <ProcessSequence.hpp>
Definition of a static process list/sequence
A compile time static list of processes. The compiler will generate a new type based on template logic containing all the elements provided by the user.
TProcess1 and TProcess2 must both be derived from BaseProcess, and are both references if possible (lvalue), otherwise (rvalue) they are just classes. This allows us to handle both, rvalue as well as lvalue Processes in the ProcessSequence.
(For your potential interest, the static version of the ProcessSequence and all Process types are based on the CRTP C++ design pattern)
Template parameters:
- Template Parameters
TProcess1
: is of type BaseProcess, either a dedicatd process, or a ProcessSequenceTProcess2
: is of type BaseProcess, either a dedicatd process, or a ProcessSequenceIndexFirstProcess
: to count and index each Process in the entire process-chain. The offset is the starting value for this ProcessSequenceIndexOfProcess1
: index of TProcess1 (counting of Process)IndexOfProcess2
: index of TProcess2 (counting of Process)
Public Functions
-
inline
ProcessSequence
(TProcess1 in_A, TProcess2 in_B)¶ Only valid user constructor will create fully initialized object.
ProcessSequence supports and encourages move semantics. You can use object, l-value references or r-value references to construct sequences.
- Parameters
in_A
: process/list Ain_A
: process/list B
-
bool
checkStep
()¶ The processes of type StackProcess do have an internal counter, so they can be exectuted only each N steps.
Often these are “maintenacne processes” that do not need to run after each single step of the simulations. In the CheckStep function it is tested if either A_ or B_ are StackProcess and if they are due for execution.
-
template<typename
TStack
>
voiddoStack
(TStack &stack)¶ Execute the StackProcess-es in the ProcessSequence.
-
template<typename
TParticle
, typenameTTrack
>
ContinuousProcessStepLengthgetMaxStepLength
(TParticle &particle, TTrack &vTrack)¶ 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.
Public Static Functions
-
static inline unsigned int constexpr
getNumberOfProcesses
()¶ static counter to uniquely index (count) all ContinuousProcess in switch sequence.