diff --git a/corsika/detail/framework/core/ParticleProperties.inl b/corsika/detail/framework/core/ParticleProperties.inl index f91c4c3c472f564f2b6060c1a94b83fcdc1a8399..feb10651867f431b71afae8814353a11116cc4d8 100644 --- a/corsika/detail/framework/core/ParticleProperties.inl +++ b/corsika/detail/framework/core/ParticleProperties.inl @@ -10,35 +10,58 @@ #include <cmath> #include <corsika/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/core/Logging.hpp> namespace corsika { - inline HEPEnergyType constexpr get_kinetic_energy_threshold(Code const p) { - return particle::detail::thresholds[static_cast<CodeIntType>(p)]; + inline HEPEnergyType constexpr get_kinetic_energy_threshold(Code const code) { + if (is_nucleus(code)) return particle::detail::threshold_nuclei; + return particle::detail::thresholds[static_cast<CodeIntType>(code)]; } - inline void constexpr set_kinetic_energy_threshold(Code const p, + inline void constexpr set_kinetic_energy_threshold(Code const code, HEPEnergyType const val) { - particle::detail::thresholds[static_cast<CodeIntType>(p)] = val; + if (is_nucleus(code)) + particle::detail::threshold_nuclei = val; + else + particle::detail::thresholds[static_cast<CodeIntType>(code)] = val; } - inline HEPMassType constexpr get_mass(Code const p) { - if (p == Code::Nucleus) - throw std::runtime_error("Cannot GetMass() of particle::Nucleus -> unspecified"); - return particle::detail::masses[static_cast<CodeIntType>(p)]; + inline HEPMassType constexpr get_mass(Code const code) { + if (is_nucleus(code)) { return get_nucleus_mass(code); } + return particle::detail::masses[static_cast<CodeIntType>(code)]; } - inline PDGCode constexpr get_PDG(Code const p) { - return particle::detail::pdg_codes[static_cast<CodeIntType>(p)]; + inline bool constexpr is_nucleus(Code const code) { return code >= Code::Nucleus; } + + inline Code constexpr get_nucleus_code(unsigned int const A, + unsigned int const Z) { // 10LZZZAAAI + if (Z > A) { throw std::runtime_error("Z cannot be larger than A in nucleus."); } + return static_cast<Code>(static_cast<CodeIntType>(Code::Nucleus) + Z * 10000 + + A * 10); + } + + inline unsigned int constexpr get_nucleus_Z(Code const code) { + return (static_cast<CodeIntType>(code) % static_cast<CodeIntType>(Code::Nucleus)) / + 10000; + } + + inline unsigned int constexpr get_nucleus_A(Code const code) { + return (static_cast<CodeIntType>(code) % 10000) / 10; } - inline PDGCode constexpr get_PDG(unsigned int A, unsigned int Z) { - return static_cast<PDGCode>(1000000000 + Z * 10000 + A * 10); // 10LZZZAAAI + inline PDGCode constexpr get_PDG(Code const code) { + if (code < Code::Nucleus) { + return particle::detail::pdg_codes[static_cast<CodeIntType>(code)]; + } + unsigned int const Z = get_nucleus_Z(code); + unsigned int const A = get_nucleus_A(code); + return static_cast<PDGCode>(static_cast<CodeIntType>(Code::Nucleus) + Z * 10000 + + A * 10); // 10LZZZAAAI } inline int16_t constexpr get_charge_number(Code const code) { - if (code == Code::Nucleus) - throw std::runtime_error("charge of particle::Nucleus undefined"); + if (is_nucleus(code)) return get_nucleus_Z(code); return particle::detail::electric_charges[static_cast<CodeIntType>(code)]; } @@ -47,6 +70,7 @@ namespace corsika { } inline std::string_view constexpr get_name(Code const code) { + if (is_nucleus(code)) { return "nucleus"; } return particle::detail::names[static_cast<CodeIntType>(code)]; } @@ -54,8 +78,9 @@ namespace corsika { return particle::detail::lifetime[static_cast<CodeIntType>(p)] * second; } - inline bool constexpr is_hadron(Code const p) { - return particle::detail::isHadron[static_cast<CodeIntType>(p)]; + inline bool constexpr is_hadron(Code const code) { + if (is_nucleus(code)) return true; + return particle::detail::isHadron[static_cast<CodeIntType>(code)]; } inline bool constexpr is_em(Code const c) { @@ -71,24 +96,6 @@ namespace corsika { c == Code::NuMuBar || c == Code::NuTauBar; } - inline int constexpr get_nucleus_A(Code const code) { - if (code == Code::Nucleus) { - throw std::runtime_error("get_nucleus_A(Code::Nucleus) is impossible!"); - } - return particle::detail::nucleusA[static_cast<CodeIntType>(code)]; - } - - inline int constexpr get_nucleus_Z(Code const code) { - if (code == Code::Nucleus) { - throw std::runtime_error("get_nucleus_Z(Code::Nucleus) is impossible!"); - } - return particle::detail::nucleusZ[static_cast<CodeIntType>(code)]; - } - - inline bool constexpr is_nucleus(Code const code) { - return (code == Code::Nucleus) || (get_nucleus_A(code) != 0); - } - inline std::ostream& operator<<(std::ostream& stream, corsika::Code const code) { return stream << get_name(code); } @@ -97,7 +104,7 @@ namespace corsika { static_assert(particle::detail::conversionArray.size() % 2 == 1); // this will fail, for the strange case where the maxPDG is negative... int constexpr maxPDG{(particle::detail::conversionArray.size() - 1) >> 1}; - auto const k = static_cast<PDGCodeType>(p); + auto const k = static_cast<PDGCodeIntType>(p); if (std::abs(k) <= maxPDG) { return particle::detail::conversionArray[k + maxPDG]; } else { @@ -105,10 +112,18 @@ namespace corsika { } } - inline HEPMassType get_nucleus_mass(unsigned int const A, unsigned int const Z) { + inline HEPMassType constexpr get_nucleus_mass(Code const code) { + unsigned int const A = get_nucleus_A(code); + unsigned int const Z = get_nucleus_Z(code); return get_mass(Code::Proton) * Z + (A - Z) * get_mass(Code::Neutron); } + inline std::string_view get_nucleus_name(Code const code) { + unsigned int const A = get_nucleus_A(code); + unsigned int const Z = get_nucleus_Z(code); + return fmt::format("Nucleus_A{}_Z{}", A, Z); + } + inline std::initializer_list<Code> constexpr get_all_particles() { return particle::detail::all_particles; } diff --git a/corsika/detail/framework/process/InteractionCounter.inl b/corsika/detail/framework/process/InteractionCounter.inl index d3572bf98ef63faf37f50d2a58cfdf4b610a4179..7a549d61da111e3a338b4b19d2b01cf7e5cc7ce2 100644 --- a/corsika/detail/framework/process/InteractionCounter.inl +++ b/corsika/detail/framework/process/InteractionCounter.inl @@ -25,14 +25,7 @@ namespace corsika { .getNuclearComposition() .getAverageMassNumber(); auto const massTarget = massNumber * constants::nucleonMass; - - if (auto const projectile_id = projectile.getPID(); projectile_id == Code::Nucleus) { - auto const A = projectile.getNuclearA(); - auto const Z = projectile.getNuclearZ(); - histogram_.fill(projectile_id, projectile.getEnergy(), massTarget, A, Z); - } else { - histogram_.fill(projectile_id, projectile.getEnergy(), massTarget); - } + histogram_.fill(projectile.getPID(), projectile.getEnergy(), massTarget); process_.doInteraction(view); } diff --git a/corsika/detail/framework/process/InteractionHistogram.inl b/corsika/detail/framework/process/InteractionHistogram.inl index efeb29c0027e98d52d49722334b9ebb51bf1460a..4f493a363bcef4a6f11a820f889c665ab0c1961b 100644 --- a/corsika/detail/framework/process/InteractionHistogram.inl +++ b/corsika/detail/framework/process/InteractionHistogram.inl @@ -21,32 +21,27 @@ namespace corsika { , inthist_lab_{detail::hist_factory(num_bins_lab, lower_edge_lab, upper_edge_lab)} { } - inline void InteractionHistogram::fill(Code projectile_id, HEPEnergyType lab_energy, - HEPEnergyType mass_target, int A, int Z) { + inline void InteractionHistogram::fill(Code const projectile_id, + HEPEnergyType const lab_energy, + HEPEnergyType const mass_target) { auto constexpr inv_eV = 1 / 1_eV; - if (projectile_id == Code::Nucleus) { - auto const sqrtS = sqrt(A * A * (constants::nucleonMass * constants::nucleonMass) + - mass_target * mass_target + 2 * lab_energy * mass_target); - - int32_t const pdg = 1'000'000'000l + Z * 10'000l + A * 10l; - - inthist_lab_(pdg, lab_energy * inv_eV); - inthist_cms_(pdg, sqrtS * inv_eV); - } else { - auto const projectile_mass = get_mass(projectile_id); - auto const sqrtS = sqrt(projectile_mass * projectile_mass + - mass_target * mass_target + 2 * lab_energy * mass_target); - - inthist_cms_(static_cast<int>(get_PDG(projectile_id)), sqrtS * inv_eV); - inthist_lab_(static_cast<int>(get_PDG(projectile_id)), lab_energy * inv_eV); - } + auto const projectile_mass = get_mass(projectile_id); + auto const sqrtS = sqrt(projectile_mass * projectile_mass + + mass_target * mass_target + 2 * lab_energy * mass_target); + + CORSIKA_LOG_INFO("pM={}, tM={}, pid={}, Elab={}, sqrtS={}, pdg={} a={} z={}", + projectile_mass / 1_GeV, mass_target / 1_GeV, projectile_id, + lab_energy / 1_GeV, sqrtS / 1_GeV, get_PDG(projectile_id), + get_nucleus_A(projectile_id), get_nucleus_Z(projectile_id)); + + inthist_cms_(static_cast<int>(get_PDG(projectile_id)), sqrtS * inv_eV); + inthist_lab_(static_cast<int>(get_PDG(projectile_id)), lab_energy * inv_eV); } inline InteractionHistogram& InteractionHistogram::operator+=( InteractionHistogram const& other) { inthist_lab_ += other.inthist_lab_; inthist_cms_ += other.inthist_cms_; - return *this; } @@ -54,7 +49,6 @@ namespace corsika { InteractionHistogram other) const { other.inthist_lab_ += inthist_lab_; other.inthist_cms_ += inthist_cms_; - return other; } } // namespace corsika diff --git a/corsika/detail/modules/ParticleCut.inl b/corsika/detail/modules/ParticleCut.inl index af19f42f09e043c3d5a248c4d2c67f6cd70e262c..0e6163af59d4f5b16a282695d4c27bbe0f460a61 100644 --- a/corsika/detail/modules/ParticleCut.inl +++ b/corsika/detail/modules/ParticleCut.inl @@ -25,7 +25,7 @@ namespace corsika { , em_count_(0) , inv_count_(0) , energy_count_() { - for (auto p : get_all_particles()) + for (auto p : get_all_particles()) { if (is_hadron(p)) // nuclei are also hadrons set_kinetic_energy_threshold(p, eHadCut); else if (is_muon(p)) @@ -34,6 +34,8 @@ namespace corsika { set_kinetic_energy_threshold(p, eEleCut); else if (p == Code::Photon) set_kinetic_energy_threshold(p, ePhoCut); + } + set_kinetic_energy_threshold(Code::Nucleus, eHadCut); CORSIKA_LOG_DEBUG( "setting kinetic energy thresholds: electrons = {} GeV, photons = {} GeV, " "hadrons = {} GeV, " @@ -53,11 +55,13 @@ namespace corsika { , inv_count_(0) , energy_count_(0) { - for (auto p : get_all_particles()) + for (auto p : get_all_particles()) { if (is_hadron(p)) set_kinetic_energy_threshold(p, eHadCut); else if (is_muon(p)) set_kinetic_energy_threshold(p, eMuCut); + } + set_kinetic_energy_threshold(Code::Nucleus, eHadCut); CORSIKA_LOG_DEBUG( "setting thresholds: hadrons = {} GeV, " "muons = {} GeV", @@ -75,6 +79,7 @@ namespace corsika { , inv_count_(0) , energy_count_(0) { for (auto p : get_all_particles()) set_kinetic_energy_threshold(p, eCut); + set_kinetic_energy_threshold(Code::Nucleus, eCut); CORSIKA_LOG_DEBUG("setting kinetic energy threshold for all particles to {} GeV", eCut / 1_GeV); } @@ -100,9 +105,9 @@ namespace corsika { auto const energyLab = vP.getKineticEnergy(); auto const pid = vP.getPID(); // nuclei - if (pid == Code::Nucleus) { + if (is_nucleus(pid)) { // calculate energy per nucleon - auto const ElabNuc = energyLab / vP.getNuclearA(); + auto const ElabNuc = energyLab / get_nucleus_A(pid); return (ElabNuc < get_kinetic_energy_threshold(pid)); } else { return (energyLab < get_kinetic_energy_threshold(pid)); diff --git a/corsika/detail/modules/StackInspector.inl b/corsika/detail/modules/StackInspector.inl index 5ab9fb6a8a258e9f1747fdb02abb8ffe6d27869c..24a356fcb749f90796db5920bef351dee2d10ac9 100644 --- a/corsika/detail/modules/StackInspector.inl +++ b/corsika/detail/modules/StackInspector.inl @@ -51,9 +51,6 @@ namespace corsika { " pos= {}" " node = {}", (i++), iterP.getPID(), (E / 1_GeV), pos, fmt::ptr(iterP.getNode())); - - if (iterP.getPID() == Code::Nucleus) - CORSIKA_LOG_INFO("nuc_ref= {}", iterP.getNucleusRef()); } } diff --git a/corsika/detail/modules/epos/Interaction.inl b/corsika/detail/modules/epos/Interaction.inl index 058dd2c7f21c3961c1de0030d3a0c86942123a28..dde502eb0b3284a83b1fd5af01708800d6e49573 100644 --- a/corsika/detail/modules/epos/Interaction.inl +++ b/corsika/detail/modules/epos/Interaction.inl @@ -63,21 +63,7 @@ namespace corsika::epos { } inline bool Interaction::isValidTarget(Code const TargetId) const { - if (is_nucleus(TargetId)) { - if (TargetId == Code::Nucleus) { - // nuclearExtension for projectiles only - CORSIKA_LOGGER_WARN(logger_, - "Invalid target!" - " Code::Nucleus only allowed for " - "projectiles! " - "This should not happen!"); - return false; - } else { - return (get_nucleus_Z(TargetId) < maxTargetMassNumber_ ? true : false); - } - } else { - return false; - } + return is_nucleus(TargetId) && (get_nucleus_A(TargetId) < maxTargetMassNumber_); } inline void Interaction::initialize() const { @@ -418,8 +404,8 @@ namespace corsika::epos { int beamA = 1; int beamZ = 1; if (is_nucleus(corsikaBeamId)) { - beamA = projectile.getNuclearA(); - beamZ = projectile.getNuclearZ(); + beamA = get_nucleus_A(corsikaBeamId); + beamZ = get_nucleus_Z(corsikaBeamId); } // get target from environment @@ -485,8 +471,8 @@ namespace corsika::epos { int beamA = 1; int beamZ = 1; if (is_nucleus(corsikaBeamId)) { - beamA = projectile.getNuclearA(); - beamZ = projectile.getNuclearZ(); + beamA = get_nucleus_A(corsikaBeamId); + beamZ = get_nucleus_Z(corsikaBeamId); CORSIKA_LOGGER_DEBUG(logger_, "A={}, Z={} ", beamA, beamZ); } @@ -579,13 +565,11 @@ namespace corsika::epos { A = 4; Z = 2; } else { - // 100ZZZAAA0 -> std. pdg code - EposCodeIntType const eposPdg = static_cast<EposCodeIntType>(eposId); - Z = int(abs(eposPdg) / 10000) % 1000; - A = int(abs(eposPdg) / 10) % 1000; + Z = get_nucleus_Z(eposId); + A = get_nucleus_Z(eposId); } auto pnew = view.addSecondary( - std::make_tuple(Code::Nucleus, momentum, pOrig, tOrig, A, Z)); + std::make_tuple(get_nucleus_code(A, Z), momentum, pOrig, tOrig)); Plab_final += pnew.getMomentum(); Elab_final += pnew.getEnergy(); } diff --git a/corsika/detail/modules/epos/ParticleConversion.inl b/corsika/detail/modules/epos/ParticleConversion.inl index 38c52adbe9e0e89b19dd574dcc8f6c490394153a..b3f34dbfef4654e164666740cc9458c219f53526 100644 --- a/corsika/detail/modules/epos/ParticleConversion.inl +++ b/corsika/detail/modules/epos/ParticleConversion.inl @@ -14,8 +14,7 @@ namespace corsika::epos { inline HEPMassType getEposMass(Code const pCode) { - if (pCode == Code::Nucleus) - throw std::runtime_error("Cannot getMass() of particle::Nucleus -> unspecified"); + if (is_nucleus(pCode)) throw std::runtime_error("Not suited for Nuclei."); auto sCode = convertToEposRaw(pCode); if (sCode == 0) throw std::runtime_error("getEposMass: unknown particle!"); diff --git a/corsika/detail/modules/qgsjetII/Interaction.inl b/corsika/detail/modules/qgsjetII/Interaction.inl index 1ee0f978d772159780968bab6625729606acfec0..c3147dbb83b00aff24e6f909220ff88586360ed4 100644 --- a/corsika/detail/modules/qgsjetII/Interaction.inl +++ b/corsika/detail/modules/qgsjetII/Interaction.inl @@ -56,7 +56,7 @@ namespace corsika::qgsjetII { int iTarget = 1; if (is_nucleus(targetId)) { iTarget = targetA; - if (iTarget > maxMassNumber_ || iTarget <= 0) { + if (iTarget > int(maxMassNumber_) || iTarget <= 0) { std::ostringstream txt; txt << "QgsjetII target outside range. Atarget=" << iTarget; throw std::runtime_error(txt.str().c_str()); @@ -65,7 +65,7 @@ namespace corsika::qgsjetII { int iProjectile = 1; if (is_nucleus(beamId)) { iProjectile = Abeam; - if (iProjectile > maxMassNumber_ || iProjectile <= 0) { + if (iProjectile > int(maxMassNumber_) || iProjectile <= 0) { std::ostringstream txt; txt << "QgsjetII projectile outside range. Aprojectile=" << iProjectile; throw std::runtime_error(txt.str().c_str()); @@ -84,12 +84,12 @@ namespace corsika::qgsjetII { } template <typename TParticle> - inline GrammageType Interaction::getInteractionLength(const TParticle& vP) const { + inline GrammageType Interaction::getInteractionLength(const TParticle& particle) const { // coordinate system, get global frame of reference CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); - const Code corsikaBeamId = vP.getPID(); + const Code corsikaBeamId = particle.getPID(); // beam particles for qgsjetII : 1, 2, 3 for p, pi, k // read from cross section code table @@ -99,19 +99,19 @@ namespace corsika::qgsjetII { MomentumVector pTarget(rootCS, {0_GeV, 0_GeV, 0_GeV}); // total momentum and energy - HEPEnergyType Elab = vP.getEnergy(); + HEPEnergyType const Elab = particle.getEnergy(); CORSIKA_LOG_DEBUG( "Interaction: LambdaInt: \n" " input energy: {} GeV" " beam can interact: {}" " beam pid: {}", - vP.getEnergy() / 1_GeV, kInteraction, vP.getPID()); + particle.getEnergy() / 1_GeV, kInteraction, corsikaBeamId); if (kInteraction) { int Abeam = 0; - if (is_nucleus(vP.getPID())) Abeam = vP.getNuclearA(); + if (is_nucleus(corsikaBeamId)) Abeam = get_nucleus_A(corsikaBeamId); // get target from environment /* @@ -120,7 +120,7 @@ namespace corsika::qgsjetII { and the boosts can be defined.. */ - auto const* currentNode = vP.getNode(); + auto const* currentNode = particle.getNode(); const auto& mediumComposition = currentNode->getModelProperties().getNuclearComposition(); @@ -159,184 +159,177 @@ namespace corsika::qgsjetII { inline void Interaction::doInteraction(TView& view) { auto const projectile = view.getProjectile(); - - const auto corsikaBeamId = projectile.getPID(); + auto const corsikaBeamId = projectile.getPID(); CORSIKA_LOG_DEBUG( "ProcessQgsjetII: " - "DoInteraction: {} interaction possible? {}", + "doInteraction: {} interaction possible? {}", corsikaBeamId, corsika::qgsjetII::canInteract(corsikaBeamId)); - if (corsika::qgsjetII::canInteract(corsikaBeamId)) { + if (!corsika::qgsjetII::canInteract(corsikaBeamId)) return; - CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); + CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); - // position and time of interaction, not used in QgsjetII - Point pOrig = projectile.getPosition(); - TimeType tOrig = projectile.getTime(); + // position and time of interaction, not used in QgsjetII + Point const pOrig = projectile.getPosition(); + TimeType const tOrig = projectile.getTime(); - // define target - // for QgsjetII is always a single nucleon - // FOR NOW: target is always at rest - auto const targetEnergyLab = 0_GeV + constants::nucleonMass; - auto const targetMomentumLab = MomentumVector(rootCS, 0_GeV, 0_GeV, 0_GeV); - FourVector const PtargLab(targetEnergyLab, targetMomentumLab); + // define target + // for QgsjetII is always a single nucleon + // FOR NOW: target is always at rest + auto const targetEnergyLab = 0_GeV + constants::nucleonMass; + auto const targetMomentumLab = MomentumVector(rootCS, 0_GeV, 0_GeV, 0_GeV); + FourVector const PtargLab(targetEnergyLab, targetMomentumLab); - // define projectile - HEPEnergyType const projectileEnergyLab = projectile.getEnergy(); - auto const projectileMomentumLab = projectile.getMomentum(); + // define projectile + HEPEnergyType const projectileEnergyLab = projectile.getEnergy(); + auto const projectileMomentumLab = projectile.getMomentum(); - int beamA = 0; - if (is_nucleus(corsikaBeamId)) beamA = projectile.getNuclearA(); + int beamA = 0; + if (is_nucleus(corsikaBeamId)) beamA = get_nucleus_A(corsikaBeamId); - HEPEnergyType const projectileEnergyLabPerNucleon = projectileEnergyLab / beamA; + HEPEnergyType const projectileEnergyLabPerNucleon = projectileEnergyLab / beamA; - CORSIKA_LOG_DEBUG( - "Interaction: ebeam lab: {} GeV" - "Interaction: pbeam lab: {} GeV", - projectileEnergyLab / 1_GeV, projectileMomentumLab.getComponents() / 1_GeV); - CORSIKA_LOG_DEBUG( - "Interaction: etarget lab: {} GeV" - "Interaction: ptarget lab: {} GeV", - targetEnergyLab / 1_GeV, targetMomentumLab.getComponents() / 1_GeV); - CORSIKA_LOG_DEBUG("Interaction: position of interaction: {}", - pOrig.getCoordinates()); - CORSIKA_LOG_DEBUG("Interaction: time: {} ", tOrig); - - // sample target mass number - auto const* currentNode = projectile.getNode(); - auto const& mediumComposition = - currentNode->getModelProperties().getNuclearComposition(); - // get cross sections for target materials - /* - Here we read the cross section from the interaction model again, - should be passed from getInteractionLength if possible - */ - auto const& compVec = mediumComposition.getComponents(); - std::vector<CrossSectionType> cross_section_of_components(compVec.size()); - - for (size_t i = 0; i < compVec.size(); ++i) { - auto const targetId = compVec[i]; - int targetA = 0; - if (is_nucleus(targetId)) targetA = get_nucleus_A(targetId); - const auto sigProd = - getCrossSection(corsikaBeamId, targetId, projectileEnergyLab, beamA, targetA); - cross_section_of_components[i] = sigProd; - } + CORSIKA_LOG_DEBUG( + "ebeam lab: {} GeV " + "pbeam lab: {} GeV ", + projectileEnergyLab / 1_GeV, projectileMomentumLab.getComponents() / 1_GeV); + CORSIKA_LOG_DEBUG( + "etarget lab: {} GeV " + "ptarget lab: {} GeV ", + targetEnergyLab / 1_GeV, targetMomentumLab.getComponents() / 1_GeV); + CORSIKA_LOG_DEBUG("position of interaction: {}", pOrig.getCoordinates()); + CORSIKA_LOG_DEBUG("time: {} ", tOrig); + + // sample target mass number + auto const* currentNode = projectile.getNode(); + auto const& mediumComposition = + currentNode->getModelProperties().getNuclearComposition(); + // get cross sections for target materials + /* + Here we read the cross section from the interaction model again, + should be passed from getInteractionLength if possible + */ + auto const& compVec = mediumComposition.getComponents(); + std::vector<CrossSectionType> cross_section_of_components(compVec.size()); + + for (size_t i = 0; i < compVec.size(); ++i) { + auto const targetId = compVec[i]; + int targetA = 0; + if (is_nucleus(targetId)) targetA = get_nucleus_A(targetId); + const auto sigProd = + getCrossSection(corsikaBeamId, targetId, projectileEnergyLab, beamA, targetA); + cross_section_of_components[i] = sigProd; + } - const auto targetCode = - mediumComposition.sampleTarget(cross_section_of_components, rng_); - CORSIKA_LOG_DEBUG("Interaction: target selected: {}", targetCode); - - int targetMassNumber = 1; // proton - if (is_nucleus(targetCode)) { // nucleus - targetMassNumber = get_nucleus_A(targetCode); - if (targetMassNumber > maxMassNumber_) - throw std::runtime_error( - "QgsjetII target mass outside range."); // LCOV_EXCL_LINE there is no - // allowed path here - } else { - if (targetCode != Proton::code) // LCOV_EXCL_LINE there is no allowed path here - throw std::runtime_error( - "QgsjetII Taget not possible."); // LCOV_EXCL_LINE there is no allowed path - // here - } - CORSIKA_LOG_DEBUG("Interaction: target qgsjetII code/A: {}", targetMassNumber); - - int projectileMassNumber = 1; // "1" means "hadron" - QgsjetIIHadronType qgsjet_hadron_type = - qgsjetII::getQgsjetIIHadronType(corsikaBeamId); - if (qgsjet_hadron_type == QgsjetIIHadronType::NucleusType) { - projectileMassNumber = projectile.getNuclearA(); - if (projectileMassNumber > maxMassNumber_) - throw std::runtime_error( - "QgsjetII projectile mass outside range."); // LCOV_EXCL_LINE there is no - // allowed path here - std::array<QgsjetIIHadronType, 2> constexpr nucleons = { - QgsjetIIHadronType::ProtonType, QgsjetIIHadronType::NeutronType}; - std::uniform_int_distribution select(0, 1); - qgsjet_hadron_type = nucleons[select(rng_)]; - } else { - // from conex: replace pi0 or rho0 with pi+/pi- in alternating sequence - if (qgsjet_hadron_type == QgsjetIIHadronType::NeutralLightMesonType) { - qgsjet_hadron_type = alternate_; - alternate_ = (alternate_ == QgsjetIIHadronType::PiPlusType - ? QgsjetIIHadronType::PiMinusType - : QgsjetIIHadronType::PiPlusType); - } + const auto targetCode = + mediumComposition.sampleTarget(cross_section_of_components, rng_); + + int targetMassNumber = 1; // proton + if (is_nucleus(targetCode)) { // nucleus + targetMassNumber = get_nucleus_A(targetCode); + if (targetMassNumber > int(maxMassNumber_)) + throw std::runtime_error( + "QgsjetII target mass outside range."); // LCOV_EXCL_LINE there is no + // allowed path here + } else { + if (targetCode != Proton::code) // LCOV_EXCL_LINE there is no allowed path here + throw std::runtime_error( + "QgsjetII Taget not possible."); // LCOV_EXCL_LINE there is no allowed path + // here + } + CORSIKA_LOG_DEBUG("target: {}, qgsjetII code/A: {}", targetCode, targetMassNumber); + + int projectileMassNumber = 1; // "1" means "hadron" + QgsjetIIHadronType qgsjet_hadron_type = + qgsjetII::getQgsjetIIHadronType(corsikaBeamId); + if (qgsjet_hadron_type == QgsjetIIHadronType::NucleusType) { + projectileMassNumber = get_nucleus_A(corsikaBeamId); + if (projectileMassNumber > int(maxMassNumber_)) + throw std::runtime_error( + "QgsjetII projectile mass outside range."); // LCOV_EXCL_LINE there is no + // allowed path here + std::array<QgsjetIIHadronType, 2> constexpr nucleons = { + QgsjetIIHadronType::ProtonType, QgsjetIIHadronType::NeutronType}; + std::uniform_int_distribution select(0, 1); + qgsjet_hadron_type = nucleons[select(rng_)]; + } else { + // from conex: replace pi0 or rho0 with pi+/pi- in alternating sequence + if (qgsjet_hadron_type == QgsjetIIHadronType::NeutralLightMesonType) { + qgsjet_hadron_type = alternate_; + alternate_ = (alternate_ == QgsjetIIHadronType::PiPlusType + ? QgsjetIIHadronType::PiMinusType + : QgsjetIIHadronType::PiPlusType); } + } - // beam id for qgsjetII - int kBeam = 2; // default: proton Shouldn't we randomize neutron/proton for nuclei? - if (corsikaBeamId != Code::Nucleus) { - kBeam = corsika::qgsjetII::convertToQgsjetIIRaw(corsikaBeamId); - // from conex - if (kBeam == 0) { // replace pi0 or rho0 with pi+/pi- - static int select = 1; - kBeam = select; - select *= -1; - } - // replace lambda by neutron - if (kBeam == 6) - kBeam = 3; - else if (kBeam == -6) - kBeam = -3; - // else if (abs(kBeam)>6) -> throw + // beam id for qgsjetII + int kBeam = 2; // default: proton Shouldn't we randomize neutron/proton for nuclei? + if (!is_nucleus(corsikaBeamId)) { + kBeam = corsika::qgsjetII::convertToQgsjetIIRaw(corsikaBeamId); + // from conex + if (kBeam == 0) { // replace pi0 or rho0 with pi+/pi- + static int select = 1; + kBeam = select; + select *= -1; } + // replace lambda by neutron + if (kBeam == 6) + kBeam = 3; + else if (kBeam == -6) + kBeam = -3; + // else if (abs(kBeam)>6) -> throw + } + + count_++; + int qgsjet_hadron_type_int = static_cast<QgsjetIICodeIntType>(qgsjet_hadron_type); + CORSIKA_LOG_DEBUG( + "qgsjet_hadron_type_int={} projectileMassNumber={} targetMassNumber={}", + qgsjet_hadron_type_int, projectileMassNumber, targetMassNumber); + qgini_(projectileEnergyLab / 1_GeV, qgsjet_hadron_type_int, projectileMassNumber, + targetMassNumber); + qgconf_(); + + // bookkeeping + MomentumVector Plab_final(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV}); + HEPEnergyType Elab_final = 0_GeV; + + // to read the secondaries + // define rotation to and from CoM frame + // CoM frame definition in QgsjetII projectile: +z + auto const& originalCS = projectileMomentumLab.getCoordinateSystem(); + CoordinateSystemPtr const zAxisFrame = + make_rotationToZ(originalCS, projectileMomentumLab); + + // fragments + QGSJetIIFragmentsStack qfs; + for (auto& fragm : qfs) { + int const A = fragm.getFragmentSize(); + if (A == 1) { // nucleon + std::uniform_real_distribution<double> select; + Code idFragm = Code::Proton; + if (select(rng_) > 0.5) { idFragm = Code::Neutron; } + + const HEPMassType nucleonMass = get_mass(idFragm); + // no pT, frgments just go forward + auto momentum = + Vector(zAxisFrame, corsika::QuantityVector<hepmomentum_d>{ + 0.0_GeV, 0.0_GeV, + sqrt((projectileEnergyLabPerNucleon + nucleonMass) * + (projectileEnergyLabPerNucleon - nucleonMass))}); + + momentum.rebase(originalCS); // transform back into standard lab frame + CORSIKA_LOG_DEBUG( + "secondary fragment> id= {}" + " p={}", + idFragm, momentum.getComponents()); + auto pnew = view.addSecondary(std::make_tuple(idFragm, momentum, pOrig, tOrig)); + Plab_final += pnew.getMomentum(); + Elab_final += pnew.getEnergy(); + + } else { // nucleus, A>1 - CORSIKA_LOG_DEBUG("Interaction: DoInteraction: E(GeV): {} GeV", - projectileEnergyLab / 1_GeV); - count_++; - int qgsjet_hadron_type_int = static_cast<QgsjetIICodeIntType>(qgsjet_hadron_type); - qgini_(projectileEnergyLab / 1_GeV, qgsjet_hadron_type_int, projectileMassNumber, - targetMassNumber); - qgconf_(); - - // bookkeeping - MomentumVector Plab_final(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV}); - HEPEnergyType Elab_final = 0_GeV; - - // to read the secondaries - // define rotation to and from CoM frame - // CoM frame definition in QgsjetII projectile: +z - auto const& originalCS = projectileMomentumLab.getCoordinateSystem(); - CoordinateSystemPtr const zAxisFrame = - make_rotationToZ(originalCS, projectileMomentumLab); - - // fragments - QGSJetIIFragmentsStack qfs; - for (auto& fragm : qfs) { - Code idFragm = Code::Nucleus; - int A = fragm.getFragmentSize(); int Z = 0; switch (A) { - case 1: { // proton/neutron - std::uniform_real_distribution<double> select; - if (select(rng_) > 0.5) { - idFragm = Code::Proton; - Z = 1; - } else { - idFragm = Code::Neutron; - Z = 0; - } - - const HEPMassType nucleonMass = get_mass(idFragm); - - auto momentum = Vector( - zAxisFrame, corsika::QuantityVector<hepmomentum_d>{ - 0.0_GeV, 0.0_GeV, - sqrt((projectileEnergyLabPerNucleon + nucleonMass) * - (projectileEnergyLabPerNucleon - nucleonMass))}); - - momentum.rebase(originalCS); // transform back into standard lab frame - CORSIKA_LOG_DEBUG( - "secondary fragment> id= {}" - " p={}", - idFragm, momentum.getComponents()); - auto pnew = - view.addSecondary(std::make_tuple(idFragm, momentum, pOrig, tOrig)); - Plab_final += pnew.getMomentum(); - Elab_final += pnew.getEnergy(); - } break; case 2: // deuterium Z = 1; break; @@ -352,58 +345,53 @@ namespace corsika::qgsjetII { } } - if (idFragm == Code::Nucleus) { // thus: not p or n - const HEPMassType nucleusMass = Proton::mass * Z + Neutron::mass * (A - Z); - auto momentum = Vector( - zAxisFrame, QuantityVector<hepmomentum_d>{ - 0.0_GeV, 0.0_GeV, - sqrt((projectileEnergyLabPerNucleon * A + nucleusMass) * - (projectileEnergyLabPerNucleon * A - nucleusMass))}); - - momentum.rebase(originalCS); // transform back into standard lab frame - CORSIKA_LOG_DEBUG( - "secondary fragment> id={}" - " p={}" - " A={}" - " Z= {}", - idFragm, momentum.getComponents(), A, Z); - - auto pnew = - view.addSecondary(std::make_tuple(idFragm, momentum, pOrig, tOrig, A, Z)); - Plab_final += pnew.getMomentum(); - Elab_final += pnew.getEnergy(); - } - } - - // secondaries - QGSJetIIStack qs; - for (auto& psec : qs) { - - auto momentum = psec.getMomentum(zAxisFrame); + HEPMassType const nucleusMass = Proton::mass * Z + Neutron::mass * (A - Z); + // no pT, frgments just go forward + auto momentum = Vector( + zAxisFrame, QuantityVector<hepmomentum_d>{ + 0.0_GeV, 0.0_GeV, + sqrt((projectileEnergyLabPerNucleon * A + nucleusMass) * + (projectileEnergyLabPerNucleon * A - nucleusMass))}); momentum.rebase(originalCS); // transform back into standard lab frame CORSIKA_LOG_DEBUG( - "secondary fragment> id= {}" - " p= {}", - corsika::qgsjetII::convertFromQgsjetII(psec.getPID()), - momentum.getComponents()); + "secondary fragment> id={}" + " p={}" + " A={}" + " Z={}", + get_nucleus_code(A, Z), momentum.getComponents(), A, Z); + auto pnew = view.addSecondary( - std::make_tuple(corsika::qgsjetII::convertFromQgsjetII(psec.getPID()), - momentum, pOrig, tOrig)); + std::make_tuple(get_nucleus_code(A, Z), momentum, pOrig, tOrig)); Plab_final += pnew.getMomentum(); Elab_final += pnew.getEnergy(); } - CORSIKA_LOG_DEBUG( - "conservation (all GeV): Ecm_final= n/a" /* << Ecm_final / 1_GeV*/ - "Elab_final=" - ", Plab_final={}" - ", N_wounded,targ={}" - ", N_wounded,proj={}" - ", N_fragm,proj={}", - Elab_final / 1_GeV, (Plab_final / 1_GeV).getComponents(), - QGSJetIIFragmentsStackData::getWoundedNucleonsTarget(), - QGSJetIIFragmentsStackData::getWoundedNucleonsProjectile(), qfs.getSize()); } - } + // secondaries + QGSJetIIStack qs; + for (auto& psec : qs) { + + auto momentum = psec.getMomentum(zAxisFrame); + + momentum.rebase(originalCS); // transform back into standard lab frame + CORSIKA_LOG_DEBUG("secondary> id= {}, p= {}", + corsika::qgsjetII::convertFromQgsjetII(psec.getPID()), + momentum.getComponents()); + auto pnew = view.addSecondary(std::make_tuple( + corsika::qgsjetII::convertFromQgsjetII(psec.getPID()), momentum, pOrig, tOrig)); + Plab_final += pnew.getMomentum(); + Elab_final += pnew.getEnergy(); + } + CORSIKA_LOG_DEBUG( + "conservation (all GeV): Ecm_final= n/a " /* << Ecm_final / 1_GeV*/ + ", Elab_final={} " + ", Plab_final={}" + ", N_wounded,targ={}" + ", N_wounded,proj={}" + ", N_fragm,proj={}", + Elab_final / 1_GeV, (Plab_final / 1_GeV).getComponents(), + QGSJetIIFragmentsStackData::getWoundedNucleonsTarget(), + QGSJetIIFragmentsStackData::getWoundedNucleonsProjectile(), qfs.getSize()); + } } // namespace corsika::qgsjetII diff --git a/corsika/detail/modules/sibyll/Interaction.inl b/corsika/detail/modules/sibyll/Interaction.inl index c6adf5e105c3ca496658d6ea0c71a43a7a18e481..e4fdeec751684a0f143fbcc4420a51132bea5cf4 100644 --- a/corsika/detail/modules/sibyll/Interaction.inl +++ b/corsika/detail/modules/sibyll/Interaction.inl @@ -262,7 +262,7 @@ namespace corsika::sibyll { if (is_nucleus(targetCode)) targetSibCode = get_nucleus_A(targetCode); if (targetCode == Proton::code) targetSibCode = 1; CORSIKA_LOG_DEBUG("Interaction: sibyll code: {}", targetSibCode); - if (targetSibCode > maxTargetMassNumber_ || targetSibCode < 1) + if (targetSibCode > int(maxTargetMassNumber_) || targetSibCode < 1) throw std::runtime_error( "Sibyll target outside range. Only nuclei with A<18 or protons are " "allowed."); diff --git a/corsika/detail/modules/sibyll/NuclearInteraction.inl b/corsika/detail/modules/sibyll/NuclearInteraction.inl index a75207f1c1372abfce16ff8f3a65f6e04140ccf0..db7788a117dd5a6cb5cb75422a10e37ebee0cffb 100644 --- a/corsika/detail/modules/sibyll/NuclearInteraction.inl +++ b/corsika/detail/modules/sibyll/NuclearInteraction.inl @@ -160,11 +160,12 @@ namespace corsika::sibyll { std::tuple<CrossSectionType, CrossSectionType> inline NuclearInteraction< TEnvironment>::getCrossSection(TParticle const& projectile, Code const TargetId) { - if (projectile.getPID() != Code::Nucleus) + if (!is_nucleus(projectile.getPID())) { throw std::runtime_error( "NuclearInteraction: getCrossSection: particle not a nucleus!"); + } - unsigned int const iBeamA = projectile.getNuclearA(); + unsigned int const iBeamA = get_nucleus_A(projectile.getPID()); HEPEnergyType LabEnergyPerNuc = projectile.getEnergy() / iBeamA; CORSIKA_LOG_DEBUG( "NuclearInteraction: getCrossSection: called with: beamNuclA={} " @@ -205,16 +206,9 @@ namespace corsika::sibyll { const Code corsikaBeamId = projectile.getPID(); - if (corsikaBeamId != Code::Nucleus) { - // check if target-style nucleus (enum), these are not allowed as projectile - if (is_nucleus(corsikaBeamId)) { - throw std::runtime_error( - "NuclearInteraction: getInteractionLength: Wrong nucleus type. Nuclear " - "projectiles should use NuclearStackExtension!"); - } else { - // no nuclear interaction - return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm); - } + if (!is_nucleus(corsikaBeamId)) { + // no nuclear interaction + return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm); } // read from cross section code table @@ -227,7 +221,7 @@ namespace corsika::sibyll { // total momentum and energy HEPEnergyType Elab = projectile.getEnergy() + constants::nucleonMass; - int const nuclA = projectile.getNuclearA(); + int const nuclA = get_nucleus_A(corsikaBeamId); auto const ElabNuc = projectile.getEnergy() / nuclA; MomentumVector pTotLab(labCS, {0.0_GeV, 0.0_GeV, 0.0_GeV}); @@ -320,14 +314,13 @@ namespace corsika::sibyll { get_name(ProjId)); // check if target-style nucleus (enum) - if (ProjId != Code::Nucleus) + if (!is_nucleus(ProjId)) { throw std::runtime_error( "NuclearInteraction: DoInteraction: Wrong nucleus type. Nuclear projectiles " "should use NuclearStackExtension!"); + } - auto const ProjMass = - projectile.getNuclearZ() * Proton::mass + - (projectile.getNuclearA() - projectile.getNuclearZ()) * Neutron::mass; + auto const ProjMass = get_mass(ProjId); CORSIKA_LOG_DEBUG("NuclearInteraction: projectile mass: {} ", ProjMass / 1_GeV); count_++; @@ -340,7 +333,7 @@ namespace corsika::sibyll { CORSIKA_LOG_DEBUG("Interaction: time: {} ", tOrig / 1_s); // projectile nucleon number - const unsigned int kAProj = projectile.getNuclearA(); + const unsigned int kAProj = get_nucleus_A(ProjId); if (kAProj > getMaxNucleusAProjectile()) throw std::runtime_error("Projectile nucleus too large for NUCLIB!"); @@ -510,19 +503,14 @@ namespace corsika::sibyll { for (int j = 0; j < nFragments; ++j) { CORSIKA_LOG_DEBUG("fragment {}: A={} px={} py={} pz={}", j, AFragments[j], fragments_.ppp[j][0], fragments_.ppp[j][1], fragments_.ppp[j][2]); - Code specCode; const auto nuclA = AFragments[j]; // get Z from stability line const auto nuclZ = int(nuclA / 2.15 + 0.7); // TODO: do we need to catch single nucleons?? - if (nuclA == 1) - // TODO: sample neutron or proton - specCode = Code::Proton; - else - specCode = Code::Nucleus; - - const HEPMassType mass = get_nucleus_mass(nuclA, nuclZ); + Code specCode = Code::Neutron; // sample neutron or proton ? + if (nuclA > 1) specCode = get_nucleus_code(nuclA, nuclZ); + HEPMassType const mass = get_mass(specCode); CORSIKA_LOG_DEBUG("NuclearInteraction: adding fragment: {}", get_name(specCode)); CORSIKA_LOG_DEBUG("NuclearInteraction: A,Z: {}, {}", nuclA, nuclZ); @@ -539,14 +527,8 @@ namespace corsika::sibyll { CORSIKA_LOG_DEBUG("NuclearInteraction: fragment momentum: {}", Plab.getSpaceLikeComponents().getComponents() / 1_GeV); - if (nuclA == 1) - // add nucleon - projectile.addSecondary( - std::make_tuple(specCode, Plab.getSpaceLikeComponents(), pOrig, tOrig)); - else - // add nucleus - projectile.addSecondary(std::make_tuple(specCode, Plab.getSpaceLikeComponents(), - pOrig, tOrig, nuclA, nuclZ)); + projectile.addSecondary( + std::make_tuple(specCode, Plab.getSpaceLikeComponents(), pOrig, tOrig)); } // add elastic nucleons to corsika stack diff --git a/corsika/detail/modules/sibyll/ParticleConversion.inl b/corsika/detail/modules/sibyll/ParticleConversion.inl index d4459a7ba026d804ee3eb6aecc90cdeb81c2feb0..3bb07d5d711be5a92e376c1ac0553a535cd1630d 100644 --- a/corsika/detail/modules/sibyll/ParticleConversion.inl +++ b/corsika/detail/modules/sibyll/ParticleConversion.inl @@ -15,8 +15,7 @@ namespace corsika::sibyll { inline HEPMassType getSibyllMass(Code const pCode) { - if (pCode == corsika::Code::Nucleus) - throw std::runtime_error("Cannot getMass() of particle::Nucleus -> unspecified"); + if (is_nucleus(pCode)) throw std::runtime_error("Not defined for nuclei."); auto sCode = convertToSibyllRaw(pCode); if (sCode == 0) throw std::runtime_error("getSibyllMass: unknown particle!"); diff --git a/corsika/detail/modules/urqmd/UrQMD.inl b/corsika/detail/modules/urqmd/UrQMD.inl index 12b9edbc372705ce20151b77fe855f8dc1e65024..80da719edae6312513999344fae7b819999980b9 100644 --- a/corsika/detail/modules/urqmd/UrQMD.inl +++ b/corsika/detail/modules/urqmd/UrQMD.inl @@ -129,7 +129,7 @@ namespace corsika::urqmd { int vAProjectile = 1) { // the following is a translation of ptsigtot() into C++ - if (vProjectileCode != Code::Nucleus && + if (!is_nucleus(vProjectileCode) && !is_nucleus(vTargetCode)) { // both particles are "special" auto const mProj = get_mass(vProjectileCode); auto const mTar = get_mass(vTargetCode); @@ -165,7 +165,7 @@ namespace corsika::urqmd { Code targetCode) const { auto const projectileCode = projectile.getPID(); - if (projectileCode == Code::Nucleus) { + if (is_nucleus(projectileCode)) { /* * unfortunately unavoidable at the moment until we have tools to get the actual * inealstic cross-section from UrQMD @@ -215,7 +215,7 @@ namespace corsika::urqmd { auto projectile = view.getProjectile(); - auto projectileCode = projectile.getPID(); + Code projectileCode = projectile.getPID(); auto const projectileEnergyLab = projectile.getEnergy(); auto const& projectileMomentumLab = projectile.getMomentum(); auto const& projectilePosition = projectile.getPosition(); @@ -246,14 +246,14 @@ namespace corsika::urqmd { ::urqmd::sys_.nsteps = 1; // initialization regarding projectile - if (Code::Nucleus == projectileCode) { + if (is_nucleus(projectileCode)) { // is this everything? ::urqmd::inputs_.prspflg = 0; - ::urqmd::sys_.Ap = projectile.getNuclearA(); - ::urqmd::sys_.Zp = projectile.getNuclearZ(); - ::urqmd::rsys_.ebeam = (projectileEnergyLab - projectile.getMass()) * (1 / 1_GeV) / - projectile.getNuclearA(); + ::urqmd::sys_.Ap = get_nucleus_A(projectileCode); + ::urqmd::sys_.Zp = get_nucleus_Z(projectileCode); + ::urqmd::rsys_.ebeam = + (projectileEnergyLab - projectile.getMass()) * (1 / 1_GeV) / ::urqmd::sys_.Ap; ::urqmd::rsys_.bdist = ::urqmd::nucrad_(targetA) + ::urqmd::nucrad_(::urqmd::sys_.Ap) + diff --git a/corsika/detail/setup/SetupStack.hpp b/corsika/detail/setup/SetupStack.hpp index 1f62ab4baaa245cb47420aee20fa53dc3617ae5a..7a1327b2e54f6dfc81824e001d2a290a4f612e8b 100644 --- a/corsika/detail/setup/SetupStack.hpp +++ b/corsika/detail/setup/SetupStack.hpp @@ -10,7 +10,7 @@ #include <corsika/framework/stack/CombinedStack.hpp> #include <corsika/stack/GeometryNodeStackExtension.hpp> -#include <corsika/stack/NuclearStackExtension.hpp> +#include <corsika/stack/VectorStack.hpp> #include <corsika/stack/WeightStackExtension.hpp> #include <corsika/stack/history/HistorySecondaryProducer.hpp> #include <corsika/stack/history/HistoryStackExtension.hpp> @@ -33,11 +33,11 @@ namespace corsika { // combine particle data stack with geometry information for tracking template <typename TStackIter> using StackWithGeometryInterface = - CombinedParticleInterface<nuclear_stack::ParticleDataStack::pi_type, - SetupGeometryDataInterface, TStackIter>; + CombinedParticleInterface<VectorStack::pi_type, SetupGeometryDataInterface, + TStackIter>; using StackWithGeometry = - CombinedStack<typename nuclear_stack::ParticleDataStack::stack_data_type, + CombinedStack<typename VectorStack::stack_data_type, node::GeometryData<setup::Environment>, StackWithGeometryInterface, DefaultSecondaryProducer>; diff --git a/corsika/detail/stack/NuclearStackExtension.inl b/corsika/detail/stack/NuclearStackExtension.inl index fa0d5941fb0d7a8fc38a6371bb5475a3015e3689..cdd377d12ca9452e601847f9ad151e43c05fb4ad 100644 --- a/corsika/detail/stack/NuclearStackExtension.inl +++ b/corsika/detail/stack/NuclearStackExtension.inl @@ -126,7 +126,7 @@ namespace corsika::nuclear_stack { setNuclearZ(Z); HEPMassType m = 0_GeV; if (PID == Code::Nucleus) { - m = get_nucleus_mass(A, Z); + m = get_nucleus_mass(get_nucleus_code(A, Z)); } else { m = get_mass(PID); } @@ -172,7 +172,7 @@ namespace corsika::nuclear_stack { setNuclearZ(Z); HEPMassType m = 0_GeV; if (PID == Code::Nucleus) { - m = get_nucleus_mass(A, Z); + m = get_nucleus_mass(get_nucleus_code(A, Z)); } else { m = get_mass(PID); } @@ -240,7 +240,7 @@ namespace corsika::nuclear_stack { inline HEPMassType NuclearParticleInterface<InnerParticleInterface, StackIteratorInterface>::getMass() const { if (super_type::getPID() == Code::Nucleus) - return get_nucleus_mass(getNuclearA(), getNuclearZ()); + return get_nucleus_mass(get_nucleus_code(getNuclearA(), getNuclearZ())); return super_type::getMass(); } diff --git a/corsika/framework/core/ParticleProperties.hpp b/corsika/framework/core/ParticleProperties.hpp index 85a65346b48b343e586516e2c8cbb1828db4ec25..8b9af126837c5d9c54942cb34b00c898283acd88 100644 --- a/corsika/framework/core/ParticleProperties.hpp +++ b/corsika/framework/core/ParticleProperties.hpp @@ -27,45 +27,49 @@ namespace corsika { /** - @defgroup Particles Particle Properties - - The properties of all particles are saved in static and flat - arrays. There is a enum corsika::Code to identify each - particles, and each individual particles has its own static class, - which can be used to retrieve its physical properties. - - The properties of all elementary particles are accessible here. The data - are taken from the Pythia ParticleData.xml file. - - Particle data can be accessed via global function in namespace corsika, or via - static classes for each particle type. These classes all have the interface (example - for the class corsika::Electron): - - @code{.cpp} - static constexpr Code code{Code::Electron}; - static constexpr Code anti_code{Code::Positron}; - static constexpr HEPMassType mass{corsika::get_mass(code)}; - static constexpr ElectricChargeType charge{corsika::get_charge(code)}; - static constexpr int charge_number{corsika::get_charge_number(code)}; - static constexpr std::string_view name{corsika::get_name(code)}; - static constexpr bool is_nucleus{corsika::is_nucleus(code)}; - @endcode - - The names, relations and properties of all particles known to CORSIKA 8 are listed - below. - - @addtogroup Particles - @{ + * @defgroup Particles Particle Properties + * + * The properties of all particles are saved in static and flat + * arrays. There is a enum corsika::Code to identify each + * particles, and each individual particles has its own static class, + * which can be used to retrieve its physical properties. + * + * The properties of all elementary particles are accessible here. The data + * are taken from the Pythia ParticleData.xml file. + * + * Particle data can be accessed via global function in namespace corsika, or via + * static classes for each particle type. These classes all have the interface (example + * for the class corsika::Electron): + * + * @code{.cpp} + * static constexpr Code code{Code::Electron}; + * static constexpr Code anti_code{Code::Positron}; + * static constexpr HEPMassType mass{corsika::get_mass(code)}; + * static constexpr ElectricChargeType charge{corsika::get_charge(code)}; + * static constexpr int charge_number{corsika::get_charge_number(code)}; + * static constexpr std::string_view name{corsika::get_name(code)}; + * static constexpr bool is_nucleus{corsika::is_nucleus(code)}; + * @endcode + * + * The names, relations and properties of all particles known to CORSIKA 8 are listed + * below. + * + * @addtogroup Particles + * @{ */ - /** The Code enum is the actual place to define CORSIKA 8 particle codes. */ - enum class Code : int16_t; + /** + * @brief The Code enum is the actual place to define CORSIKA 8 particle codes. + */ + enum class Code : int32_t; - /** Specifically for PDG ids */ + /** + * @brief Specifically for PDG ids. + */ enum class PDGCode : int32_t; using CodeIntType = std::underlying_type<Code>::type; - using PDGCodeType = std::underlying_type<PDGCode>::type; + using PDGCodeIntType = std::underlying_type<PDGCode>::type; // forward declarations to be used in GeneratedParticleProperties int16_t constexpr get_charge_number(Code const); //!< electric charge in units of e @@ -88,31 +92,81 @@ namespace corsika { //! Particle code according to PDG, "Monte Carlo Particle Numbering Scheme" PDGCode constexpr get_PDG(Code const); - PDGCode constexpr get_PDG(unsigned int A, unsigned int Z); std::string_view constexpr get_name(Code const); //!< name of the particle as string TimeType constexpr get_lifetime(Code const); //!< lifetime - //! true iff the particle is a hard-coded nucleus or Code::Nucleus - bool constexpr is_nucleus(Code const); bool constexpr is_hadron(Code const); //!< true iff particle is hadron bool constexpr is_em(Code const); //!< true iff particle is electron, positron or photon bool constexpr is_muon(Code const); //!< true iff particle is mu+ or mu- bool constexpr is_neutrino(Code const); //!< true iff particle is (anti-) neutrino - int constexpr get_nucleus_A( + + /** + * @brief Creates the Code for a nucleus of type 10LZZZAAAI. + * + * @return internal nucleus Code + */ + Code constexpr get_nucleus_code(unsigned int const A, unsigned int const Z); + /** + * @brief Checks if Code corresponds to a nucleus. + * + * @return true if nucleus. + * @return false if not nucleus. + */ + bool constexpr is_nucleus(Code const); + + /** + * @brief Get the mass number A for nucleus. + * + * @return int size of nucleus. + */ + unsigned int constexpr get_nucleus_A( Code const); //!< returns A for hard-coded nucleus, otherwise 0 - int constexpr get_nucleus_Z( + + /** + * @brief Get the charge number Z for nucleus. + * + * @return int charge of nucleus. + */ + unsigned int constexpr get_nucleus_Z( Code const); //!< returns Z for hard-coded nucleus, otherwise 0 - //! returns mass of (A,Z) nucleus, disregarding binding energy - HEPMassType get_nucleus_mass(unsigned int const, unsigned int const); + /** + * @brief Calculates the mass of nucleus. + * + * @return HEPMassType the mass of (A,Z) nucleus, disregarding binding energy. + */ + HEPMassType constexpr get_nucleus_mass(Code const code); + + /** + * @brief Get the nucleus name. + * + * @param code + * @return std::string + */ + inline std::string_view get_nucleus_name(Code const code); - //! convert PDG code to CORSIKA 8 internal code + /** + * @brief convert PDG code to CORSIKA 8 internal code. + * + * @return Code internal code. + */ Code convert_from_PDG(PDGCode const); + /** + * @brief Returns list of all non-nuclei particles. + * + * @return std::initializer_list<Code> constexpr + */ std::initializer_list<Code> constexpr get_all_particles(); - //! the output stream operator for human-readable particle codes + /** + * @brief Code output operator. + * + * The output stream operator for human-readable particle codes. + * + * @return std::ostream& + */ std::ostream& operator<<(std::ostream&, corsika::Code); /** @}*/ diff --git a/corsika/framework/process/InteractionHistogram.hpp b/corsika/framework/process/InteractionHistogram.hpp index 78796f609e3a83316a52d818cf045425af7c507a..b687153b58e96bf4fb4235cb431318424c9136af 100644 --- a/corsika/framework/process/InteractionHistogram.hpp +++ b/corsika/framework/process/InteractionHistogram.hpp @@ -57,11 +57,11 @@ namespace corsika { @param projectile_id corsika::Code of particle @param lab_energy Energy in lab. frame @param mass_target Mass of target particle - @param A if projectile_id is corsika::Nucleus : Mass of nucleus - @param Z if projectile_id is corsika::Nucleus : Charge of nucleus + @param A if projectile_id is Nucleus : Mass of nucleus + @param Z if projectile_id is Nucleus : Charge of nucleus */ - void fill(Code projectile_id, HEPEnergyType lab_energy, HEPEnergyType mass_target, - int A = 0, int Z = 0); + void fill(Code const projectile_id, HEPEnergyType const lab_energy, + HEPEnergyType const mass_target); //! return histogram in c.m.s. frame hist_type const& CMSHist() const { return inthist_cms_; } diff --git a/corsika/modules/epos/Interaction.hpp b/corsika/modules/epos/Interaction.hpp index efaac0705f33174fa1910c780791e59651eaf1c1..56900ca01cdf99f41f6dc38b7cc9578bc6e7afad 100644 --- a/corsika/modules/epos/Interaction.hpp +++ b/corsika/modules/epos/Interaction.hpp @@ -77,8 +77,8 @@ namespace corsika::epos { std::shared_ptr<spdlog::logger> logger_ = get_logger("corsika_epos_Interaction"); HEPEnergyType const minEnergyCoM_ = 6 * 1e9 * electronvolt; HEPEnergyType const maxEnergyCoM_ = 2.e6 * 1e9 * electronvolt; - int const maxTargetMassNumber_ = 20; - int const minNuclearTargetA_ = 4; + static unsigned int constexpr maxTargetMassNumber_ = 20; + static unsigned int constexpr minNuclearTargetA_ = 4; }; } // namespace corsika::epos diff --git a/corsika/modules/epos/ParticleConversion.hpp b/corsika/modules/epos/ParticleConversion.hpp index 3ee82a72168acf9479ae7a4e2e4d6a479def7fc1..736b93074d3e50d42c110a249283f7a31f779443 100644 --- a/corsika/modules/epos/ParticleConversion.hpp +++ b/corsika/modules/epos/ParticleConversion.hpp @@ -21,7 +21,7 @@ namespace corsika::epos { using EposCodeIntType = std::underlying_type<EposCode>::type; /** - These are the possible projectile for which Epos knows the cross section + * These are the possible projectile for which Epos knows the cross section. */ enum class EposXSClass : int8_t { CannotInteract = 0, @@ -34,14 +34,27 @@ namespace corsika::epos { #include <corsika/modules/epos/Generated.inc> - EposCode constexpr convertToEpos(Code pCode) { - return corsika2epos[static_cast<CodeIntType>(pCode)]; + unsigned int constexpr get_nucleus_A(EposCode const eposId) { + // 100ZZZAAA0 -> std. pdg code + EposCodeIntType const eposPdg = static_cast<EposCodeIntType>(eposId); + return int(abs(eposPdg) / 10) % 1000; + } + unsigned int constexpr get_nucleus_Z(EposCode const eposId) { + // 100ZZZAAA0 -> std. pdg code + EposCodeIntType const eposPdg = static_cast<EposCodeIntType>(eposId); + return int(abs(eposPdg) / 10000) % 1000; + } + + EposCode constexpr convertToEpos(Code const code) { + return corsika2epos[static_cast<CodeIntType>(code)]; } - Code constexpr convertFromEpos(EposCode pCode) { - EposCodeIntType const s = static_cast<EposCodeIntType>(pCode); + Code constexpr convertFromEpos(EposCode const eposId) { + EposCodeIntType const s = static_cast<EposCodeIntType>(eposId); // if nucleus (pdg-id) - if (s >= 1000000000) { return Code::Nucleus; } + if (s >= 1000000000) { + return get_nucleus_code(get_nucleus_A(eposId), get_nucleus_Z(eposId)); + } auto const corsikaCode = epos2corsika[s - minEpos]; if (corsikaCode == Code::Unknown) { throw std::runtime_error(std::string("EPOS/CORSIKA conversion of ") @@ -51,16 +64,19 @@ namespace corsika::epos { return corsikaCode; } - int constexpr convertToEposRaw(Code pCode) { - return static_cast<int>(convertToEpos(pCode)); + int constexpr convertToEposRaw(Code const code) { + return static_cast<int>(convertToEpos(code)); } - int constexpr getEposXSCode(Code pCode) { + int constexpr getEposXSCode(Code const code) { + if (is_nucleus(code)) { return static_cast<EposXSClassIntType>(EposXSClass::Baryon); } return static_cast<EposXSClassIntType>( - corsika2eposXStype[static_cast<CodeIntType>(pCode)]); + corsika2eposXStype[static_cast<CodeIntType>(code)]); } - bool constexpr canInteract(Code pCode) { return getEposXSCode(pCode) > 0; } + bool constexpr canInteract(Code const code) { + return is_nucleus(code) || getEposXSCode(code) > 0; + } HEPMassType getEposMass(Code const); diff --git a/corsika/modules/qgsjetII/Interaction.hpp b/corsika/modules/qgsjetII/Interaction.hpp index 7af63723f5670fa0de59aea92c98f232b145d8d4..0030de2fccc3438377c11a801e0206e62d55a0c0 100644 --- a/corsika/modules/qgsjetII/Interaction.hpp +++ b/corsika/modules/qgsjetII/Interaction.hpp @@ -29,7 +29,7 @@ namespace corsika::qgsjetII { ~Interaction(); bool wasInitialized() { return initialized_; } - int getMaxTargetMassNumber() const { return maxMassNumber_; } + unsigned int getMaxTargetMassNumber() const { return maxMassNumber_; } bool isValidTarget(corsika::Code TargetId) const { return is_nucleus(TargetId) && (get_nucleus_A(TargetId) < maxMassNumber_); } @@ -57,7 +57,7 @@ namespace corsika::qgsjetII { corsika::default_prng_type& rng_ = corsika::RNGManager<>::getInstance().getRandomStream("qgsjet"); - const int maxMassNumber_ = 208; + static unsigned int constexpr maxMassNumber_ = 208; }; } // namespace corsika::qgsjetII diff --git a/corsika/modules/qgsjetII/ParticleConversion.hpp b/corsika/modules/qgsjetII/ParticleConversion.hpp index 473365f126a54e2249198d6ad1efc912363a7e96..3b4f689b8b7b1af73367f5f6a9355c273206d657 100644 --- a/corsika/modules/qgsjetII/ParticleConversion.hpp +++ b/corsika/modules/qgsjetII/ParticleConversion.hpp @@ -62,37 +62,37 @@ namespace corsika::qgsjetII { return corsika2qgsjetII[static_cast<CodeIntType>(pCode)]; } - Code constexpr convertFromQgsjetII(QgsjetIICode pCode) { - auto const pCodeInt = static_cast<QgsjetIICodeIntType>(pCode); - auto const corsikaCode = qgsjetII2corsika[pCodeInt - minQgsjetII]; + Code constexpr convertFromQgsjetII(QgsjetIICode const code) { + auto const codeInt = static_cast<QgsjetIICodeIntType>(code); + auto const corsikaCode = qgsjetII2corsika[codeInt - minQgsjetII]; if (corsikaCode == Code::Unknown) { throw std::runtime_error(std::string("QGSJETII/CORSIKA conversion of pCodeInt=") - .append(std::to_string(pCodeInt)) + .append(std::to_string(codeInt)) .append(" impossible")); } return corsikaCode; } - QgsjetIICodeIntType constexpr convertToQgsjetIIRaw(Code pCode) { - return static_cast<QgsjetIICodeIntType>(convertToQgsjetII(pCode)); + QgsjetIICodeIntType constexpr convertToQgsjetIIRaw(Code const code) { + return static_cast<QgsjetIICodeIntType>(convertToQgsjetII(code)); } - QgsjetIIXSClass constexpr getQgsjetIIXSCode(Code pCode) { - // if (pCode == corsika::particles::Code::Nucleus) - // static_cast(QgsjetIIXSClassIntType>(); - return corsika2qgsjetIIXStype[static_cast<CodeIntType>(pCode)]; + QgsjetIIXSClass constexpr getQgsjetIIXSCode(Code const code) { + return corsika2qgsjetIIXStype[static_cast<CodeIntType>(code)]; } - QgsjetIIXSClassIntType constexpr getQgsjetIIXSCodeRaw(Code pCode) { - return static_cast<QgsjetIIXSClassIntType>(getQgsjetIIXSCode(pCode)); + QgsjetIIXSClassIntType constexpr getQgsjetIIXSCodeRaw(Code const code) { + return static_cast<QgsjetIIXSClassIntType>(getQgsjetIIXSCode(code)); } - bool constexpr canInteract(Code pCode) { - return getQgsjetIIXSCode(pCode) != QgsjetIIXSClass::CannotInteract; + bool constexpr canInteract(Code const code) { + if (is_nucleus(code)) return true; + return getQgsjetIIXSCode(code) != QgsjetIIXSClass::CannotInteract; } - QgsjetIIHadronType constexpr getQgsjetIIHadronType(Code pCode) { - return corsika2qgsjetIIHadronType[static_cast<CodeIntType>(pCode)]; + QgsjetIIHadronType constexpr getQgsjetIIHadronType(Code const code) { + if (is_nucleus(code)) return QgsjetIIHadronType::NucleusType; + return corsika2qgsjetIIHadronType[static_cast<CodeIntType>(code)]; } } // namespace corsika::qgsjetII diff --git a/corsika/modules/sibyll/Interaction.hpp b/corsika/modules/sibyll/Interaction.hpp index 423d9319b9c9458265d65f1a28f0a0f1a17240f2..b53fb63080b4a0a44b751a9abf9e73f60b940401 100644 --- a/corsika/modules/sibyll/Interaction.hpp +++ b/corsika/modules/sibyll/Interaction.hpp @@ -52,15 +52,15 @@ namespace corsika::sibyll { void doInteraction(TSecondaries&); private: - int getMaxTargetMassNumber() const { return maxTargetMassNumber_; } + unsigned int constexpr getMaxTargetMassNumber() const { return maxTargetMassNumber_; } HEPEnergyType getMinEnergyCoM() const { return minEnergyCoM_; } HEPEnergyType getMaxEnergyCoM() const { return maxEnergyCoM_; } default_prng_type& RNG_ = RNGManager<>::getInstance().getRandomStream("sibyll"); const HEPEnergyType minEnergyCoM_ = 10. * 1e9 * electronvolt; const HEPEnergyType maxEnergyCoM_ = 1.e6 * 1e9 * electronvolt; - const int maxTargetMassNumber_ = 18; - const int minNuclearTargetA_ = 4; + static unsigned int constexpr maxTargetMassNumber_ = 18; + static unsigned int constexpr minNuclearTargetA_ = 4; // data members int count_ = 0; diff --git a/examples/corsika.cpp b/examples/corsika.cpp index 09d997c5d7d343165874964418063fb6ce211d8a..f7fc083e86337ce34c94539fdb41b65219707dc1 100644 --- a/examples/corsika.cpp +++ b/examples/corsika.cpp @@ -397,11 +397,7 @@ int main(int argc, char** argv) { stack.clear(); // add the desired particle to the stack - if (A > 1) { - stack.addParticle(std::make_tuple(beamCode, plab, injectionPos, 0_ns, A, Z)); - } else { - stack.addParticle(std::make_tuple(beamCode, plab, injectionPos, 0_ns)); - } + stack.addParticle(std::make_tuple(beamCode, plab, injectionPos, 0_ns)); // if we want to fix the first location of the shower if (force_interaction) { diff --git a/examples/vertical_EAS.cpp b/examples/vertical_EAS.cpp index 6800a84be8858d31ed01d36d213ef56754a265b1..4b10e0436a04891b727c0310fec7a4b4ca950147 100644 --- a/examples/vertical_EAS.cpp +++ b/examples/vertical_EAS.cpp @@ -131,7 +131,7 @@ int main(int argc, char** argv) { 50_uT, 0_T}); builder.setNuclearComposition( {{Code::Nitrogen, Code::Oxygen}, - {0.7847f, 1.f - 0.7847f}}); // values taken from AIRES manual, Ar removed for now + {0.7847, 1. - 0.7847}}); // values taken from AIRES manual, Ar removed for now builder.addExponentialLayer(1222.6562_g / (1_cm * 1_cm), 994186.38_cm, 2_km); builder.addExponentialLayer(1222.6562_g / (1_cm * 1_cm), 994186.38_cm, 4_km); diff --git a/src/framework/core/CMakeLists.txt b/src/framework/core/CMakeLists.txt index 097908cf269ed53aa4465c0f920455f8ae8215a2..4faa8829e543b17d6905b8dbcd4c957bfff4761f 100644 --- a/src/framework/core/CMakeLists.txt +++ b/src/framework/core/CMakeLists.txt @@ -7,10 +7,10 @@ add_custom_command ( OUTPUT ${output_dir}/GeneratedParticleProperties.inc ${output_dir}/GeneratedParticleClasses.inc ${output_dir}/particle_db.pkl - COMMAND ${input_dir}/pdxml_reader.py ${input_dir}/ParticleData.xml - ${input_dir}/NuclearData.xml - ${input_dir}/ParticleClassNames.xml - DEPENDS ${input_dir}/pdxml_reader.py + COMMAND ${input_dir}/code_generator.py ${input_dir}/ParticleData.xml + ${input_dir}/NuclearData.xml + ${input_dir}/ParticleClassNames.xml + DEPENDS ${input_dir}/code_generator.py ${input_dir}/ParticleData.xml ${input_dir}/NuclearData.xml ${input_dir}/ParticleClassNames.xml diff --git a/src/framework/core/NuclearData.xml b/src/framework/core/NuclearData.xml index 73eda0ef2350aa6849df60c61a34231dd9fff869..257b6f260a43ddad22bdd6be5e99a545f6dd1cb4 100644 --- a/src/framework/core/NuclearData.xml +++ b/src/framework/core/NuclearData.xml @@ -1,8 +1,5 @@ <chapter name="Nuclear Data"> -<particle id="1000000000" name="nucleus" A="0" Z="0" > -</particle> - <particle id="1000010010" name="hydrogen" A="1" Z="1" > </particle> @@ -60,10 +57,22 @@ <particle id="1000541280" name="xenon" A="128" Z="54" > </particle> +<particle id="1000741840" name="tungsten" A="184" Z="74" > +</particle> + +<particle id="1000791970" name="gold" A="197" Z="79" > +</particle> + <particle id="1000822080" name="lead" A="208" Z="82" > </particle> <particle id="1000862220" name="radon" A="222" Z="86" > </particle> +<particle id="1000922380" name="uranium" A="238" Z="92" > +</particle> + +<particle id="1001243080" name="ralfium" A="308" Z="124" > +</particle> + </chapter> diff --git a/src/framework/core/pdxml_reader.py b/src/framework/core/code_generator.py similarity index 84% rename from src/framework/core/pdxml_reader.py rename to src/framework/core/code_generator.py index 13a79f33482d77e2e037217bf9ebd0e05a0b45bb..e06488c7b4da21840a26986e4514741d17a6c197 100755 --- a/src/framework/core/pdxml_reader.py +++ b/src/framework/core/code_generator.py @@ -19,6 +19,11 @@ mproton = 0.9382720813 # GeV namespace = "corsika" +# IDs of Nuclei are 10LZZZAAAI +nucleusIdStr = "10{L:01d}{Z:03d}{A:03d}{I:01d}" # used with .format(L=,Z=,A=,I=) +nucleusIdOffset = int(nucleusIdStr.format(L=0,A=0,Z=0,I=0)) + + ############################################################## # # reading xml input data, return line by line particle data @@ -238,7 +243,7 @@ def read_nuclei_db(filename, particle_db, classnames): "mass": mass, # in GeV "electric_charge": electric_charge, # in e/3 "lifetime": lifetime, - "ngc_code": next(counter), + "ngc_code": int(nucleusIdStr.format(L=0,A=A,Z=Z,I=0)), "A": A, "Z": Z, "isNucleus": True, @@ -297,22 +302,37 @@ def gen_conversion_PDG_ngc(particle_db): # # return string with enum of all internal particle codes # -def gen_internal_enum(particle_db): +def gen_internal_enum(particle_db, nuclei_db): string = ("//! @cond EXCLUDE_DOXY\n" "enum class Code : CodeIntType {\n" " FirstParticle = 1, // if you want to loop over particles, you want to start with \"1\" \n") # identifier for eventual loops... - for k in filter(lambda k: "ngc_code" in particle_db[k], particle_db): + # non-nuclei loop + for k in filter(lambda k: "ngc_code" in particle_db[k] and not particle_db[k]["isNucleus"], + particle_db): last_ngc_id = particle_db[k]['ngc_code'] string += " {key:s} = {code:d},\n".format(key=k, code=last_ngc_id) - string += (" LastParticle = {:d},\n" # identifier for eventual loops... - "}}; //! @endcond").format(last_ngc_id + 1) + string += " LastParticle = {:d},\n".format(last_ngc_id + 1) # identifier for eventual loops... - if last_ngc_id > 0x7fff: # does not fit into int16_t + if last_ngc_id > 0x7fffffff: # does not fit into int32_t, this will never happen.... raise Exception( "Integer overflow in internal particle code definition prevented!") + if last_ngc_id + 1 >= nucleusIdOffset: + raise Exception( + "Too many particles. Fix conflict with Code::Nuclear == {:d} (just increase id...) !").format(nucleusIdOffset) + + # marker to mark the beginning of generic nuclear IDs: 1aaazzz + string += " Nucleus = {:d},\n".format(nucleusIdOffset) # identifier for Nuclei + + # nuclei loop + for k in filter(lambda k: "ngc_code" in nuclei_db[k] and nuclei_db[k]["isNucleus"], + nuclei_db): + last_ngc_id = nuclei_db[k]['ngc_code'] + string += " {key:s} = {code:d},\n".format(key=k, code=last_ngc_id) + + string += "}; //! @endcond" return string @@ -322,7 +342,7 @@ def gen_internal_enum(particle_db): # def gen_pdg_enum(particle_db): string = ("//! @cond EXCLUDE_DOXY\n" - "enum class PDGCode : PDGCodeType {\n") + "enum class PDGCode : PDGCodeIntType {\n") for cId in particle_db: pdgCode = particle_db[cId]['pdg'] @@ -363,6 +383,7 @@ def gen_properties(particle_db): for k in particle_db: string += " 0 * corsika::units::si::electronvolt, // {name:s}\n".format( name = k) string += "};\n\n" + string += "static corsika::units::si::HEPEnergyType threshold_nuclei = 0_eV;\n" # PDG code table string += "static constexpr std::array<PDGCode, size> pdg_codes = {\n" @@ -377,7 +398,7 @@ def gen_properties(particle_db): string += "};\n" # electric charges table - string += "static constexpr std::array<int16_t, size> electric_charges = {\n" + string += "static constexpr std::array<int32_t, size> electric_charges = {\n" for p in particle_db.values(): string += " {charge:d},\n".format(charge=p['electric_charge'] // 3) string += "};\n" @@ -409,22 +430,6 @@ def gen_properties(particle_db): string += " {val},\n".format(val=value) string += "};\n" - ### nuclear data ### - - # nucleus mass number A - string += "static constexpr std::array<int16_t, size> nucleusA = {\n" - for p in particle_db.values(): - A = p.get('A', 0) - string += " {val},\n".format(val=A) - string += "};\n" - - # nucleus charge number Z - string += "static constexpr std::array<int16_t, size> nucleusZ = {\n" - for p in particle_db.values(): - Z = p.get('Z', 0) - string += " {val},\n".format(val=Z) - string += "};\n" - return string @@ -432,35 +437,36 @@ def gen_properties(particle_db): # # return string with a list of classes for all particles # -def gen_classes(particle_db): +def gen_classes(particle_db, nuclei_db): string = ("// list of C++ classes to access particle properties\n" "/** @defgroup ParticleClasses \n" " @{ */\n") - for cname in particle_db: + common_db = OrderedDict(list(particle_db.items()) + list(nuclei_db.items())) + for cname in common_db: if cname == "Nucleus": string += "// skipping Nucleus" continue antiP = 'Unknown' - for cname_anti in particle_db: - if (particle_db[cname_anti]['name'] == particle_db[cname]['antiName']): + for cname_anti in common_db: + if (common_db[cname_anti]['name'] == common_db[cname]['antiName']): antiP = cname_anti break string += "\n" string += "/** @class " + cname + "\n\n" string += " * Particle properties are taken from the PYTHIA8 ParticleData.xml file:<br>\n" - string += " * - pdg=" + str(particle_db[cname]['pdg']) + "\n" - string += " * - mass=" + str(particle_db[cname]['mass']) + " GeV \n" + string += " * - pdg=" + str(common_db[cname]['pdg']) + "\n" + string += " * - mass=" + str(common_db[cname]['mass']) + " GeV \n" string += " * - charge= " + \ - str(particle_db[cname]['electric_charge'] // 3) + " \n" + str(common_db[cname]['electric_charge'] // 3) + " \n" string += " * - name=" + str(cname) + "\n" string += " * - anti=" + str(antiP) + "\n" - if (particle_db[cname]['isNucleus']): - string += " * - nuclear A=" + str(particle_db[cname]['A']) + "\n" - string += " * - nuclear Z=" + str(particle_db[cname]['Z']) + "\n" + if (common_db[cname]['isNucleus']): + string += " * - nuclear A=" + str(common_db[cname]['A']) + "\n" + string += " * - nuclear Z=" + str(common_db[cname]['Z']) + "\n" string += "*/\n\n" string += "class " + cname + " {\n" string += " /** @cond EXCLUDE_DOXY */ \n" @@ -473,7 +479,7 @@ def gen_classes(particle_db): string += " static constexpr int charge_number{corsika::get_charge_number(code)};\n" string += " static constexpr std::string_view name{corsika::get_name(code)};\n" string += " static constexpr bool is_nucleus{corsika::is_nucleus(code)};\n" - if particle_db[cname]['isNucleus']: + if common_db[cname]['isNucleus']: string += " static constexpr int nucleus_A{corsika::get_nucleus_A(code)};\n" string += " static constexpr int nucleus_Z{corsika::get_nucleus_Z(code)};\n" string += " private:\n" @@ -490,7 +496,7 @@ def gen_classes(particle_db): # # def inc_start(): - string = ('// generated by pdxml_reader.py\n' + string = ('// generated by framework/core/code_generator.py\n' '// MANUAL EDITS ON OWN RISK. THEY WILL BE OVERWRITTEN. \n' '\n' 'namespace corsika {\n' @@ -531,8 +537,9 @@ def inc_end(): # # Serialize particle_db into file # -def serialize_particle_db(particle_db, file): - pickle.dump(particle_db, file) +def serialize_particle_db(particle_db, nuclei_db, file): + common_db = OrderedDict(list(particle_db.items()) + list(nuclei_db.items())) + pickle.dump(common_db, file) ################################################################### @@ -546,16 +553,17 @@ if __name__ == "__main__": sys.argv[0]), file=sys.stderr) sys.exit(1) - print("\n pdxml_reader.py: automatically produce particle properties from input files\n") + print("\n code_generator.py: automatically produce particle properties from input files\n") - names = read_class_names(sys.argv[3]) - particle_db = OrderedDict() - read_pythia_db(sys.argv[1], particle_db, names) - read_nuclei_db(sys.argv[2], particle_db, names) + names = read_class_names(sys.argv[3]) # re-names and conventions + particle_db = OrderedDict() # the DB for pythia8 pdg particles + read_pythia_db(sys.argv[1], particle_db, names) # pythia8 pdg DB + nuclei_db = OrderedDict() # the DB for specific nuclei + read_nuclei_db(sys.argv[2], nuclei_db, names) # list of nuclei with open("GeneratedParticleProperties.inc", "w") as f: print(inc_start(), file=f) - print(gen_internal_enum(particle_db), file=f) + print(gen_internal_enum(particle_db, nuclei_db), file=f) print(gen_pdg_enum(particle_db), file=f) print(detail_start(), file=f) print(gen_properties(particle_db), file=f) @@ -565,8 +573,8 @@ if __name__ == "__main__": with open("GeneratedParticleClasses.inc", "w") as f: print(inc_start(), file=f) - print(gen_classes(particle_db), file=f) + print(gen_classes(particle_db, nuclei_db), file=f) print(inc_end(), file=f) with open("particle_db.pkl", "wb") as f: - serialize_particle_db(particle_db, f) + serialize_particle_db(particle_db, nuclei_db, f) diff --git a/src/modules/epos/code_generator.py b/src/modules/epos/code_generator.py index f47efbb965fafc025e6b5a43c9e11e99178d87e3..c3de621e9bff0f089dd550069e60a8a584bcec5f 100755 --- a/src/modules/epos/code_generator.py +++ b/src/modules/epos/code_generator.py @@ -39,7 +39,7 @@ def read_epos_codes(filename, particle_db): particle_db[identifier]["epos_code"] = int(epos_code) particle_db[identifier]["epos_xsType"] = xsType except KeyError as e: - raise Exception("Identifier '{:s}' not found in particle_db".format(identifier)) + raise Exception("Identifier '{:s}' not found in CORSIKA8 particle_db".format(identifier)) def set_default_epos_definition(particle_db): @@ -49,7 +49,7 @@ def set_default_epos_definition(particle_db): This is achieved here. - The function return nothing, but modified the input particle_db by adding the + The function returns nothing, but modified the input particle_db by adding the fields 'xsType' and 'hadronType' ''' for identifier, pData in particle_db.items(): @@ -83,6 +83,7 @@ def generate_corsika2epos(particle_db): ''' string = "std::array<EposCode, {:d}> constexpr corsika2epos = {{\n".format(len(particle_db)) for identifier, pData in particle_db.items(): + if pData['isNucleus']: continue if 'epos_code' in pData: string += " EposCode::{:s}, \n".format(identifier) else: @@ -98,6 +99,7 @@ def generate_corsika2epos_xsType(particle_db): ''' string = "std::array<EposXSClass, {:d}> constexpr corsika2eposXStype = {{\n".format(len(particle_db)) for identifier, pData in particle_db.items(): + if pData['isNucleus']: continue if 'epos_xsType' in pData: string += " EposXSClass::{:s}, // {:s}\n".format(pData['epos_xsType'], identifier) else: @@ -116,7 +118,6 @@ def generate_epos2corsika(particle_db) : for identifier, pData in particle_db.items() : if 'epos_code' in pData: minID = min(minID, pData['epos_code']) - string += "EposCodeIntType constexpr minEpos = {:d};\n\n".format(minID) pDict = {} diff --git a/src/modules/epos/epos_codes.dat b/src/modules/epos/epos_codes.dat index 9c942914e92a10fbd3bbb8b42750b66d315d8ce7..70b6cb380bf1e79651a426e7e5eae36aebbf0104 100644 --- a/src/modules/epos/epos_codes.dat +++ b/src/modules/epos/epos_codes.dat @@ -7,7 +7,7 @@ Unknown 0 0 CannotInteract # Here is the list of particles known to EPOS -Photon 10 0 CannotInteract +Photon 10 0 CannotInteract Electron 12 0 CannotInteract Positron -12 0 CannotInteract MuMinus 14 0 CannotInteract diff --git a/src/modules/qgsjetII/code_generator.py b/src/modules/qgsjetII/code_generator.py index 8321aad19ab1ae30252b930800a62aa7f0fd7b6b..b867e91dfeeb86a3bb44737d55ce5872f223b8cb 100755 --- a/src/modules/qgsjetII/code_generator.py +++ b/src/modules/qgsjetII/code_generator.py @@ -120,6 +120,7 @@ def generate_corsika2qgsjetII(particle_db): ''' string = "std::array<QgsjetIICode, {:d}> constexpr corsika2qgsjetII = {{\n".format(len(particle_db)) for identifier, pData in particle_db.items(): + if pData['isNucleus']: continue if 'qgsjetII_code' in pData: string += " QgsjetIICode::{:s}, \n".format(identifier) else: @@ -134,6 +135,7 @@ def generate_corsika2qgsjetII_xsType(particle_db): ''' string = "std::array<QgsjetIIXSClass, {:d}> constexpr corsika2qgsjetIIXStype = {{\n".format(len(particle_db)) for identifier, pData in particle_db.items(): + if pData['isNucleus']: continue modelCodeXS = pData.get("qgsjetII_xsType", "CannotInteract") string += " QgsjetIIXSClass::{:s}, // {:s}\n".format(modelCodeXS, identifier if modelCodeXS else identifier + " (not implemented in QGSJETII)") string += "};\n" @@ -146,6 +148,7 @@ def generate_corsika2qgsjetII_hadronType(particle_db): ''' string = "std::array<QgsjetIIHadronType, {:d}> constexpr corsika2qgsjetIIHadronType = {{\n".format(len(particle_db)) for identifier, pData in particle_db.items(): + if pData['isNucleus']: continue modelCode = pData.get("qgsjetII_hadronType", "UndefinedType") string += " QgsjetIIHadronType::{:s}, // {:s}\n".format(modelCode, identifier if modelCode else identifier + " (not implemented in QGSJETII)") string += "};\n" diff --git a/src/modules/sibyll/code_generator.py b/src/modules/sibyll/code_generator.py index 22cb11022741597b6807c844766dcf0158f24365..20407f2c7e7cfe1808ab2c92b9c9ddf081feee7b 100755 --- a/src/modules/sibyll/code_generator.py +++ b/src/modules/sibyll/code_generator.py @@ -63,6 +63,7 @@ def generate_corsika2sibyll(particle_db): ''' string = "std::array<SibyllCode, {:d}> constexpr corsika2sibyll = {{\n".format(len(particle_db)) for identifier, pData in particle_db.items(): + if pData['isNucleus']: continue if 'sibyll_code' in pData: string += " SibyllCode::{:s}, \n".format(identifier) else: @@ -78,6 +79,7 @@ def generate_corsika2sibyll_xsType(particle_db): ''' string = "std::array<SibyllXSClass, {:d}> constexpr corsika2sibyllXStype = {{\n".format(len(particle_db)) for identifier, pData in particle_db.items(): + if pData['isNucleus']: continue if 'sibyll_xsType' in pData: string += " SibyllXSClass::{:s}, // {:s}\n".format(pData['sibyll_xsType'], identifier) else: diff --git a/tests/common/SetupTestStack.hpp b/tests/common/SetupTestStack.hpp index d41f1aa2726f65a7eeb7a31b3132e38ad51e1be8..a5bfb3d23622a3da7f0a1ea4102f514735005906 100644 --- a/tests/common/SetupTestStack.hpp +++ b/tests/common/SetupTestStack.hpp @@ -35,7 +35,7 @@ namespace corsika::setup::testing { **/ inline std::tuple<std::unique_ptr<setup::Stack>, std::unique_ptr<setup::StackView>> - setup_stack(Code vProjectileType, int vA, int vZ, HEPEnergyType vMomentum, + setup_stack(Code vProjectileType, HEPEnergyType vMomentum, setup::Environment::BaseNodeType* const vNodePtr, CoordinateSystemPtr const& cs) { @@ -44,19 +44,11 @@ namespace corsika::setup::testing { Point const origin(cs, {0_m, 0_m, 0_m}); MomentumVector const pLab(cs, {vMomentum, 0_GeV, 0_GeV}); - if (vProjectileType == Code::Nucleus) { - auto particle = - stack->addParticle(std::make_tuple(Code::Nucleus, pLab, origin, 0_ns, vA, vZ)); - particle.setNode(vNodePtr); - return std::make_tuple(std::move(stack), - std::make_unique<setup::StackView>(particle)); - } else { // not a nucleus - auto particle = - stack->addParticle(std::make_tuple(vProjectileType, pLab, origin, 0_ns)); - particle.setNode(vNodePtr); - return std::make_tuple(std::move(stack), - std::make_unique<setup::StackView>(particle)); - } + auto particle = + stack->addParticle(std::make_tuple(vProjectileType, pLab, origin, 0_ns)); + particle.setNode(vNodePtr); + return std::make_tuple(std::move(stack), + std::make_unique<setup::StackView>(particle)); } } // namespace corsika::setup::testing diff --git a/tests/framework/testCascade.hpp b/tests/framework/testCascade.hpp index 638424f893c9fa1fef7dd957b1d7fc0010285cc2..cb6e0b5a0c8e06ab7a51fbf6c5a2565760171e97 100644 --- a/tests/framework/testCascade.hpp +++ b/tests/framework/testCascade.hpp @@ -14,7 +14,7 @@ #include <corsika/framework/stack/CombinedStack.hpp> #include <corsika/framework/stack/SecondaryView.hpp> #include <corsika/stack/GeometryNodeStackExtension.hpp> -#include <corsika/stack/NuclearStackExtension.hpp> +#include <corsika/stack/VectorStack.hpp> using TestEnvironmentInterface = corsika::IEmpty; using TestEnvironmentType = corsika::Environment<TestEnvironmentInterface>; @@ -26,12 +26,13 @@ using SetupGeometryDataInterface = // combine particle data stack with geometry information for tracking template <typename StackIter> using StackWithGeometryInterface = - corsika::CombinedParticleInterface<corsika::nuclear_stack::ParticleDataStack::pi_type, + corsika::CombinedParticleInterface<corsika::VectorStack::pi_type, SetupGeometryDataInterface, StackIter>; -using TestCascadeStack = corsika::CombinedStack< - typename corsika::nuclear_stack::ParticleDataStack::stack_data_type, - corsika::node::GeometryData<TestEnvironmentType>, StackWithGeometryInterface>; +using TestCascadeStack = + corsika::CombinedStack<typename corsika::VectorStack::stack_data_type, + corsika::node::GeometryData<TestEnvironmentType>, + StackWithGeometryInterface>; /* See also Issue 161 diff --git a/tests/framework/testInteractionCounter.cpp b/tests/framework/testInteractionCounter.cpp index 4b4b7ff25dca0ba6a5cf44018c9efde66a150e82..4ea5d49b04f462e43517ed96b3bf6f565a29fba3 100644 --- a/tests/framework/testInteractionCounter.cpp +++ b/tests/framework/testInteractionCounter.cpp @@ -33,12 +33,11 @@ const std::string refDataDir = std::string(REFDATADIR); // from cmake struct DummyProcess { template <typename TParticle> - GrammageType getInteractionLength([[maybe_unused]] TParticle const& particle) { + GrammageType getInteractionLength(TParticle const&) { return 100_g / 1_cm / 1_cm; } - template <typename TParticle> - void doInteraction([[maybe_unused]] TParticle& projectile) {} + void doInteraction(TParticle&) {} }; TEST_CASE("InteractionCounter", "[process]") { @@ -58,7 +57,7 @@ TEST_CASE("InteractionCounter", "[process]") { SECTION("DoInteraction nucleus") { unsigned short constexpr A = 14, Z = 7; auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Nucleus, A, Z, 105_TeV, (setup::Environment::BaseNodeType* const)nodePtr, + get_nucleus_code(A, Z), 105_TeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); CHECK(stackPtr->getEntries() == 1); CHECK(secViewPtr->getEntries() == 0); @@ -103,7 +102,7 @@ TEST_CASE("InteractionCounter", "[process]") { SECTION("DoInteraction Lambda") { auto constexpr code = Code::Lambda0; auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - code, 0, 0, 105_TeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); + code, 105_TeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); CHECK(stackPtr->getEntries() == 1); CHECK(secViewPtr->getEntries() == 0); diff --git a/tests/framework/testParticles.cpp b/tests/framework/testParticles.cpp index 322c553c7a45358a61e3e389fafb888a15b7d59d..f12faf8039a3baa7031416e49bfe5e9bc4c8d467 100644 --- a/tests/framework/testParticles.cpp +++ b/tests/framework/testParticles.cpp @@ -47,7 +47,7 @@ TEST_CASE("ParticleProperties", "[Particles]") { CHECK(Electron::name == "e-"); CHECK(get_name(Code::Electron) == "e-"); CHECK(PiMinus::name == "pi-"); - CHECK(Iron::name == "iron"); + CHECK(Iron::name == "nucleus"); CHECK(Photon::name == "photon"); } @@ -112,7 +112,6 @@ TEST_CASE("ParticleProperties", "[Particles]") { CHECK(is_hadron(Code::Proton)); CHECK(is_hadron(Code::PiPlus)); CHECK(is_hadron(Code::Oxygen)); - CHECK(is_hadron(Code::Nucleus)); } SECTION("Particle groups: muons") { @@ -155,10 +154,24 @@ TEST_CASE("ParticleProperties", "[Particles]") { CHECK(Hydrogen::nucleus_Z == 1); CHECK(Tritium::nucleus_A == 3); - // Nucleus is a generic object, it has no specific properties - CHECK_THROWS(get_nucleus_Z(Code::Nucleus)); - CHECK_THROWS(get_nucleus_A(Code::Nucleus)); - CHECK_THROWS(get_mass(Code::Nucleus)); - CHECK_THROWS(get_charge(Code::Nucleus)); + CHECK(is_nucleus(get_nucleus_code(1, 1))); + CHECK(is_nucleus(get_nucleus_code(100, 100))); + CHECK(get_nucleus_code(208, 82) == Code::Lead); + CHECK_FALSE(is_nucleus(Code::Electron)); + CHECK(is_nucleus(Code::Lead)); + CHECK(get_nucleus_Z(Code::Lead) == 82); + CHECK(get_nucleus_A(Code::Lead) == 208); + + // impossible nucleus + CHECK_THROWS(get_nucleus_code(20, 40)); + + // getters + auto const testId = get_nucleus_code(40, 20); + CHECK(get_nucleus_A(testId) == 40); + CHECK(get_nucleus_Z(testId) == 20); + CHECK(is_nucleus(testId)); + CHECK(get_nucleus_mass(testId) == 20 * Proton::mass + 20 * Neutron::mass); + CHECK(get_name(testId) == "nucleus"); + CHECK(get_charge(testId) == 20 * constants::e); } } diff --git a/tests/modules/testEpos.cpp b/tests/modules/testEpos.cpp index aa2a006f29602efe6b66e841d304df29a357921c..3eab3eaafb7ddf1cfc169798dddd9cc7120d80ec 100644 --- a/tests/modules/testEpos.cpp +++ b/tests/modules/testEpos.cpp @@ -29,7 +29,7 @@ using namespace corsika; using namespace corsika::epos; -TEST_CASE("epos", "modules") { +TEST_CASE("epos", "module,process") { logging::set_level(logging::level::trace); @@ -209,7 +209,7 @@ TEST_CASE("EposInterface", "modules") { const HEPEnergyType P0 = 60_GeV; auto [stack, viewPtr] = setup::testing::setup_stack( - Code::Proton, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); + Code::Proton, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); MomentumVector plab = MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack setup::StackView& view = *viewPtr; @@ -238,7 +238,7 @@ TEST_CASE("EposInterface", "modules") { const HEPEnergyType P0 = 10_TeV; auto [stack, viewPtr] = setup::testing::setup_stack( - Code::Nucleus, 8, 4, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); + get_nucleus_code(8, 4), P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); MomentumVector plab = MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack setup::StackView& view = *viewPtr; diff --git a/tests/modules/testObservationPlane.cpp b/tests/modules/testObservationPlane.cpp index 1ed62d52453cf5c235d359e4958c2f2dbaa3a177..e350c2fb2f0f5d24a8f69c6719658e5c1d6e6391 100644 --- a/tests/modules/testObservationPlane.cpp +++ b/tests/modules/testObservationPlane.cpp @@ -41,8 +41,7 @@ TEST_CASE("ObservationPlane", "interface") { ObservationPlane has origin at 10,0,0 and a normal in x-direction */ - auto [stack, viewPtr] = - setup::testing::setup_stack(Code::NuE, 0, 0, 1_GeV, nodePtr, cs); + auto [stack, viewPtr] = setup::testing::setup_stack(Code::NuE, 1_GeV, nodePtr, cs); [[maybe_unused]] setup::StackView& view = *viewPtr; auto particle = stack->getNextParticle(); diff --git a/tests/modules/testParticleCut.cpp b/tests/modules/testParticleCut.cpp index ea3a8bbe552d874ae5d26d9841caf7b556381e5c..453764066699e3c5f4683720787083e32cc668ce 100644 --- a/tests/modules/testParticleCut.cpp +++ b/tests/modules/testParticleCut.cpp @@ -24,7 +24,7 @@ using namespace corsika; -TEST_CASE("ParticleCut", "processes") { +TEST_CASE("ParticleCut", "process,continuous,secondary") { logging::set_level(logging::level::info); @@ -123,12 +123,12 @@ TEST_CASE("ParticleCut", "processes") { proType, Ebelow, DirectionVector(rootCS, {1, 0, 0}), point0, 0_ns)); unsigned short A = 18; unsigned short Z = 8; - projectile.addSecondary(std::make_tuple(Code::Nucleus, Eabove * A, + projectile.addSecondary(std::make_tuple(get_nucleus_code(A, Z), Eabove * A, DirectionVector(rootCS, {1, 0, 0}), point0, - 0_ns, A, Z)); - projectile.addSecondary(std::make_tuple(Code::Nucleus, Ebelow * A, + 0_ns)); + projectile.addSecondary(std::make_tuple(get_nucleus_code(A, Z), Ebelow * A, DirectionVector(rootCS, {1, 0, 0}), point0, - 0_ns, A, Z)); + 0_ns)); cut.doSecondaries(view); @@ -160,12 +160,12 @@ TEST_CASE("ParticleCut", "processes") { unsigned short A = 18; unsigned short Z = 8; - projectile.addSecondary(std::make_tuple(Code::Nucleus, 4_GeV * A, + projectile.addSecondary(std::make_tuple(get_nucleus_code(A, Z), 4_GeV * A, DirectionVector(rootCS, {1, 0, 0}), point0, - 0_ns, A, Z)); - projectile.addSecondary(std::make_tuple(Code::Nucleus, 6_GeV * A, + 0_ns)); + projectile.addSecondary(std::make_tuple(get_nucleus_code(A, Z), 6_GeV * A, DirectionVector(rootCS, {1, 0, 0}), point0, - 0_ns, A, Z)); + 0_ns)); cut.doSecondaries(view); diff --git a/tests/modules/testPythia8.cpp b/tests/modules/testPythia8.cpp index f6809d4a61b4e6015e625a5c302ab8e7fd8ad713..0e449f16b6a38eaeac30b95a3475c7b302532f76 100644 --- a/tests/modules/testPythia8.cpp +++ b/tests/modules/testPythia8.cpp @@ -104,7 +104,7 @@ TEST_CASE("Pythia8Interface", "modules") { SECTION("pythia decay") { HEPEnergyType const P0 = 10_GeV; auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::PiPlus, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); + Code::PiPlus, P0, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); auto& stack = *stackPtr; auto& view = *secViewPtr; @@ -164,8 +164,7 @@ TEST_CASE("Pythia8Interface", "modules") { // this will be a p-p collision at sqrts=3.5TeV -> no problem for pythia auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Proton, 0, 0, 7_TeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::Proton, 7_TeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); auto& view = *secViewPtr; auto const particle = stackPtr->getNextParticle(); @@ -198,8 +197,7 @@ TEST_CASE("Pythia8Interface", "modules") { // this is a projectile nucleus with very little energy auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Oxygen, 0, 0, 17_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::Oxygen, 17_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); auto& view = *secViewPtr; auto particle = stackPtr->first(); @@ -215,8 +213,7 @@ TEST_CASE("Pythia8Interface", "modules") { // this is a projectile neutron with very little energy auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Neutron, 0, 0, 1_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::Neutron, 1_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); auto& view = *secViewPtr; auto particle = stackPtr->first(); @@ -240,7 +237,7 @@ TEST_CASE("Pythia8Interface", "modules") { // resonable projectile, but tool low energy auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Proton, 0, 0, 1_GeV, (setup::Environment::BaseNodeType* const)nodePtr_Fe, + Code::Proton, 1_GeV, (setup::Environment::BaseNodeType* const)nodePtr_Fe, *csPtr_Fe); auto& view = *secViewPtr; { [[maybe_unused]] auto const& dummy_StackPtr = stackPtr; } diff --git a/tests/modules/testQGSJetII.cpp b/tests/modules/testQGSJetII.cpp index 33ba73d46943e9a98dcda0ee17f0ed1ad9654594..ccad0cd7eb42fc2c0574b627fe849be4030d8b86 100644 --- a/tests/modules/testQGSJetII.cpp +++ b/tests/modules/testQGSJetII.cpp @@ -129,7 +129,7 @@ TEST_CASE("QgsjetII", "[processes]") { #include <SetupTestEnvironment.hpp> #include <SetupTestStack.hpp> -TEST_CASE("QgsjetIIInterface", "[processes]") { +TEST_CASE("QgsjetIIInterface", "interaction,processes") { logging::set_level(logging::level::info); @@ -142,8 +142,7 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { SECTION("InteractionInterface") { auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Proton, 0, 0, 110_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::Proton, 110_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); setup::StackView& view = *(secViewPtr.get()); auto particle = stackPtr->first(); auto projectile = secViewPtr->getProjectile(); @@ -155,16 +154,16 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { CHECK(length / (1_g / square(1_cm)) == Approx(93.04).margin(0.1)); - /*********************************** - It as turned out already two times (#291 and #307) that the detailed output of - QGSJetII event generation depends on the gfortran version used. This is not reliable - and cannot be tested in a unit test here. One related problem was already found (#291) - and is realted to undefined behaviour in the evaluation of functions in logical - expressions. It is not clear if #307 is the same issue. + /* ********************************** + As it turned out already two times (#291 and #307) that the detailed output of + QGSJetII event generation depends on the gfortran version used. This is not reliable + and cannot be tested in a unit test here. One related problem was already found + (#291) and is realted to undefined behaviour in the evaluation of functions in logical + expressions. It is not clear if #307 is the same issue. CHECK(view.getSize() == 14); CHECK(sumCharge(view) == 2); - ************************************/ + *********************************** */ auto const secMomSum = sumMomentum(view, projectileMomentum.getCoordinateSystem()); CHECK((secMomSum - projectileMomentum).getNorm() / projectileMomentum.getNorm() == Approx(0).margin(1e-2)); @@ -173,7 +172,7 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { SECTION("InteractionInterface Nuclei") { auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Nucleus, 60, 30, 20100_GeV, + get_nucleus_code(60, 30), 20100_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); setup::StackView& view = *(secViewPtr.get()); auto particle = stackPtr->first(); @@ -182,9 +181,9 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { corsika::qgsjetII::Interaction model; model.doInteraction(view); // this also should produce some fragments - CHECK(view.getSize() == Approx(350).margin(100)); // this is not physics validation + CHECK(view.getSize() == Approx(300).margin(100)); // this is not physics validation int countFragments = 0; - for (auto const& sec : view) { countFragments += (sec.getPID() == Code::Nucleus); } + for (auto const& sec : view) { countFragments += (is_nucleus(sec.getPID())); } CHECK(countFragments == Approx(4).margin(2)); // this is not physics validation [[maybe_unused]] const GrammageType length = model.getInteractionLength(particle); @@ -195,7 +194,7 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { SECTION("Heavy nuclei") { auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Nucleus, 1000, 1000, 1100_GeV, + get_nucleus_code(1000, 1000), 1100_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); setup::StackView& view = *(secViewPtr.get()); auto particle = stackPtr->first(); @@ -215,7 +214,7 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { SECTION("Allowed Particles") { { // electron auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Electron, 0, 0, 100_GeV, (setup::Environment::BaseNodeType* const)nodePtr, + Code::Electron, 100_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); auto particle = stackPtr->first(); @@ -225,8 +224,7 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { } { // pi0 is internally converted into pi+/pi- auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Pi0, 0, 0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::Pi0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] auto particle = stackPtr->first(); corsika::qgsjetII::Interaction model; @@ -235,8 +233,7 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { } { // rho0 is internally converted into pi-/pi+ auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Rho0, 0, 0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::Rho0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] auto particle = stackPtr->first(); corsika::qgsjetII::Interaction model; @@ -245,7 +242,7 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { } { // Lambda is internally converted into neutron auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Lambda0, 0, 0, 100_GeV, (setup::Environment::BaseNodeType* const)nodePtr, + Code::Lambda0, 100_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] auto particle = stackPtr->first(); @@ -255,8 +252,8 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { } { // AntiLambda is internally converted into anti neutron auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Lambda0Bar, 0, 0, 1000_GeV, - (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); + Code::Lambda0Bar, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, + *csPtr); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] auto particle = stackPtr->first(); corsika::qgsjetII::Interaction model; diff --git a/tests/modules/testSibyll.cpp b/tests/modules/testSibyll.cpp index f544204c238709dc9c1464694f87a7556f63a42b..68e69fe57c2a8237efd9e6c5bd1f7a1853478d88 100644 --- a/tests/modules/testSibyll.cpp +++ b/tests/modules/testSibyll.cpp @@ -150,7 +150,7 @@ TEST_CASE("SibyllInterface", "modules") { const HEPEnergyType P0 = 60_GeV; auto [stack, viewPtr] = setup::testing::setup_stack( - Code::Proton, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); + Code::Proton, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); MomentumVector plab = MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack setup::StackView& view = *viewPtr; @@ -237,7 +237,7 @@ TEST_CASE("SibyllInterface", "modules") { const HEPEnergyType P0 = 5_GeV; auto [stack, viewPtr] = setup::testing::setup_stack( - Code::Proton, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); + Code::Proton, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); MomentumVector plab = MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack setup::StackView& view = *viewPtr; @@ -256,7 +256,7 @@ TEST_CASE("SibyllInterface", "modules") { const HEPEnergyType P0 = 1000_EeV; auto [stack, viewPtr] = setup::testing::setup_stack( - Code::Proton, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); + Code::Proton, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); { [[maybe_unused]] auto const& dummy1 = stack; } MomentumVector plab = MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack @@ -272,7 +272,7 @@ TEST_CASE("SibyllInterface", "modules") { auto const& cs1 = *csPtr1; const HEPEnergyType P0 = 150_GeV; auto [stack, viewPtr] = setup::testing::setup_stack( - Code::Electron, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr1, cs1); + Code::Electron, P0, (setup::Environment::BaseNodeType* const)nodePtr1, cs1); { [[maybe_unused]] auto const& dummy1 = stack; } MomentumVector plab = MomentumVector( cs1, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack @@ -285,7 +285,7 @@ TEST_CASE("SibyllInterface", "modules") { SECTION("NuclearInteractionInterface") { auto [stack, viewPtr] = - setup::testing::setup_stack(Code::Nucleus, 8, 4, 900_GeV, + setup::testing::setup_stack(get_nucleus_code(8, 4), 900_GeV, (setup::Environment::BaseNodeType* const)nodePtr, cs); setup::StackView& view = *viewPtr; auto particle = stack->first(); @@ -306,9 +306,8 @@ TEST_CASE("SibyllInterface", "modules") { SECTION("DecayInterface") { - auto [stackPtr, viewPtr] = - setup::testing::setup_stack(Code::Lambda0, 0, 0, 10_GeV, - (setup::Environment::BaseNodeType* const)nodePtr, cs); + auto [stackPtr, viewPtr] = setup::testing::setup_stack( + Code::Lambda0, 10_GeV, (setup::Environment::BaseNodeType* const)nodePtr, cs); setup::StackView& view = *viewPtr; auto& stack = *stackPtr; auto particle = stack.first(); @@ -327,7 +326,7 @@ TEST_CASE("SibyllInterface", "modules") { SECTION("DecayInterface - decay not handled") { // sibyll does not know the higgs for example auto [stackPtr, viewPtr] = setup::testing::setup_stack( - Code::H0, 0, 0, 10_GeV, (setup::Environment::BaseNodeType* const)nodePtr, cs); + Code::H0, 10_GeV, (setup::Environment::BaseNodeType* const)nodePtr, cs); setup::StackView& view = *viewPtr; auto& stack = *stackPtr; auto particle = stack.first(); diff --git a/tests/modules/testStackInspector.cpp b/tests/modules/testStackInspector.cpp index 9464e54a55508bf5948ff4650a834f5a04bd34de..ec2157e3e79cff3a1680692b482bf6f5eac159f3 100644 --- a/tests/modules/testStackInspector.cpp +++ b/tests/modules/testStackInspector.cpp @@ -38,9 +38,9 @@ TEST_CASE("StackInspector", "modules") { stack.addParticle(std::make_tuple(Code::Electron, MomentumVector(rootCS, {0_GeV, 0_GeV, -1_GeV}), Point(rootCS, {0_m, 0_m, 10_km}), 0_ns)); - stack.addParticle(std::make_tuple(Code::Nucleus, + stack.addParticle(std::make_tuple(get_nucleus_code(16, 8), MomentumVector(rootCS, {0_GeV, 0_GeV, -1_GeV}), - Point(rootCS, {0_m, 0_m, 10_km}), 0_ns, 16, 8)); + Point(rootCS, {0_m, 0_m, 10_km}), 0_ns)); SECTION("interface") { diff --git a/tests/modules/testTracking.cpp b/tests/modules/testTracking.cpp index 243cbffa7df9bc47b2486b048be356381587d6db..d1d967d6f38e58a9b5cff769589939bf0042ed48 100644 --- a/tests/modules/testTracking.cpp +++ b/tests/modules/testTracking.cpp @@ -167,7 +167,7 @@ TEMPLATE_TEST_CASE("Tracking", "tracking", tracking_leapfrog_curved::Tracking, targetPtr->addChild(std::move(target_2_behind)); targetPtr->addChild(std::move(target_2_partly_behind)); - auto [stack, viewPtr] = setup::testing::setup_stack(PID, 0, 0, P0, targetPtr, cs); + auto [stack, viewPtr] = setup::testing::setup_stack(PID, P0, targetPtr, cs); { [[maybe_unused]] auto& viewPtr_dum = viewPtr; } auto particle = stack->first(); // Note: momentum in X-direction @@ -257,7 +257,7 @@ TEST_CASE("TrackingLeapFrogCurved") { tracking_leapfrog_curved::Tracking tracking; Point const center(cs, {0_m, 0_m, 0_m}); - auto [stack, viewPtr] = setup::testing::setup_stack(PID, 0, 0, P0, worldPtr, cs); + auto [stack, viewPtr] = setup::testing::setup_stack(PID, P0, worldPtr, cs); { [[maybe_unused]] auto& viewPtr_dum = viewPtr; } auto particle = stack->first(); // Note: momentum in X-direction @@ -291,7 +291,7 @@ TEST_CASE("TrackingLeapFrogCurved") { auto* targetPtr = target.get(); worldPtr->addChild(std::move(target)); - auto [stack, viewPtr] = setup::testing::setup_stack(PID, 0, 0, P0, targetPtr, cs); + auto [stack, viewPtr] = setup::testing::setup_stack(PID, P0, targetPtr, cs); { [[maybe_unused]] auto& viewPtr_dum = viewPtr; } // prevent warning auto particle = stack->first(); // Note: momentum in X-direction @@ -323,8 +323,7 @@ TEMPLATE_TEST_CASE("TrackingFail", "doesntwork", tracking_leapfrog_curved::Track TestType tracking; Point const center(cs, {0_m, 0_m, 0_m}); - auto [stack, viewPtr] = - setup::testing::setup_stack(Code::Proton, 0, 0, P0, worldPtr, cs); + auto [stack, viewPtr] = setup::testing::setup_stack(Code::Proton, P0, worldPtr, cs); { [[maybe_unused]] auto& viewPtr_dum = viewPtr; } auto particle = stack->first(); NonExistingDummyObject const dummy; @@ -376,7 +375,7 @@ TEMPLATE_TEST_CASE("TrackingPlane", "plane", tracking_leapfrog_curved::Tracking, TestType tracking; Point const center(cs, {0_m, 0_m, 0_m}); - auto [stack, viewPtr] = setup::testing::setup_stack(PID, 0, 0, P0, worldPtr, cs); + auto [stack, viewPtr] = setup::testing::setup_stack(PID, P0, worldPtr, cs); { [[maybe_unused]] auto& viewPtr_dum = viewPtr; } auto particle = stack->first(); // Note: momentum in X-direction diff --git a/tests/modules/testUrQMD.cpp b/tests/modules/testUrQMD.cpp index b5c207a59e7b48487897404cdfee93a376aa1049..89bde00d2e1772b943f933311ce3f258e438502b 100644 --- a/tests/modules/testUrQMD.cpp +++ b/tests/modules/testUrQMD.cpp @@ -82,7 +82,7 @@ TEST_CASE("UrQMD") { Code::K0Bar, Code::K0Long}; for (auto code : validProjectileCodes) { - auto [stack, view] = setup::testing::setup_stack(code, 0, 0, 100_GeV, nodePtr, cs); + auto [stack, view] = setup::testing::setup_stack(code, 100_GeV, nodePtr, cs); CHECK(stack->getEntries() == 1); CHECK(view->getEntries() == 0); @@ -96,8 +96,7 @@ TEST_CASE("UrQMD") { auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Argon); auto const& cs = *csPtr; { [[maybe_unused]] auto const& env_dummy = env; } - auto [stack, view] = - setup::testing::setup_stack(Code::Proton, 0, 0, 100_GeV, nodePtr, cs); + auto [stack, view] = setup::testing::setup_stack(Code::Proton, 100_GeV, nodePtr, cs); [[maybe_unused]] setup::StackView& viewRef = *(view.get()); CHECK(urqmd.getInteractionLength(stack->getNextParticle()) / 1_g * square(1_cm) == Approx(105).margin(5)); @@ -107,8 +106,7 @@ TEST_CASE("UrQMD") { auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Omega); auto const& cs = *csPtr; { [[maybe_unused]] auto const& env_dummy = env; } - auto [stack, view] = - setup::testing::setup_stack(Code::Neutron, 0, 0, 100_GeV, nodePtr, cs); + auto [stack, view] = setup::testing::setup_stack(Code::Neutron, 100_GeV, nodePtr, cs); [[maybe_unused]] setup::StackView& viewRef = *(view.get()); CHECK_THROWS(urqmd.getInteractionLength(stack->getNextParticle())); } @@ -120,7 +118,7 @@ TEST_CASE("UrQMD") { unsigned short constexpr A = 14, Z = 7; auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::Nucleus, A, Z, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, + get_nucleus_code(A, Z), 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); [[maybe_unused]] setup::StackView& viewRef = *(secViewPtr.get()); CHECK(stackPtr->getEntries() == 1); @@ -145,8 +143,7 @@ TEST_CASE("UrQMD") { [[maybe_unused]] auto const& node_dummy = nodePtr; // against warnings auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::PiPlus, 0, 0, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::PiPlus, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); CHECK(stackPtr->getEntries() == 1); CHECK(secViewPtr->getEntries() == 0); @@ -172,8 +169,7 @@ TEST_CASE("UrQMD") { [[maybe_unused]] auto const& node_dummy = nodePtr; // against warnings auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::PiPlus, 0, 0, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::PiPlus, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); [[maybe_unused]] auto particle = stackPtr->first(); CHECK_THROWS(urqmd.doInteraction(*secViewPtr)); // Code::Proton not a valid target } @@ -184,8 +180,7 @@ TEST_CASE("UrQMD") { [[maybe_unused]] auto const& node_dummy = nodePtr; // against warnings auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::PiPlus, 0, 0, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::PiPlus, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); CHECK(stackPtr->getEntries() == 1); CHECK(secViewPtr->getEntries() == 0); @@ -211,8 +206,7 @@ TEST_CASE("UrQMD") { [[maybe_unused]] auto const& node_dummy = nodePtr; // against warnings auto [stackPtr, secViewPtr] = setup::testing::setup_stack( - Code::K0Long, 0, 0, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, - *csPtr); + Code::K0Long, 40_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); CHECK(stackPtr->getEntries() == 1); CHECK(secViewPtr->getEntries() == 0); diff --git a/tests/stack/CMakeLists.txt b/tests/stack/CMakeLists.txt index 58aa2b3025ea50c492d7cba79e6d3f9749277e59..1314fd435a88474ce1df7cc8bf54cc918f30e5e9 100644 --- a/tests/stack/CMakeLists.txt +++ b/tests/stack/CMakeLists.txt @@ -1,12 +1,10 @@ set (test_stack_sources TestMain.cpp testHistoryStack.cpp -# testHistoryView.cpp testGeometryNodeStackExtension.cpp testWeightStackExtension.cpp testDummyStack.cpp testVectorStack.cpp - testNuclearStackExtension.cpp ) CORSIKA_ADD_TEST (testStack SOURCES ${test_stack_sources}) diff --git a/tests/stack/testNuclearStackExtension.cpp b/tests/stack/testNuclearStackExtension.cpp deleted file mode 100644 index 98727de42d47a31426877c35224782b675077107..0000000000000000000000000000000000000000 --- a/tests/stack/testNuclearStackExtension.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * (c) Copyright 2018 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. - */ - -#include <corsika/framework/geometry/RootCoordinateSystem.hpp> -#include <corsika/stack/NuclearStackExtension.hpp> -#include <corsika/framework/core/PhysicalUnits.hpp> - -using namespace corsika; - -#include <catch2/catch.hpp> - -#include <iostream> -using namespace std; - -TEST_CASE("NuclearStackExtension", "stack") { - - logging::set_level(logging::level::info); - - CoordinateSystemPtr const& dummyCS = get_root_CoordinateSystem(); - - SECTION("write non nucleus") { - nuclear_stack::NuclearStackExtension<VectorStack, - nuclear_stack::ExtendedParticleInterfaceType> - s; - s.addParticle( - std::make_tuple(Code::Electron, 1.5_GeV, DirectionVector(dummyCS, {0, 1, 0}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)); - CHECK(s.getEntries() == 1); - } - - SECTION("write nucleus") { - - nuclear_stack::NuclearStackExtension<VectorStack, - nuclear_stack::ExtendedParticleInterfaceType> - s; - s.addParticle(std::make_tuple( - Code::Nucleus, MomentumVector(dummyCS, {10_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 10)); - CHECK(s.getEntries() == 1); - } - - SECTION("write invalid nucleus") { - nuclear_stack::ParticleDataStack s; - CHECK_THROWS(s.addParticle( - std::make_tuple(Code::Nucleus, 1.5_GeV, DirectionVector(dummyCS, {1, 0, 0}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 0, 0))); - } - - SECTION("read non nucleus") { - nuclear_stack::ParticleDataStack s; - s.addParticle( - std::make_tuple(Code::Electron, MomentumVector(dummyCS, {0_GeV, 10_GeV, 0_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)); - const auto pout = s.getNextParticle(); - CHECK(pout.getPID() == Code::Electron); - CHECK(pout.getEnergy() == sqrt(square(10_GeV) + square(Electron::mass))); - CHECK(pout.getTime() == 100_s); - } - - SECTION("read nucleus") { - auto const A = 10; - auto const Z = 9; - nuclear_stack::ParticleDataStack s; - s.addParticle( - std::make_tuple(Code::Nucleus, 1.5_GeV, DirectionVector(dummyCS, {1, 0, 0}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, A, Z)); - const auto pout = s.getNextParticle(); - CHECK(pout.getPID() == Code::Nucleus); - CHECK(pout.getEnergy() == 1.5_GeV + pout.getMass()); - CHECK(pout.getMass() == get_nucleus_mass(A, Z)); - CHECK(pout.getKineticEnergy() == 1.5_GeV); - CHECK(pout.getTime() == 100_s); - CHECK(pout.getNuclearA() == 10); - CHECK(pout.getNuclearZ() == 9); - - // -> set to rest - auto pout_mod = s.begin(); - pout_mod.setMomentum(MomentumVector{dummyCS, {0_GeV, 0_GeV, 0_GeV}}); - CHECK(pout_mod.getKineticEnergy() / 1_GeV == Approx(0)); - } - - SECTION("read invalid nucleus") { - nuclear_stack::ParticleDataStack s; - s.addParticle( - std::make_tuple(Code::Electron, MomentumVector(dummyCS, {1_GeV, 1_GeV, 10_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)); - const auto pout = s.getNextParticle(); - CHECK_THROWS(pout.getNuclearA()); - CHECK_THROWS(pout.getNuclearZ()); - } - - SECTION("stack fill and cleanup") { - - nuclear_stack::ParticleDataStack s; - // add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2! - for (int i = 0; i < 99; ++i) { - if ((i + 1) % 10 == 0) { - s.addParticle(std::make_tuple( - Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, i, i / 2)); - } else { - s.addParticle(std::make_tuple( - Code::Electron, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)); - } - } - - CHECK(s.getEntries() == 99); - for (int i = 0; i < 99; ++i) s.getNextParticle().erase(); - CHECK(s.getEntries() == 0); - } - - SECTION("stack operations") { - - nuclear_stack::ParticleDataStack s; - // add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2! - // i=9, 19, 29, etc. are nuclei - for (int i = 0; i < 99; ++i) { - if ((i + 1) % 10 == 0) { - unsigned int const A = i; - unsigned int const Z = i / 2; - s.addParticle(std::make_tuple( - - Code::Nucleus, i * 15_GeV - get_nucleus_mass(A, Z), - DirectionVector(dummyCS, {0, 0, 1}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, A, Z)); - } else { - s.addParticle(std::make_tuple(Code::Electron, i * 1.5_GeV - Electron::mass, - DirectionVector(dummyCS, {1, 0, 0}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), - 100_s)); - } - } - - // copy - { - s.copy(s.begin() + 9, s.begin() + 10); // nuclei to non-nuclei - const auto& p9 = s.cbegin() + 9; - const auto& p10 = s.cbegin() + 10; - - CHECK(p9.getPID() == Code::Nucleus); - CHECK(p9.getEnergy() == 9 * 15_GeV); - CHECK(p9.getTime() == 100_s); - CHECK(p9.getNuclearA() == 9); - CHECK(p9.getNuclearZ() == 9 / 2); - - CHECK(p10.getPID() == Code::Nucleus); - CHECK(p10.getEnergy() == 9 * 15_GeV); - CHECK(p10.getTime() == 100_s); - CHECK(p10.getNuclearA() == 9); - CHECK(p10.getNuclearZ() == 9 / 2); - } - - // copy - { - s.copy(s.begin() + 93, s.begin() + 9); // non-nuclei to nuclei - const auto& p93 = s.cbegin() + 93; - const auto& p9 = s.cbegin() + 9; - - CHECK(p9.getPID() == Code::Electron); - CHECK(p9.getEnergy() == 93 * 1.5_GeV); - CHECK(p9.getTime() == 100_s); - - CHECK(p93.getPID() == Code::Electron); - CHECK(p93.getEnergy() == 93 * 1.5_GeV); - CHECK(p93.getTime() == 100_s); - } - - // copy - { - s.copy(s.begin() + 89, s.begin() + 79); // nuclei to nuclei - const auto& p89 = s.cbegin() + 89; - const auto& p79 = s.cbegin() + 79; - - CHECK(p89.getPID() == Code::Nucleus); - CHECK(p89.getEnergy() == 89 * 15_GeV); - CHECK(p89.getTime() == 100_s); - - CHECK(p79.getPID() == Code::Nucleus); - CHECK(p79.getEnergy() == 89 * 15_GeV); - CHECK(p79.getTime() == 100_s); - } - - // invalid copy - { CHECK_THROWS(s.copy(s.begin(), s.end() + 1000)); } - - // swap - { - s.swap(s.begin() + 11, s.begin() + 10); - const auto& p11 = s.cbegin() + 11; // now: nucleus - const auto& p10 = s.cbegin() + 10; // now: electron - - CHECK(p11.getPID() == Code::Nucleus); - CHECK(p11.getEnergy() == 9 * 15_GeV); - CHECK(p11.getTime() == 100_s); - CHECK(p11.getNuclearA() == 9); - CHECK(p11.getNuclearZ() == 9 / 2); - - CHECK(p10.getPID() == Code::Electron); - CHECK(p10.getEnergy() == 11 * 1.5_GeV); - CHECK(p10.getTime() == 100_s); - } - - // swap two nuclei - { - s.swap(s.begin() + 29, s.begin() + 59); - const auto& p29 = s.cbegin() + 29; - const auto& p59 = s.cbegin() + 59; - - CHECK(p29.getPID() == Code::Nucleus); - CHECK(p29.getEnergy() == 59 * 15_GeV); - CHECK(p29.getTime() == 100_s); - CHECK(p29.getNuclearA() == 59); - CHECK(p29.getNuclearZ() == 59 / 2); - - CHECK(p59.getPID() == Code::Nucleus); - CHECK(p59.getEnergy() == 29 * 15_GeV); - CHECK(p59.getTime() == 100_s); - CHECK(p59.getNuclearA() == 29); - CHECK(p59.getNuclearZ() == 29 / 2); - } - - for (int i = 0; i < 99; ++i) s.last().erase(); - CHECK(s.getEntries() == 0); - } - - SECTION("not allowed") { - - nuclear_stack::NuclearStackExtension<VectorStack, - nuclear_stack::ExtendedParticleInterfaceType> - s; - - // not valid, no A,Z (implicit A=Z=0): - CHECK_THROWS(s.addParticle( - std::make_tuple(Code::Nucleus, 100_GeV, DirectionVector(dummyCS, {1, 0, 0}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s))); - CHECK_THROWS(s.addParticle( - std::make_tuple(Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s))); - - // not valid, non-Code::Nuclei with A and Z - CHECK_THROWS(s.addParticle(std::make_tuple( - Code::Oxygen, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 20, 10))); - - // not valid, non-Code::Nuclei with A and Z - CHECK_THROWS(s.addParticle(std::make_tuple( - Code::Oxygen, 100_GeV, DirectionVector(dummyCS, {0, 0, 1}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 20, 10))); - - // valid, non-Nucleus with implicit A=Z=0 - s.addParticle( - std::make_tuple(Code::Proton, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)); - - // valid, for further use - auto particle = s.addParticle( - std::make_tuple(Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 5)); - - // not valid, Oxygen, but A and Z - CHECK_THROWS(particle.addSecondary(std::make_tuple( - Code::Oxygen, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 20, 10))); - - // not valid, Nucleus, no A, Z - CHECK_THROWS(particle.addSecondary( - std::make_tuple(Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s))); - - // not valid, Nucleus, no A, Z, and Energy - CHECK_THROWS(particle.addSecondary( - std::make_tuple(Code::Nucleus, 100_GeV, DirectionVector(dummyCS, {1, 0, 0}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s))); - - // add a another nucleus, so there are two now - s.addParticle( - std::make_tuple(Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 9)); - - // not valid, since end() is not a valid entry - CHECK_THROWS(s.swap(s.begin(), s.end())); - } -}