diff --git a/corsika/detail/modules/sibyll/InteractionModel.inl b/corsika/detail/modules/sibyll/InteractionModel.inl index 1af79a9d2ba646901a0d81f16289abe2a1a7c6cf..1541e8cb9c9cab72b71c9b0b84b90f79246639da 100644 --- a/corsika/detail/modules/sibyll/InteractionModel.inl +++ b/corsika/detail/modules/sibyll/InteractionModel.inl @@ -51,14 +51,14 @@ namespace corsika::sibyll { targA = get_nucleus_A(targetId); } - if ((is_nucleus(targetId) && - (targA < minNuclearTargetA_ || targA >= maxTargetMassNumber_)) && - targetId != Code::Proton && targetId != Code::Hydrogen && - targetId != Code::Neutron) { + if (is_nucleus(targetId)) { + if (targA != 1 && (targA < minNuclearTargetA_ || targA >= maxTargetMassNumber_)) { + throw std::runtime_error("Target outside of allowed range for SIBYLL"); + } + } else if (targetId != Code::Proton && targetId != Code::Neutron) { throw std::runtime_error("Target cannot be handled by SIBYLL"); } - - if (is_nucleus(projectileId) && !corsika::sibyll::canInteract(projectileId)) { + if (is_nucleus(projectileId) || !corsika::sibyll::canInteract(projectileId)) { throw std::runtime_error("Projectile cannot be handled by SIBYLL"); } } @@ -73,7 +73,8 @@ namespace corsika::sibyll { double dummy, dum1, dum3, dum4, dumdif[3]; // dummies needed for fortran call int const iBeam = corsika::sibyll::getSibyllXSCode( - projectileId); // 0 (can not interact, 1: proton-like, 2: pion-like, 3:kaon-like) + projectileId); // 0 (can not interact, 1: proton-like, 2: pion-like, + // 3:kaon-like) double const dEcm = sqrtSnn / 1_GeV; // single nucleon target (p,n, hydrogen) or 4<=A<=18 diff --git a/corsika/detail/modules/sibyll/NuclearInteractionModel.inl b/corsika/detail/modules/sibyll/NuclearInteractionModel.inl index 8811e0eeafc791e63d8e98f08462280ed56e4d0c..820839ff065697e42512eb43f54e1c07a98bb62d 100644 --- a/corsika/detail/modules/sibyll/NuclearInteractionModel.inl +++ b/corsika/detail/modules/sibyll/NuclearInteractionModel.inl @@ -49,7 +49,7 @@ namespace corsika::sibyll { hadronicInteraction_.isValid(Code::Proton, targetId, sqrtSnn, 1, targetA); // throws // projectile limits: - if (is_nucleus(projectileId)) { + if (!is_nucleus(projectileId)) { throw std::runtime_error("can only handle nuclear projectile"); } if (projectileA >= getMaxNucleusAProjectile() || projectileA < 2) { diff --git a/corsika/modules/sibyll/InteractionModel.hpp b/corsika/modules/sibyll/InteractionModel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4cba07fa5ee3ae4a920dca118a64d187c890853e --- /dev/null +++ b/corsika/modules/sibyll/InteractionModel.hpp @@ -0,0 +1,125 @@ +/* + * (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. + */ + +#pragma once + +#include <corsika/framework/core/ParticleProperties.hpp> +#include <corsika/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/random/RNGManager.hpp> +#include <corsika/framework/utility/COMBoost.hpp> +#include <tuple> + +namespace corsika::sibyll { + + /** + * @brief sibyll::InteractionModel provides the SIBYLL proton-nucleus interaction model. + * + * This is a TModel argument for InteractionProcess<TModel>. + */ + + class InteractionModel { + + public: + InteractionModel(); + ~InteractionModel(); + + /** + * @brief Set the Verbose flag. + * + * If flag is true, SIBYLL will printout additional secondary particle information + * lists, etc. + * + * @param flag to switch. + */ + void setVerbose(bool const flag); + + /** + * @brief evaluated validity of collision system. + * + * sibyll only accepts nuclei with 4<=A<=18 as targets, or protons aka Hydrogen or + * neutrons (p,n == nucleon). + */ + void constexpr isValid(Code const projectileId, Code const targetId, + HEPEnergyType const sqrtSnn, unsigned int const projectileA, + unsigned int const targetA) const; + + /** + * @brief returns inelastic AND elastic cross sections. + * + * These cross sections must correspond to the process described in doInteraction + * AND elastic scattering (sigma_tot = sigma_inel + sigma_el). Allowed targets are: + * nuclei or single nucleons (p,n,hydrogen). This "InelEla" method is used since + * Sibyll must be useful inside the NuclearInteraction model, which requires that. + * + * @param projectile is the Code of the projectile + * @param target is the Code of the target + * @param sqrtSnn is the center-of-mass energy (per nucleon pair) + * @param Aprojectil is the mass number of the projectils, if it is a nucleus + * @param Atarget is the mass number of the target, if it is a nucleus + * + * @return a tuple of: inelastic cross section, elastic cross section + */ + std::tuple<CrossSectionType, CrossSectionType> getCrossSectionInelEla( + Code const projectile, Code const target, HEPEnergyType const sqrtSnn, + unsigned int const Aprojectile = 1, unsigned int const Atarget = 1) const; + + /** + * @brief returns inelastic (production) cross section. + * + * This cross section must correspond to the process described in doInteraction. + * Allowed targets are: nuclei or single nucleons (p,n,hydrogen). + * + * @param projectile is the Code of the projectile + * @param target is the Code of the target + * @param sqrtSnn is the center-of-mass energy (per nucleon pair) + * @param Aprojectil is the mass number of the projectils, if it is a nucleus + * @param Atarget is the mass number of the target, if it is a nucleus + * + * @return inelastic cross section + * elastic cross section + */ + CrossSectionType getCrossSection(Code const projectile, Code const target, + HEPEnergyType const sqrtSnn, + unsigned int const Aprojectile = 1, + unsigned int const Atarget = 1) const { + return std::get<0>( + getCrossSectionInelEla(projectile, target, sqrtSnn, Aprojectile, Atarget)); + } + + /** + * In this function SIBYLL is called to produce one event. The + * event is copied (and boosted) into the shower lab frame. + */ + + template <typename TSecondaries> + void doInteraction(TSecondaries&, COMBoost const& boost, Code const projectile, + Code const target, HEPEnergyType const sqrtSnn, + unsigned int const Aprojectile = 1, + unsigned int const Atarget = 1); + + private: + HEPEnergyType constexpr getMinEnergyCoM() const { return minEnergyCoM_; } + HEPEnergyType constexpr getMaxEnergyCoM() const { return maxEnergyCoM_; } + + // hard model limits + static HEPEnergyType constexpr minEnergyCoM_ = 10. * 1e9 * electronvolt; + static HEPEnergyType constexpr maxEnergyCoM_ = 1.e6 * 1e9 * electronvolt; + static unsigned int constexpr maxTargetMassNumber_ = 18; + static unsigned int constexpr minNuclearTargetA_ = 4; + + default_prng_type& RNG_ = RNGManager<>::getInstance().getRandomStream("sibyll"); + + // data members + int count_ = 0; + int nucCount_ = 0; + bool sibyll_listing_; + }; + +} // namespace corsika::sibyll + +#include <corsika/detail/modules/sibyll/InteractionModel.inl> diff --git a/corsika/modules/sibyll/NuclearInteractionModel.hpp b/corsika/modules/sibyll/NuclearInteractionModel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..61b2f807e68190fc1f948174fb3087175359f5e1 --- /dev/null +++ b/corsika/modules/sibyll/NuclearInteractionModel.hpp @@ -0,0 +1,78 @@ +/* + * (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. + */ + +#pragma once + +#include <corsika/framework/core/ParticleProperties.hpp> +#include <corsika/framework/random/RNGManager.hpp> +#include <corsika/framework/utility/COMBoost.hpp> + +namespace corsika::sibyll { + + /** + * The sibyll::NuclearInteractionModel provides the SIBYLL semi superposition model. + * + * can transform a proton-nucleus interaction model into a nucleus-nucleus interaction + * model. + * + * @tparam TNucleonModel + */ + template <class TEnvironment, class TNucleonModel> + class NuclearInteractionModel { + + public: + NuclearInteractionModel(TNucleonModel&, TEnvironment const&); + ~NuclearInteractionModel(); + + void constexpr isValid(Code const projectileId, Code const targetId, + HEPEnergyType const sqrtSnn, unsigned int const projectileA, + unsigned int const targetA) const; + + void initializeNuclearCrossSections(); + void printCrossSectionTable(Code) const; + CrossSectionType readCrossSectionTable(int const, Code const, + HEPEnergyType const) const; + HEPEnergyType getMinEnergyPerNucleonCoM() const { return gMinEnergyPerNucleonCoM_; } + HEPEnergyType getMaxEnergyPerNucleonCoM() const { return gMaxEnergyPerNucleonCoM_; } + unsigned int constexpr getMaxNucleusAProjectile() const { + return gMaxNucleusAProjectile_; + } + unsigned int constexpr getMaxNFragments() const { return gMaxNFragments_; } + unsigned int constexpr getNEnergyBins() const { return gNEnBins_; } + + CrossSectionType getCrossSection(Code const, Code const, HEPEnergyType const, + unsigned int const projectileA = 1, + unsigned int const targetA = 1) const; + + template <typename TSecondaryView> + void doInteraction(TSecondaryView&, COMBoost const& boost, Code const, Code const, + HEPEnergyType const, unsigned int const projectileA = 1, + unsigned int const targetA = 1); + + private: + int count_ = 0; + int nucCount_ = 0; + + TEnvironment const& environment_; + TNucleonModel& hadronicInteraction_; + std::map<Code, int> targetComponentsIndex_; + default_prng_type& RNG_ = RNGManager<>::getInstance().getRandomStream("sibyll"); + static unsigned int constexpr gNSample_ = + 500; // number of samples in MC estimation of cross section + static unsigned int constexpr gMaxNucleusAProjectile_ = 56; + static unsigned int constexpr gNEnBins_ = 6; + static unsigned int constexpr gMaxNFragments_ = 60; + // energy limits defined by table used for cross section in signuc.f + // 10**1 GeV to 10**6 GeV + static HEPEnergyType constexpr gMinEnergyPerNucleonCoM_ = 10. * 1e9 * electronvolt; + static HEPEnergyType constexpr gMaxEnergyPerNucleonCoM_ = 1.e6 * 1e9 * electronvolt; + }; + +} // namespace corsika::sibyll + +#include <corsika/detail/modules/sibyll/NuclearInteractionModel.inl> diff --git a/tests/modules/testSibyll.cpp b/tests/modules/testSibyll.cpp index 8bc4879f93c320d63774fe5c7579e932eb705fc5..477f1899b1970b8f478933640427cd5ba9791b4a 100644 --- a/tests/modules/testSibyll.cpp +++ b/tests/modules/testSibyll.cpp @@ -146,8 +146,8 @@ TEST_CASE("SibyllInterface", "modules") { CHECK_THROWS(model.isValid(Code::Proton, Code::Iron, 100_GeV, 1, 56)); CHECK_NOTHROW(model.isValid(Code::Proton, Code::Oxygen, 100_GeV, 1, 16)); // beam particles - CHECK_NOTHROW(model.isValid(Code::Electron, Code::Oxygen, 100_GeV, 1, 1)); - CHECK_NOTHROW(model.isValid(Code::Nucleus, Code::Oxygen, 100_GeV, 1, 20)); + CHECK_THROWS(model.isValid(Code::Electron, Code::Oxygen, 100_GeV, 1, 1)); + CHECK_THROWS(model.isValid(Code::Nucleus, Code::Oxygen, 100_GeV, 1, 20)); // energy too low CHECK_THROWS(model.isValid(Code::Proton, Code::Proton, 9_GeV, 1, 1)); CHECK_NOTHROW(model.isValid(Code::Proton, Code::Proton, 11_GeV, 1, 1));