diff --git a/corsika/detail/modules/epos/InteractionModel.inl b/corsika/detail/modules/epos/InteractionModel.inl index f9e8925b7b2da6d94744a6d2afcad1c4fefdfa6a..dbaeba716a2aba70d7d3bf5a55dd617d2585609f 100644 --- a/corsika/detail/modules/epos/InteractionModel.inl +++ b/corsika/detail/modules/epos/InteractionModel.inl @@ -76,7 +76,7 @@ namespace corsika::epos { ::epos::aaset_(iarg); // debug output settings - ::epos::prnt1_.ish = 0; // debug level in epos, 0: off, 6: medium output + ::epos::prnt1_.ish = 0; ::epos::prnt3_.iwseed = 0; // 1: printout seeds, 0: off ::epos::files_.ifch = 6; // output unit, 6: screen @@ -144,18 +144,18 @@ namespace corsika::epos { inline void InteractionModel::initializeEventCoM(Code const idBeam, int const iBeamA, int const iBeamZ, Code const idTarget, int const iTargetA, int const iTargetZ, - HEPEnergyType const Ecm) const { + HEPEnergyType const EcmNN) const { CORSIKA_LOGGER_TRACE(logger_, "initialize event in CoM frame!" " Ecm={}", - Ecm); + EcmNN); ::epos::lept1_.engy = -1.; ::epos::enrgy_.ecms = -1.; ::epos::enrgy_.elab = -1.; ::epos::enrgy_.ekin = -1.; ::epos::hadr1_.pnll = -1.; - ::epos::enrgy_.ecms = Ecm / 1_GeV; // -> c.m.s. frame + ::epos::enrgy_.ecms = EcmNN / 1_GeV; // -> c.m.s. frame CORSIKA_LOGGER_TRACE(logger_, "inside EPOS: Ecm={}, Elab={}", ::epos::enrgy_.ecms, ::epos::enrgy_.elab); @@ -366,43 +366,48 @@ namespace corsika::epos { count_ = count_ + 1; - // define projectile - // define projectile, in lab frame - auto const sqrtS2 = (projectileP4 + targetP4).getNormSqr(); - HEPEnergyType const sqrtS = sqrt(sqrtS2); - if (!isValid(projectileId, targetId, sqrtS)) { + // define nucleon-nucleon center-of-mass frame + auto const projectileP4NN = + projectileP4 / (is_nucleus(projectileId) ? get_nucleus_A(projectileId) : 1); + auto const targetP4NN = + targetP4 / (is_nucleus(targetId) ? get_nucleus_A(targetId) : 1); + auto const SNN = (projectileP4NN + targetP4NN).getNormSqr(); + HEPEnergyType const sqrtSNN = sqrt(SNN); + if (!isValid(projectileId, targetId, sqrtSNN)) { throw std::runtime_error("invalid projectile/target/energy combination."); } - HEPEnergyType const Elab = (sqrtS2 - static_pow<2>(get_mass(projectileId)) - + HEPEnergyType const Elab = (SNN - static_pow<2>(get_mass(projectileId)) - static_pow<2>(get_mass(targetId))) / (2 * get_mass(targetId)); // system of initial-state - COMBoost const boost(projectileP4, targetP4); + COMBoost const boost(projectileP4NN, targetP4NN); auto const& originalCS = boost.getOriginalCS(); auto const& csPrime = boost.getRotatedCS(); // z is along the CM motion (projectile, in Cascade) - HEPMomentumType const pLabMag = - sqrt((Elab - get_mass(projectileId)) * (Elab + get_mass(projectileId))); - MomentumVector pLab(csPrime, {0_eV, 0_eV, pLabMag}); - CORSIKA_LOGGER_DEBUG(logger_, "doInteraction: interaction, projectile id={}, E={}, p3={} ", projectileId, projectileP4.getTimeLikeComponent(), projectileP4.getSpaceLikeComponents()); + CORSIKA_LOGGER_DEBUG( + logger_, "doInteraction: projectile per-nucleon ENN={}, p3NN={} ", + projectileP4NN.getTimeLikeComponent(), projectileP4NN.getSpaceLikeComponents()); CORSIKA_LOGGER_DEBUG( logger_, "doInteraction: interaction, target id={}, E={}, p3={} ", targetId, targetP4.getTimeLikeComponent(), targetP4.getSpaceLikeComponents()); - CORSIKA_LOGGER_DEBUG(logger_, "doInteraction: Elab={}, sqrtS={} ", Elab, sqrtS); + CORSIKA_LOGGER_DEBUG(logger_, "doInteraction: target per-nucleon ENN={}, p3NN={} ", + targetP4NN.getTimeLikeComponent(), + targetP4NN.getSpaceLikeComponents()); + CORSIKA_LOGGER_DEBUG(logger_, "doInteraction: Elab={}, sqrtSNN={} ", Elab, sqrtSNN); int beamA = 1; int beamZ = 1; if (is_nucleus(projectileId)) { beamA = get_nucleus_A(projectileId); beamZ = get_nucleus_Z(projectileId); - CORSIKA_LOGGER_DEBUG(logger_, "A={}, Z={} ", beamA, beamZ); + CORSIKA_LOGGER_DEBUG(logger_, "projectile: A={}, Z={} ", beamA, beamZ); } // // from corsika7 interface @@ -412,8 +417,9 @@ namespace corsika::epos { if (is_nucleus(targetId)) { targetA = get_nucleus_A(targetId); targetZ = get_nucleus_Z(targetId); + CORSIKA_LOGGER_DEBUG(logger_, "target: A={}, Z={} ", beamA, beamZ); } - initializeEventCoM(projectileId, beamA, beamZ, targetId, targetA, targetZ, sqrtS); + initializeEventCoM(projectileId, beamA, beamZ, targetId, targetA, targetZ, sqrtSNN); // create event int iarg = 1; diff --git a/corsika/detail/modules/qgsjetII/InteractionModel.inl b/corsika/detail/modules/qgsjetII/InteractionModel.inl index 13ad2d0c814ff994a47c4bd00ec8d9632d85442d..649fb3ddb7e11192fa3ab2c0851efdd0626b17be 100644 --- a/corsika/detail/modules/qgsjetII/InteractionModel.inl +++ b/corsika/detail/modules/qgsjetII/InteractionModel.inl @@ -70,11 +70,14 @@ namespace corsika::qgsjetII { } // define projectile, in lab frame - auto const sqrtS2 = (projectileP4 + targetP4).getNormSqr(); - auto const sqrtS = sqrt(sqrtS2); - if (!isValid(projectileId, targetId, sqrtS)) { return CrossSectionType::zero(); } + auto const SNN = + (projectileP4 / (is_nucleus(projectileId) ? get_nucleus_A(projectileId) : 1) + + targetP4 / (is_nucleus(targetId) ? get_nucleus_A(targetId) : 1)) + .getNormSqr(); + auto const sqrtSNN = sqrt(SNN); + if (!isValid(projectileId, targetId, sqrtSNN)) { return CrossSectionType::zero(); } HEPEnergyType const Elab = - calculate_lab_energy(sqrtS2, get_mass(projectileId), get_mass(targetId)); + calculate_lab_energy(SNN, get_mass(projectileId), get_mass(targetId)); int const iBeam = static_cast<QgsjetIIXSClassIntType>( corsika::qgsjetII::getQgsjetIIXSCode(projectileId)); @@ -104,14 +107,25 @@ namespace corsika::qgsjetII { projectileId, corsika::qgsjetII::canInteract(projectileId)); // define projectile, in lab frame - auto const sqrtS2 = (projectileP4 + targetP4).getNormSqr(); - auto const sqrtS = sqrt(sqrtS2); + auto const SNN = + (projectileP4 / (is_nucleus(projectileId) ? get_nucleus_A(projectileId) : 1) + + targetP4 / (is_nucleus(targetId) ? get_nucleus_A(targetId) : 1)) + .getNormSqr(); + auto const sqrtS = sqrt(SNN); if (!corsika::qgsjetII::canInteract(projectileId) || !isValid(projectileId, targetId, sqrtS)) { throw std::runtime_error("invalid target/projectile/energy combination."); } - HEPEnergyType const Elab = - calculate_lab_energy(sqrtS2, get_mass(projectileId), get_mass(targetId)); + auto const projectileMass = + (is_nucleus(projectileId) ? constants::nucleonMass : get_mass(projectileId)); + auto const targetMass = + (projectileId == Code::Proton + ? get_mass(Code::Proton) + : constants::nucleonMass); // qgsjet target is always proton or nucleon. + // always nucleon?? + + // lab energy/hadron + HEPEnergyType const Elab = calculate_lab_energy(SNN, projectileMass, targetMass); int beamA = 0; if (is_nucleus(projectileId)) { beamA = get_nucleus_A(projectileId); } @@ -163,18 +177,18 @@ namespace corsika::qgsjetII { // rest. // system of initial-state - COMBoost boost(projectileP4, targetP4); + COMBoost boost(projectileP4 / projectileMassNumber, targetP4 / targetMassNumber); auto const& originalCS = boost.getOriginalCS(); auto const& csPrime = boost.getRotatedCS(); // z is along the CM motion (projectile, in Cascade) HEPMomentumType const pLabMag = - sqrt((Elab - get_mass(projectileId)) * (Elab + get_mass(projectileId))); + sqrt((Elab - projectileMass) * (Elab + projectileMass)); MomentumVector pLab(csPrime, {0_eV, 0_eV, pLabMag}); - // internal QGSJetII system - COMBoost boostInternal({Elab, pLab}, get_mass(targetId)); + // internal QGSJetII system: hadron-nucleon lab. frame! + COMBoost boostInternal({Elab, pLab}, targetMass); // fragments QGSJetIIFragmentsStack qfs; @@ -265,7 +279,7 @@ namespace corsika::qgsjetII { Plab_final += pnew.getMomentum(); Elab_final += pnew.getEnergy(); } - } // namespace corsika::qgsjetII + } // secondaries QGSJetIIStack qs; diff --git a/tests/modules/testQGSJetII.cpp b/tests/modules/testQGSJetII.cpp index 966928f9a06d8dfade6ddebca63c9639a7d2a90c..e9caaecf8c3341c53351e78c023a96838af2bd76 100644 --- a/tests/modules/testQGSJetII.cpp +++ b/tests/modules/testQGSJetII.cpp @@ -123,6 +123,8 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { logging::set_level(logging::level::info); + RNGManager<>::getInstance().registerRandomStream("qgsjet"); + auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Oxygen); auto const& cs = *csPtr; [[maybe_unused]] auto const& env_dummy = env; @@ -174,7 +176,7 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { corsika::qgsjetII::InteractionModel model; model.doInteraction(view, pid, Code::Oxygen, projectileP4, targetP4); // this also should produce some fragments - CHECK(view.getSize() == Approx(300).margin(150)); // this is not physics validation + CHECK(view.getSize() == Approx(150).margin(150)); // this is not physics validation int countFragments = 0; for (auto const& sec : view) { countFragments += (is_nucleus(sec.getPID())); } CHECK(countFragments == Approx(4).margin(2)); // this is not physics validation @@ -216,7 +218,7 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { {sqrt(static_pow<2>(1_TeV) + static_pow<2>(Pi0::mass)), MomentumVector{cs, 1_TeV, 0_GeV, 0_GeV}}, {Oxygen::mass, MomentumVector{cs, 0_eV, 0_eV, 0_eV}}); - CHECK(view.getSize() == Approx(10).margin(8)); // this is not physics validation + CHECK(view.getSize() == Approx(20).margin(20)); // this is not physics validation } { // rho0 is internally converted into pi-/pi+ auto [stackPtr, secViewPtr] = setup::testing::setup_stack( @@ -228,7 +230,7 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { {sqrt(static_pow<2>(1_TeV) + static_pow<2>(Rho0::mass)), MomentumVector{cs, 1_TeV, 0_GeV, 0_GeV}}, {Oxygen::mass, MomentumVector{cs, 0_eV, 0_eV, 0_eV}}); - CHECK(view.getSize() == Approx(25).margin(20)); // this is not physics validation + CHECK(view.getSize() == Approx(50).margin(50)); // this is not physics validation } { // Lambda is internally converted into neutron auto [stackPtr, secViewPtr] = setup::testing::setup_stack( @@ -241,7 +243,7 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { {sqrt(static_pow<2>(100_GeV) + static_pow<2>(Lambda0::mass)), MomentumVector{cs, 100_GeV, 0_GeV, 0_GeV}}, {Oxygen::mass, MomentumVector{cs, 0_eV, 0_eV, 0_eV}}); - CHECK(view.getSize() == Approx(25).margin(20)); // this is not physics validation + CHECK(view.getSize() == Approx(50).margin(50)); // this is not physics validation } { // AntiLambda is internally converted into anti neutron auto [stackPtr, secViewPtr] = setup::testing::setup_stack(