IAP GITLAB

Skip to content
Snippets Groups Projects
Commit d7ac9f8a authored by ralfulrich's avatar ralfulrich Committed by Ralf Ulrich
Browse files

qgsjetII new interface

parent 6b237f7c
No related branches found
No related tags found
No related merge requests found
...@@ -6,10 +6,8 @@ ...@@ -6,10 +6,8 @@
* the license. * the license.
*/ */
#include <corsika/modules/qgsjetII/Interaction.hpp> #include <corsika/modules/qgsjetII/InteractionModel.hpp>
#include <corsika/media/Environment.hpp>
#include <corsika/media/NuclearComposition.hpp>
#include <corsika/framework/geometry/QuantityVector.hpp> #include <corsika/framework/geometry/QuantityVector.hpp>
#include <corsika/framework/geometry/FourVector.hpp> #include <corsika/framework/geometry/FourVector.hpp>
#include <corsika/modules/qgsjetII/ParticleConversion.hpp> #include <corsika/modules/qgsjetII/ParticleConversion.hpp>
...@@ -18,14 +16,13 @@ ...@@ -18,14 +16,13 @@
#include <corsika/framework/utility/COMBoost.hpp> #include <corsika/framework/utility/COMBoost.hpp>
#include <sstream> #include <sstream>
#include <string>
#include <tuple> #include <tuple>
#include <qgsjet-II-04.hpp> #include <qgsjet-II-04.hpp>
namespace corsika::qgsjetII { namespace corsika::qgsjetII {
inline Interaction::Interaction(boost::filesystem::path dataPath) { inline InteractionModel::InteractionModel(boost::filesystem::path const dataPath) {
CORSIKA_LOG_DEBUG("Reading QGSJetII data tables from {}", dataPath); CORSIKA_LOG_DEBUG("Reading QGSJetII data tables from {}", dataPath);
// initialize QgsjetII // initialize QgsjetII
...@@ -38,246 +35,121 @@ namespace corsika::qgsjetII { ...@@ -38,246 +35,121 @@ namespace corsika::qgsjetII {
} }
} }
inline Interaction::~Interaction() { inline InteractionModel::~InteractionModel() {
CORSIKA_LOG_DEBUG("QgsjetII::Interaction n= {}", count_); CORSIKA_LOG_DEBUG("QgsjetII::InteractionModel n= {}", count_);
} }
inline CrossSectionType Interaction::getCrossSection(const Code beamId, inline void InteractionModel::isValid(Code const projectileId,
const Code targetId, Code const targetId) const {
const HEPEnergyType Elab, if (is_nucleus(targetId)) {
const unsigned int Abeam, size_t iTarget = get_nucleus_A(targetId);
const unsigned int targetA) const { if (iTarget > int(maxMassNumber_) || iTarget <= 0) {
double sigProd = std::numeric_limits<double>::infinity(); std::ostringstream txt;
txt << "QgsjetII target outside range. Atarget=" << iTarget;
if (corsika::qgsjetII::canInteract(beamId)) { throw std::runtime_error(txt.str().c_str());
int const iBeam = static_cast<QgsjetIIXSClassIntType>(
corsika::qgsjetII::getQgsjetIIXSCode(beamId));
int iTarget = 1;
if (is_nucleus(targetId)) {
iTarget = targetA;
if (iTarget > int(maxMassNumber_) || iTarget <= 0) {
std::ostringstream txt;
txt << "QgsjetII target outside range. Atarget=" << iTarget;
throw std::runtime_error(txt.str().c_str());
}
}
int iProjectile = 1;
if (is_nucleus(beamId)) {
iProjectile = Abeam;
if (iProjectile > int(maxMassNumber_) || iProjectile <= 0) {
std::ostringstream txt;
txt << "QgsjetII projectile outside range. Aprojectile=" << iProjectile;
throw std::runtime_error(txt.str().c_str());
}
} }
} else if (targetId != Proton::code) {
CORSIKA_LOG_DEBUG( std::ostringstream txt;
"QgsjetII::getCrossSection Elab= {} GeV iBeam= {}" txt << "QgsjetII not valid target=" << targetId;
" iProjectile= {} iTarget= {}", throw std::runtime_error(txt.str().c_str());
Elab / 1_GeV, iBeam, iProjectile, iTarget);
sigProd = qgsect_(Elab / 1_GeV, iBeam, iProjectile, iTarget);
CORSIKA_LOG_DEBUG("QgsjetII::getCrossSection sigProd= {} mb", sigProd);
} }
return sigProd * 1_mb; if (is_nucleus(projectileId)) {
size_t iProjectile = get_nucleus_A(projectileId);
if (iProjectile > int(maxMassNumber_) || iProjectile <= 0) {
std::ostringstream txt;
txt << "QgsjetII projectile outside range. Aprojectile=" << iProjectile;
throw std::runtime_error(txt.str().c_str());
}
} else if (!is_hadron(projectileId)) {
std::ostringstream txt;
txt << "QgsjetII projectile can only be hadrons. Is=" << projectileId;
throw std::runtime_error(txt.str().c_str());
}
} }
template <typename TParticle> inline CrossSectionType InteractionModel::getCrossSection(
inline GrammageType Interaction::getInteractionLength(const TParticle& particle) const { Code const projectileId, Code const targetId, FourMomentum const& projectileP4,
FourMomentum const& targetP4) const {
// coordinate system, get global frame of reference double sigProd = std::numeric_limits<double>::infinity();
CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem();
const Code corsikaBeamId = particle.getPID(); if (!corsika::qgsjetII::canInteract(projectileId)) { return sigProd * 1_mb; }
// beam particles for qgsjetII : 1, 2, 3 for p, pi, k isValid(projectileId, targetId); // throws
// read from cross section code table
const bool kInteraction = corsika::qgsjetII::canInteract(corsikaBeamId);
// FOR NOW: assume target is at rest // define projectile, in lab frame
MomentumVector pTarget(rootCS, {0_GeV, 0_GeV, 0_GeV}); auto const sqrtS2 = (projectileP4 + targetP4).getNormSqr();
HEPEnergyType const Elab = (sqrtS2 - static_pow<2>(get_mass(projectileId)) -
static_pow<2>(get_mass(targetId))) /
(2 * get_mass(targetId));
// total momentum and energy int const iBeam = static_cast<QgsjetIIXSClassIntType>(
HEPEnergyType const Elab = particle.getEnergy(); corsika::qgsjetII::getQgsjetIIXSCode(projectileId));
int iTarget = 1;
if (is_nucleus(targetId)) { iTarget = get_nucleus_A(targetId); }
int iProjectile = 1;
if (is_nucleus(projectileId)) { iProjectile = get_nucleus_A(projectileId); }
CORSIKA_LOG_DEBUG( CORSIKA_LOG_DEBUG(
"Interaction: LambdaInt: \n" "QgsjetII::getCrossSection Elab= {} GeV iBeam= {}"
" input energy: {} GeV" " iProjectile= {} iTarget= {}",
" beam can interact: {}" Elab / 1_GeV, iBeam, iProjectile, iTarget);
" beam pid: {}", sigProd = qgsect_(Elab / 1_GeV, iBeam, iProjectile, iTarget);
particle.getEnergy() / 1_GeV, kInteraction, corsikaBeamId); CORSIKA_LOG_DEBUG("QgsjetII::getCrossSection sigProd= {} mb", sigProd);
if (kInteraction) {
int Abeam = 0;
if (is_nucleus(corsikaBeamId)) Abeam = get_nucleus_A(corsikaBeamId);
// get target from environment
/*
the target should be defined by the Environment,
ideally as full particle object so that the four momenta
and the boosts can be defined..
*/
auto const* currentNode = particle.getNode();
const auto& mediumComposition =
currentNode->getModelProperties().getNuclearComposition();
CrossSectionType weightedProdCrossSection =
mediumComposition.getWeightedSum([=](Code targetID) -> CrossSectionType {
int targetA = 0;
if (is_nucleus(targetID)) targetA = get_nucleus_A(targetID);
return getCrossSection(corsikaBeamId, targetID, Elab, Abeam, targetA);
});
CORSIKA_LOG_DEBUG(
"Interaction: "
"IntLength: weighted CrossSection (mb): {}",
weightedProdCrossSection / 1_mb);
// calculate interaction length in medium
GrammageType const int_length = mediumComposition.getAverageMassNumber() *
constants::u / weightedProdCrossSection;
CORSIKA_LOG_DEBUG(
"Interaction: "
"interaction length (g/cm2): {}",
int_length / (0.001_kg) * 1_cm * 1_cm);
return int_length;
}
return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm); return sigProd * 1_mb;
} }
/** template <typename TSecondaries>
In this function QGSJETII is called to produce one event. The inline void InteractionModel::doInteraction(TSecondaries& view, Code const projectileId,
event is copied (and boosted) into the shower lab frame. Code const targetId,
*/ FourMomentum const& projectileP4,
FourMomentum const& targetP4) {
template <typename TView>
inline void Interaction::doInteraction(TView& view) {
auto const projectile = view.getProjectile();
auto const corsikaBeamId = projectile.getPID();
CORSIKA_LOG_DEBUG( CORSIKA_LOG_DEBUG(
"ProcessQgsjetII: " "ProcessQgsjetII: "
"doInteraction: {} interaction possible? {}", "doInteraction: {} interaction possible? {}",
corsikaBeamId, corsika::qgsjetII::canInteract(corsikaBeamId)); projectileId, corsika::qgsjetII::canInteract(projectileId));
if (!corsika::qgsjetII::canInteract(corsikaBeamId)) return; if (!corsika::qgsjetII::canInteract(projectileId)) return;
CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); isValid(projectileId, targetId); // throws
// position and time of interaction, not used in QgsjetII
Point const pOrig = projectile.getPosition();
TimeType const tOrig = projectile.getTime();
// define target CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem();
// for QgsjetII is always a single nucleon
// FOR NOW: target is always at rest
auto const targetEnergyLab = 0_GeV + constants::nucleonMass;
auto const targetMomentumLab = MomentumVector(rootCS, 0_GeV, 0_GeV, 0_GeV);
FourVector const PtargLab(targetEnergyLab, targetMomentumLab);
// define projectile // define projectile, in lab frame
HEPEnergyType const projectileEnergyLab = projectile.getEnergy(); auto const sqrtS2 = (projectileP4 + targetP4).getNormSqr();
auto const projectileMomentumLab = projectile.getMomentum(); HEPEnergyType const Elab = (sqrtS2 - static_pow<2>(get_mass(projectileId)) -
static_pow<2>(get_mass(targetId))) /
(2 * get_mass(targetId));
int beamA = 0; int beamA = 0;
if (is_nucleus(corsikaBeamId)) beamA = get_nucleus_A(corsikaBeamId); if (is_nucleus(projectileId)) { beamA = get_nucleus_A(projectileId); }
HEPEnergyType const projectileEnergyLabPerNucleon = projectileEnergyLab / beamA;
CORSIKA_LOG_DEBUG( CORSIKA_LOG_DEBUG("ebeam lab: {} GeV ", Elab / 1_GeV);
"ebeam lab: {} GeV "
"pbeam lab: {} GeV ",
projectileEnergyLab / 1_GeV, projectileMomentumLab.getComponents() / 1_GeV);
CORSIKA_LOG_DEBUG(
"etarget lab: {} GeV "
"ptarget lab: {} GeV ",
targetEnergyLab / 1_GeV, targetMomentumLab.getComponents() / 1_GeV);
CORSIKA_LOG_DEBUG("position of interaction: {}", pOrig.getCoordinates());
CORSIKA_LOG_DEBUG("time: {} ", tOrig);
// sample target mass number
auto const* currentNode = projectile.getNode();
auto const& mediumComposition =
currentNode->getModelProperties().getNuclearComposition();
// get cross sections for target materials
/*
Here we read the cross section from the interaction model again,
should be passed from getInteractionLength if possible
*/
auto const& compVec = mediumComposition.getComponents();
std::vector<CrossSectionType> cross_section_of_components(compVec.size());
for (size_t i = 0; i < compVec.size(); ++i) {
auto const targetId = compVec[i];
int targetA = 0;
if (is_nucleus(targetId)) targetA = get_nucleus_A(targetId);
const auto sigProd =
getCrossSection(corsikaBeamId, targetId, projectileEnergyLab, beamA, targetA);
cross_section_of_components[i] = sigProd;
}
const auto targetCode = int targetMassNumber = 1; // proton
mediumComposition.sampleTarget(cross_section_of_components, rng_); if (is_nucleus(targetId)) { // nucleus
targetMassNumber = get_nucleus_A(targetId);
int targetMassNumber = 1; // proton
if (is_nucleus(targetCode)) { // nucleus
targetMassNumber = get_nucleus_A(targetCode);
if (targetMassNumber > int(maxMassNumber_))
throw std::runtime_error(
"QgsjetII target mass outside range."); // LCOV_EXCL_LINE there is no
// allowed path here
} else {
if (targetCode != Proton::code) // LCOV_EXCL_LINE there is no allowed path here
throw std::runtime_error(
"QgsjetII Taget not possible."); // LCOV_EXCL_LINE there is no allowed path
// here
} }
CORSIKA_LOG_DEBUG("target: {}, qgsjetII code/A: {}", targetCode, targetMassNumber); CORSIKA_LOG_DEBUG("target: {}, qgsjetII code/A: {}", targetId, targetMassNumber);
// select QGSJetII internal projectile type
int projectileMassNumber = 1; // "1" means "hadron" int projectileMassNumber = 1; // "1" means "hadron"
QgsjetIIHadronType qgsjet_hadron_type = QgsjetIIHadronType qgsjet_hadron_type = qgsjetII::getQgsjetIIHadronType(projectileId);
qgsjetII::getQgsjetIIHadronType(corsikaBeamId);
if (qgsjet_hadron_type == QgsjetIIHadronType::NucleusType) { if (qgsjet_hadron_type == QgsjetIIHadronType::NucleusType) {
projectileMassNumber = get_nucleus_A(corsikaBeamId); projectileMassNumber = get_nucleus_A(projectileId);
if (projectileMassNumber > int(maxMassNumber_))
throw std::runtime_error(
"QgsjetII projectile mass outside range."); // LCOV_EXCL_LINE there is no
// allowed path here
std::array<QgsjetIIHadronType, 2> constexpr nucleons = { std::array<QgsjetIIHadronType, 2> constexpr nucleons = {
QgsjetIIHadronType::ProtonType, QgsjetIIHadronType::NeutronType}; QgsjetIIHadronType::ProtonType, QgsjetIIHadronType::NeutronType};
std::uniform_int_distribution select(0, 1); std::uniform_int_distribution select(0, 1);
qgsjet_hadron_type = nucleons[select(rng_)]; qgsjet_hadron_type = nucleons[select(rng_)];
} else { } else if (qgsjet_hadron_type == QgsjetIIHadronType::NeutralLightMesonType) {
// from conex: replace pi0 or rho0 with pi+/pi- in alternating sequence // from conex: replace pi0 or rho0 with pi+/pi- in alternating sequence
if (qgsjet_hadron_type == QgsjetIIHadronType::NeutralLightMesonType) { qgsjet_hadron_type = alternate_;
qgsjet_hadron_type = alternate_; alternate_ =
alternate_ = (alternate_ == QgsjetIIHadronType::PiPlusType (alternate_ == QgsjetIIHadronType::PiPlusType ? QgsjetIIHadronType::PiMinusType
? QgsjetIIHadronType::PiMinusType : QgsjetIIHadronType::PiPlusType);
: QgsjetIIHadronType::PiPlusType);
}
}
// beam id for qgsjetII
int kBeam = 2; // default: proton Shouldn't we randomize neutron/proton for nuclei?
if (!is_nucleus(corsikaBeamId)) {
kBeam = corsika::qgsjetII::convertToQgsjetIIRaw(corsikaBeamId);
// from conex
if (kBeam == 0) { // replace pi0 or rho0 with pi+/pi-
static int select = 1;
kBeam = select;
select *= -1;
}
// replace lambda by neutron
if (kBeam == 6)
kBeam = 3;
else if (kBeam == -6)
kBeam = -3;
// else if (abs(kBeam)>6) -> throw
} }
count_++; count_++;
...@@ -285,8 +157,7 @@ namespace corsika::qgsjetII { ...@@ -285,8 +157,7 @@ namespace corsika::qgsjetII {
CORSIKA_LOG_DEBUG( CORSIKA_LOG_DEBUG(
"qgsjet_hadron_type_int={} projectileMassNumber={} targetMassNumber={}", "qgsjet_hadron_type_int={} projectileMassNumber={} targetMassNumber={}",
qgsjet_hadron_type_int, projectileMassNumber, targetMassNumber); qgsjet_hadron_type_int, projectileMassNumber, targetMassNumber);
qgini_(projectileEnergyLab / 1_GeV, qgsjet_hadron_type_int, projectileMassNumber, qgini_(Elab / 1_GeV, qgsjet_hadron_type_int, projectileMassNumber, targetMassNumber);
targetMassNumber);
qgconf_(); qgconf_();
// bookkeeping // bookkeeping
...@@ -296,9 +167,29 @@ namespace corsika::qgsjetII { ...@@ -296,9 +167,29 @@ namespace corsika::qgsjetII {
// to read the secondaries // to read the secondaries
// define rotation to and from CoM frame // define rotation to and from CoM frame
// CoM frame definition in QgsjetII projectile: +z // CoM frame definition in QgsjetII projectile: +z
auto const& originalCS = projectileMomentumLab.getCoordinateSystem();
CoordinateSystemPtr const zAxisFrame = // QGSJetII, both, in input and output only considers the lab frame with a target at
make_rotationToZ(originalCS, projectileMomentumLab); // rest.
// system of initial-state
COMBoost boost(projectileP4, targetP4);
auto const& originalCS = boost.getOriginalCS();
auto const& csPrime =
boost.getRotatedCS(); // z is along the CM motion (projectile, in Cascade)
MomentumVector const projectileMomentum = projectileP4.getSpaceLikeComponents();
HEPMomentumType const pLabMag =
sqrt((Elab - get_mass(projectileId)) * (Elab + get_mass(projectileId)));
MomentumVector pLab(csPrime, {0_eV, 0_eV, pLabMag});
// internal QGSJetII system
COMBoost boostInternal({Elab, pLab}, get_mass(targetId));
// position and time of interaction, not used in QgsjetII
auto const projectile = view.getProjectile();
Point const pOrig = projectile.getPosition();
TimeType const tOrig = projectile.getTime();
// fragments // fragments
QGSJetIIFragmentsStack qfs; QGSJetIIFragmentsStack qfs;
...@@ -310,19 +201,26 @@ namespace corsika::qgsjetII { ...@@ -310,19 +201,26 @@ namespace corsika::qgsjetII {
if (select(rng_) > 0.5) { idFragm = Code::Neutron; } if (select(rng_) > 0.5) { idFragm = Code::Neutron; }
const HEPMassType nucleonMass = get_mass(idFragm); const HEPMassType nucleonMass = get_mass(idFragm);
// no pT, frgments just go forward // no pT, fragments just go forward
auto momentum = HEPEnergyType const projectileEnergyLabPerNucleon = Elab / beamA;
Vector(zAxisFrame, corsika::QuantityVector<hepmomentum_d>{ MomentumVector momentum{csPrime,
0.0_GeV, 0.0_GeV, {0.0_GeV, 0.0_GeV,
sqrt((projectileEnergyLabPerNucleon + nucleonMass) * sqrt((projectileEnergyLabPerNucleon + nucleonMass) *
(projectileEnergyLabPerNucleon - nucleonMass))}); (projectileEnergyLabPerNucleon - nucleonMass))}};
// this is not "CoM" here, but rather the system defined by projectile+target,
// which in Cascade-mode is already lab
auto const P4com =
boostInternal.toCoM(FourVector{projectileEnergyLabPerNucleon, momentum});
auto const P4output = boost.fromCoM(P4com);
auto p3output = P4output.getSpaceLikeComponents();
p3output.rebase(originalCS); // transform back into standard lab frame
momentum.rebase(originalCS); // transform back into standard lab frame
CORSIKA_LOG_DEBUG( CORSIKA_LOG_DEBUG(
"secondary fragment> id= {}" "secondary fragment> id= {}"
" p={}", " p={}",
idFragm, momentum.getComponents()); idFragm, p3output.getComponents());
auto pnew = view.addSecondary(std::make_tuple(idFragm, momentum, pOrig, tOrig)); auto pnew = view.addSecondary(std::make_tuple(idFragm, p3output, pOrig, tOrig));
Plab_final += pnew.getMomentum(); Plab_final += pnew.getMomentum();
Elab_final += pnew.getEnergy(); Elab_final += pnew.getEnergy();
...@@ -347,22 +245,30 @@ namespace corsika::qgsjetII { ...@@ -347,22 +245,30 @@ namespace corsika::qgsjetII {
HEPMassType const nucleusMass = Proton::mass * Z + Neutron::mass * (A - Z); HEPMassType const nucleusMass = Proton::mass * Z + Neutron::mass * (A - Z);
// no pT, frgments just go forward // no pT, frgments just go forward
auto momentum = Vector( HEPEnergyType const projectileEnergyLabPerNucleon = Elab / beamA;
zAxisFrame, QuantityVector<hepmomentum_d>{ MomentumVector momentum{
0.0_GeV, 0.0_GeV, csPrime,
sqrt((projectileEnergyLabPerNucleon * A + nucleusMass) * {0.0_GeV, 0.0_GeV,
(projectileEnergyLabPerNucleon * A - nucleusMass))}); sqrt((projectileEnergyLabPerNucleon * A + nucleusMass) *
(projectileEnergyLabPerNucleon * A - nucleusMass))}};
// this is not "CoM" here, but rather the system defined by projectile+target,
// which in Cascade-mode is already lab
auto const P4com =
boostInternal.toCoM(FourVector{projectileEnergyLabPerNucleon * A, momentum});
auto const P4output = boost.fromCoM(P4com);
auto p3output = P4output.getSpaceLikeComponents();
p3output.rebase(originalCS); // transform back into standard lab frame
momentum.rebase(originalCS); // transform back into standard lab frame
CORSIKA_LOG_DEBUG( CORSIKA_LOG_DEBUG(
"secondary fragment> id={}" "secondary fragment> id={}"
" p={}" " p={}"
" A={}" " A={}"
" Z={}", " Z={}",
get_nucleus_code(A, Z), momentum.getComponents(), A, Z); get_nucleus_code(A, Z), p3output.getComponents(), A, Z);
auto pnew = view.addSecondary( auto pnew = view.addSecondary(
std::make_tuple(get_nucleus_code(A, Z), momentum, pOrig, tOrig)); std::make_tuple(get_nucleus_code(A, Z), p3output, pOrig, tOrig));
Plab_final += pnew.getMomentum(); Plab_final += pnew.getMomentum();
Elab_final += pnew.getEnergy(); Elab_final += pnew.getEnergy();
} }
...@@ -372,14 +278,19 @@ namespace corsika::qgsjetII { ...@@ -372,14 +278,19 @@ namespace corsika::qgsjetII {
QGSJetIIStack qs; QGSJetIIStack qs;
for (auto& psec : qs) { for (auto& psec : qs) {
auto momentum = psec.getMomentum(zAxisFrame); auto momentum = psec.getMomentum(csPrime);
// this is not "CoM" here, but rather the system defined by projectile+target,
// which in Cascade-mode is already lab
auto const P4com = boostInternal.toCoM(FourVector{psec.getEnergy(), momentum});
auto const P4output = boost.fromCoM(P4com);
auto p3output = P4output.getSpaceLikeComponents();
p3output.rebase(originalCS); // transform back into standard lab frame
momentum.rebase(originalCS); // transform back into standard lab frame
CORSIKA_LOG_DEBUG("secondary> id= {}, p= {}", CORSIKA_LOG_DEBUG("secondary> id= {}, p= {}",
corsika::qgsjetII::convertFromQgsjetII(psec.getPID()), corsika::qgsjetII::convertFromQgsjetII(psec.getPID()),
momentum.getComponents()); p3output.getComponents());
auto pnew = view.addSecondary(std::make_tuple( auto pnew = view.addSecondary(std::make_tuple(
corsika::qgsjetII::convertFromQgsjetII(psec.getPID()), momentum, pOrig, tOrig)); corsika::qgsjetII::convertFromQgsjetII(psec.getPID()), p3output, pOrig, tOrig));
Plab_final += pnew.getMomentum(); Plab_final += pnew.getMomentum();
Elab_final += pnew.getEnergy(); Elab_final += pnew.getEnergy();
} }
......
...@@ -156,8 +156,8 @@ namespace corsika::sibyll { ...@@ -156,8 +156,8 @@ namespace corsika::sibyll {
auto const tmp = psib.getMomentum().getComponents(); auto const tmp = psib.getMomentum().getComponents();
auto const pCoM = MomentumVector(csPrime, tmp); auto const pCoM = MomentumVector(csPrime, tmp);
HEPEnergyType const eCoM = psib.getEnergy(); HEPEnergyType const eCoM = psib.getEnergy();
auto const Plab = boost.fromCoM(FourVector{eCoM, pCoM}); auto const P4lab = boost.fromCoM(FourVector{eCoM, pCoM});
auto const p3lab = Plab.getSpaceLikeComponents(); auto const p3lab = P4lab.getSpaceLikeComponents();
// add to corsika stack // add to corsika stack
auto pnew = secondaries.addSecondary(std::make_tuple( auto pnew = secondaries.addSecondary(std::make_tuple(
...@@ -167,19 +167,20 @@ namespace corsika::sibyll { ...@@ -167,19 +167,20 @@ namespace corsika::sibyll {
Elab_final += pnew.getEnergy(); Elab_final += pnew.getEnergy();
Ecm_final += psib.getEnergy(); Ecm_final += psib.getEnergy();
} }
HEPEnergyType const Elab_initial = { // just output
static_pow<2>(sqrtSnn) / (2 * constants::nucleonMass); HEPEnergyType const Elab_initial =
CORSIKA_LOG_DEBUG( static_pow<2>(sqrtSnn) / (2 * constants::nucleonMass);
"conservation (all GeV): " CORSIKA_LOG_DEBUG(
"sqrtSnn={}, sqrtSnn_final={}, " "conservation (all GeV): "
"Elab_initial={}, Elab_final={}, " "sqrtSnn={}, sqrtSnn_final={}, "
"diff(%)={}, " "Elab_initial={}, Elab_final={}, "
"E in nucleons={}, " "diff(%)={}, "
"Plab_final={} ", "E in nucleons={}, "
sqrtSnn / 1_GeV, Ecm_final * 2. / (get_nwounded() + 1) / 1_GeV, Elab_initial, "Plab_final={} ",
Elab_final / 1_GeV, (Elab_final - Elab_initial) / Elab_initial * 100, sqrtSnn / 1_GeV, Ecm_final * 2. / (get_nwounded() + 1) / 1_GeV, Elab_initial,
constants::nucleonMass * get_nwounded() / 1_GeV, Elab_final / 1_GeV, (Elab_final - Elab_initial) / Elab_initial * 100,
(Plab_final / 1_GeV).getComponents()); constants::nucleonMass * get_nwounded() / 1_GeV,
} // namespace corsika::sibyll (Plab_final / 1_GeV).getComponents());
}
}
} // namespace corsika::sibyll } // namespace corsika::sibyll
...@@ -25,11 +25,11 @@ namespace corsika { ...@@ -25,11 +25,11 @@ namespace corsika {
*/ */
/** /**
* @class COMBoost * @class COMBoost
* @ingroup Utilities * @ingroup Utilities
* *
* This utility class handles Lorentz boost between different * This utility class handles Lorentz boost (in one spatial direction)
* referenence frames, using FourVector. * between different referenence frames, using FourVector.
* *
* The class is initialized with projectile and optionally target * The class is initialized with projectile and optionally target
* energy/momentum data. During initialization, a rotation matrix is * energy/momentum data. During initialization, a rotation matrix is
...@@ -47,16 +47,26 @@ namespace corsika { ...@@ -47,16 +47,26 @@ namespace corsika {
class COMBoost { class COMBoost {
public: public:
//! construct a COMBoost given four-vector of projectile and mass of target (target at /**
//! rest) * Construct a COMBoost given four-vector of projectile and mass of target (target at
* rest).
*
* The FourMomentum and mass define the lab system.
*/
COMBoost(FourMomentum const& P4projectile, HEPEnergyType const massTarget); COMBoost(FourMomentum const& P4projectile, HEPEnergyType const massTarget);
//! construct a COMBoost given two four-vectors of projectile target /**
COMBoost(FourMomentum const& P4projectile, FourMomentum const& P4target); * Construct a COMBoost to boost into the rest frame given a 3-momentum and mass.
*/
//! construct a COMBoost to boost into the rest frame given a 3-momentum and mass
COMBoost(MomentumVector const& momentum, HEPEnergyType const mass); COMBoost(MomentumVector const& momentum, HEPEnergyType const mass);
/**
* Construct a COMBoost given two four-vectors of projectile target.
*
* The tow FourMomentum can define an arbitrary system.
*/
COMBoost(FourMomentum const& P4projectile, FourMomentum const& P4target);
//! transforms a 4-momentum from lab frame to the center-of-mass frame //! transforms a 4-momentum from lab frame to the center-of-mass frame
template <typename FourVector> template <typename FourVector>
FourVector toCoM(FourVector const& p4) const; FourVector toCoM(FourVector const& p4) const;
...@@ -65,10 +75,10 @@ namespace corsika { ...@@ -65,10 +75,10 @@ namespace corsika {
template <typename FourVector> template <typename FourVector>
FourVector fromCoM(FourVector const& p4) const; FourVector fromCoM(FourVector const& p4) const;
//! returns the rotated coordinate system //! returns the rotated coordinate system: +z is projectile direction
CoordinateSystemPtr getRotatedCS() const; CoordinateSystemPtr getRotatedCS() const;
//! returns the original coordinate system //! returns the original coordinate system of the projectile (lab)
CoordinateSystemPtr getOriginalCS() const; CoordinateSystemPtr getOriginalCS() const;
protected: protected:
......
...@@ -31,8 +31,7 @@ namespace corsika { ...@@ -31,8 +31,7 @@ namespace corsika {
* simulation into a projected grammage range and counts for * simulation into a projected grammage range and counts for
* different particle species when they cross dX (default: 10g/cm2) * different particle species when they cross dX (default: 10g/cm2)
* boundaries. * boundaries.
* */
**/
class LongitudinalProfile : public ContinuousProcess<LongitudinalProfile> { class LongitudinalProfile : public ContinuousProcess<LongitudinalProfile> {
......
...@@ -8,4 +8,23 @@ ...@@ -8,4 +8,23 @@
#pragma once #pragma once
#include <corsika/modules/qgsjetII/Interaction.hpp> #include <corsika/modules/qgsjetII/InteractionModel.hpp>
#include <corsika/framework/process/InteractionProcess.hpp>
/**
* @file QGSJetII.hpp
*
* Includes all the parts of the QGSJetII model. Defines the InteractionProcess<TModel>
* classes needed for the ProcessSequence.
*/
namespace corsika::qgsjetII {
/**
* @brief qgsjetII::Interaction is the process for ProcessSequence.
*
* The qgsjetII::InteractionModel is wrapped as an InteractionProcess here in order
* to provide all the functions for ProcessSequence.
*/
class Interaction : public InteractionModel, public InteractionProcess<Interaction> {};
} // namespace corsika::qgsjetII
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
/** /**
* @file Sibyll.hpp * @file Sibyll.hpp
* *
* Includes all the parts of the Sibyll model. Defines the InteractoinProcess<TModel> * Includes all the parts of the Sibyll model. Defines the InteractionProcess<TModel>
* classes needed for the ProcessSequence. * classes needed for the ProcessSequence.
*/ */
...@@ -26,7 +26,7 @@ namespace corsika::sibyll { ...@@ -26,7 +26,7 @@ namespace corsika::sibyll {
/** /**
* @brief sibyll::Interaction is the process for ProcessSequence. * @brief sibyll::Interaction is the process for ProcessSequence.
* *
* The sibyll::Model is wrapped as an InteractionProcess here in order * The sibyll::InteractionModel is wrapped as an InteractionProcess here in order
* to provide all the functions for ProcessSequence. * to provide all the functions for ProcessSequence.
*/ */
class Interaction : public InteractionModel, public InteractionProcess<Interaction> {}; class Interaction : public InteractionModel, public InteractionProcess<Interaction> {};
......
...@@ -8,58 +8,70 @@ ...@@ -8,58 +8,70 @@
#pragma once #pragma once
#include <corsika/modules/qgsjetII/ParticleConversion.hpp>
#include <qgsjet-II-04.hpp>
#include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/core/ParticleProperties.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/random/RNGManager.hpp> #include <corsika/framework/random/RNGManager.hpp>
#include <corsika/framework/process/InteractionProcess.hpp> #include <corsika/framework/utility/COMBoost.hpp>
#include <corsika/modules/qgsjetII/ParticleConversion.hpp>
#include <corsika/framework/utility/CorsikaData.hpp> #include <corsika/framework/utility/CorsikaData.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <qgsjet-II-04.hpp>
#include <string>
namespace corsika::qgsjetII { namespace corsika::qgsjetII {
class Interaction : public corsika::InteractionProcess<Interaction> { class InteractionModel {
public: public:
Interaction(boost::filesystem::path dataPath = corsika_data("QGSJetII")); InteractionModel(boost::filesystem::path dataPath = corsika_data("QGSJetII"));
~Interaction(); ~InteractionModel();
bool wasInitialized() { return initialized_; } /**
unsigned int getMaxTargetMassNumber() const { return maxMassNumber_; } * Throws exception if invalid system is passed.
bool isValidTarget(corsika::Code TargetId) const { *
return is_nucleus(TargetId) && (get_nucleus_A(TargetId) < maxMassNumber_); * @param beamId
} * @param targetId
*/
CrossSectionType getCrossSection(const Code, const Code, const HEPEnergyType, void isValid(Code const beamId, Code const targetId) const;
const unsigned int Abeam = 0,
const unsigned int Atarget = 0) const;
template <typename TParticle>
GrammageType getInteractionLength(TParticle const&) const;
/** /**
In this function QGSJETII is called to produce one event. The * Return the QGSJETII inelastic/production cross section.
event is copied (and boosted) into the shower lab frame. *
* 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 Aprojectile 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.
*/ */
CrossSectionType getCrossSection(Code const projectile, Code const target,
FourMomentum const& projectileP4,
FourMomentum const& targetP4) const;
template <typename TSecondaryView> /**
void doInteraction(TSecondaryView&); * In this function QGSJETII is called to produce one event.
*
* The event is copied (and boosted) into the shower lab frame.
*/
template <typename TSecondaries>
void doInteraction(TSecondaries&, Code const projectile, Code const target,
FourMomentum const& projectileP4, FourMomentum const& targetP4);
private: private:
int count_ = 0; int count_ = 0;
bool initialized_ = false;
QgsjetIIHadronType alternate_ = QgsjetIIHadronType alternate_ =
QgsjetIIHadronType::PiPlusType; // for pi0, rho0 projectiles QgsjetIIHadronType::PiPlusType; // for pi0, rho0 projectiles
corsika::default_prng_type& rng_ = corsika::default_prng_type& rng_ =
corsika::RNGManager<>::getInstance().getRandomStream("qgsjet"); corsika::RNGManager<>::getInstance().getRandomStream("qgsjet");
static unsigned int constexpr maxMassNumber_ = 208; static size_t constexpr maxMassNumber_ = 208;
}; };
} // namespace corsika::qgsjetII } // namespace corsika::qgsjetII
#include <corsika/detail/modules/qgsjetII/Interaction.inl> #include <corsika/detail/modules/qgsjetII/InteractionModel.inl>
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
namespace corsika::qgsjetII { namespace corsika::qgsjetII {
/** /**
These are the possible secondaries produced by QGSJetII * These are the possible secondaries produced by QGSJetII.
*/ */
enum class QgsjetIICode : int8_t; enum class QgsjetIICode : int8_t;
using QgsjetIICodeIntType = std::underlying_type<QgsjetIICode>::type; using QgsjetIICodeIntType = std::underlying_type<QgsjetIICode>::type;
/** /**
These are the possible projectile for which QGSJetII knwos cross section * These are the possible projectile for which QGSJetII knwos cross section.
*/ */
enum class QgsjetIIXSClass : int8_t { enum class QgsjetIIXSClass : int8_t {
CannotInteract = 0, CannotInteract = 0,
...@@ -32,7 +32,7 @@ namespace corsika::qgsjetII { ...@@ -32,7 +32,7 @@ namespace corsika::qgsjetII {
using QgsjetIIXSClassIntType = std::underlying_type<QgsjetIIXSClass>::type; using QgsjetIIXSClassIntType = std::underlying_type<QgsjetIIXSClass>::type;
/** /**
These are the only possible projectile types in QGSJetII * These are the only possible projectile types in QGSJetII.
*/ */
enum class QgsjetIIHadronType : int8_t { enum class QgsjetIIHadronType : int8_t {
UndefinedType = 0, UndefinedType = 0,
...@@ -58,7 +58,7 @@ namespace corsika::qgsjetII { ...@@ -58,7 +58,7 @@ namespace corsika::qgsjetII {
namespace corsika::qgsjetII { namespace corsika::qgsjetII {
QgsjetIICode constexpr convertToQgsjetII(Code pCode) { QgsjetIICode constexpr convertToQgsjetII(Code const pCode) {
return corsika2qgsjetII[static_cast<CodeIntType>(pCode)]; return corsika2qgsjetII[static_cast<CodeIntType>(pCode)];
} }
......
...@@ -48,7 +48,7 @@ namespace corsika::sibyll { ...@@ -48,7 +48,7 @@ namespace corsika::sibyll {
HEPEnergyType const sqrtSnn) const; HEPEnergyType const sqrtSnn) const;
/** /**
* @brief returns inelastic AND elastic cross sections. * Returns inelastic AND elastic cross sections.
* *
* These cross sections must correspond to the process described in doInteraction * These cross sections must correspond to the process described in doInteraction
* AND elastic scattering (sigma_tot = sigma_inel + sigma_el). Allowed targets are: * AND elastic scattering (sigma_tot = sigma_inel + sigma_el). Allowed targets are:
...@@ -68,7 +68,7 @@ namespace corsika::sibyll { ...@@ -68,7 +68,7 @@ namespace corsika::sibyll {
FourMomentum const& targetP4) const; FourMomentum const& targetP4) const;
/** /**
* @brief returns inelastic (production) cross section. * Returns inelastic (production) cross section.
* *
* This cross section must correspond to the process described in doInteraction. * This cross section must correspond to the process described in doInteraction.
* Allowed targets are: nuclei or single nucleons (p,n,hydrogen). * Allowed targets are: nuclei or single nucleons (p,n,hydrogen).
......
...@@ -4,7 +4,7 @@ set (test_modules_sources ...@@ -4,7 +4,7 @@ set (test_modules_sources
testTracking.cpp testTracking.cpp
## testExecTime.cpp --> needs to be fixed, see #326 ## testExecTime.cpp --> needs to be fixed, see #326
testObservationPlane.cpp testObservationPlane.cpp
#testQGSJetII.cpp testQGSJetII.cpp
#testPythia8.cpp #testPythia8.cpp
#testUrQMD.cpp #testUrQMD.cpp
#testCONEX.cpp #testCONEX.cpp
......
...@@ -6,8 +6,7 @@ ...@@ -6,8 +6,7 @@
* the license. * the license.
*/ */
#include <corsika/modules/qgsjetII/Interaction.hpp> #include <corsika/modules/QGSJetII.hpp>
#include <corsika/modules/qgsjetII/ParticleConversion.hpp>
#include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/core/ParticleProperties.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
...@@ -49,6 +48,7 @@ auto sumMomentum(TStackView const& view, CoordinateSystemPtr const& vCS) { ...@@ -49,6 +48,7 @@ auto sumMomentum(TStackView const& view, CoordinateSystemPtr const& vCS) {
TEST_CASE("QgsjetII", "[processes]") { TEST_CASE("QgsjetII", "[processes]") {
logging::set_level(logging::level::info); logging::set_level(logging::level::info);
RNGManager<>::getInstance().registerRandomStream("qgsjet");
SECTION("Corsika -> QgsjetII") { SECTION("Corsika -> QgsjetII") {
CHECK(corsika::qgsjetII::convertToQgsjetII(PiMinus::code) == CHECK(corsika::qgsjetII::convertToQgsjetII(PiMinus::code) ==
...@@ -91,6 +91,14 @@ TEST_CASE("QgsjetII", "[processes]") { ...@@ -91,6 +91,14 @@ TEST_CASE("QgsjetII", "[processes]") {
CHECK(corsika::qgsjetII::getQgsjetIIXSCode(Code::PiMinus) == CHECK(corsika::qgsjetII::getQgsjetIIXSCode(Code::PiMinus) ==
corsika::qgsjetII::QgsjetIIXSClass::LightMesons); corsika::qgsjetII::QgsjetIIXSClass::LightMesons);
} }
SECTION("valid") {
corsika::qgsjetII::InteractionModel model;
CHECK_THROWS(model.isValid(Code::Electron, Code::Proton));
CHECK_THROWS(model.isValid(Code::Proton, Code::Electron));
}
} }
#include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/Point.hpp>
...@@ -115,25 +123,23 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { ...@@ -115,25 +123,23 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") {
logging::set_level(logging::level::info); logging::set_level(logging::level::info);
auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Oxygen); auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Oxygen);
auto const& cs = *csPtr;
[[maybe_unused]] auto const& env_dummy = env; [[maybe_unused]] auto const& env_dummy = env;
[[maybe_unused]] auto const& node_dummy = nodePtr; [[maybe_unused]] auto const& node_dummy = nodePtr;
RNGManager<>::getInstance().registerRandomStream("qgsjet");
SECTION("InteractionInterface") { SECTION("InteractionInterface") {
auto [stackPtr, secViewPtr] = setup::testing::setup_stack( auto [stackPtr, secViewPtr] = setup::testing::setup_stack(
Code::Proton, 110_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); Code::Proton, 110_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr);
setup::StackView& view = *(secViewPtr.get()); setup::StackView& view = *(secViewPtr.get());
auto particle = stackPtr->first();
auto projectile = secViewPtr->getProjectile(); auto projectile = secViewPtr->getProjectile();
auto const projectileMomentum = projectile.getMomentum(); auto const projectileMomentum = projectile.getMomentum();
corsika::qgsjetII::Interaction model; corsika::qgsjetII::InteractionModel model;
model.doInteraction(view); model.doInteraction(view, Code::Proton, Code::Oxygen,
[[maybe_unused]] const GrammageType length = model.getInteractionLength(particle); {sqrt(static_pow<2>(110_GeV) + static_pow<2>(Proton::mass)),
MomentumVector{cs, 110_GeV, 0_GeV, 0_GeV}},
CHECK(length / (1_g / square(1_cm)) == Approx(93.04).margin(0.1)); {Oxygen::mass, MomentumVector{cs, {0_eV, 0_eV, 0_eV}}});
/* ********************************** /* **********************************
As it turned out already two times (#291 and #307) that the detailed output of As it turned out already two times (#291 and #307) that the detailed output of
...@@ -152,24 +158,25 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { ...@@ -152,24 +158,25 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") {
SECTION("InteractionInterface Nuclei") { SECTION("InteractionInterface Nuclei") {
HEPEnergyType const P0 = 20100_GeV;
MomentumVector const plab = MomentumVector(cs, {P0, 0_eV, 0_eV});
Code const pid = get_nucleus_code(60, 30);
auto [stackPtr, secViewPtr] = setup::testing::setup_stack( auto [stackPtr, secViewPtr] = setup::testing::setup_stack(
get_nucleus_code(60, 30), 20100_GeV, pid, P0, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr);
(setup::Environment::BaseNodeType* const)nodePtr, *csPtr);
setup::StackView& view = *(secViewPtr.get()); setup::StackView& view = *(secViewPtr.get());
auto particle = stackPtr->first();
auto projectile = secViewPtr->getProjectile();
auto const projectileMomentum = projectile.getMomentum();
corsika::qgsjetII::Interaction model; HEPEnergyType const Elab = sqrt(static_pow<2>(P0) + static_pow<2>(get_mass(pid)));
model.doInteraction(view); // this also should produce some fragments FourMomentum const projectileP4(Elab, plab);
FourMomentum const targetP4(Oxygen::mass, MomentumVector(cs, {0_eV, 0_eV, 0_eV}));
view.clear();
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(300).margin(150)); // this is not physics validation
int countFragments = 0; int countFragments = 0;
for (auto const& sec : view) { countFragments += (is_nucleus(sec.getPID())); } for (auto const& sec : view) { countFragments += (is_nucleus(sec.getPID())); }
CHECK(countFragments == Approx(4).margin(2)); // this is not physics validation CHECK(countFragments == Approx(4).margin(2)); // this is not physics validation
[[maybe_unused]] const GrammageType length = model.getInteractionLength(particle);
CHECK(length / (1_g / square(1_cm)) ==
Approx(12).margin(2)); // this is not physics validation
} }
SECTION("Heavy nuclei") { SECTION("Heavy nuclei") {
...@@ -178,38 +185,33 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { ...@@ -178,38 +185,33 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") {
get_nucleus_code(1000, 1000), 1100_GeV, get_nucleus_code(1000, 1000), 1100_GeV,
(setup::Environment::BaseNodeType* const)nodePtr, *csPtr); (setup::Environment::BaseNodeType* const)nodePtr, *csPtr);
setup::StackView& view = *(secViewPtr.get()); setup::StackView& view = *(secViewPtr.get());
auto particle = stackPtr->first();
auto projectile = secViewPtr->getProjectile(); auto projectile = secViewPtr->getProjectile();
auto const projectileMomentum = projectile.getMomentum(); auto const projectileMomentum = projectile.getMomentum();
corsika::qgsjetII::Interaction model; corsika::qgsjetII::InteractionModel model;
FourMomentum const aP4(100_GeV, {cs, 99_GeV, 0_GeV, 0_GeV});
FourMomentum const bP4(1_TeV, {cs, 0.9_TeV, 0_GeV, 0_GeV});
CHECK_THROWS(model.getCrossSection(get_nucleus_code(10, 5),
get_nucleus_code(1000, 500), aP4, bP4));
CHECK_THROWS(model.getCrossSection(Code::Nucleus, Code::Nucleus, aP4, bP4));
CHECK_THROWS( CHECK_THROWS(
model.getCrossSection(Code::Nucleus, Code::Nucleus, 100_GeV, 10., 1000.)); model.doInteraction(view, get_nucleus_code(1000, 500), Code::Oxygen, aP4, bP4));
CHECK_THROWS(
model.getCrossSection(Code::Nucleus, Code::Nucleus, 100_GeV, 1000., 10.));
CHECK_THROWS(model.doInteraction(view));
CHECK_THROWS(model.getInteractionLength(particle));
} }
SECTION("Allowed Particles") { SECTION("Allowed Particles") {
{ // electron
auto [stackPtr, secViewPtr] = setup::testing::setup_stack(
Code::Electron, 100_GeV, (setup::Environment::BaseNodeType* const)nodePtr,
*csPtr);
[[maybe_unused]] setup::StackView& view = *(secViewPtr.get());
auto particle = stackPtr->first();
corsika::qgsjetII::Interaction model;
GrammageType const length = model.getInteractionLength(particle);
CHECK(length / (1_g / square(1_cm)) == std::numeric_limits<double>::infinity());
}
{ // pi0 is internally converted into pi+/pi- { // pi0 is internally converted into pi+/pi-
auto [stackPtr, secViewPtr] = setup::testing::setup_stack( auto [stackPtr, secViewPtr] = setup::testing::setup_stack(
Code::Pi0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); Code::Pi0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr);
[[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get());
[[maybe_unused]] auto particle = stackPtr->first(); [[maybe_unused]] auto particle = stackPtr->first();
corsika::qgsjetII::Interaction model; corsika::qgsjetII::InteractionModel model;
model.doInteraction(view); model.doInteraction(view, Code::Pi0, Code::Oxygen,
{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(10).margin(8)); // this is not physics validation
} }
{ // rho0 is internally converted into pi-/pi+ { // rho0 is internally converted into pi-/pi+
...@@ -217,8 +219,11 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { ...@@ -217,8 +219,11 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") {
Code::Rho0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr); Code::Rho0, 1000_GeV, (setup::Environment::BaseNodeType* const)nodePtr, *csPtr);
[[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get());
[[maybe_unused]] auto particle = stackPtr->first(); [[maybe_unused]] auto particle = stackPtr->first();
corsika::qgsjetII::Interaction model; corsika::qgsjetII::InteractionModel model;
model.doInteraction(view); model.doInteraction(view, Code::Rho0, Code::Oxygen,
{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(25).margin(20)); // this is not physics validation
} }
{ // Lambda is internally converted into neutron { // Lambda is internally converted into neutron
...@@ -227,8 +232,11 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { ...@@ -227,8 +232,11 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") {
*csPtr); *csPtr);
[[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get());
[[maybe_unused]] auto particle = stackPtr->first(); [[maybe_unused]] auto particle = stackPtr->first();
corsika::qgsjetII::Interaction model; corsika::qgsjetII::InteractionModel model;
model.doInteraction(view); model.doInteraction(view, Code::Lambda0, Code::Oxygen,
{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(25).margin(20)); // this is not physics validation
} }
{ // AntiLambda is internally converted into anti neutron { // AntiLambda is internally converted into anti neutron
...@@ -237,8 +245,11 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") { ...@@ -237,8 +245,11 @@ TEST_CASE("QgsjetIIInterface", "interaction,processes") {
*csPtr); *csPtr);
[[maybe_unused]] setup::StackView& view = *(secViewPtr.get()); [[maybe_unused]] setup::StackView& view = *(secViewPtr.get());
[[maybe_unused]] auto particle = stackPtr->first(); [[maybe_unused]] auto particle = stackPtr->first();
corsika::qgsjetII::Interaction model; corsika::qgsjetII::InteractionModel model;
model.doInteraction(view); model.doInteraction(view, Code::Lambda0Bar, Code::Oxygen,
{sqrt(static_pow<2>(1_TeV) + static_pow<2>(Lambda0Bar::mass)),
MomentumVector{cs, 1_TeV, 0_GeV, 0_GeV}},
{Oxygen::mass, MomentumVector{cs, 0_eV, 0_eV, 0_eV}});
CHECK(view.getSize() == Approx(70).margin(67)); // this is not physics validation CHECK(view.getSize() == Approx(70).margin(67)); // this is not physics validation
} }
} }
......
...@@ -88,7 +88,6 @@ TEST_CASE("Sibyll", "modules") { ...@@ -88,7 +88,6 @@ TEST_CASE("Sibyll", "modules") {
#include <corsika/framework/geometry/Vector.hpp> #include <corsika/framework/geometry/Vector.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/core/ParticleProperties.hpp>
#include <SetupTestEnvironment.hpp> #include <SetupTestEnvironment.hpp>
...@@ -186,9 +185,9 @@ TEST_CASE("SibyllInterface", "modules") { ...@@ -186,9 +185,9 @@ TEST_CASE("SibyllInterface", "modules") {
model.setVerbose(true); model.setVerbose(true);
HEPEnergyType const Elab = sqrt(static_pow<2>(P0) + static_pow<2>(Proton::mass)); HEPEnergyType const Elab = sqrt(static_pow<2>(P0) + static_pow<2>(Proton::mass));
FourMomentum const projectileP4(Elab, plab); FourMomentum const projectileP4(Elab, plab);
FourMomentum const nucleonP4(Oxygen::mass, MomentumVector(cs, {0_eV, 0_eV, 0_eV})); FourMomentum const nucleusP4(Oxygen::mass, MomentumVector(cs, {0_eV, 0_eV, 0_eV}));
view.clear(); view.clear();
model.doInteraction(view, Code::Proton, Code::Oxygen, projectileP4, nucleonP4); model.doInteraction(view, Code::Proton, Code::Oxygen, projectileP4, nucleusP4);
auto const pSum = sumMomentum(view, cs); auto const pSum = sumMomentum(view, cs);
/* /*
...@@ -255,7 +254,7 @@ TEST_CASE("SibyllInterface", "modules") { ...@@ -255,7 +254,7 @@ TEST_CASE("SibyllInterface", "modules") {
Approx(0).margin(plab.getNorm() * 0.05 / 1_GeV)); Approx(0).margin(plab.getNorm() * 0.05 / 1_GeV));
CHECK(pSum.getNorm() / P0 == Approx(1).margin(0.05)); CHECK(pSum.getNorm() / P0 == Approx(1).margin(0.05));
[[maybe_unused]] CrossSectionType const cx = [[maybe_unused]] CrossSectionType const cx =
model.getCrossSection(Code::Proton, Code::Oxygen, projectileP4, nucleonP4); model.getCrossSection(Code::Proton, Code::Oxygen, projectileP4, nucleusP4);
CHECK(cx / 1_mb == Approx(300).margin(1)); CHECK(cx / 1_mb == Approx(300).margin(1));
// CHECK(view.getEntries() == 9); //! \todo: this was 20 before refactory-2020: check // CHECK(view.getEntries() == 9); //! \todo: this was 20 before refactory-2020: check
// "also sibyll not stable wrt. to compiler // "also sibyll not stable wrt. to compiler
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment