IAP GITLAB

Skip to content
Snippets Groups Projects
Commit c96767ee authored by Maximilian Sackel's avatar Maximilian Sackel
Browse files

add further doc and some minor fixes in particle cut

parent dbc61589
No related branches found
No related tags found
No related merge requests found
...@@ -195,7 +195,6 @@ int main(int argc, char** argv) { ...@@ -195,7 +195,6 @@ int main(int argc, char** argv) {
process::on_shell_check::OnShellCheck reset_particle_mass(1.e-3, 1.e-1, false); process::on_shell_check::OnShellCheck reset_particle_mass(1.e-3, 1.e-1, false);
process::energy_loss::EnergyLoss eLoss(showerAxis);
process::longitudinal_profile::LongitudinalProfile longprof{showerAxis}; process::longitudinal_profile::LongitudinalProfile longprof{showerAxis};
Plane const obsPlane(showerCore, Vector<dimensionless_d>(rootCS, {0., 0., 1.})); Plane const obsPlane(showerCore, Vector<dimensionless_d>(rootCS, {0., 0., 1.}));
...@@ -205,10 +204,6 @@ int main(int argc, char** argv) { ...@@ -205,10 +204,6 @@ int main(int argc, char** argv) {
process::UrQMD::UrQMD urqmd; process::UrQMD::UrQMD urqmd;
process::interaction_counter::InteractionCounter urqmdCounted{urqmd}; process::interaction_counter::InteractionCounter urqmdCounted{urqmd};
/* process::conex_source_cut::CONEXSourceCut conexSource( */
/* center, showerAxis, t, injectionHeight, E0, */
/* particles::GetPDG(particles::Code::Proton)); */
// assemble all processes into an ordered process list // assemble all processes into an ordered process list
auto sibyllSequence = sibyllNucCounted << sibyllCounted; auto sibyllSequence = sibyllNucCounted << sibyllCounted;
...@@ -216,8 +211,6 @@ int main(int argc, char** argv) { ...@@ -216,8 +211,6 @@ int main(int argc, char** argv) {
55_GeV); 55_GeV);
auto decaySequence = decayPythia << decaySibyll; auto decaySequence = decayPythia << decaySibyll;
//auto sequence = switchProcess << reset_particle_mass << decaySequence << conexSource
// << longprof << eLoss << cut << observationLevel;
auto sequence = switchProcess << reset_particle_mass << decaySequence << proposalCounted << cut << em_continuous auto sequence = switchProcess << reset_particle_mass << decaySequence << proposalCounted << cut << em_continuous
<< longprof << observationLevel; << longprof << observationLevel;
...@@ -231,16 +224,12 @@ int main(int argc, char** argv) { ...@@ -231,16 +224,12 @@ int main(int argc, char** argv) {
EAS.Run(); EAS.Run();
eLoss.PrintProfile(); // print longitudinal profile
/* conexSource.SolveCE(); */
cut.ShowResults(); cut.ShowResults();
const HEPEnergyType Efinal = const HEPEnergyType Efinal =
cut.GetCutEnergy() + cut.GetInvEnergy() + cut.GetEmEnergy(); cut.GetCutEnergy() + cut.GetInvEnergy() + cut.GetEmEnergy();
cout << "total cut energy (GeV): " << Efinal / 1_GeV << endl cout << "total cut energy (GeV): " << Efinal / 1_GeV << endl
<< "relative difference (%): " << (Efinal / E0 - 1) * 100 << endl; << "relative difference (%): " << (Efinal / E0 - 1) * 100 << endl;
cout << "total dEdX energy (GeV): " << eLoss.GetTotal() / 1_GeV << endl
<< "relative difference (%): " << eLoss.GetTotal() / E0 * 100 << endl;
auto const hists = sibyllCounted.GetHistogram() + sibyllNucCounted.GetHistogram() + auto const hists = sibyllCounted.GetHistogram() + sibyllNucCounted.GetHistogram() +
urqmdCounted.GetHistogram() + proposalCounted.GetHistogram(); urqmdCounted.GetHistogram() + proposalCounted.GetHistogram();
......
...@@ -84,7 +84,7 @@ namespace corsika::process { ...@@ -84,7 +84,7 @@ namespace corsika::process {
ParticleCut::ParticleCut(const units::si::HEPEnergyType eCut, bool discardEm, bool discardInv) ParticleCut::ParticleCut(const units::si::HEPEnergyType eCut, bool discardEm, bool discardInv)
: eCut_(eCut) : eCut_(eCut)
, discardEm_(cutEm) , discardEm_(discardEm)
, discardInv_(discardInv) { , discardInv_(discardInv) {
emEnergy_ = 0_GeV; emEnergy_ = 0_GeV;
......
...@@ -18,8 +18,8 @@ namespace corsika::process { ...@@ -18,8 +18,8 @@ namespace corsika::process {
class ParticleCut : public process::SecondariesProcess<ParticleCut> { class ParticleCut : public process::SecondariesProcess<ParticleCut> {
units::si::HEPEnergyType const eCut_; units::si::HEPEnergyType const eCut_;
bool cutEm_; bool discardEm_;
bool cutInv_; bool discardInv_;
units::si::HEPEnergyType energy_ = 0 * units::si::electronvolt; units::si::HEPEnergyType energy_ = 0 * units::si::electronvolt;
units::si::HEPEnergyType emEnergy_ = 0 * units::si::electronvolt; units::si::HEPEnergyType emEnergy_ = 0 * units::si::electronvolt;
......
...@@ -23,10 +23,19 @@ namespace corsika::process::proposal { ...@@ -23,10 +23,19 @@ namespace corsika::process::proposal {
void ContinuousProcess::BuildCalculator(particles::Code code, void ContinuousProcess::BuildCalculator(particles::Code code,
environment::NuclearComposition const& comp) { environment::NuclearComposition const& comp) {
// search crosssection builder for given particle
auto p_cross = cross.find(code); auto p_cross = cross.find(code);
if (p_cross == cross.end()) if (p_cross == cross.end())
throw std::runtime_error("PROPOSAL could not find corresponding builder"); throw std::runtime_error("PROPOSAL could not find corresponding builder");
// interpolate the crosssection for given media and energy cut. These may
// take some minutes if you have to build the tables and cannot read the
// from disk
auto c = p_cross->second(media.at(&comp), cut); auto c = p_cross->second(media.at(&comp), cut);
// Build displacement integral and scattering object and interpolate them too and
// saved in the calc map by a key build out of a hash of composed of the component and
// particle code.
auto disp = PROPOSAL::make_displacement(c, true); auto disp = PROPOSAL::make_displacement(c, true);
auto scatter = PROPOSAL::make_scattering("highland", particle[code], media.at(&comp)); auto scatter = PROPOSAL::make_scattering("highland", particle[code], media.at(&comp));
calc[std::make_pair(&comp, code)] = calc[std::make_pair(&comp, code)] =
...@@ -38,31 +47,35 @@ namespace corsika::process::proposal { ...@@ -38,31 +47,35 @@ namespace corsika::process::proposal {
particle_cut::ParticleCut& _cut) particle_cut::ParticleCut& _cut)
: ProposalProcessBase(_env, _cut) {} : ProposalProcessBase(_env, _cut) {}
template <>
HEPEnergyType ContinuousProcess::TotalEnergyLoss(setup::Stack::ParticleType const& vP,
GrammageType const& vDX) {
auto c = GetCalculator(vP, calc);
return vP.GetEnergy() - get<DISPLACEMENT>(c->second)->UpperLimitTrackIntegral(
vP.GetEnergy() / 1_MeV, vDX / 1_g * 1_cm * 1_cm) *
1_MeV;
}
template <> template <>
void ContinuousProcess::Scatter(setup::Stack::ParticleType& vP, void ContinuousProcess::Scatter(setup::Stack::ParticleType& vP,
HEPEnergyType const& loss, HEPEnergyType const& loss,
GrammageType const& grammage) { GrammageType const& grammage) {
// Get or build corresponding calculators
auto c = GetCalculator(vP, calc); auto c = GetCalculator(vP, calc);
// Cast corsika vector to proposal vector
auto d = vP.GetDirection().GetComponents(); auto d = vP.GetDirection().GetComponents();
auto direction = PROPOSAL::Vector3D(d.GetX().magnitude(), d.GetY().magnitude(), auto direction = PROPOSAL::Vector3D(d.GetX().magnitude(), d.GetY().magnitude(),
d.GetZ().magnitude()); d.GetZ().magnitude());
auto E_f = vP.GetEnergy() - loss; // final energy
auto E_f = vP.GetEnergy() - loss;
// draw random numbers required for scattering process
std::uniform_real_distribution<double> distr(0., 1.); std::uniform_real_distribution<double> distr(0., 1.);
auto rnd = array<double, 4>(); auto rnd = array<double, 4>();
for (auto& it : rnd) it = distr(fRNG); for (auto& it : rnd) it = distr(fRNG);
// calculate deflection based on particle energy, loss
auto [mean_dir, final_dir] = get<SCATTERING>(c->second)->Scatter( auto [mean_dir, final_dir] = get<SCATTERING>(c->second)->Scatter(
grammage / 1_g * square(1_cm), vP.GetEnergy() / 1_MeV, E_f / 1_MeV, direction, grammage / 1_g * square(1_cm), vP.GetEnergy() / 1_MeV, E_f / 1_MeV, direction,
rnd); rnd);
// TODO: neglect mean direction deflection because Trajectory is a const ref
(void)mean_dir; (void)mean_dir;
// update particle direction after continuous loss caused by multiple
// scattering
auto vec = corsika::geometry::QuantityVector( auto vec = corsika::geometry::QuantityVector(
final_dir.GetX() * E_f, final_dir.GetY() * E_f, final_dir.GetZ() * E_f); final_dir.GetX() * E_f, final_dir.GetY() * E_f, final_dir.GetZ() * E_f);
vP.SetMomentum(corsika::stack::MomentumVector( vP.SetMomentum(corsika::stack::MomentumVector(
...@@ -74,11 +87,26 @@ namespace corsika::process::proposal { ...@@ -74,11 +87,26 @@ namespace corsika::process::proposal {
EProcessReturn ContinuousProcess::DoContinuous(setup::Stack::ParticleType& vP, EProcessReturn ContinuousProcess::DoContinuous(setup::Stack::ParticleType& vP,
setup::Trajectory const& vT) { setup::Trajectory const& vT) {
if (!CanInteract(vP.GetPID())) return process::EProcessReturn::eOk; if (!CanInteract(vP.GetPID())) return process::EProcessReturn::eOk;
// calculate passed grammage
auto dX = vP.GetNode()->GetModelProperties().IntegratedGrammage(vT, vT.GetLength()); auto dX = vP.GetNode()->GetModelProperties().IntegratedGrammage(vT, vT.GetLength());
auto energy_loss = TotalEnergyLoss(vP, dX);
if (vP.GetChargeNumber() != 0) Scatter(vP, energy_loss, dX); // Get or build corresponding track integral calculator and solve the
vP.SetEnergy(vP.GetEnergy() - energy_loss); // integral
if (vP.GetEnergy() <= cut.GetECut()) return process::EProcessReturn::eParticleAbsorbed; auto c = GetCalculator(vP, calc);
auto final_energy = get<DISPLACEMENT>(c->second)->UpperLimitTrackIntegral(
vP.GetEnergy() / 1_MeV, dX / 1_g * 1_cm * 1_cm) *
1_MeV;
// if the particle has a charge take multiple scattering into account
if (vP.GetChargeNumber() != 0 && vP.GetEnergy() > final_energy)
Scatter(vP, vP.GetEnergy() - final_energy, dX);
// Update the energy and absorbe the particle if it's below the energy
// threshold, because it will no longer propagated.
vP.SetEnergy(final_energy);
if (std::fabs((vP.GetEnergy() - cut.GetECut() )/ cut.GetECut()) < 0.01)
return process::EProcessReturn::eParticleAbsorbed;
vP.SetMomentum(vP.GetMomentum() * vP.GetEnergy() / vP.GetMomentum().GetNorm()); vP.SetMomentum(vP.GetMomentum() * vP.GetEnergy() / vP.GetMomentum().GetNorm());
return process::EProcessReturn::eOk; return process::EProcessReturn::eOk;
} }
...@@ -88,12 +116,22 @@ namespace corsika::process::proposal { ...@@ -88,12 +116,22 @@ namespace corsika::process::proposal {
setup::Stack::ParticleType const& vP, setup::Trajectory const& vT) { setup::Stack::ParticleType const& vP, setup::Trajectory const& vT) {
if (!CanInteract(vP.GetPID())) if (!CanInteract(vP.GetPID()))
return units::si::meter * std::numeric_limits<double>::infinity(); return units::si::meter * std::numeric_limits<double>::infinity();
// Limit the step size of a conitnous loss. The maximal continuous loss seems to be a
// hyper parameter which must be adjusted.
auto energy_lim = 0.9 * vP.GetEnergy(); auto energy_lim = 0.9 * vP.GetEnergy();
// If energy lim is below the cut it couldn't be descriped by these process. So the
// energy_lim is replaced by the cut.
if (cut.GetECut() > energy_lim) energy_lim = cut.GetECut(); if (cut.GetECut() > energy_lim) energy_lim = cut.GetECut();
// solving the track integral for giving energy lim
auto c = GetCalculator(vP, calc); auto c = GetCalculator(vP, calc);
auto grammage = get<DISPLACEMENT>(c->second)->SolveTrackIntegral( auto grammage = get<DISPLACEMENT>(c->second)->SolveTrackIntegral(
vP.GetEnergy() / 1_MeV, energy_lim / 1_MeV) * vP.GetEnergy() / 1_MeV, energy_lim / 1_MeV) *
1_g / square(1_cm); 1_g / square(1_cm);
// return it in distance aequivalent
return vP.GetNode()->GetModelProperties().ArclengthFromGrammage(vT, grammage); return vP.GetNode()->GetModelProperties().ArclengthFromGrammage(vT, grammage);
} }
......
...@@ -43,19 +43,14 @@ namespace corsika::process::proposal { ...@@ -43,19 +43,14 @@ namespace corsika::process::proposal {
void BuildCalculator(particles::Code, environment::NuclearComposition const&) final; void BuildCalculator(particles::Code, environment::NuclearComposition const&) final;
public: public:
//!
//! Produces the continuous loss calculator for leptons based on nuclear //! Produces the continuous loss calculator for leptons based on nuclear
//! compositions and stochastic description limited by the particle cut. //! compositions and stochastic description limited by the particle cut.
//! //!
template <typename TEnvironment> template <typename TEnvironment>
ContinuousProcess(TEnvironment const&, particle_cut::ParticleCut&); ContinuousProcess(TEnvironment const&, particle_cut::ParticleCut&);
//!
//! Calculates the energy of the particle which has passed the given
//! grammage.
//!
template <typename Particle>
corsika::units::si::HEPEnergyType TotalEnergyLoss(
Particle const&, corsika::units::si::GrammageType const&);
//! //!
//! Multiple Scattering of the lepton. Stochastic deflection is not yet taken into //! Multiple Scattering of the lepton. Stochastic deflection is not yet taken into
......
...@@ -31,10 +31,20 @@ namespace corsika::process::proposal { ...@@ -31,10 +31,20 @@ namespace corsika::process::proposal {
void Interaction::BuildCalculator(particles::Code code, void Interaction::BuildCalculator(particles::Code code,
environment::NuclearComposition const& comp) { environment::NuclearComposition const& comp) {
// search crosssection builder for given particle
auto p_cross = cross.find(code); auto p_cross = cross.find(code);
if (p_cross == cross.end()) if (p_cross == cross.end())
throw std::runtime_error("PROPOSAL could not find corresponding builder"); throw std::runtime_error("PROPOSAL could not find corresponding builder");
// interpolate the crosssection for given media and energy cut. These may
// take some minutes if you have to build the tables and cannot read the
// from disk
auto c = p_cross->second(media.at(&comp), cut); auto c = p_cross->second(media.at(&comp), cut);
// Look which interactions take place and build the corresponding
// interaction and secondarie builder. The interaction integral will
// interpolated too and saved in the calc map by a key build out of a hash
// of composed of the component and particle code.
auto inter_types = PROPOSAL::CrossSectionVector::GetInteractionTypes(c); auto inter_types = PROPOSAL::CrossSectionVector::GetInteractionTypes(c);
calc[std::make_pair(&comp, code)] = std::make_tuple( calc[std::make_pair(&comp, code)] = std::make_tuple(
PROPOSAL::make_secondaries(inter_types, particle[code], media.at(&comp)), PROPOSAL::make_secondaries(inter_types, particle[code], media.at(&comp)),
...@@ -45,11 +55,19 @@ namespace corsika::process::proposal { ...@@ -45,11 +55,19 @@ namespace corsika::process::proposal {
corsika::process::EProcessReturn Interaction::DoInteraction( corsika::process::EProcessReturn Interaction::DoInteraction(
setup::StackView::StackIterator& vP) { setup::StackView::StackIterator& vP) {
if (CanInteract(vP.GetPID())) { if (CanInteract(vP.GetPID())) {
auto c = GetCalculator(vP, calc); // [CrossSections] // Get or build corresponding calculators
auto c = GetCalculator(vP, calc);
// Get the rates of the interaction types for every component.
std::uniform_real_distribution<double> distr(0., 1.); std::uniform_real_distribution<double> distr(0., 1.);
// sample a interaction-type, loss and component
auto rates = get<INTERACTION>(c->second)->Rates(vP.GetEnergy() / 1_MeV); auto rates = get<INTERACTION>(c->second)->Rates(vP.GetEnergy() / 1_MeV);
auto [type, comp_ptr, v] = get<INTERACTION>(c->second)->SampleLoss( auto [type, comp_ptr, v] = get<INTERACTION>(c->second)->SampleLoss(
vP.GetEnergy() / 1_MeV, rates, distr(fRNG)); vP.GetEnergy() / 1_MeV, rates, distr(fRNG));
// Read how much random numbers are required to calculate the secondaries.
// Calculate the secondaries and deploy them on the corsika stack.
auto rnd = vector<double>(get<SECONDARIES>(c->second)->RequiredRandomNumbers(type)); auto rnd = vector<double>(get<SECONDARIES>(c->second)->RequiredRandomNumbers(type));
for (auto& it : rnd) it = distr(fRNG); for (auto& it : rnd) it = distr(fRNG);
auto point = PROPOSAL::Vector3D(vP.GetPosition().GetX() / 1_cm, auto point = PROPOSAL::Vector3D(vP.GetPosition().GetX() / 1_cm,
......
...@@ -23,24 +23,44 @@ namespace corsika::process::proposal { ...@@ -23,24 +23,44 @@ namespace corsika::process::proposal {
using namespace corsika::units::si; using namespace corsika::units::si;
//!
//! Electro-magnetic and gamma stochastic losses produced by proposal. It makes
//! use of interpolation tables which are runtime intensive calculation, but can be
//! reused by setting the \param PROPOSAL::InterpolationDef::path_to_tables variable.
//!
class Interaction : public InteractionProcess<Interaction>, ProposalProcessBase { class Interaction : public InteractionProcess<Interaction>, ProposalProcessBase {
enum { SECONDARIES, INTERACTION };
using calculator_t = tuple<unique_ptr<PROPOSAL::SecondariesCalculator>, using calculator_t = tuple<unique_ptr<PROPOSAL::SecondariesCalculator>,
unique_ptr<PROPOSAL::Interaction>>; unique_ptr<PROPOSAL::Interaction>>;
std::unordered_map<calc_key_t, calculator_t, hash> calc; std::unordered_map<calc_key_t, calculator_t, hash>
calc; //!< Stores the secondaries and interaction calculators.
//!
//! Build the secondaries and interaction calculators and add it to calc.
//!
void BuildCalculator(particles::Code, environment::NuclearComposition const&) final; void BuildCalculator(particles::Code, environment::NuclearComposition const&) final;
enum { SECONDARIES, INTERACTION };
public: public:
//!
//! Produces the stoachastic loss calculator for leptons based on nuclear
//! compositions and stochastic description limited by the particle cut.
//!
template <typename TEnvironment> template <typename TEnvironment>
Interaction(TEnvironment const& env, particle_cut::ParticleCut& cut); Interaction(TEnvironment const& env, particle_cut::ParticleCut& cut);
//!
//! Calculate the rates for the different targets and interactions. Sample a
//! pair of interaction-type, component and rate, followed by sampling a loss and
//! produce the corresponding secondaries and store them on the particle stack.
//!
template <typename Particle> template <typename Particle>
corsika::process::EProcessReturn DoInteraction(Particle&); corsika::process::EProcessReturn DoInteraction(Particle&);
//!
//! Calculates the mean free path length
//!
template <typename TParticle> template <typename TParticle>
corsika::units::si::GrammageType GetInteractionLength(TParticle const& p); corsika::units::si::GrammageType GetInteractionLength(TParticle const& p);
}; };
......
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