diff --git a/Documentation/Examples/proposal_example.cc b/Documentation/Examples/proposal_example.cc index 3fb41d1698f02a1cd361088a2b44acf28def9b54..de16fc65db2f361cea0ccb74aa28d8cbe089bf3d 100644 --- a/Documentation/Examples/proposal_example.cc +++ b/Documentation/Examples/proposal_example.cc @@ -29,6 +29,7 @@ #include <corsika/utl/CorsikaFenv.h> #include <corsika/process/track_writer/TrackWriter.h> #include <corsika/process/proposal/Interaction.h> +#include <corsika/process/proposal/ContinuousProcess.h> #include <iomanip> #include <iostream> @@ -137,6 +138,7 @@ int main(int argc, char** argv) { process::particle_cut::ParticleCut cut(10_GeV); process::proposal::Interaction proposal(env, cut); + process::proposal::ContinuousProcess em_continuous(env, cut); process::interaction_counter::InteractionCounter proposalCounted(proposal); process::track_writer::TrackWriter trackWriter("tracks.dat"); @@ -150,7 +152,12 @@ int main(int argc, char** argv) { process::observation_plane::ObservationPlane observationLevel(obsPlane, "particles.dat"); - auto sequence = proposalCounted << longprof << proposal << cut << observationLevel << trackWriter; + auto sequence = proposalCounted + << cut + << em_continuous + << longprof + << observationLevel + << trackWriter; // define air shower object, run simulation tracking_line::TrackingLine tracking; cascade::Cascade EAS(env, tracking, sequence, stack); diff --git a/Processes/Proposal/ContinuousProcess.cc b/Processes/Proposal/ContinuousProcess.cc index 5914d529606bf264da310ad46eed8717ddbe6e7e..d222a80b121e21c7de1de50e03fd1df820f026f4 100644 --- a/Processes/Proposal/ContinuousProcess.cc +++ b/Processes/Proposal/ContinuousProcess.cc @@ -1,6 +1,7 @@ #include <PROPOSAL/PROPOSAL.h> #include <corsika/environment/IMediumModel.h> #include <corsika/environment/NuclearComposition.h> +#include <corsika/process/particle_cut/ParticleCut.h> #include <corsika/process/proposal/ContinuousProcess.h> #include <corsika/process/proposal/Interaction.h> #include <corsika/setup/SetupEnvironment.h> @@ -28,20 +29,20 @@ namespace corsika::process::proposal { }; bool ContinuousProcess::CanInteract(particles::Code pcode) const noexcept { - auto search = particles.find(pcode); - if (search != particles.end()) return true; + if (particles.find(pcode) != particles.end()) return true; return false; } template <> ContinuousProcess::ContinuousProcess(SetupEnvironment const& _env, - CORSIKA_ParticleCut const& _cut) - : cut(make_shared<const PROPOSAL::EnergyCutSettings>(_cut.GetECut() / 1_MeV, 1, - false)) { + CORSIKA_ParticleCut& _cut) + : cut(_cut) + , fRNG(corsika::random::RNGManager::GetInstance().GetRandomStream("proposal")) { auto all_compositions = std::vector<const NuclearComposition*>(); _env.GetUniverse()->walk([&](auto& vtn) { - if (vtn.HasModelProperties()) + if (vtn.HasModelProperties()) { all_compositions.push_back(&vtn.GetModelProperties().GetNuclearComposition()); + } }); for (auto& ncarg : all_compositions) { auto comp_vec = std::vector<PROPOSAL::Components::Component>(); @@ -60,47 +61,32 @@ namespace corsika::process::proposal { HEPEnergyType ContinuousProcess::TotalEnergyLoss(SetupParticle const& vP, GrammageType const vDX) { - auto calc_ptr = GetCalculator(vP); - auto upper_energy = calc_ptr->second->UpperLimitTrackIntegral( - vP.GetEnergy() / 1_MeV, vDX / 1_g * 1_cm * 1_cm); - std::cout << "upper_energy: " << upper_energy << "MeV" << std::endl; - return upper_energy * 1_MeV; + std::cout << "distance: " << vDX / 1_g * 1_cm * 1_cm << std::endl; + return vP.GetEnergy() - GetCalculator(vP)->second->UpperLimitTrackIntegral( + vP.GetEnergy() / 1_MeV, vDX / 1_g * 1_cm * 1_cm) * + 1_MeV; } - void ContinuousProcess::Init() {} template <> - EProcessReturn ContinuousProcess::DoContinuous(SetupParticle& vP, SetupTrack const& vT) { + EProcessReturn ContinuousProcess::DoContinuous(SetupParticle& vP, + SetupTrack const& vT) { if (vP.GetChargeNumber() == 0) return process::EProcessReturn::eOk; - std::cout << "DoContinuous..." << std::endl; - GrammageType const dX = - vP.GetNode()->GetModelProperties().IntegratedGrammage(vT, vT.GetLength()); - HEPEnergyType dE = TotalEnergyLoss(vP, dX); - auto E = vP.GetEnergy(); - const auto Ekin = E - vP.GetMass(); - auto Enew = E + dE; - auto status = process::EProcessReturn::eOk; - if (-dE > Ekin) { - dE = -Ekin; - Enew = vP.GetMass(); - status = process::EProcessReturn::eParticleAbsorbed; - } - vP.SetEnergy(Enew); - auto pnew = vP.GetMomentum(); - vP.SetMomentum(pnew * Enew / pnew.GetNorm()); - return status; + auto dX = vP.GetNode()->GetModelProperties().IntegratedGrammage(vT, vT.GetLength()); + vP.SetEnergy(vP.GetEnergy() - TotalEnergyLoss(vP, dX)); + if (vP.GetEnergy() < cut.GetECut()) return process::EProcessReturn::eParticleAbsorbed; + vP.SetMomentum(vP.GetMomentum() * vP.GetEnergy() / vP.GetMomentum().GetNorm()); + return process::EProcessReturn::eOk; } template <> units::si::LengthType ContinuousProcess::MaxStepLength(SetupParticle const& vP, SetupTrack const& vT) { - auto constexpr dX = 1_g / square(1_cm); - auto const dE = -TotalEnergyLoss(vP, dX); // dE > 0 - auto const maxLoss = 0.01 * vP.GetEnergy(); - auto const maxGrammage = maxLoss / dE * dX; - - return vP.GetNode()->GetModelProperties().ArclengthFromGrammage(vT, - maxGrammage) * - 1.0001; // to make sure particle gets absorbed when DoContinuous() is called + auto energy_lim = 0.9 * vP.GetEnergy() / 1_MeV; + auto grammage = GetCalculator(vP)->second->SolveTrackIntegral(vP.GetEnergy() / 1_MeV, + energy_lim) * + 1_g / square(1_cm); + return vP.GetNode()->GetModelProperties().ArclengthFromGrammage(vT, grammage) * + 1.0001; } } // namespace corsika::process::proposal diff --git a/Processes/Proposal/ContinuousProcess.h b/Processes/Proposal/ContinuousProcess.h index 58b19ec2910a61d84ef7965a6cdbe50a4d6ea58f..e0cfe6e2679fda8389c44a230160c571a81b0b9b 100644 --- a/Processes/Proposal/ContinuousProcess.h +++ b/Processes/Proposal/ContinuousProcess.h @@ -24,6 +24,7 @@ using std::unordered_map; using namespace corsika::environment; +using namespace corsika::units::si; using CORSIKA_ParticleCut = corsika::process::particle_cut::ParticleCut; @@ -31,75 +32,56 @@ namespace corsika::process::proposal { class ContinuousProcess : public corsika::process::ContinuousProcess<ContinuousProcess> { - private: - shared_ptr<const PROPOSAL::EnergyCutSettings> cut; - + CORSIKA_ParticleCut& cut; + corsika::random::RNG& fRNG; static unordered_map<particles::Code, PROPOSAL::ParticleDef> particles; unordered_map<const NuclearComposition*, PROPOSAL::Medium> media; - corsika::random::RNG& fRNG = - corsika::random::RNGManager::GetInstance().GetRandomStream("proposal"); bool CanInteract(particles::Code pcode) const noexcept; - struct interaction_hash { - size_t operator()(const std::pair<const NuclearComposition*, particles::Code>& p) const - { - auto hash1 = std::hash<const NuclearComposition*>{}(p.first); - auto hash2 = std::hash<particles::Code>{}(p.second); - return hash1 ^ hash2; - } + using calc_key_t = std::pair<const NuclearComposition*, particles::Code>; + + struct disp_hash { + size_t operator()(const calc_key_t& p) const { + return std::hash<const NuclearComposition*>{}(p.first) ^ + std::hash<particles::Code>{}(p.second); + } }; - unordered_map<std::pair<const NuclearComposition*, particles::Code>, unique_ptr<PROPOSAL::Displacement>, interaction_hash> calc; + unordered_map<calc_key_t, unique_ptr<PROPOSAL::Displacement>, disp_hash> calc; + + template <typename Particle> + auto BuildCalculator(particles::Code code, Particle p_def, + NuclearComposition const& comp) { + auto medium = media.at(&comp); + auto cross = GetStdCrossSections( + p_def, media.at(&comp), + make_shared<const PROPOSAL::EnergyCutSettings>(cut.GetECut() / 1_MeV, 1, false), + true); + auto [insert_it, success] = calc.insert( + {std::make_pair(&comp, code), PROPOSAL::make_displacement(cross, true)}); + return insert_it; + } auto BuildCalculator(particles::Code corsika_code, NuclearComposition const& comp) { - auto medium = media.at(&comp); - if (corsika_code == particles::Code::Gamma) { - auto cross = GetStdCrossSections(PROPOSAL::GammaDef(), media.at(&comp), cut, true); - auto [insert_it, success] = - calc.insert({std::make_pair(&comp, corsika_code), PROPOSAL::make_displacement(cross, true)}); - return insert_it; - } - if (corsika_code == particles::Code::Electron) { - auto cross = GetStdCrossSections(PROPOSAL::EMinusDef(), media.at(&comp), cut, true); - auto [insert_it, success] = - calc.insert({std::make_pair(&comp, corsika_code), PROPOSAL::make_displacement(cross, true)}); - return insert_it; - } - if (corsika_code == particles::Code::Positron) { - auto cross = GetStdCrossSections(PROPOSAL::EPlusDef(), media.at(&comp), cut, true); - auto [insert_it, success] = - calc.insert({std::make_pair(&comp, corsika_code), PROPOSAL::make_displacement(cross, true)}); - return insert_it; - } - if (corsika_code == particles::Code::MuMinus) { - auto cross = GetStdCrossSections(PROPOSAL::MuMinusDef(), media.at(&comp), cut, true); - auto [insert_it, success] = - calc.insert({std::make_pair(&comp, corsika_code), PROPOSAL::make_displacement(cross, true)}); - return insert_it; - } - if (corsika_code == particles::Code::MuPlus) { - auto cross = GetStdCrossSections(PROPOSAL::MuPlusDef(), media.at(&comp), cut, true); - auto [insert_it, success] = - calc.insert({std::make_pair(&comp, corsika_code), PROPOSAL::make_displacement(cross, true)}); - return insert_it; - } - if (corsika_code == particles::Code::TauMinus) { - auto cross = GetStdCrossSections(PROPOSAL::TauMinusDef(), media.at(&comp), cut, true); - auto [insert_it, success] = - calc.insert({std::make_pair(&comp, corsika_code), PROPOSAL::make_displacement(cross, true)}); - return insert_it; - } - if (corsika_code == particles::Code::TauPlus) { - auto cross = GetStdCrossSections(PROPOSAL::TauPlusDef(), media.at(&comp), cut, true); - auto [insert_it, success] = - calc.insert({std::make_pair(&comp, corsika_code), PROPOSAL::make_displacement(cross, true)}); - return insert_it; - } - throw std::runtime_error("PROPOSAL could not find corresponding builder"); + if (corsika_code == particles::Code::Gamma) + return BuildCalculator(particles::Code::Gamma, PROPOSAL::GammaDef(), comp); + if (corsika_code == particles::Code::Electron) + return BuildCalculator(particles::Code::Electron, PROPOSAL::EMinusDef(), comp); + if (corsika_code == particles::Code::Positron) + return BuildCalculator(particles::Code::Positron, PROPOSAL::EPlusDef(), comp); + if (corsika_code == particles::Code::MuMinus) + return BuildCalculator(particles::Code::MuMinus, PROPOSAL::MuMinusDef(), comp); + if (corsika_code == particles::Code::MuPlus) + return BuildCalculator(particles::Code::MuPlus, PROPOSAL::MuPlusDef(), comp); + if (corsika_code == particles::Code::TauMinus) + return BuildCalculator(particles::Code::TauMinus, PROPOSAL::TauMinusDef(), comp); + if (corsika_code == particles::Code::TauPlus) + return BuildCalculator(particles::Code::TauPlus, PROPOSAL::TauPlusDef(), comp); + throw std::runtime_error("PROPOSAL could not find corresponding builder"); } - + template <typename Particle> auto GetCalculator(Particle& vP) { auto& comp = vP.GetNode()->GetModelProperties().GetNuclearComposition(); @@ -113,15 +95,15 @@ namespace corsika::process::proposal { public: template <typename TEnvironment> - ContinuousProcess(TEnvironment const& env, CORSIKA_ParticleCut const& cut); + ContinuousProcess(TEnvironment const& env, CORSIKA_ParticleCut& cut); - void Init(); + void Init(){}; template <typename Particle, typename Track> - EProcessReturn DoContinuous(Particle&, Track const&) ; + EProcessReturn DoContinuous(Particle&, Track const&); template <typename Particle, typename Track> - units::si::LengthType MaxStepLength(Particle const& p, Track const& track) ; + units::si::LengthType MaxStepLength(Particle const& p, Track const& track); }; } // namespace corsika::process::proposal diff --git a/Processes/Proposal/Interaction.cc b/Processes/Proposal/Interaction.cc index 4394ae868f89dfce4871cc8c077f6eb2fb00cb34..60ae3c81f64fdeeafed295838272e35357f58ccd 100644 --- a/Processes/Proposal/Interaction.cc +++ b/Processes/Proposal/Interaction.cc @@ -35,9 +35,8 @@ namespace corsika::process::proposal { } template <> - Interaction::Interaction(SetupEnvironment const& _env, CORSIKA_ParticleCut const& _cut) - : cut(make_shared<const PROPOSAL::EnergyCutSettings>(_cut.GetECut() / 1_MeV, 1, - false)) + Interaction::Interaction(SetupEnvironment const& _env, CORSIKA_ParticleCut& _cut) + : cut(_cut) , fRNG(corsika::random::RNGManager::GetInstance().GetRandomStream("proposal")) { auto all_compositions = std::vector<const NuclearComposition*>(); _env.GetUniverse()->walk([&](auto& vtn) { diff --git a/Processes/Proposal/Interaction.h b/Processes/Proposal/Interaction.h index 54597a656717fe9dca37c5a3e58bf196c620a8bf..6d0ad2f37c8b0183598cebed10fce5a37cd5d749 100644 --- a/Processes/Proposal/Interaction.h +++ b/Processes/Proposal/Interaction.h @@ -21,6 +21,7 @@ #include "PROPOSAL/PROPOSAL.h" using namespace corsika::environment; +using namespace corsika::units::si; using CORSIKA_ParticleCut = corsika::process::particle_cut::ParticleCut; using std::make_pair; @@ -29,14 +30,11 @@ using std::make_tuple; namespace corsika::process::proposal { class Interaction : public corsika::process::InteractionProcess<Interaction> { - - shared_ptr<const PROPOSAL::EnergyCutSettings> cut; - + CORSIKA_ParticleCut& cut; + corsika::random::RNG& fRNG; static std::unordered_map<particles::Code, PROPOSAL::ParticleDef> particles; std::unordered_map<const NuclearComposition*, PROPOSAL::Medium> media; - corsika::random::RNG& fRNG; - bool CanInteract(particles::Code pcode) const noexcept; using calculator_t = tuple<unique_ptr<PROPOSAL::SecondariesCalculator>, @@ -53,12 +51,15 @@ namespace corsika::process::proposal { std::unordered_map<calc_key_t, calculator_t, interaction_hash> calculators; template <typename Particle> - auto BuildCalculator(particles::Code corsika_code, Particle p_def, + auto BuildCalculator(particles::Code code, Particle p_def, NuclearComposition const& comp) { - auto cross = GetStdCrossSections(p_def, media.at(&comp), cut, true); + auto cross = GetStdCrossSections( + p_def, media.at(&comp), + make_shared<const PROPOSAL::EnergyCutSettings>(cut.GetECut() / 1_MeV, 1, false), + true); auto inter_types = PROPOSAL::CrossSectionVector::GetInteractionTypes(cross); auto [insert_it, success] = calculators.insert( - {make_pair(&comp, corsika_code), + {make_pair(&comp, code), make_tuple(PROPOSAL::make_secondaries(inter_types, p_def, media.at(&comp)), PROPOSAL::make_interaction(cross, true))}); return insert_it; @@ -93,15 +94,15 @@ namespace corsika::process::proposal { public: template <typename TEnvironment> - Interaction(TEnvironment const& env, CORSIKA_ParticleCut const& cut); + Interaction(TEnvironment const& env, CORSIKA_ParticleCut& cut); - void Init() {}; + void Init(){}; template <typename Particle> corsika::process::EProcessReturn DoInteraction(Particle&); template <typename TParticle> corsika::units::si::GrammageType GetInteractionLength(TParticle const& p); - }; // namespace corsika::process::proposal + }; } // namespace corsika::process::proposal #endif