diff --git a/corsika/detail/modules/sibyll/Decay.inl b/corsika/detail/modules/sibyll/Decay.inl index e1e3978b29932ecbe2c42cae5d1513205e69d899..eff18c5408e16e3ffa629ad2591cf82f28a6ddd6 100644 --- a/corsika/detail/modules/sibyll/Decay.inl +++ b/corsika/detail/modules/sibyll/Decay.inl @@ -90,7 +90,7 @@ namespace corsika::sibyll { const double gamma = E / m; - const TimeType t0 = corsika::GetLifetime(vP.GetPID()); + const TimeType t0 = corsika::lifetime(vP.GetPID()); auto const lifetime = gamma * t0; const auto mkin = @@ -123,7 +123,7 @@ namespace corsika::sibyll { vP.GetMomentum(), // setting particle mass with Corsika values, may be inconsistent // with sibyll internal values - corsika::GetMass(pCode)); + corsika::mass(pCode)); // remember position Point const decayPoint = vP.GetPosition(); TimeType const t0 = vP.GetTime(); diff --git a/corsika/detail/modules/sibyll/Interaction.inl b/corsika/detail/modules/sibyll/Interaction.inl index 1aa26e4159e763b5d7aa81fcf5b69c7d5d68ad9f..cbd8b9f3a2826aed6f76b91b36bea8edc8e32073 100644 --- a/corsika/detail/modules/sibyll/Interaction.inl +++ b/corsika/detail/modules/sibyll/Interaction.inl @@ -87,13 +87,13 @@ namespace corsika::sibyll { "Interaction: GetCrossSection: CoM energy outside range for Sibyll!"); } const double dEcm = CoMenergy / 1_GeV; - if (corsika::IsNucleus(TargetId)) { - const int iTarget = corsika::GetNucleusA(TargetId); + if (corsika::is_nucleus(TargetId)) { + const int iTarget = corsika::nucleus_A(TargetId); if (iTarget > maxTargetMassNumber_ || iTarget == 0) throw std::runtime_error( "Sibyll target outside range. Only nuclei with A<18 are allowed."); sib_sigma_hnuc_(iBeam, iTarget, dEcm, sigProd, dummy, sigEla); - } else if (TargetId == corsika::Proton::GetCode()) { + } else if (TargetId == corsika::Code::Proton) { sib_sigma_hp_(iBeam, dEcm, dum1, sigEla, sigProd, dumdif, dum3, dum4); } else { // no interaction in sibyll possible, return infinite cross section? or throw? @@ -186,7 +186,7 @@ namespace corsika::sibyll { << "DoInteraction: " << corsikaBeamId << " interaction? " << corsika::sibyll::CanInteract(corsikaBeamId) << std::endl; - if (corsika::IsNucleus(corsikaBeamId)) { + if (corsika::is_nucleus(corsikaBeamId)) { // nuclei handled by different process, this should not happen throw std::runtime_error("Nuclear projectile are not handled by SIBYLL!"); } @@ -276,8 +276,8 @@ namespace corsika::sibyll { allowed air in atmosphere also contains some Argon. */ int targetSibCode = -1; - if (IsNucleus(targetCode)) targetSibCode = GetNucleusA(targetCode); - if (targetCode == corsika::Proton::GetCode()) targetSibCode = 1; + if (is_nucleus(targetCode)) targetSibCode = nucleus_A(targetCode); + if (targetCode == corsika::Code::Proton) targetSibCode = 1; std::cout << "Interaction: sibyll code: " << targetSibCode << std::endl; if (targetSibCode > maxTargetMassNumber_ || targetSibCode < 1) throw std::runtime_error( diff --git a/corsika/detail/modules/sibyll/NuclearInteraction.inl b/corsika/detail/modules/sibyll/NuclearInteraction.inl index 0cd03c264c90531829eeb1d30597407346b12a57..d4399233c023f31f021f46361031d3b5f3aa1a36 100644 --- a/corsika/detail/modules/sibyll/NuclearInteraction.inl +++ b/corsika/detail/modules/sibyll/NuclearInteraction.inl @@ -50,7 +50,7 @@ namespace corsika::sibyll { for (unsigned int i = 0; i < GetNEnergyBins(); ++i) { std::cout << " " << i << " "; for (auto& n : pNuclei) { - auto const j = GetNucleusA(n); + auto const j = corsika::nucleus_A(n); std::cout << " " << std::setprecision(5) << std::setw(8) << cnucsignuc_.sigma[j - 1][k][i]; } @@ -85,7 +85,7 @@ namespace corsika::sibyll { for (auto& ptarg : allElementsInUniverse) { ++k; std::cout << "NuclearInteraction: init target component: " << ptarg << std::endl; - const int ib = GetNucleusA(ptarg); + const int ib = corsika::nucleus_A(ptarg); if (!hadronicInteraction_.IsValidTarget(ptarg)) { std::cout << "NuclearInteraction::InitializeNuclearCrossSections: target nucleus? id=" @@ -217,7 +217,7 @@ namespace corsika::sibyll { if (corsikaBeamId != corsika::Code::Nucleus) { // check if target-style nucleus (enum), these are not allowed as projectile - if (corsika::IsNucleus(corsikaBeamId)) + if (corsika::is_nucleus(corsikaBeamId)) throw std::runtime_error( "NuclearInteraction: GetInteractionLength: Wrong nucleus type. Nuclear " "projectiles should use NuclearStackExtension!"); @@ -326,9 +326,7 @@ namespace corsika::sibyll { "NuclearInteraction: DoInteraction: Wrong nucleus type. Nuclear projectiles " "should use NuclearStackExtension!"); - auto const ProjMass = - vP.GetNuclearZ() * corsika::Proton::GetMass() + - (vP.GetNuclearA() - vP.GetNuclearZ()) * corsika::Neutron::GetMass(); + auto const ProjMass = corsika::nucleus_mass(vP.GetNuclearA(), vP.GetNuclearZ()); std::cout << "NuclearInteraction: projectile mass: " << ProjMass / 1_GeV << std::endl; count_++; @@ -414,7 +412,7 @@ namespace corsika::sibyll { // sample target nucleon number // // proton stand-in for nucleon - const auto beamId = corsika::Proton::GetCode(); + const auto beamId = corsika::Code::Proton; auto const* const currentNode = vP.GetNode(); const auto& mediumComposition = currentNode->GetModelProperties().GetNuclearComposition(); @@ -447,8 +445,8 @@ namespace corsika::sibyll { allowed air in atmosphere also contains some Argon. */ int kATarget = -1; - if (IsNucleus(targetCode)) kATarget = GetNucleusA(targetCode); - if (targetCode == corsika::Proton::GetCode()) kATarget = 1; + if (corsika::is_nucleus(targetCode)) kATarget = corsika::nucleus_A(targetCode); + else if (targetCode == corsika::Code::Proton) kATarget = 1; std::cout << "NuclearInteraction: nuclib target code: " << kATarget << std::endl; if (!hadronicInteraction_.IsValidTarget(targetCode)) throw std::runtime_error("target outside range. "); @@ -459,7 +457,7 @@ namespace corsika::sibyll { << std::endl; // get nucleon-nucleon cross section // (needed to determine number of nucleon-nucleon scatterings) - const auto protonId = corsika::Proton::GetCode(); + const auto protonId = corsika::Code::Proton; const auto [prodCrossSection, elaCrossSection] = hadronicInteraction_.GetCrossSection(protonId, protonId, EcmNN); const double sigProd = prodCrossSection / 1_mb; @@ -519,10 +517,7 @@ namespace corsika::sibyll { else specCode = corsika::Code::Nucleus; - // TODO: mass of nuclei? - const HEPMassType mass = - corsika::Proton::GetMass() * nuclZ + - (nuclA - nuclZ) * corsika::Neutron::GetMass(); // this neglects binding energy + const HEPMassType mass = corsika::nucleus_mass(nuclA, nuclZ); std::cout << "NuclearInteraction: adding fragment: " << specCode << std::endl; std::cout << "NuclearInteraction: A,Z: " << nuclA << "," << nuclZ << std::endl; @@ -565,7 +560,7 @@ namespace corsika::sibyll { // CORSIKA 7 way // elastic nucleons inherit momentum from original projectile // neglecting momentum transfer in interaction - const double mass_ratio = corsika::GetMass(elaNucCode) / ProjMass; + const double mass_ratio = corsika::mass(elaNucCode) / ProjMass; auto const Plab = PprojLab * mass_ratio; vP.AddSecondary(std::tuple<corsika::Code, si::HEPEnergyType, @@ -578,7 +573,7 @@ namespace corsika::sibyll { std::cout << "calculate inelastic nucleon-nucleon interactions.." << std::endl; for (int j = 0; j < nInelNucleons; ++j) { // TODO: sample neutron or proton - auto pCode = corsika::Proton::GetCode(); + auto pCode = corsika::Code::Proton; // temporarily add to stack, will be removed after interaction in DoInteraction std::cout << "inelastic interaction no. " << j << std::endl; auto inelasticNucleon = vP.AddSecondary( diff --git a/corsika/media/NuclearComposition.hpp b/corsika/media/NuclearComposition.hpp index 94eef28088dad629805e71e4e4723e963a90d7c2..f7f4bd5a25391901ff59846afdfbe67798ce6763 100644 --- a/corsika/media/NuclearComposition.hpp +++ b/corsika/media/NuclearComposition.hpp @@ -72,10 +72,10 @@ namespace corsika { , fAvgMassNumber(std::inner_product( pComponents.cbegin(), pComponents.cend(), pFractions.cbegin(), 0., std::plus<double>(), [](auto const compID, auto const fraction) -> double { - if (IsNucleus(compID)) { - return GetNucleusA(compID) * fraction; + if (is_nucleus(compID)) { + return nucleus_A(compID) * fraction; } else { - return GetMass(compID) / ConvertSIToHEP(constants::u) * fraction; + return mass(compID) / ConvertSIToHEP(constants::u) * fraction; } })) { assert(pComponents.size() == pFractions.size()); diff --git a/corsika/modules/sibyll/Interaction.hpp b/corsika/modules/sibyll/Interaction.hpp index 387d3e7f2666673b96cfa0d94b5f835545656da6..8f0869e51e47849a644af56248bb734a2243951d 100644 --- a/corsika/modules/sibyll/Interaction.hpp +++ b/corsika/modules/sibyll/Interaction.hpp @@ -46,8 +46,7 @@ namespace corsika::sibyll { HEPEnergyType GetMinEnergyCoM() const { return minEnergyCoM_; } HEPEnergyType GetMaxEnergyCoM() const { return maxEnergyCoM_; } bool IsValidTarget(corsika::Code TargetId) const { - return (corsika::GetNucleusA(TargetId) < maxTargetMassNumber_) && - corsika::IsNucleus(TargetId); + return corsika::is_nucleus(TargetId) && (corsika::nucleus_A(TargetId) < maxTargetMassNumber_); } std::tuple<CrossSectionType, CrossSectionType> GetCrossSection( diff --git a/corsika/stack/NuclearStackExtension.hpp b/corsika/stack/NuclearStackExtension.hpp index ac433e4de5724fe94aa83b4ea9284cb1c39be787..c4f8274233ea273caf75e2410a74148534fea267 100644 --- a/corsika/stack/NuclearStackExtension.hpp +++ b/corsika/stack/NuclearStackExtension.hpp @@ -23,372 +23,342 @@ namespace corsika { -/** - * @namespace nuclear_extension - * - * Add A and Z data to existing stack (currently SuperStupidStack) of particle - * properties. This is done via inheritance, not via CombinedStack since the nuclear - * data is stored ONLY when needed (for nuclei) and not for all particles. Thus, this is - * a new, derived Stack object. - * - * Only for Code::Nucleus particles A and Z are stored, not for all - * normal elementary particles. - * - * Thus in your code, make sure to always check <code> - * particle.GetPID()==Code::Nucleus </code> before attempting to - * read any nuclear information. - * - * - */ - - -/** - * @class NuclearParticleInterface - * - * Define ParticleInterface for NuclearStackExtension Stack derived from - * ParticleInterface of Inner stack class - */ -template < template <typename> class InnerParticleInterface, typename StackIteratorInterface> -struct NuclearParticleInterface : public InnerParticleInterface<StackIteratorInterface> { - - typedef InnerParticleInterface<StackIteratorInterface> super_type; - - - -public: - - - typedef std::tuple< - corsika::Code, corsika::units::si::HEPEnergyType, - momentum_type, corsika::Point, - corsika::units::si::TimeType> particle_data_type; - - typedef std::tuple< - corsika::Code, corsika::units::si::HEPEnergyType, - momentum_type, corsika::Point, - corsika::units::si::TimeType, - unsigned short, unsigned short> altenative_particle_data_type; - - - typedef corsika::Vector<corsika::units::si::hepmomentum_d> momentum_type; - - void setParticleData(particle_data_type const& v) { - - if (std::get<0>(v) == corsika::Code::Nucleus) { - std::ostringstream err; - err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; - throw std::runtime_error(err.str()); - } - - super_type::setParticleData(v); - setNucleusRef(-1); // this is not a nucleus - } - - void setParticleData( altenative_particle_data_type const& v) - { - const unsigned short A = std::get<5>(v); - const unsigned short Z = std::get<6>(v); - if (std::get<0>(v) != corsika::Code::Nucleus || A == 0 || Z == 0) { - std::ostringstream err; - err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; - throw std::runtime_error(err.str()); - } - setNucleusRef(super_type::GetStackData().getNucleusNextRef()); // store this nucleus data ref - setNuclearA(A); - setNuclearZ(Z); - super_type::setParticleData(particle_data_type{std::get<0>(v), std::get<1>(v), - std::get<2>(v), std::get<3>(v), std::get<4>(v)}); - } - - void setParticleData( super_type& p, particle_data_type const& v) - { - if (std::get<0>(v) == corsika::Code::Nucleus) { - std::ostringstream err; - err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; - throw std::runtime_error(err.str()); - } - - super_type::setParticleData(p, particle_data_type{std::get<0>(v), std::get<1>(v), - std::get<2>(v), std::get<3>(v), std::get<4>(v)}); - - setNucleusRef(-1); // this is not a nucleus - } - - void setParticleData( super_type& p, altenative_particle_data_type const& v) { - - const unsigned short A = std::get<5>(v); - const unsigned short Z = std::get<6>(v); - - if (std::get<0>(v) != corsika::Code::Nucleus || A == 0 || Z == 0) { - std::ostringstream err; - err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; - throw std::runtime_error(err.str()); - } - - setNucleusRef(super_type::GetStackData().getNucleusNextRef()); // store this nucleus data ref - setNuclearA(A); - setNuclearZ(Z); - super_type::setParticleData(p, particle_data_type{std::get<0>(v), std::get<1>(v), - std::get<2>(v), std::get<3>(v), - std::get<4>(v)}); - } - - std::string as_string() const { - return fmt::format( - "{}, nuc({})", super_type::as_string(), - (isNucleus() ? fmt::format("A={}, Z={}", getNuclearA(), getNuclearZ()) - : "n/a")); - } - - /** - * @name individual setters - * @{ - */ - void setNuclearA(const unsigned short vA) { - super_type::GetStackData().setNuclearA(super_type::GetIndex(), vA); - } - void setNuclearZ(const unsigned short vZ) { - super_type::GetStackData().setNuclearZ(super_type::GetIndex(), vZ); - } - /// @} - - /** - * @name individual getters - * @{ - */ - int getNuclearA() const { return super_type::GetStackData().getNuclearA(super_type::GetIndex()); } - int getNuclearZ() const { return super_type::GetStackData().getNuclearZ(super_type::GetIndex()); } - /// @} - - /** - * Overwrite normal GetParticleMass function with nuclear version - */ - corsika::units::si::HEPMassType getMass() const { - if (super_type::GetPID() == - corsika::Code::Nucleus) - return corsika::GetNucleusMass(getNuclearA(), getNuclearZ()); - return super_type::getMass(); - } - /** - * Overwirte normal GetChargeNumber function with nuclear version - **/ - int16_t getChargeNumber() const { - if (super_type::GetPID() == - corsika::Code::Nucleus) - return getNuclearZ(); - return super_type::getChargeNumber(); - } - - int getNucleusRef() const { - return super_type::GetStackData().getNucleusRef(GetIndex()); - } // LCOV_EXCL_LINE - -protected: - - void setNucleusRef(const int vR) { - super_type::GetStackData().setNucleusRef(super_type::GetIndex(), vR); - } - - bool isNucleus() const { - return super_type::GetStackData().isNucleus(super_type::GetIndex()); - } -}; - -/** - * @class NuclearStackExtension - * - * Memory implementation of adding nuclear inforamtion to the - * existing particle stack defined in class InnerStackImpl. - * - * Inside the NuclearStackExtension class there is a dedicated - * fNucleusRef index, where fNucleusRef[i] is referring to the - * correct A and Z for a specific particle index i. fNucleusRef[i] - * == -1 means that this is not a nucleus, and a subsequent call to - * GetNucleusA would produce an exception. - */ -template <typename InnerStackImpl> -class NuclearStackExtensionImpl : public InnerStackImpl { - - typedef InnerStackImpl super_type; - -public: - - typedef std::vector<int> nucleus_ref_type; - typedef std::vector<unsigned short> nuclear_a_type; - typedef std::vector<unsigned short> nuclear_z_type; - - - NuclearStackExtensionImpl()= default; - - NuclearStackExtensionImpl( NuclearStackExtensionImpl<InnerStackImpl> const&)= default; - - NuclearStackExtensionImpl( NuclearStackExtensionImpl<InnerStackImpl> &&)= default; - - NuclearStackExtensionImpl<InnerStackImpl>& - operator=( NuclearStackExtensionImpl<InnerStackImpl> const&)= default; - - NuclearStackExtensionImpl<InnerStackImpl>& - operator=( NuclearStackExtensionImpl<InnerStackImpl> &&)= default; - - void init() { - super_type::init(); - } - - void dump() { - super_type::dump(); - } - - void clear() { - super_type::clear(); - nucleusRef_.clear(); - nuclearA_.clear(); - nuclearZ_.clear(); - } - - unsigned int getSize() const { - return nucleusRef_.size(); - } - - unsigned int getCapacity() const { - return nucleusRef_.capacity(); - } - - void setNuclearA(const unsigned int i, const unsigned short vA) { - nuclearA_[getNucleusRef(i)] = vA; - } - - void setNuclearZ(const unsigned int i, const unsigned short vZ) { - nuclearZ_[getNucleusRef(i)] = vZ; - } - - void setNucleusRef(const unsigned int i, const int v) { - nucleusRef_[i] = v; - } - - int getNuclearA(const unsigned int i) const { - return nuclearA_[getNucleusRef(i)]; - } - - int getNuclearZ(const unsigned int i) const { - return nuclearZ_[getNucleusRef(i)]; - } - // this function will create new storage for Nuclear Properties, and return the - // reference to it - int getNucleusNextRef() { - nuclearA_.push_back(0); - nuclearZ_.push_back(0); - return nuclearA_.size() - 1; - } - - int getNucleusRef(const unsigned int i) const { - if (nucleusRef_[i] >= 0) return nucleusRef_[i]; - std::ostringstream err; - err << "NuclearStackExtension: no nucleus at ref=" << i; - throw std::runtime_error(err.str()); - } - - bool isNucleus(const unsigned int i) const { return nucleusRef_[i] >= 0; } - - /** - * Function to copy particle at location i1 in stack to i2 - */ - void copy(const unsigned int i1, const unsigned int i2) { - // index range check - if (i1 >= getSize() || i2 >= getSize()) { - std::ostringstream err; - err << "NuclearStackExtension: trying to access data beyond size of stack!"; - throw std::runtime_error(err.str()); - } - // copy internal particle data p[i2] = p[i1] - super_type::copy(i1, i2); - // check if any of p[i1] or p[i2] was a Code::Nucleus - const int ref1 = nucleusRef_[i1]; - const int ref2 = nucleusRef_[i2]; - if (ref2 < 0) { - if (ref1 >= 0) { - // i1 is nucleus, i2 is not - nucleusRef_[i2] = getNucleusNextRef(); - nuclearA_[nucleusRef_[i2]] = nuclearA_[ref1]; - nuclearZ_[nucleusRef_[i2]] = nuclearZ_[ref1]; - } else { - // neither i1 nor i2 are nuclei - } - } else { - if (ref1 >= 0) { - // both are nuclei, i2 is overwritten with nucleus i1 - // fNucleusRef stays the same, but A and Z data is overwritten - nuclearA_[ref2] = nuclearA_[ref1]; - nuclearZ_[ref2] = nuclearZ_[ref1]; - } else { - // i2 is overwritten with non-nucleus i1 - nucleusRef_[i2] = -1; // flag as non-nucleus - nuclearA_.erase(nuclearA_.cbegin() + ref2); // remove data for i2 - nuclearZ_.erase(nuclearZ_.cbegin() + ref2); // remove data for i2 - const int n = nucleusRef_.size(); // update fNucleusRef: indices above ref2 - // must be decremented by 1 - for (int i = 0; i < n; ++i) { - if (nucleusRef_[i] > ref2) { nucleusRef_[i] -= 1; } - } - } - } - } - - /** - * Function to copy particle at location i2 in stack to i1 - */ - void swap(const unsigned int i1, const unsigned int i2) { - // index range check - if (i1 >= getSize() || i2 >= getSize()) { - std::ostringstream err; - err << "NuclearStackExtension: trying to access data beyond size of stack!"; - throw std::runtime_error(err.str()); - } - // swap original particle data - super_type::swap(i1, i2); - // swap corresponding nuclear reference data - std::swap(nucleusRef_[i2], nucleusRef_[i1]); - } - - void incrementSize() { - super_type::incrementSize(); - nucleusRef_.push_back(-1); - } - - void decrementSize() { - super_type::decrementSize(); - if (nucleusRef_.size() > 0) { - const int ref = nucleusRef_.back(); - nucleusRef_.pop_back(); - if (ref >= 0) { - nuclearA_.erase(nuclearA_.begin() + ref); - nuclearZ_.erase(nuclearZ_.begin() + ref); - const int n = nucleusRef_.size(); - for (int i = 0; i < n; ++i) { - if (nucleusRef_[i] >= ref) { nucleusRef_[i] -= 1; } - } - } - } - } - -private: - /// the actual memory to store particle data - - nucleus_ref_type nucleusRef_; - nuclear_a_type nuclearA_; - nuclear_z_type nuclearZ_; - -}; // end class NuclearStackExtensionImpl - -template <typename InnerStack, template <typename> typename _PI> -using NuclearStackExtension = - Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, _PI> ; - -// -template <typename StackIter> -using ExtendedParticleInterfaceType = NuclearParticleInterface<SuperStupidStack, StackIter>; - -// the particle data stack with extra nuclear information: -using ParticleDataStack = NuclearStackExtension<SuperStupidStack, ExtendedParticleInterfaceType>; - - + /** + * @namespace nuclear_extension + * + * Add A and Z data to existing stack of particle properties. + * + * Only for Code::Nucleus particles A and Z are stored, not for all + * normal elementary particles. + * + * Thus in your code, make sure to always check <code> + * particle.GetPID()==Code::Nucleus </code> before attempting to + * read any nuclear information. + * + * + */ + + typedef corsika::Vector<hepmomentum_d> MomentumVector; + + namespace nuclear_extension { + + /** + * @class NuclearParticleInterface + * + * Define ParticleInterface for NuclearStackExtension Stack derived from + * ParticleInterface of Inner stack class + */ + template <template <typename> typename InnerParticleInterface, + typename StackIteratorInterface> + class NuclearParticleInterface + : public InnerParticleInterface<StackIteratorInterface> { + + protected: + using InnerParticleInterface<StackIteratorInterface>::GetStackData; + using InnerParticleInterface<StackIteratorInterface>::GetIndex; + + public: + void SetParticleData( + const std::tuple<corsika::Code, HEPEnergyType, corsika::MomentumVector, + corsika::Point, TimeType>& v) { + if (std::get<0>(v) == corsika::Code::Nucleus) { + std::ostringstream err; + err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; + throw std::runtime_error(err.str()); + } + InnerParticleInterface<StackIteratorInterface>::SetParticleData(v); + SetNucleusRef(-1); // this is not a nucleus + } + + void SetParticleData( + const std::tuple<corsika::Code, HEPEnergyType, corsika::MomentumVector, + corsika::Point, TimeType, unsigned short, unsigned short>& v) { + const unsigned short A = std::get<5>(v); + const unsigned short Z = std::get<6>(v); + if (std::get<0>(v) != corsika::Code::Nucleus || A == 0 || Z == 0) { + std::ostringstream err; + err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; + throw std::runtime_error(err.str()); + } + SetNucleusRef(GetStackData().GetNucleusNextRef()); // store this nucleus data ref + SetNuclearA(A); + SetNuclearZ(Z); + InnerParticleInterface<StackIteratorInterface>::SetParticleData( + std::tuple<corsika::Code, HEPEnergyType, corsika::MomentumVector, + corsika::Point, TimeType>{std::get<0>(v), std::get<1>(v), + std::get<2>(v), std::get<3>(v), + std::get<4>(v)}); + } + + void SetParticleData( + InnerParticleInterface<StackIteratorInterface>& p, + const std::tuple<corsika::Code, HEPEnergyType, corsika::MomentumVector, + corsika::Point, TimeType>& v) { + if (std::get<0>(v) == corsika::Code::Nucleus) { + std::ostringstream err; + err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; + throw std::runtime_error(err.str()); + } + InnerParticleInterface<StackIteratorInterface>::SetParticleData( + p, std::tuple<corsika::Code, HEPEnergyType, corsika::MomentumVector, + corsika::Point, TimeType>{std::get<0>(v), std::get<1>(v), + std::get<2>(v), std::get<3>(v), + std::get<4>(v)}); + SetNucleusRef(-1); // this is not a nucleus + } + + void SetParticleData( + InnerParticleInterface<StackIteratorInterface>& p, + const std::tuple<corsika::Code, HEPEnergyType, corsika::MomentumVector, + corsika::Point, TimeType, unsigned short, unsigned short>& v) { + const unsigned short A = std::get<5>(v); + const unsigned short Z = std::get<6>(v); + if (std::get<0>(v) != corsika::Code::Nucleus || A == 0 || Z == 0) { + std::ostringstream err; + err << "NuclearStackExtension: no A and Z specified for new Nucleus!"; + throw std::runtime_error(err.str()); + } + SetNucleusRef(GetStackData().GetNucleusNextRef()); // store this nucleus data ref + SetNuclearA(A); + SetNuclearZ(Z); + InnerParticleInterface<StackIteratorInterface>::SetParticleData( + p, std::tuple<corsika::Code, HEPEnergyType, corsika::MomentumVector, + corsika::Point, TimeType>{std::get<0>(v), std::get<1>(v), + std::get<2>(v), std::get<3>(v), + std::get<4>(v)}); + } + + /** + * @name individual setters + * @{ + */ + void SetNuclearA(const unsigned short vA) { + GetStackData().SetNuclearA(GetIndex(), vA); + } + void SetNuclearZ(const unsigned short vZ) { + GetStackData().SetNuclearZ(GetIndex(), vZ); + } + /// @} + + /** + * @name individual getters + * @{ + */ + int GetNuclearA() const { return GetStackData().GetNuclearA(GetIndex()); } + int GetNuclearZ() const { return GetStackData().GetNuclearZ(GetIndex()); } + /// @} + + /** + * Overwrite normal GetParticleMass function with nuclear version + */ + HEPMassType GetMass() const { + if (InnerParticleInterface<StackIteratorInterface>::GetPID() == + corsika::Code::Nucleus) + return corsika::nucleus_mass(GetNuclearA(), GetNuclearZ()); + return InnerParticleInterface<StackIteratorInterface>::GetMass(); + } + /** + * Overwirte normal GetChargeNumber function with nuclear version + **/ + int16_t GetChargeNumber() const { + if (InnerParticleInterface<StackIteratorInterface>::GetPID() == + corsika::Code::Nucleus) + return GetNuclearZ(); + return InnerParticleInterface<StackIteratorInterface>::GetChargeNumber(); + } + + int GetNucleusRef() const { return GetStackData().GetNucleusRef(GetIndex()); } + + protected: + void SetNucleusRef(const int vR) { GetStackData().SetNucleusRef(GetIndex(), vR); } + }; + + /** + * @class NuclearStackExtension + * + * Memory implementation of adding nuclear inforamtion to the + * existing particle stack defined in class InnerStackImpl. + * + * Inside the NuclearStackExtension class there is a dedicated + * fNucleusRef index, where fNucleusRef[i] is referring to the + * correct A and Z for a specific particle index i. fNucleusRef[i] + * == -1 means that this is not a nucleus, and a subsequent call to + * GetNucleusA would produce an exception. + */ + template <typename InnerStackImpl> + class NuclearStackExtensionImpl : public InnerStackImpl { + + public: + void Init() { InnerStackImpl::Init(); } + void Dump() { InnerStackImpl::Dump(); } + + void Clear() { + InnerStackImpl::Clear(); + fNucleusRef.clear(); + fNuclearA.clear(); + fNuclearZ.clear(); + } + + unsigned int GetSize() const { return fNucleusRef.size(); } + unsigned int GetCapacity() const { return fNucleusRef.capacity(); } + + void SetNuclearA(const unsigned int i, const unsigned short vA) { + fNuclearA[GetNucleusRef(i)] = vA; + } + void SetNuclearZ(const unsigned int i, const unsigned short vZ) { + fNuclearZ[GetNucleusRef(i)] = vZ; + } + void SetNucleusRef(const unsigned int i, const int v) { fNucleusRef[i] = v; } + + int GetNuclearA(const unsigned int i) const { return fNuclearA[GetNucleusRef(i)]; } + int GetNuclearZ(const unsigned int i) const { return fNuclearZ[GetNucleusRef(i)]; } + // this function will create new storage for Nuclear Properties, and return the + // reference to it + int GetNucleusNextRef() { + fNuclearA.push_back(0); + fNuclearZ.push_back(0); + return fNuclearA.size() - 1; + } + + int GetNucleusRef(const unsigned int i) const { + if (fNucleusRef[i] >= 0) return fNucleusRef[i]; + std::ostringstream err; + err << "NuclearStackExtension: no nucleus at ref=" << i; + throw std::runtime_error(err.str()); + } + + /** + * Function to copy particle at location i1 in stack to i2 + */ + void Copy(const unsigned int i1, const unsigned int i2) { + // index range check + if (i1 >= GetSize() || i2 >= GetSize()) { + std::ostringstream err; + err << "NuclearStackExtension: trying to access data beyond size of stack!"; + throw std::runtime_error(err.str()); + } + // copy internal particle data p[i2] = p[i1] + InnerStackImpl::Copy(i1, i2); + // check if any of p[i1] or p[i2] was a Code::Nucleus + const int ref1 = fNucleusRef[i1]; + const int ref2 = fNucleusRef[i2]; + if (ref2 < 0) { + if (ref1 >= 0) { + // i1 is nucleus, i2 is not + fNucleusRef[i2] = GetNucleusNextRef(); + fNuclearA[fNucleusRef[i2]] = fNuclearA[ref1]; + fNuclearZ[fNucleusRef[i2]] = fNuclearZ[ref1]; + } else { + // neither i1 nor i2 are nuclei + } + } else { + if (ref1 >= 0) { + // both are nuclei, i2 is overwritten with nucleus i1 + // fNucleusRef stays the same, but A and Z data is overwritten + fNuclearA[ref2] = fNuclearA[ref1]; + fNuclearZ[ref2] = fNuclearZ[ref1]; + } else { + // i2 is overwritten with non-nucleus i1 + fNucleusRef[i2] = -1; // flag as non-nucleus + fNuclearA.erase(fNuclearA.cbegin() + ref2); // remove data for i2 + fNuclearZ.erase(fNuclearZ.cbegin() + ref2); // remove data for i2 + const int n = fNucleusRef.size(); // update fNucleusRef: indices above ref2 + // must be decremented by 1 + for (int i = 0; i < n; ++i) { + if (fNucleusRef[i] > ref2) { fNucleusRef[i] -= 1; } + } + } + } + } + + /** + * Function to copy particle at location i2 in stack to i1 + */ + void Swap(const unsigned int i1, const unsigned int i2) { + // index range check + if (i1 >= GetSize() || i2 >= GetSize()) { + std::ostringstream err; + err << "NuclearStackExtension: trying to access data beyond size of stack!"; + throw std::runtime_error(err.str()); + } + // swap original particle data + InnerStackImpl::Swap(i1, i2); + // swap corresponding nuclear reference data + std::swap(fNucleusRef[i2], fNucleusRef[i1]); + } + + void IncrementSize() { + InnerStackImpl::IncrementSize(); + fNucleusRef.push_back(-1); + } + + void DecrementSize() { + InnerStackImpl::DecrementSize(); + if (fNucleusRef.size() > 0) { + const int ref = fNucleusRef.back(); + fNucleusRef.pop_back(); + if (ref >= 0) { + fNuclearA.erase(fNuclearA.begin() + ref); + fNuclearZ.erase(fNuclearZ.begin() + ref); + const int n = fNucleusRef.size(); + for (int i = 0; i < n; ++i) { + if (fNucleusRef[i] >= ref) { fNucleusRef[i] -= 1; } + } + } + } + } + + private: + /// the actual memory to store particle data + + std::vector<int> fNucleusRef; + std::vector<unsigned short> fNuclearA; + std::vector<unsigned short> fNuclearZ; + + }; // end class NuclearStackExtensionImpl + + // template<typename StackIteratorInterface> + // using NuclearParticleInterfaceType<StackIteratorInterface> = + // NuclearParticleInterface< ,StackIteratorInterface> + + // works, but requires stupd _PI class + // template<typename SS> using TEST = + // NuclearParticleInterface<corsika::super_stupid::SuperStupidStack::PIType, + // SS>; + template <typename InnerStack, template <typename> typename _PI> + using NuclearStackExtension = + Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, _PI>; + + // ---- + + // I'm dont't manage to do this properly....... + /* + template<typename TT, typename SS> using TESTi = typename + NuclearParticleInterface<TT::template PIType, SS>::ExtendedParticleInterface; + template<typename TT, typename SS> using TEST1 = TESTi<TT, SS>; + template<typename SS> using TEST2 = TEST1<typename + corsika::super_stupid::SuperStupidStack, SS>; + + using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename + InnerStack::StackImpl>, TEST2>; + */ + /* + // .... this should be fixed .... + + template <typename InnerStack, typename SS=StackIteratorInterface> + //using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename + InnerStack::StackImpl>, NuclearParticleInterface<typename InnerStack::template PIType, + StackIteratorInterface>::ExtendedParticleInterface>; using NuclearStackExtension = + Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, TEST1<typename + corsika::super_stupid::SuperStupidStack, SS> >; + + //template <typename InnerStack> + // using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename + InnerStack::StackImpl>, TEST<typename + corsika::super_stupid::SuperStupidStack::PIType>>; + //using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename + InnerStack::StackImpl>, TEST>; + */ + + } // namespace nuclear_extension } // namespace corsika diff --git a/corsika/stack/SuperStupidStack.hpp b/corsika/stack/SuperStupidStack.hpp index ffa0e4cb20b33a2534624e3d6b0462ddd4931af7..d83dda4f3d8cbf3e2026d5d603c144e1d4eebe95 100644 --- a/corsika/stack/SuperStupidStack.hpp +++ b/corsika/stack/SuperStupidStack.hpp @@ -108,8 +108,8 @@ namespace corsika { corsika::Vector<dimensionless_d> GetDirection() const { return GetMomentum() / GetEnergy(); } - HEPMassType GetMass() const { return corsika::GetMass(GetPID()); } - int16_t GetChargeNumber() const { return corsika::GetChargeNumber(GetPID()); } + HEPMassType GetMass() const { return corsika::mass(GetPID()); } + int16_t GetChargeNumber() const { return corsika::charge_number(GetPID()); } ///@} }; diff --git a/tests/modules/testSibyll.cpp b/tests/modules/testSibyll.cpp index d203c652336b446160e8c834fe171997ad2f94df..c6666ab41844505182f05a0e18bd347f511bc180 100644 --- a/tests/modules/testSibyll.cpp +++ b/tests/modules/testSibyll.cpp @@ -23,26 +23,26 @@ using namespace corsika::sibyll; TEST_CASE("Sibyll", "[processes]") { SECTION("Sibyll -> Corsika") { - REQUIRE(Electron::GetCode() == + REQUIRE(Code::Electron == corsika::sibyll::ConvertFromSibyll(corsika::sibyll::SibyllCode::Electron)); } SECTION("Corsika -> Sibyll") { - REQUIRE(corsika::sibyll::ConvertToSibyll(Electron::GetCode()) == + REQUIRE(corsika::sibyll::ConvertToSibyll(Code::Electron) == corsika::sibyll::SibyllCode::Electron); - REQUIRE(corsika::sibyll::ConvertToSibyllRaw(Proton::GetCode()) == 13); + REQUIRE(corsika::sibyll::ConvertToSibyllRaw(Code::Proton) == 13); } SECTION("canInteractInSibyll") { - REQUIRE(corsika::sibyll::CanInteract(Proton::GetCode())); + REQUIRE(corsika::sibyll::CanInteract(Code::Proton)); REQUIRE(corsika::sibyll::CanInteract(Code::XiCPlus)); - REQUIRE_FALSE(corsika::sibyll::CanInteract(Electron::GetCode())); - REQUIRE_FALSE(corsika::sibyll::CanInteract(SigmaC0::GetCode())); + REQUIRE_FALSE(corsika::sibyll::CanInteract(Code::Electron)); + REQUIRE_FALSE(corsika::sibyll::CanInteract(Code::SigmaC0)); - REQUIRE_FALSE(corsika::sibyll::CanInteract(Nucleus::GetCode())); - REQUIRE_FALSE(corsika::sibyll::CanInteract(Helium::GetCode())); + REQUIRE_FALSE(corsika::sibyll::CanInteract(Code::Nucleus)); + REQUIRE_FALSE(corsika::sibyll::CanInteract(Code::Helium)); } SECTION("cross-section type") { @@ -101,7 +101,7 @@ TEST_CASE("SibyllInterface", "[processes]") { corsika::setup::Stack stack; const HEPEnergyType E0 = 100_GeV; - HEPMomentumType P0 = sqrt(E0 * E0 - Proton::GetMass() * Proton::GetMass()); + HEPMomentumType P0 = sqrt(E0 * E0 - Proton::mass() * Proton::mass()); auto plab = corsika::MomentumVector(cs, {0_GeV, 0_GeV, -P0}); corsika::Point pos(cs, 0_m, 0_m, 0_m); auto particle = stack.AddParticle( @@ -123,7 +123,7 @@ TEST_CASE("SibyllInterface", "[processes]") { setup::Stack stack; const HEPEnergyType E0 = 400_GeV; - HEPMomentumType P0 = sqrt(E0 * E0 - Proton::GetMass() * Proton::GetMass()); + HEPMomentumType P0 = sqrt(E0 * E0 - Proton::mass() * Proton::mass()); auto plab = corsika::MomentumVector(cs, {0_GeV, 0_GeV, -P0}); corsika::Point pos(cs, 0_m, 0_m, 0_m); @@ -147,7 +147,7 @@ TEST_CASE("SibyllInterface", "[processes]") { setup::Stack stack; const HEPEnergyType E0 = 10_GeV; - HEPMomentumType P0 = sqrt(E0 * E0 - Proton::GetMass() * Proton::GetMass()); + HEPMomentumType P0 = sqrt(E0 * E0 - Proton::mass() * Proton::mass()); auto plab = corsika::MomentumVector(cs, {0_GeV, 0_GeV, -P0}); corsika::Point pos(cs, 0_m, 0_m, 0_m); auto particle = stack.AddParticle(