diff --git a/corsika/detail/modules/epos/InteractionModel.inl b/corsika/detail/modules/epos/InteractionModel.inl index 97fe7ef4b077063650d3d0cae0798c22e0bdf735..039d9635de189d5c6a96309e6a96b4bd07365dd7 100644 --- a/corsika/detail/modules/epos/InteractionModel.inl +++ b/corsika/detail/modules/epos/InteractionModel.inl @@ -28,13 +28,12 @@ namespace corsika::epos { : data_path_(dataPath) , epos_listing_(epos_printout_on) { // initialize Eposlhc - static bool initialized = false; - if (!initialized) { + if (!isInitialized_) { + isInitialized_ = true; if (dataPath == "") { data_path_ = (std::string(corsika_data("EPOS").c_str()) + "/").c_str(); } initialize(); - initialized = true; } setParticlesStable(); } @@ -136,9 +135,9 @@ namespace corsika::epos { strcpy(::epos::fname_.fncs, CS.data); ::epos::nfname_.nfncs = CS.length; - // dummy event (prepare commons) - initializeEventLab(Code::Iron, Iron::nucleus_A, Iron::nucleus_Z, Code::Argon, - Argon::nucleus_A, Argon::nucleus_Z, 100_GeV); + // initialiazes maximum energy and mass + initializeEventLab(Code::Lead, Lead::nucleus_A, Lead::nucleus_Z, Code::Lead, + Lead::nucleus_A, Lead::nucleus_Z, 1_TeV); } inline void InteractionModel::initializeEventCoM(Code const idBeam, int const iBeamA, @@ -157,11 +156,8 @@ namespace corsika::epos { ::epos::enrgy_.ecms = Ecm / 1_GeV; // -> c.m.s. frame - CORSIKA_LOGGER_TRACE(logger_, - "inside EPOS: " - "Ecm={}, " - "Elab={}", - ::epos::enrgy_.ecms, ::epos::enrgy_.elab); + CORSIKA_LOGGER_TRACE(logger_, "inside EPOS: Ecm={}, Elab={}", ::epos::enrgy_.ecms, + ::epos::enrgy_.elab); configureParticles(idBeam, iBeamA, iBeamZ, idTarget, iTargetA, iTargetZ); ::epos::ainit_(); @@ -184,11 +180,7 @@ namespace corsika::epos { // hadron-nucleon momentum ::epos::hadr1_.pnll = float(Plab / 1_GeV); // -> lab frame - CORSIKA_LOGGER_TRACE(logger_, - "inside EPOS: " - "Ecm={}, " - "Elab={}, " - "Pnll={}", + CORSIKA_LOGGER_TRACE(logger_, "inside EPOS: Ecm={}, Elab={}, Pnll={}", ::epos::enrgy_.ecms, ::epos::enrgy_.elab, ::epos::hadr1_.pnll); configureParticles(idBeam, iBeamA, iBeamZ, idTarget, iTargetA, iTargetZ); @@ -449,13 +441,12 @@ namespace corsika::epos { // create event int iarg = 1; ::epos::aepos_(iarg); - ::epos::afinal_(); - if (epos_listing_) { + if (epos_listing_) { // LCOV_EXCL_START char nam[9] = "EPOSLHC&"; ::epos::alistf_(nam, 9); - } + } // LCOV_EXCL_STOP // NSTORE-part diff --git a/corsika/detail/modules/sibyll/InteractionModel.inl b/corsika/detail/modules/sibyll/InteractionModel.inl index 9ecb434bc62cb5a0bbccc6a13ce889032b4bdcda..99f078673c2d80df3c6251bd6d22eed25a077c4f 100644 --- a/corsika/detail/modules/sibyll/InteractionModel.inl +++ b/corsika/detail/modules/sibyll/InteractionModel.inl @@ -151,8 +151,9 @@ namespace corsika::sibyll { HEPEnergyType Elab_final = 0_GeV, Ecm_final = 0_GeV; for (auto& psib : ss) { // abort on particles that have decayed in Sibyll. Should not happen! - if (psib.hasDecayed()) + if (psib.hasDecayed()) { // LCOV_EXCL_START throw std::runtime_error("found particle that decayed in SIBYLL!"); + } // LCOV_EXCL_STOP // transform 4-momentum to lab. frame // note that the momentum needs to be rotated back diff --git a/corsika/detail/modules/sibyll/NuclearInteractionModel.inl b/corsika/detail/modules/sibyll/NuclearInteractionModel.inl index c2bfecd92a79c33c4a108460ba0fd4d3d710cf2b..4a564c7e96bcc64e059dfec58b43eb3f5b8ed7ac 100644 --- a/corsika/detail/modules/sibyll/NuclearInteractionModel.inl +++ b/corsika/detail/modules/sibyll/NuclearInteractionModel.inl @@ -57,10 +57,10 @@ namespace corsika::sibyll { inline void NuclearInteractionModel<TEnvironment, TNucleonModel>::printCrossSectionTable( Code const pCode) const { - if (!hadronicInteraction_.isValid(Code::Proton, pCode, 100_GeV)) { + if (!hadronicInteraction_.isValid(Code::Proton, pCode, 100_GeV)) { // LCOV_EXCL_START CORSIKA_LOG_ERROR("Invalid target type {} for hadron interaction model.", pCode); return; - } + } // LCOV_EXCL_STOP int const k = targetComponentsIndex_.at(pCode); Code const pNuclei[] = {Code::Helium, Code::Lithium7, Code::Oxygen, @@ -200,6 +200,9 @@ namespace corsika::sibyll { // model is only designed for projectile nuclei. Collisions are broken down into // "nucleon-target" collisions. + if (!is_nucleus(projectileId)) { + throw std::runtime_error("Can only handle nuclear projectiles."); + } size_t const projectileA = get_nucleus_A(projectileId); // this is center-of-mass for projectile_nucleon - target diff --git a/corsika/modules/epos/InteractionModel.hpp b/corsika/modules/epos/InteractionModel.hpp index 5a2c4a2901844988cb6d696c0d390022ae794b7d..0f08a919b7cc640d20351235dfc2164b155dbe50 100644 --- a/corsika/modules/epos/InteractionModel.hpp +++ b/corsika/modules/epos/InteractionModel.hpp @@ -83,6 +83,8 @@ namespace corsika::epos { void setParticlesStable() const; private: + inline static bool isInitialized_ = false; + std::string data_path_; unsigned int count_ = 0; bool epos_listing_; diff --git a/tests/modules/testEpos.cpp b/tests/modules/testEpos.cpp index 4700eab1091cf545a887b5b19ed06ae7227d00b6..d0f13d94fa941ae6931b9874b43d208240d9b5ad 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", "module,process") { +TEST_CASE("EposBasics", "module,process") { logging::set_level(logging::level::trace); @@ -71,6 +71,7 @@ TEST_CASE("Epos", "module,process") { SECTION("epos mass") { CHECK_FALSE(corsika::epos::getEposMass(Code::Electron) / 1_GeV == Approx(0)); + CHECK_THROWS(corsika::epos::getEposMass(Code::Unknown)); } /* @@ -88,6 +89,7 @@ TEST_CASE("Epos", "module,process") { CHECK(p == convert_from_PDG(getEposPDGId(p))); } } + CHECK_THROWS(getEposPDGId(Code::Oxygen)); } } @@ -118,16 +120,17 @@ auto sqs2elab(HEPEnergyType const sqs, HEPEnergyType const ma, HEPEnergyType con return (sqs * sqs - ma * ma - mb * mb) / 2. / mb; } -TEST_CASE("EposInterface", "modules") { +TEST_CASE("Epos", "modules") { logging::set_level(logging::level::trace); + RNGManager<>::getInstance().registerRandomStream("epos"); + InteractionModel model; + auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Oxygen); auto const& cs = *csPtr; [[maybe_unused]] auto const& env_dummy = env; - RNGManager<>::getInstance().registerRandomStream("epos"); - SECTION("InteractionInterface - random number") { auto const rndm = ::epos::rangen_(); CHECK(rndm > 0); @@ -136,8 +139,6 @@ TEST_CASE("EposInterface", "modules") { SECTION("InteractionInterface - isValid") { - InteractionModel model; - CHECK_FALSE(model.isValid(Code::Proton, Code::Electron, 100_GeV)); CHECK(model.isValid(Code::Proton, Code::Hydrogen, 100_GeV)); CHECK(model.isValid(Code::Proton, Code::Helium, 100_GeV)); @@ -147,8 +148,6 @@ TEST_CASE("EposInterface", "modules") { SECTION("InteractionInterface - getCrossSectionInelEla") { - InteractionModel model; - // hydrogen target == proton target == neutron target auto const [xs_prod_pp, xs_ela_pp] = model.getCrossSectionInelEla( Code::Proton, Code::Proton, @@ -172,12 +171,19 @@ TEST_CASE("EposInterface", "modules") { CHECK(xs_prod_pp == xs_prod_pn); CHECK(xs_ela_pp == xs_ela_pHydrogen); CHECK(xs_ela_pn == xs_ela_pHydrogen); + + // invalid system + auto const [xs_prod_0, xs_ela_0] = model.getCrossSectionInelEla( + Code::Electron, Code::Electron, + {sqrt(static_pow<2>(100_GeV) + static_pow<2>(Electron::mass)), + {cs, 100_GeV, 0_GeV, 0_GeV}}, + {Electron::mass, {cs, 0_GeV, 0_GeV, 0_GeV}}); + CHECK(xs_prod_0 / 1_mb == Approx(0)); + CHECK(xs_ela_0 / 1_mb == Approx(0)); } SECTION("InteractionModelInterface - hadron cross sections") { - InteractionModel model; - // p-p at 7TeV around 70mb according to LHC auto const xs_prod = model.getCrossSection( Code::Proton, Code::Proton, @@ -211,8 +217,6 @@ TEST_CASE("EposInterface", "modules") { SECTION("InteractionInterface - nuclear cross sections") { - InteractionModel model; - auto const xs_prod = model.getCrossSection( Code::Proton, Code::Oxygen, {100_GeV, @@ -228,35 +232,67 @@ TEST_CASE("EposInterface", "modules") { {Oxygen::mass, {cs, 0_GeV, 0_GeV, 0_GeV}}); CHECK(xs_prod2 / 1_mb == Approx(1076.7).margin(3.1)); } -} - -TEST_CASE("EposDoInteractionNucleus", "module") { - - logging::set_level(logging::level::trace); - - auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Oxygen); - auto const& cs = *csPtr; - [[maybe_unused]] auto const& env_dummy = env; - - RNGManager<>::getInstance().registerRandomStream("epos"); - - InteractionModel model; - - SECTION("InteractionInterface - nuclear projectile") { + /* + SECTION("InteractionInterface - invalid") { + Code const pid = Code::Electron; + HEPEnergyType const P0 = 10_TeV; + auto [stack, viewPtr] = setup::testing::setup_stack( + pid, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); + setup::StackView& view = *viewPtr; + CHECK_THROWS(model.doInteraction( + view, pid, Code::Oxygen, + {sqrt(static_pow<2>(P0) + static_pow<2>(get_mass(pid))), {cs, P0, 0_GeV, + 0_GeV}}, {Oxygen::mass, {cs, 0_GeV, 0_GeV, 0_GeV}})); + } + */ + /* + SECTION("InteractionInterface - nuclear projectile") { + + HEPEnergyType const P0 = 10_TeV; + Code const pid = get_nucleus_code(40, 20); + auto [stack, viewPtr] = setup::testing::setup_stack( + pid, 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; + + // @todo This is very obscure since it fails for -O2, but for both clang and gcc ??? + model.doInteraction(view, pid, Code::Oxygen, + {sqrt(static_pow<2>(P0) + static_pow<2>(get_mass(pid))), plab}, + {Oxygen::mass, {cs, 0_GeV, 0_GeV, 0_GeV}}); + + auto const pSum = sumMomentum(view, cs); + + CHECK(pSum.getComponents(cs).getX() / P0 == Approx(1).margin(0.05)); + CHECK(pSum.getComponents(cs).getY() / 1_GeV == + Approx(0).margin(0.5)); // this is not physics validation + CHECK(pSum.getComponents(cs).getZ() / 1_GeV == + Approx(0).margin(0.5)); // this is not physics validation + + CHECK((pSum - plab).getNorm() / 1_GeV == + Approx(0).margin(plab.getNorm() * 0.05 / 1_GeV)); + CHECK(pSum.getNorm() / P0 == Approx(1).margin(0.05)); + // [[maybe_unused]] const GrammageType length = + // model.getInteractionLength(particle); + // CHECK(length / 1_g * 1_cm * 1_cm == + // Approx(30).margin(20)); // this is no physics validation + }*/ + + // SECTION("InteractionInterface") + { HEPEnergyType const P0 = 10_TeV; - Code const pid = get_nucleus_code(40, 20); + Code const pid = Code::Proton; auto [stack, viewPtr] = setup::testing::setup_stack( pid, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs); MomentumVector plab = - MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack + MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setup::StackView& view = *viewPtr; // @todo This is very obscure since it fails for -O2, but for both clang and gcc ??? - model.doInteraction( - view, pid, Code::Oxygen, - {sqrt(static_pow<2>(P0) + static_pow<2>(get_mass(pid))), {cs, P0, 0_GeV, 0_GeV}}, - {Oxygen::mass, {cs, 0_GeV, 0_GeV, 0_GeV}}); + model.doInteraction(view, pid, Code::Oxygen, + {sqrt(static_pow<2>(P0) + static_pow<2>(get_mass(pid))), plab}, + {Oxygen::mass, {cs, 0_GeV, 0_GeV, 0_GeV}}); auto const pSum = sumMomentum(view, cs); @@ -274,4 +310,4 @@ TEST_CASE("EposDoInteractionNucleus", "module") { // CHECK(length / 1_g * 1_cm * 1_cm == // Approx(30).margin(20)); // this is no physics validation } -} +} \ No newline at end of file diff --git a/tests/modules/testSibyll.cpp b/tests/modules/testSibyll.cpp index 7cd05aa6ef07d0fb936f833cf6cdaf073dc15489..042dc72a873d657b3e7da682fdead5d15df67e86 100644 --- a/tests/modules/testSibyll.cpp +++ b/tests/modules/testSibyll.cpp @@ -100,27 +100,9 @@ auto sumMomentum(TStackView const& view, CoordinateSystemPtr const& vCS) { return sum; } -/* -calculate COM boost object assuming fixed target collision with projectile -*/ -COMBoost getCOMboost(HEPEnergyType const& eProjectileLab, - MomentumVector const& pProjectileLab, - CoordinateSystemPtr const& cs) { - // define target - // for Sibyll is always a single nucleon - // FOR NOW: target is always at rest - auto const pTargetLab = MomentumVector(cs, 0_GeV, 0_GeV, 0_GeV); - FourVector const P4projLab(eProjectileLab, pProjectileLab); - // define target kinematics in lab frame - // define boost to and from CoM frame - // CoM frame definition in Sibyll projectile: +z - COMBoost const boost(P4projLab, constants::nucleonMass); - return boost; -} - TEST_CASE("SibyllInterface", "modules") { - logging::set_level(logging::level::info); + logging::set_level(logging::level::trace); // the environment and stack should eventually disappear from here auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Oxygen); @@ -168,6 +150,11 @@ TEST_CASE("SibyllInterface", "modules") { CHECK(xs_ela_pp == xs_ela_pHydrogen); CHECK(xs_ela_pn == xs_ela_pHydrogen); + // invalids + auto const xs_prod_0 = model.getCrossSection(Code::Electron, Code::Proton, aP4, bP4); + CHECK(xs_prod_0 / 1_mb == Approx(0)); + CHECK_THROWS(model.doInteraction(view, Code::Electron, Code::Proton, aP4, bP4)); + CHECK_THROWS(convertFromSibyll(corsika::sibyll::SibyllCode::Unknown)); } @@ -274,8 +261,18 @@ TEST_CASE("SibyllInterface", "modules") { MomentumVector(cs, {0_eV, 0_eV, 0_eV})); model.doInteraction(view, pid, Code::Oxygen, P4, targetP4); CrossSectionType const cx = model.getCrossSection(pid, Code::Oxygen, P4, targetP4); - CHECK(cx / 1_mb == Approx(1250).margin(100)); // this is not physics validation - CHECK(view.getSize() == Approx(40).margin(30)); // this is not physics validation + CHECK(cx / 1_mb == Approx(1250).margin(100)); // this is not physics validation + CHECK(view.getSize() == Approx(150).margin(140)); // this is not physics validation + + // invalid to underlying model + FourMomentum P4mu( + 100_GeV, + {cs, {sqrt(static_pow<2>(100_GeV) - static_pow<2>(MuPlus::mass)), 0_eV, 0_eV}}); + CrossSectionType const cx0 = + model.getCrossSection(Code::MuPlus, Code::Oxygen, P4mu, targetP4); + CHECK(cx0 / 1_mb == Approx(0)); + + CHECK_THROWS(model.doInteraction(view, Code::MuPlus, Code::Oxygen, P4mu, targetP4)); } } diff --git a/tests/modules/testUrQMD.cpp b/tests/modules/testUrQMD.cpp index 3b3da197bf501a9fdf73b11fcf851c39fe953182..f75d59b75b44a41d25376d013c9d9e0d813efa32 100644 --- a/tests/modules/testUrQMD.cpp +++ b/tests/modules/testUrQMD.cpp @@ -89,6 +89,7 @@ TEST_CASE("UrQMD") { } SECTION("cross sections") { + FourMomentum const targetP4{Nitrogen::mass, {rootCS, {0_eV, 0_eV, 0_eV}}}; HEPMomentumType const P0 = 100_GeV; @@ -108,6 +109,9 @@ TEST_CASE("UrQMD") { CORSIKA_LOG_INFO("UrQMD cross seciton for {} is {} mb", code, cx / 1_mb); CHECK(cx / 1_mb == Approx(checkCX[i++] / 1_mb).margin(1)); } + + // invalid + CHECK_THROWS(urqmd.getTabulatedCrossSection(Code::Proton, Code::Proton, 100_GeV)); } SECTION("pion+ projectile") {