From 47a4ae403b8284c7008d73265f09d3b7b9e25234 Mon Sep 17 00:00:00 2001 From: Felix Riehn <felix@matilda> Date: Wed, 19 May 2021 12:12:01 +0100 Subject: [PATCH] fixed cross section types, read tables instead of calculate anew --- corsika/detail/modules/epos/Interaction.inl | 184 +++++++++++++------- corsika/modules/epos/Interaction.hpp | 25 ++- corsika/modules/epos/ParticleConversion.hpp | 6 +- modules/epos/epos.hpp | 13 +- src/modules/epos/code_generator.py | 2 +- tests/modules/testEpos.cpp | 56 +++--- 6 files changed, 193 insertions(+), 93 deletions(-) diff --git a/corsika/detail/modules/epos/Interaction.inl b/corsika/detail/modules/epos/Interaction.inl index 79cc7cd0a..be56c26dc 100644 --- a/corsika/detail/modules/epos/Interaction.inl +++ b/corsika/detail/modules/epos/Interaction.inl @@ -232,7 +232,7 @@ namespace corsika::epos { "Beam={}, " "BeamA={}, " "BeamZ={}, " - "Target={}" + "Target={}, " "TargetA={}, " "TargetZ={} ", idBeam, iBeamA, iBeamZ, idTarget, iTargetA, iTargetZ); @@ -241,8 +241,10 @@ namespace corsika::epos { ::epos::hadr25_.idprojin = convertToEposRaw(Code::Proton); ::epos::nucl1_.laproj = iBeamZ; // get_nucleus_Z(idBeam); ::epos::nucl1_.maproj = iBeamA; // get_nucleus_A(idBeam); + ::epos::had10_.iclpro = corsika::epos::getEposXSCode(Code::Proton); } else { ::epos::hadr25_.idprojin = convertToEposRaw(idBeam); + ::epos::had10_.iclpro = corsika::epos::getEposXSCode(idBeam); ::epos::nucl1_.laproj = -1; ::epos::nucl1_.maproj = 1; } @@ -251,14 +253,17 @@ namespace corsika::epos { ::epos::hadr25_.idtargin = convertToEposRaw(Code::Proton); ::epos::nucl1_.matarg = iTargetA; // get_nucleus_A(idTarget); ::epos::nucl1_.latarg = iTargetZ; // get_nucleus_Z(idTarget); + ::epos::had10_.icltar = corsika::epos::getEposXSCode(Code::Proton); } else if (idTarget == Code::Proton || idTarget == Code::Hydrogen) { ::epos::hadr25_.idtargin = convertToEposRaw(Code::Proton); ::epos::nucl1_.matarg = 1; ::epos::nucl1_.latarg = -1; + ::epos::had10_.icltar = corsika::epos::getEposXSCode(Code::Proton); } else if (idTarget == Code::Neutron) { ::epos::hadr25_.idtargin = convertToEposRaw(Code::Neutron); ::epos::nucl1_.matarg = 1; ::epos::nucl1_.latarg = -1; + ::epos::had10_.icltar = corsika::epos::getEposXSCode(Code::Proton); } else { throw std::runtime_error("Epos: configure_particles: target outside range!"); } @@ -267,33 +272,36 @@ namespace corsika::epos { "Id beam={}, " "Z beam={}, " "A beam={}, " + "XS beam={}, " "Id target={}, " "Z target={}, " - "A target={}", + "A target={}, " + "XS target={} ", ::epos::hadr25_.idprojin, ::epos::nucl1_.laproj, - ::epos::nucl1_.maproj, ::epos::hadr25_.idtargin, - ::epos::nucl1_.latarg, ::epos::nucl1_.matarg); + ::epos::nucl1_.maproj, ::epos::had10_.iclpro, + ::epos::hadr25_.idtargin, ::epos::nucl1_.latarg, + ::epos::nucl1_.matarg, ::epos::had10_.icltar); } inline Interaction::~Interaction() { CORSIKA_LOGGER_DEBUG(logger_, "n={} ", count_); } - inline std::tuple<corsika::CrossSectionType, corsika::CrossSectionType> - Interaction::getCrossSection(corsika::Code const BeamId, corsika::Code const TargetId, - const corsika::HEPEnergyType EnergyCOM) const { - if (!is_nucleus(BeamId)) - return getCrossSection(BeamId, 1, 1, TargetId, get_nucleus_A(TargetId), - get_nucleus_Z(TargetId), EnergyCOM); - else - throw("nuclear projecile, call getCrossSection with : BeamId, BeamA, BeamZ, ..."); - } + // inline std::tuple<corsika::CrossSectionType, corsika::CrossSectionType> + // Interaction::getCrossSection(corsika::Code const BeamId, corsika::Code const TargetId, + // const corsika::HEPEnergyType EnergyCOM) const { + // if (!is_nucleus(BeamId)) + // return getCrossSection(BeamId, 1, 1, TargetId, get_nucleus_A(TargetId), + // get_nucleus_Z(TargetId), EnergyCOM); + // else + // throw("nuclear projecile, call getCrossSection with : BeamId, BeamA, BeamZ, ..."); + // } inline std::tuple<corsika::CrossSectionType, corsika::CrossSectionType> - Interaction::getCrossSection(corsika::Code const BeamId, int const BeamA, + Interaction::calcCrossSectionCoM(corsika::Code const BeamId, int const BeamA, int const BeamZ, corsika::Code const TargetId, int const TargetA, int const TargetZ, const corsika::HEPEnergyType EnergyCOM) const { CORSIKA_LOGGER_DEBUG(logger_, - "getCrossSection: input:" + "calcCrossSection: input:" " beamId={}, beamA={}, beamZ={}" " target={}, targetA={}, targetZ={}" " Ecm={:4.3f} GeV,", @@ -304,29 +312,29 @@ namespace corsika::epos { BeamId); // 0 (can not interact, 1: proton-like, 2: pion-like, 3:kaon-like) if (!iBeam) throw std::runtime_error( - "getCrossSection: interaction of beam hadron not defined in " + "calcCrossSectionCoM: interaction of beam hadron not defined in " "Epos!"); CORSIKA_LOGGER_TRACE(logger_, "projectile cross section type={} " - "(0: cannot interact, 1:baryon, 2:pion, 3:kaon, 4:nucleus)", + "(0: cannot interact, 1:pion, 2:baryon, 3:kaon)", iBeam); - // reset beam particle // (1: proton-like, 2: pion-like, 3:kaon-like, 4:nucleus) + // reset beam particle // (1: pion-like, 2: proton-like, 3:kaon-like) if (iBeam == 1) - initialize_event_CoM(Code::Proton, BeamA, BeamZ, TargetId, TargetA, TargetZ, - EnergyCOM); - else if (iBeam == 2) initialize_event_CoM(Code::PiPlus, BeamA, BeamZ, TargetId, TargetA, TargetZ, EnergyCOM); + else if (iBeam == 2) + initialize_event_CoM(Code::Proton, BeamA, BeamZ, TargetId, TargetA, TargetZ, + EnergyCOM); else if (iBeam == 3) initialize_event_CoM(Code::KPlus, BeamA, BeamZ, TargetId, TargetA, TargetZ, EnergyCOM); - else if (iBeam == 4) - initialize_event_CoM(Code::Nucleus, BeamA, BeamZ, TargetId, TargetA, TargetZ, - EnergyCOM); + // else if (iBeam == 4) + // initialize_event_CoM(Code::Nucleus, BeamA, BeamZ, TargetId, TargetA, TargetZ, + // EnergyCOM); else throw std::runtime_error( - "getCrossSection: interaction of beam hadron not defined in " + "calcCrossSectionCoM: interaction of beam hadron not defined in " "Epos!"); //::epos::xsigma_(); @@ -349,33 +357,88 @@ namespace corsika::epos { //::epos::crseaaepos_(sigTot, sigProd, sigCut, sigEla); CORSIKA_LOGGER_DEBUG(logger_, - "getCrossSection: output:" + "calcCrossSectionCoM: output:" " sigProd={} mb," " sigEla={} mb", sigProd, sigEla); return std::make_tuple(sigProd * 1_mb, sigEla * 1_mb); + } + + inline std::tuple<corsika::CrossSectionType, corsika::CrossSectionType> + Interaction::readCrossSectionTableLab(Code const BeamId, int const BeamA, + int const BeamZ, Code const TargetId, + HEPEnergyType const EnergyLab) const { + CORSIKA_LOGGER_DEBUG(logger_, + "readCrossSectionTableLab: input: " + "beamId={}, " + "beamA={}, " + "beamZ={} " + "targetId={}, " + "ELab={:4.3f} GeV,", + BeamId, BeamA, BeamZ, TargetId, EnergyLab / 1_GeV); // read cross section from epos internal tables + int Abeam; + float Ekin = -1; + + if (is_nucleus(BeamId)) { + Abeam = BeamA; + // kinetic energy per nucleon + Ekin = (EnergyLab / Abeam - constants::nucleonMass) / 1_GeV; + } else { + ::epos::hadr2_.idproj = convertToEposRaw(BeamId); + int const iBeam = corsika::epos::getEposXSCode( + BeamId); // 0 (can not interact, 1: pion-like, 2: proton-like, 3:kaon-like) + CORSIKA_LOGGER_TRACE(logger_, + "projectile cross section type={} " + "(0: cannot interact, 1:pion, 2:baryon, 3:kaon)", + iBeam); + + ::epos::had10_.iclpro = iBeam; + Abeam = 1; + Ekin = (EnergyLab - get_mass(BeamId)) / 1_GeV; + } + if (Ekin < 0) { + CORSIKA_LOGGER_ERROR(logger_, + "Negative kinetic energy!" + "Ekin={}", + Ekin); + throw std::runtime_error("Epos cross section failed! Negative kinetic energy!"); + } + + int Atarget; + if (is_nucleus(TargetId)) + Atarget = get_nucleus_A(TargetId); + else + Atarget = 1; + + int iMode = 3; // 0: air, >0 not air + + CORSIKA_LOGGER_DEBUG(logger_, + "inside Epos " + "beamId={}, beamXS={}", + ::epos::hadr2_.idproj, ::epos::had10_.iclpro); + + float sigProdEpos = ::epos::eposcrse_(Ekin, Abeam, Atarget, iMode); + float sigElaEpos = ::epos::eposelacrse_(Ekin, Abeam, Atarget, iMode); - // int Abeam; - // int iBeamId; - // if(is_nucleus(BeamId)){ - // Abeam = get_nucleus_A(BeamId); - // iBeamId = 1; //convertToEposRaw(BeamId); - // } else { - // ::epos::hadr2_.idproj = convertToEposRaw(BeamId); - // Abeam = 1; - // } - // int Atarget; - // if(is_nucleus(TargetId)) - // Atarget = get_nucleus_A(TargetId); - // else - - // float Ekin = (EnergyLab-get_mass(BeamId)) / 1_GeV; - // float sigProdEpos = ::epos::eposcrse_(Ekin,iBeamId); - // float sigElaEpos = ::epos::eposelacrse_(); - // return std::make_tuple(sigProdEpos * 1_mb, sigElaEpos * 1_mb); + return std::make_tuple(sigProdEpos * 1_mb, sigElaEpos * 1_mb); + } + + inline std::tuple<corsika::CrossSectionType, corsika::CrossSectionType> + Interaction::getCrossSectionLab(corsika::Code const BeamId, int const BeamA, + int const BeamZ, corsika::Code const TargetId, + int const TargetA, int const TargetZ, + const corsika::HEPEnergyType EnergyLab) const { + CORSIKA_LOGGER_DEBUG(logger_, + "getCrossSectionLab: input:" + " beamId={}, beamA={}, beamZ={}" + " target={}, targetA={}, targetZ={}" + " ELab={:4.3f} GeV,", + BeamId, BeamA, BeamZ, TargetId, TargetA, TargetZ, + EnergyLab / 1_GeV); + return readCrossSectionTableLab(BeamId, BeamA, BeamZ, TargetId, EnergyLab); } template <> @@ -417,13 +480,13 @@ namespace corsika::epos { // total momentum and energy HEPEnergyType Elab = projectile.getEnergy() + constants::nucleonMass; - MomentumVector pTotLab(labCS, {0_GeV, 0_GeV, 0_GeV}); - pTotLab += pLab; - pTotLab += pTarget; - auto const pTotLabNorm = pTotLab.getNorm(); + // MomentumVector pTotLab(labCS, {0_GeV, 0_GeV, 0_GeV}); + // pTotLab += pLab; + // pTotLab += pTarget; + // auto const pTotLabNorm = pTotLab.getNorm(); // calculate cm. energy - const HEPEnergyType ECoM = sqrt( - (Elab + pTotLabNorm) * (Elab - pTotLabNorm)); // binomial for numerical accuracy + // const HEPEnergyType ECoM = sqrt( + // (Elab + pTotLabNorm) * (Elab - pTotLabNorm)); // binomial for numerical accuracy auto const* currentNode = projectile.getNode(); const auto& mediumComposition = @@ -431,9 +494,9 @@ namespace corsika::epos { si::CrossSectionType weightedProdCrossSection = mediumComposition.getWeightedSum( [=](corsika::Code targetID) -> si::CrossSectionType { - return std::get<0>(this->getCrossSection(corsikaBeamId, beamA, beamZ, - targetID, get_nucleus_A(targetID), - get_nucleus_Z(targetID), ECoM)); + return std::get<0>(this->getCrossSectionLab(corsikaBeamId, beamA, beamZ, + targetID, get_nucleus_A(targetID), + get_nucleus_Z(targetID), Elab)); }); CORSIKA_LOGGER_DEBUG(logger_, "InteractionLength: weighted CrossSection (mb): {} ", @@ -485,11 +548,11 @@ namespace corsika::epos { HEPEnergyType const projectileMomentumLabPerNucleon = projectileMomentum / beamA; // define target - auto const eTargetLab = 0_GeV + constants::nucleonMass; - HEPEnergyType const Etot = eProjectileLab + eTargetLab; + // auto const eTargetLab = 0_GeV + constants::nucleonMass; + // HEPEnergyType const Etot = eProjectileLab + eTargetLab; // invariant mass, i.e. cm. energy - HEPEnergyType const Ecm = - sqrt((Etot + projectileMomentum) * (Etot - projectileMomentum)); + // HEPEnergyType const Ecm = + // sqrt((Etot + projectileMomentum) * (Etot - projectileMomentum)); // sample target mass number auto const* currentNode = projectile.getNode(); @@ -506,9 +569,9 @@ namespace corsika::epos { for (size_t i = 0; i < compVec.size(); ++i) { auto const targetId = compVec[i]; - [[maybe_unused]] auto const [sigProd, sigEla] = - getCrossSection(corsikaBeamId, beamA, beamZ, targetId, - get_nucleus_A(targetId), get_nucleus_Z(targetId), Ecm); + [[maybe_unused]] auto const [sigProd, sigEla] = getCrossSectionLab( + corsikaBeamId, beamA, beamZ, targetId, get_nucleus_A(targetId), + get_nucleus_Z(targetId), eProjectileLab); cross_section_of_components[i] = sigProd; } @@ -535,7 +598,6 @@ namespace corsika::epos { ::epos::afinal_(); if (epos_listing_) { - //std::string nam = "EPOSLHC&"; char nam[9] = "EPOSLHC&"; ::epos::alistf_(nam); } diff --git a/corsika/modules/epos/Interaction.hpp b/corsika/modules/epos/Interaction.hpp index 0f7c1f6ba..647fbec75 100644 --- a/corsika/modules/epos/Interaction.hpp +++ b/corsika/modules/epos/Interaction.hpp @@ -27,13 +27,30 @@ namespace corsika::epos { //! returns production and elastic cross section for hadrons in epos. Inputs are: //! CorsikaId of beam particle, CorsikaId of target particle, center-of-mass energy. - //! Allowed targets are: nuclei or single nucleons (p,n,hydrogen). - std::tuple<CrossSectionType, CrossSectionType> getCrossSection( + //! Allowed targets are: nuclei or single nucleons (p,n,hydrogen). This routine + //! calculates the cross sections from scratch. Very slow! + std::tuple<CrossSectionType, CrossSectionType> calcCrossSectionCoM( Code const, int const, int const, Code const, int const, int const, HEPEnergyType const) const; - std::tuple<CrossSectionType, CrossSectionType> getCrossSection( - Code const, Code const, HEPEnergyType const) const; + //! returns production and elastic cross section for hadrons in epos by reading + //! pre-calculated tables from epos. + std::tuple<CrossSectionType, CrossSectionType> readCrossSectionTableLab( + Code const, int const, int const, Code const, HEPEnergyType const) const; + + //! returns production and elastic cross section. Allowed configurations are + //! hadron-nucleon, hadron-nucleus and nucleus-nucleus. Inputs are particle id's mass + //! and charge numbers and total energy in the lab. + std::tuple<CrossSectionType, CrossSectionType> getCrossSectionLab( + Code const, int const, int const, Code const, int const, int const, + HEPEnergyType const) const; + + // std::tuple<CrossSectionType, CrossSectionType> getCrossSection( + // Code const, int const, int const, Code const, int const, int const, + // HEPEnergyType const) const; + + // std::tuple<CrossSectionType, CrossSectionType> getCrossSection( + // Code const, Code const, HEPEnergyType const) const; template <typename TParticle> GrammageType getInteractionLength(TParticle const&) const; diff --git a/corsika/modules/epos/ParticleConversion.hpp b/corsika/modules/epos/ParticleConversion.hpp index 252ebea38..e50c80848 100644 --- a/corsika/modules/epos/ParticleConversion.hpp +++ b/corsika/modules/epos/ParticleConversion.hpp @@ -25,10 +25,10 @@ namespace corsika::epos { */ enum class EposXSClass : int8_t { CannotInteract = 0, - Baryon = 1, - Pion = 2, + Baryon = 2, + Pion = 1, Kaon = 3, - Nucleus = 4 + Charm = 4, }; using EposXSClassIntType = std::underlying_type<EposXSClass>::type; diff --git a/modules/epos/epos.hpp b/modules/epos/epos.hpp index d8b77d359..a5ad0c9ff 100644 --- a/modules/epos/epos.hpp +++ b/modules/epos/epos.hpp @@ -52,8 +52,8 @@ namespace epos { void conini_(); void psaini_(); - void idspin_(int&, int&, int&, int&); - void iclass_(int&, int&); + //void idspin_(int&, int&, int&, int&); + // void iclass_(int&, int&); void emsini_(double&, int&, int&); void paramini_(int&); void xsigma_(); @@ -489,6 +489,15 @@ namespace epos { int nody[mxnody]; } nodcy_; + + // integer iclpro,icltar,iclegy + // common/had10/iclpro,icltar,iclegy + extern struct { + int iclpro; + int icltar; + int iclegy; + } had10_; + /** Small helper class to provide a data-directory name in the format eposlhc expects */ diff --git a/src/modules/epos/code_generator.py b/src/modules/epos/code_generator.py index 970495cc0..74d2e05e2 100755 --- a/src/modules/epos/code_generator.py +++ b/src/modules/epos/code_generator.py @@ -57,7 +57,7 @@ def set_default_epos_definition(particle_db): xsType = "CannotInteract" hadronType = "UndefinedType" if (pData['isNucleus']): - xsType = "Nucleus" + xsType = "Baryon" hadronType = "NucleusType" pData['epos_xsType'] = xsType diff --git a/tests/modules/testEpos.cpp b/tests/modules/testEpos.cpp index 68b31673d..75f74acb3 100644 --- a/tests/modules/testEpos.cpp +++ b/tests/modules/testEpos.cpp @@ -119,6 +119,11 @@ auto sumMomentum(TStackView const& view, CoordinateSystemPtr const& vCS) { return sum; } +auto sqs2elab(HEPEnergyType const sqs, HEPEnergyType const ma, + HEPEnergyType const mb){ + return (sqs * sqs - ma * ma - mb * mb) / 2. / mb; +} + TEST_CASE("EposInterface", "[processes]") { corsika_logger->set_pattern("[%n:%^%-8l%$] custom pattern: %v"); @@ -148,17 +153,17 @@ TEST_CASE("EposInterface", "[processes]") { CHECK_FALSE(model.isValidTarget(Code::Iron)); CHECK(model.isValidTarget(Code::Oxygen)); - // hydrogen target == proton target == neutron target - // auto const [xs_prod_pp, xs_ela_pp] = - // model.getCrossSection(Code::Proton, Code::Proton, 100_GeV); - // auto const [xs_prod_pn, xs_ela_pn] = - // model.getCrossSection(Code::Proton, Code::Neutron, 100_GeV); - // auto const [xs_prod_pHydrogen, xs_ela_pHydrogen] = - // model.getCrossSection(Code::Proton, 1, 1, Code::Hydrogen, 1, 1, 100_GeV); - // CHECK(xs_prod_pp == xs_prod_pHydrogen); - // CHECK(xs_prod_pp == xs_prod_pn); - // CHECK(xs_ela_pp == xs_ela_pHydrogen); - // CHECK(xs_ela_pn == xs_ela_pHydrogen); + // hydrogen target == proton target == neutron target + auto const [xs_prod_pp, xs_ela_pp] = + model.getCrossSectionLab(Code::Proton, 1, 1, Code::Proton, 1, 1, 100_GeV); + auto const [xs_prod_pn, xs_ela_pn] = + model.getCrossSectionLab(Code::Proton, 1, 1, Code::Neutron, 1, 0, 100_GeV); + auto const [xs_prod_pHydrogen, xs_ela_pHydrogen] = + model.getCrossSectionLab(Code::Proton, 1, 1, Code::Hydrogen, 1, 1, 100_GeV); + CHECK(xs_prod_pp == xs_prod_pHydrogen); + CHECK(xs_prod_pp == xs_prod_pn); + CHECK(xs_ela_pp == xs_ela_pHydrogen); + CHECK(xs_ela_pn == xs_ela_pHydrogen); } SECTION("InteractionInterface - hadron cross sections") { @@ -166,19 +171,22 @@ TEST_CASE("EposInterface", "[processes]") { Interaction model; // eposlhc accepts protons or nuclei with 4<=A<=18 as targets - // p-p at 7TeV + // p-p at 7TeV around 70mb according to LHC auto const [xs_prod, xs_ela] = - model.getCrossSection(Code::Proton, Code::Proton, 7_TeV); + model.getCrossSectionLab(Code::Proton, 1, 1, Code::Proton, 1, 1, + sqs2elab(7_TeV, Proton::mass, Proton::mass)); CHECK(xs_prod / 1_mb == Approx(70.7).margin(2.1)); // pi-n at 7TeV auto const [xs_prod1, xs_ela1] = - model.getCrossSection(Code::PiPlus, Code::Neutron, 7_TeV); + model.getCrossSectionLab(Code::PiPlus, 0, 0, Code::Neutron, 1, 0, + sqs2elab(7_TeV, PiPlus::mass, Neutron::mass)); CHECK(xs_prod1 / 1_mb == Approx(52.7).margin(2.1)); // k-p at 7TeV auto const [xs_prod2, xs_ela2] = - model.getCrossSection(Code::KPlus, Code::Proton, 7_TeV); + model.getCrossSectionLab(Code::KPlus, 0, 0, Code::Proton, 1, 1, + sqs2elab(7_TeV, KPlus::mass, Proton::mass)); CHECK(xs_prod2 / 1_mb == Approx(45.7).margin(2.1)); } @@ -187,15 +195,20 @@ TEST_CASE("EposInterface", "[processes]") { Interaction model; // eposlhc accepts protons or nuclei with 4<=A<=18 as targets - auto const [xs_prod, xs_ela] = - model.getCrossSection(Code::Proton, Code::Oxygen, 100_GeV); - CHECK(xs_prod / 1_mb == Approx(327.7).margin(5.1)); + auto const [xs_prod, xs_ela] = model.getCrossSectionLab( + Code::Proton, 1, 1, Code::Oxygen, Oxygen::nucleus_A, Oxygen::nucleus_Z, 100_GeV); + CHECK(xs_prod / 1_mb == Approx(287.0).margin(5.1)); - auto const [xs_prod2, xs_ela2] = model.getCrossSection( + auto const [xs_prod2, xs_ela2] = model.getCrossSectionLab( Code::Nitrogen, Nitrogen::nucleus_A, Nitrogen::nucleus_Z, Code::Oxygen, - Oxygen::nucleus_A, Oxygen::nucleus_Z, 10_GeV); + Oxygen::nucleus_A, Oxygen::nucleus_Z, 400_GeV); CHECK(xs_prod2 / 1_mb == Approx(1076.7).margin(3.1)); + // nuclear stack extension, particle "Nucleus" + auto const [xs_prod3, xs_ela3] = model.getCrossSectionLab( + Code::Nucleus, Nitrogen::nucleus_A, Nitrogen::nucleus_Z, Code::Oxygen, + Oxygen::nucleus_A, Oxygen::nucleus_Z, 400_GeV); + CHECK(xs_prod2 / xs_prod3 == 1); } SECTION("InteractionInterface - low energy") { @@ -252,8 +265,7 @@ TEST_CASE("EposInterface", "[processes]") { 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(12.8).margin(0.1)); + CHECK(length / 1_g * 1_cm * 1_cm == Approx(12.8).margin(4.1)); } - } -- GitLab