diff --git a/CMakeLists.txt b/CMakeLists.txt index 62d488fa2713a44964460d939aa6a5742b1840d8..b6969bead512aacffc631f993a6a77d6e4f06bff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ project ( LANGUAGES CXX ) +# as long as there still are modules using it: enable_language (Fortran) # ignore many irrelevant Up-to-date messages during install diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc index 49ab47047d476934a45de114f015cbfeea2c260b..f9f344d4470a9a5638a00d8c041c87eb90a0b27b 100644 --- a/Documentation/Examples/cascade_example.cc +++ b/Documentation/Examples/cascade_example.cc @@ -27,6 +27,8 @@ #include <corsika/geometry/Sphere.h> #include <corsika/process/sibyll/ParticleConversion.h> +#include <corsika/process/sibyll/ProcessDecay.h> + #include <corsika/units/PhysicalUnits.h> #include <iostream> @@ -38,6 +40,7 @@ using namespace corsika::process; using namespace corsika::units; using namespace corsika::particles; using namespace corsika::random; +using namespace corsika::setup; using namespace corsika::geometry; using namespace corsika::environment; @@ -45,16 +48,206 @@ using namespace std; using namespace corsika::units::si; static int fCount = 0; +static EnergyType fEnergy = 0. * 1_GeV; + +// FOR NOW: global static variables for ParticleCut process +// this is just wrong... +static EnergyType fEmEnergy; +static int fEmCount; + +static EnergyType fInvEnergy; +static int fInvCount; + +class ProcessEMCut : public corsika::process::BaseProcess<ProcessEMCut> { +public: + ProcessEMCut() {} + template <typename Particle> + bool isBelowEnergyCut(Particle& p) const { + // FOR NOW: center-of-mass energy hard coded + const EnergyType Ecm = sqrt(2. * p.GetEnergy() * 0.93827_GeV); + if (p.GetEnergy() < 50_GeV || Ecm < 10_GeV) + return true; + else + return false; + } + + bool isEmParticle(Code pCode) const { + bool is_em = false; + // FOR NOW: switch + switch (pCode) { + case Code::Electron: + is_em = true; + break; + case Code::Gamma: + is_em = true; + break; + default: + break; + } + return is_em; + } + + void defineEmParticles() const { + // create bool array identifying em particles + } + + bool isInvisible(Code pCode) const { + bool is_inv = false; + // FOR NOW: switch + switch (pCode) { + case Code::NuE: + is_inv = true; + break; + case Code::NuEBar: + is_inv = true; + break; + case Code::NuMu: + is_inv = true; + break; + case Code::NuMuBar: + is_inv = true; + break; + case Code::MuPlus: + is_inv = true; + break; + case Code::MuMinus: + is_inv = true; + break; + + default: + break; + } + return is_inv; + } + + template <typename Particle> + double MinStepLength(Particle& p, setup::Trajectory&) const { + const Code pid = p.GetPID(); + if (isEmParticle(pid) || isInvisible(pid)) { + cout << "ProcessCut: MinStep: next cut: " << 0. << endl; + return 0.; + } else { + double next_step = std::numeric_limits<double>::infinity(); + cout << "ProcessCut: MinStep: next cut: " << next_step << endl; + return next_step; + } + } + + template <typename Particle, typename Stack> + EProcessReturn DoContinuous(Particle&, setup::Trajectory&, Stack&) const { + // cout << "ProcessCut: DoContinous: " << p.GetPID() << endl; + // cout << " is em: " << isEmParticle( p.GetPID() ) << endl; + // cout << " is inv: " << isInvisible( p.GetPID() ) << endl; + // const Code pid = p.GetPID(); + // if( isEmParticle( pid ) ){ + // cout << "removing em. particle..." << endl; + // fEmEnergy += p.GetEnergy(); + // fEmCount += 1; + // p.Delete(); + // return EProcessReturn::eParticleAbsorbed; + // } + // if ( isInvisible( pid ) ){ + // cout << "removing inv. particle..." << endl; + // fInvEnergy += p.GetEnergy(); + // fInvCount += 1; + // p.Delete(); + // return EProcessReturn::eParticleAbsorbed; + // } + return EProcessReturn::eOk; + } + + template <typename Particle, typename Stack> + void DoDiscrete(Particle& p, Stack&) const { + cout << "ProcessCut: DoDiscrete: " << p.GetPID() << endl; + const Code pid = p.GetPID(); + if (isEmParticle(pid)) { + cout << "removing em. particle..." << endl; + fEmEnergy += p.GetEnergy(); + fEmCount += 1; + p.Delete(); + } else if (isInvisible(pid)) { + cout << "removing inv. particle..." << endl; + fInvEnergy += p.GetEnergy(); + fInvCount += 1; + p.Delete(); + } else if (isBelowEnergyCut(p)) { + cout << "removing low en. particle..." << endl; + fEnergy += p.GetEnergy(); + fCount += 1; + p.Delete(); + } + } + + void Init() { + fEmEnergy = 0. * 1_GeV; + fEmCount = 0; + fInvEnergy = 0. * 1_GeV; + fInvCount = 0; + fEnergy = 0. * 1_GeV; + // defineEmParticles(); + } + + void ShowResults() { + cout << " ******************************" << endl + << " ParticleCut: " << endl + << " energy in em. component (GeV): " << fEmEnergy / 1_GeV << endl + << " no. of em. particles injected: " << fEmCount << endl + << " energy in inv. component (GeV): " << fInvEnergy / 1_GeV << endl + << " no. of inv. particles injected: " << fInvCount << endl + << " ******************************" << endl; + } + + EnergyType GetInvEnergy() { return fInvEnergy; } + + EnergyType GetCutEnergy() { return fEnergy; } + + EnergyType GetEmEnergy() { return fEmEnergy; } + +private: +}; class ProcessSplit : public corsika::process::InteractionProcess<ProcessSplit> { public: ProcessSplit() {} + void setTrackedParticlesStable() const { + /* + Sibyll is hadronic generator + only hadrons decay + */ + // set particles unstable + corsika::process::sibyll::setHadronsUnstable(); + // make tracked particles stable + std::cout << "ProcessSplit: setting tracked hadrons stable.." << std::endl; + setup::Stack ds; + ds.NewParticle().SetPID(Code::PiPlus); + ds.NewParticle().SetPID(Code::PiMinus); + ds.NewParticle().SetPID(Code::KPlus); + ds.NewParticle().SetPID(Code::KMinus); + ds.NewParticle().SetPID(Code::K0Long); + ds.NewParticle().SetPID(Code::K0Short); + + for (auto& p : ds) { + int s_id = process::sibyll::ConvertToSibyllRaw(p.GetPID()); + // set particle stable by setting table value negative + s_csydec_.idb[s_id - 1] = (-1) * abs(s_csydec_.idb[s_id - 1]); + p.Delete(); + } + } + template <typename Particle, typename Track> double GetInteractionLength(Particle& p, Track&) const { + + // coordinate system, get global frame of reference + CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS(); + + const Code corsikaBeamId = p.GetPID(); + // beam particles for sibyll : 1, 2, 3 for p, pi, k // read from cross section code table - int kBeam = 1; + int kBeam = process::sibyll::GetSibyllXSCode(corsikaBeamId); + + bool kInteraction = process::sibyll::CanInteract(corsikaBeamId); /* the target should be defined by the Environment, @@ -63,33 +256,55 @@ public: */ // target nuclei: A < 18 // FOR NOW: assume target is oxygen - int kTarget = 1; - double beamEnergy = p.GetEnergy() / 1_GeV; + int kTarget = 16; + + EnergyType Etot = p.GetEnergy() + kTarget * corsika::particles::Proton::GetMass(); + super_stupid::MomentumVector Ptot( + rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second}); + // FOR NOW: assume target is at rest + super_stupid::MomentumVector pTarget( + rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second}); + Ptot += p.GetMomentum(); + Ptot += pTarget; + // calculate cm. energy + EnergyType sqs = sqrt(Etot * Etot - Ptot.squaredNorm() * si::constants::cSquared); + double Ecm = sqs / 1_GeV; + std::cout << "ProcessSplit: " - << "MinStep: en: " << beamEnergy << " pid:" << kBeam << std::endl; - double prodCrossSection, dummy, dum1, dum2, dum3, dum4; - double dumdif[3]; + << "MinStep: input en: " << p.GetEnergy() / 1_GeV << endl + << " beam can interact:" << kBeam << endl + << " beam XS code:" << kBeam << endl + << " beam pid:" << p.GetPID() << endl + << " target mass number:" << kTarget << std::endl; - if (kTarget == 1) - sib_sigma_hp_(kBeam, beamEnergy, dum1, dum2, prodCrossSection, dumdif, dum3, dum4); - else - sib_sigma_hnuc_(kBeam, kTarget, beamEnergy, prodCrossSection, dummy); + double int_length = 0; + if (kInteraction) { - std::cout << "ProcessSplit: " - << "MinStep: sibyll return: " << prodCrossSection << std::endl; - CrossSectionType sig = prodCrossSection * 1_mbarn; - std::cout << "ProcessSplit: " - << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl; + double prodCrossSection, dummy, dum1, dum2, dum3, dum4; + double dumdif[3]; + + if (kTarget == 1) + sib_sigma_hp_(kBeam, Ecm, dum1, dum2, prodCrossSection, dumdif, dum3, dum4); + else + sib_sigma_hnuc_(kBeam, kTarget, Ecm, prodCrossSection, dummy); + + std::cout << "ProcessSplit: " + << "MinStep: sibyll return: " << prodCrossSection << std::endl; + CrossSectionType sig = prodCrossSection * 1_mbarn; + std::cout << "ProcessSplit: " + << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl; + + const MassType nucleon_mass = 0.93827_GeV / corsika::units::si::constants::cSquared; + std::cout << "ProcessSplit: " + << "nucleon mass " << nucleon_mass << std::endl; + // calculate interaction length in medium + int_length = kTarget * (nucleon_mass / 1_g) / (sig / 1_cmeter / 1_cmeter); + // pick random step lenth + std::cout << "ProcessSplit: " + << "interaction length (g/cm2): " << int_length << std::endl; + } else + int_length = std::numeric_limits<double>::infinity(); - const MassType nucleon_mass = 0.93827_GeV / corsika::units::si::constants::cSquared; - std::cout << "ProcessSplit: " - << "nucleon mass " << nucleon_mass << std::endl; - // calculate interaction length in medium - double int_length = kTarget * (nucleon_mass / 1_g) / (sig / 1_cmeter / 1_cmeter); - // pick random step lenth - std::cout << "ProcessSplit: " - << "interaction length (g/cm2): " << int_length << std::endl; - // add exponential sampling /* what are the units of the output? slant depth or 3space length? @@ -110,9 +325,38 @@ public: template <typename Particle, typename Stack> void DoInteraction(Particle& p, Stack& s) const { - cout << "DoInteraction: " << p.GetPID() << " interaction? " + cout << "ProcessSibyll: " + << "DoInteraction: " << p.GetPID() << " interaction? " << process::sibyll::CanInteract(p.GetPID()) << endl; if (process::sibyll::CanInteract(p.GetPID())) { + cout << "defining coordinates" << endl; + // coordinate system, get global frame of reference + CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS(); + + QuantityVector<length_d> const coordinates{0_m, 0_m, 0_m}; + Point pOrig(rootCS, coordinates); + + /* + the target should be defined by the Environment, + ideally as full particle object so that the four momenta + and the boosts can be defined.. + + here we need: GetTargetMassNumber() or GetTargetPID()?? + GetTargetMomentum() (zero in EAS) + */ + // FOR NOW: set target to proton + int kTarget = 1; // env.GetTargetParticle().GetPID(); + + cout << "defining target momentum.." << endl; + // FOR NOW: target is always at rest + const EnergyType Etarget = 0. * 1_GeV + corsika::particles::Proton::GetMass(); + const auto pTarget = super_stupid::MomentumVector( + rootCS, 0. * 1_GeV / si::constants::c, 0. * 1_GeV / si::constants::c, + 0. * 1_GeV / si::constants::c); + cout << "target momentum (GeV/c): " + << pTarget.GetComponents() / 1_GeV * si::constants::c << endl; + cout << "beam momentum (GeV/c): " + << p.GetMomentum().GetComponents() / 1_GeV * si::constants::c << endl; // get energy of particle from stack /* @@ -121,18 +365,30 @@ public: (assuming proton at rest as target AND assuming no pT, i.e. shower frame-z is aligned with hadron-int-frame-z) */ + // total energy: E_beam + E_target + // in lab. frame: E_beam + m_target*c**2 EnergyType E = p.GetEnergy(); - EnergyType Ecm = sqrt(2. * E * 0.93827_GeV); + EnergyType Etot = E + Etarget; + // total momentum + super_stupid::MomentumVector Ptot = p.GetMomentum(); // + pTarget; + // invariant mass, i.e. cm. energy + EnergyType Ecm = sqrt(Etot * Etot - + Ptot.squaredNorm() * + si::constants::cSquared); // sqrt( 2. * E * 0.93827_GeV ); + /* + get transformation between Stack-frame and SibStack-frame + for EAS Stack-frame is lab. frame, could be different for CRMC-mode + the transformation should be derived from the input momenta + */ + const double gamma = Etot / Ecm; + const auto gambet = Ptot / (Ecm / si::constants::c); - int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID()); + std::cout << "ProcessSplit: " + << " DoDiscrete: gamma:" << gamma << endl; + std::cout << "ProcessSplit: " + << " DoDiscrete: gambet:" << gambet.GetComponents() << endl; - /* - the target should be defined by the Environment, - ideally as full particle object so that the four momenta - and the boosts can be defined.. - */ - // FOR NOW: set target to proton - int kTarget = 1; // p.GetPID(); + int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID()); std::cout << "ProcessSplit: " << " DoInteraction: E(GeV):" << E / 1_GeV << " Ecm(GeV): " << Ecm / 1_GeV @@ -148,7 +404,8 @@ public: // running sibyll, filling stack sibyll_(kBeam, kTarget, sqs); // running decays - // decsib_(); + setTrackedParticlesStable(); + decsib_(); // print final state int print_unit = 6; sib_list_(print_unit); @@ -159,49 +416,62 @@ public: // add particles from sibyll to stack // link to sibyll stack SibStack ss; - /* - get transformation between Stack-frame and SibStack-frame - for EAS Stack-frame is lab. frame, could be different for CRMC-mode - the transformation should be derived from the input momenta - in general transformation is rotation + boost - */ - const EnergyType proton_mass = 0.93827_GeV; - const double gamma = (E + proton_mass) / (Ecm); - const double gambet = sqrt(E * E - proton_mass * proton_mass) / Ecm; // SibStack does not know about momentum yet so we need counter to access momentum // array in Sibyll int i = -1; - for (auto& p : ss) { + super_stupid::MomentumVector Ptot_final( + rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second}); + for (auto& psib : ss) { ++i; - // transform to lab. frame, primitve - const double en_lab = gambet * s_plist_.p[2][i] + gamma * p.GetEnergy(); + // skip particles that have decayed in Sibyll + if (abs(s_plist_.llist[i]) > 100) continue; + + // transform energy to lab. frame, primitve + // compute beta_vec * p_vec + // arbitrary Lorentz transformation based on sibyll routines + const auto gammaBetaComponents = gambet.GetComponents(); + const auto pSibyllComponents = psib.GetMomentum().GetComponents(); + EnergyType en_lab = 0. * 1_GeV; + MomentumType p_lab_components[3]; + en_lab = psib.GetEnergy() * gamma; + EnergyType pnorm = 0. * 1_GeV; + for (int j = 0; j < 3; ++j) + pnorm += (pSibyllComponents[j] * gammaBetaComponents[j] * si::constants::c) / + (gamma + 1.); + pnorm += psib.GetEnergy(); + + for (int j = 0; j < 3; ++j) { + p_lab_components[j] = pSibyllComponents[j] - (-1) * pnorm * + gammaBetaComponents[j] / + si::constants::c; + en_lab -= + (-1) * pSibyllComponents[j] * gammaBetaComponents[j] * si::constants::c; + } + // add to corsika stack auto pnew = s.NewParticle(); - pnew.SetEnergy(en_lab * 1_GeV); - pnew.SetPID(process::sibyll::ConvertFromSibyll(p.GetPID())); + pnew.SetEnergy(en_lab); + pnew.SetPID(process::sibyll::ConvertFromSibyll(psib.GetPID())); + + corsika::geometry::QuantityVector<momentum_d> p_lab_c{ + p_lab_components[0], p_lab_components[1], p_lab_components[2]}; + pnew.SetMomentum(super_stupid::MomentumVector(rootCS, p_lab_c)); + Ptot_final += pnew.GetMomentum(); } + // cout << "tot. momentum final (GeV/c): " << Ptot_final.GetComponents() / 1_GeV * + // si::constants::c << endl; } - } else - p.Delete(); + } } void Init() { fCount = 0; - // define reference frame? --> defines boosts between corsika stack and model stack. - - // initialize random numbers for sibyll - // FOR NOW USE SIBYLL INTERNAL !!! - // rnd_ini_(); - corsika::random::RNGManager& rmng = corsika::random::RNGManager::GetInstance(); rmng.RegisterRandomStream("s_rndm"); - // // corsika::random::RNG srng; - // auto srng = rmng.GetRandomStream("s_rndm"); - // test random number generator std::cout << "ProcessSplit: " << " test sequence of random numbers." << std::endl; @@ -211,29 +481,11 @@ public: // initialize Sibyll sibyll_ini_(); - // set particles stable / unstable - // use stack to loop over particles - setup::Stack ds; - ds.NewParticle().SetPID(Code::Proton); - ds.NewParticle().SetPID(Code::Neutron); - ds.NewParticle().SetPID(Code::PiPlus); - ds.NewParticle().SetPID(Code::PiMinus); - ds.NewParticle().SetPID(Code::KPlus); - ds.NewParticle().SetPID(Code::KMinus); - ds.NewParticle().SetPID(Code::K0Long); - ds.NewParticle().SetPID(Code::K0Short); - - for (auto& p : ds) { - int s_id = process::sibyll::ConvertToSibyllRaw(p.GetPID()); - // set particle stable by setting table value negative - cout << "ProcessSplit: Init: setting " << p.GetPID() << "(" << s_id << ")" - << " stable in Sibyll .." << endl; - s_csydec_.idb[s_id] = -s_csydec_.idb[s_id - 1]; - p.Delete(); - } + setTrackedParticlesStable(); } int GetCount() { return fCount; } + EnergyType GetEnergy() { return fEnergy; } private: }; @@ -245,9 +497,6 @@ double s_rndm_(int&) { return rmng() / (double)rmng.max(); } -class A {}; -class B : public A {}; - int main() { corsika::environment::Environment env; // dummy environment auto& universe = *(env.GetUniverse()); @@ -266,20 +515,37 @@ int main() { universe.AddChild(std::move(theMedium)); + CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS(); + tracking_line::TrackingLine<setup::Stack> tracking(env); stack_inspector::StackInspector<setup::Stack> p0(true); + ProcessSplit p1; - const auto sequence = p0 + p1; + corsika::process::sibyll::ProcessDecay p2; + ProcessEMCut p3; + const auto sequence = /*p0 +*/ p1 + p2 + p3; setup::Stack stack; corsika::cascade::Cascade EAS(tracking, sequence, stack); stack.Clear(); auto particle = stack.NewParticle(); - EnergyType E0 = 100_TeV; + EnergyType E0 = 100_GeV; + MomentumType P0 = sqrt(E0 * E0 - 0.93827_GeV * 0.93827_GeV) / si::constants::c; + auto plab = super_stupid::MomentumVector(rootCS, 0. * 1_GeV / si::constants::c, + 0. * 1_GeV / si::constants::c, P0); particle.SetEnergy(E0); + particle.SetMomentum(plab); particle.SetPID(Code::Proton); + particle.SetTime(0_ns); + Point p(rootCS, 0_m, 0_m, 0_m); + particle.SetPosition(p); EAS.Init(); EAS.Run(); - cout << "Result: E0=" << E0 / 1_GeV << "GeV, count=" << p1.GetCount() << endl; + cout << "Result: E0=" << E0 / 1_GeV + << "GeV, particles below energy threshold =" << p1.GetCount() << endl; + cout << "total energy below threshold (GeV): " << p1.GetEnergy() / 1_GeV << std::endl; + p3.ShowResults(); + cout << "total energy (GeV): " + << (p3.GetCutEnergy() + p3.GetInvEnergy() + p3.GetEmEnergy()) / 1_GeV << endl; } diff --git a/Framework/Cascade/SibStack.h b/Framework/Cascade/SibStack.h index 7e9bd3bac3bc743bea8fcb0c2b0d1d401e16efae..a25316553da2182f6da9b2668f7f67336ede9a84 100644 --- a/Framework/Cascade/SibStack.h +++ b/Framework/Cascade/SibStack.h @@ -7,9 +7,12 @@ #include <corsika/cascade/sibyll2.3c.h> #include <corsika/process/sibyll/ParticleConversion.h> #include <corsika/stack/Stack.h> +#include <corsika/units/PhysicalUnits.h> using namespace std; using namespace corsika::stack; +using namespace corsika::units; +using namespace corsika::geometry; class SibStackData { @@ -19,13 +22,30 @@ public: void Clear() { s_plist_.np = 0; } int GetSize() const { return s_plist_.np; } +#warning check actual capacity of sibyll stack int GetCapacity() const { return 8000; } void SetId(const int i, const int v) { s_plist_.llist[i] = v; } - void SetEnergy(const int i, const double v) { s_plist_.p[3][i] = v; } + void SetEnergy(const int i, const EnergyType v) { s_plist_.p[3][i] = v / 1_GeV; } + void SetMomentum(const int i, const super_stupid::MomentumVector& v) { + auto tmp = v.GetComponents(); + for (int idx = 0; idx < 3; ++idx) + s_plist_.p[idx][i] = tmp[idx] / 1_GeV * si::constants::c; + } int GetId(const int i) const { return s_plist_.llist[i]; } - double GetEnergy(const int i) const { return s_plist_.p[3][i]; } + + EnergyType GetEnergy(const int i) const { return s_plist_.p[3][i] * 1_GeV; } + + super_stupid::MomentumVector GetMomentum(const int i) const { + CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCS(); + corsika::geometry::QuantityVector<momentum_d> components{ + s_plist_.p[0][i] * 1_GeV / si::constants::c, + s_plist_.p[1][i] * 1_GeV / si::constants::c, + s_plist_.p[2][i] * 1_GeV / si::constants::c}; + super_stupid::MomentumVector v1(rootCS, components); + return v1; + } void Copy(const int i1, const int i2) { s_plist_.llist[i1] = s_plist_.llist[i2]; @@ -45,13 +65,19 @@ class ParticleInterface : public ParticleBase<StackIteratorInterface> { using ParticleBase<StackIteratorInterface>::GetIndex; public: - void SetEnergy(const double v) { GetStackData().SetEnergy(GetIndex(), v); } - double GetEnergy() const { return GetStackData().GetEnergy(GetIndex()); } + void SetEnergy(const EnergyType v) { GetStackData().SetEnergy(GetIndex(), v); } + EnergyType GetEnergy() const { return GetStackData().GetEnergy(GetIndex()); } void SetPID(const int v) { GetStackData().SetId(GetIndex(), v); } corsika::process::sibyll::SibyllCode GetPID() const { return static_cast<corsika::process::sibyll::SibyllCode>( GetStackData().GetId(GetIndex())); } + super_stupid::MomentumVector GetMomentum() const { + return GetStackData().GetMomentum(GetIndex()); + } + void SetMomentum(const super_stupid::MomentumVector& v) { + GetStackData().SetMomentum(GetIndex(), v); + } }; typedef Stack<SibStackData, ParticleInterface> SibStack; diff --git a/Framework/Geometry/BaseTrajectory.h b/Framework/Geometry/BaseTrajectory.h index feedace208c89eefc0ecd02cd066e0dc5eadf1a4..5540fc89d62e240217b79346d86aa32b04004baf 100644 --- a/Framework/Geometry/BaseTrajectory.h +++ b/Framework/Geometry/BaseTrajectory.h @@ -46,7 +46,7 @@ namespace corsika::geometry { corsika::units::si::LengthType) const = 0; virtual LengthType ArcLength(corsika::units::si::TimeType t1, - corsika::units::si::TimeType t2) const = 0; + corsika::units::si::TimeType t2) const = 0; virtual corsika::units::si::TimeType GetDuration( corsika::units::si::TimeType t1, corsika::units::si::TimeType t2) const { diff --git a/Framework/Geometry/Helix.h b/Framework/Geometry/Helix.h index 0fa07e64277f534a815e7e067c08e88e0901d783..2c8f6b8792cb204e652d1222b38f7849b70e0792 100644 --- a/Framework/Geometry/Helix.h +++ b/Framework/Geometry/Helix.h @@ -58,8 +58,8 @@ namespace corsika::geometry { auto GetRadius() const { return radius; } - corsika::units::si::LengthType ArcLength( - corsika::units::si::TimeType t1, corsika::units::si::TimeType t2) const { + corsika::units::si::LengthType ArcLength(corsika::units::si::TimeType t1, + corsika::units::si::TimeType t2) const { return (vPar + vPerp).norm() * (t2 - t1); } diff --git a/Framework/Geometry/Trajectory.h b/Framework/Geometry/Trajectory.h index f3cabbac7886225846fd8cae1ca7079237812749..5bfcea0216ee6fd496275003b307cccc3f804ee8 100644 --- a/Framework/Geometry/Trajectory.h +++ b/Framework/Geometry/Trajectory.h @@ -12,8 +12,8 @@ #ifndef _include_TRAJECTORY_H #define _include_TRAJECTORY_H -#include <corsika/units/PhysicalUnits.h> #include <corsika/geometry/Point.h> +#include <corsika/units/PhysicalUnits.h> using corsika::units::si::LengthType; using corsika::units::si::TimeType; diff --git a/Processes/Sibyll/CMakeLists.txt b/Processes/Sibyll/CMakeLists.txt index f2e4a9fee1aabbbb5196a597db36de06e6385594..a0985a1ad2304e7e5bd4f1024cf43b5cefaf8bc4 100644 --- a/Processes/Sibyll/CMakeLists.txt +++ b/Processes/Sibyll/CMakeLists.txt @@ -20,6 +20,7 @@ set ( set ( MODEL_HEADERS ParticleConversion.h + ProcessDecay.h ${PROJECT_BINARY_DIR}/Processes/Sibyll/Generated.inc ) diff --git a/Processes/Sibyll/ProcessDecay.h b/Processes/Sibyll/ProcessDecay.h new file mode 100644 index 0000000000000000000000000000000000000000..701094e733ad463f673c8d73cdee0bdf34bdddab --- /dev/null +++ b/Processes/Sibyll/ProcessDecay.h @@ -0,0 +1,156 @@ +#ifndef _include_ProcessDecay_h_ +#define _include_ProcessDecay_h_ + +#include <corsika/process/ContinuousProcess.h> + +#include <corsika/cascade/SibStack.h> +#include <corsika/process/sibyll/ParticleConversion.h> +#include <corsika/setup/SetupTrajectory.h> + +// using namespace corsika::particles; + +namespace corsika::process { + + namespace sibyll { + + void setHadronsUnstable() { + // name? also makes EM particles stable + + // loop over all particles in sibyll + // should be changed to loop over human readable list + // i.e. corsika::particles::ListOfParticles() + std::cout << "Sibyll: setting hadrons unstable.." << std::endl; + // make ALL particles unstable, then set EM stable + for (auto& p : corsika2sibyll) { + // std::cout << (int)p << std::endl; + const int sibCode = (int)p; + // skip unknown and antiparticles + if (sibCode < 1) continue; + // std::cout << "Sibyll: Decay: setting " << ConvertFromSibyll( + // static_cast<SibyllCode> ( sibCode ) ) << " unstable" << std::endl; + s_csydec_.idb[sibCode - 1] = abs(s_csydec_.idb[sibCode - 1]); + // std::cout << "decay table value: " << s_csydec_.idb[ sibCode - 1 ] << + // std::endl; + } + // set Leptons and Proton and Neutron stable + // use stack to loop over particles + setup::Stack ds; + ds.NewParticle().SetPID(corsika::particles::Code::Proton); + ds.NewParticle().SetPID(corsika::particles::Code::Neutron); + ds.NewParticle().SetPID(corsika::particles::Code::Electron); + ds.NewParticle().SetPID(corsika::particles::Code::Positron); + ds.NewParticle().SetPID(corsika::particles::Code::NuE); + ds.NewParticle().SetPID(corsika::particles::Code::NuEBar); + ds.NewParticle().SetPID(corsika::particles::Code::MuMinus); + ds.NewParticle().SetPID(corsika::particles::Code::MuPlus); + ds.NewParticle().SetPID(corsika::particles::Code::NuMu); + ds.NewParticle().SetPID(corsika::particles::Code::NuMuBar); + + for (auto& p : ds) { + int s_id = process::sibyll::ConvertToSibyllRaw(p.GetPID()); + // set particle stable by setting table value negative + // cout << "Sibyll: setting " << p.GetPID() << "(" << s_id << ")" + // << " stable in Sibyll .." << endl; + s_csydec_.idb[s_id - 1] = (-1) * abs(s_csydec_.idb[s_id - 1]); + p.Delete(); + } + } + + class ProcessDecay : public corsika::process::BaseProcess<ProcessDecay> { + public: + ProcessDecay() {} + void Init() { + // setHadronsUnstable(); + } + + void setAllStable() { + // name? also makes EM particles stable + + // loop over all particles in sibyll + // should be changed to loop over human readable list + // i.e. corsika::particles::ListOfParticles() + for (auto& p : corsika2sibyll) { + // std::cout << (int)p << std::endl; + const int sibCode = (int)p; + // skip unknown and antiparticles + if (sibCode < 1) continue; + std::cout << "Sibyll: Decay: setting " + << ConvertFromSibyll(static_cast<SibyllCode>(sibCode)) << " stable" + << std::endl; + s_csydec_.idb[sibCode - 1] = -1 * abs(s_csydec_.idb[sibCode - 1]); + std::cout << "decay table value: " << s_csydec_.idb[sibCode - 1] << std::endl; + } + } + + friend void setHadronsUnstable(); + + template <typename Particle> + double MinStepLength(Particle& p, setup::Trajectory&) const { + corsika::units::hep::EnergyType E = p.GetEnergy(); + corsika::units::hep::MassType m = corsika::particles::GetMass(p.GetPID()); + // env.GetDensity(); + + const MassDensityType density = 1.25e-3 * kilogram / (1_cm * 1_cm * 1_cm); + + const double gamma = E / m; + + TimeType t0 = GetLifetime(p.GetPID()); + cout << "ProcessDecay: code: " << (p.GetPID()) << endl; + cout << "ProcessDecay: MinStep: t0: " << t0 << endl; + cout << "ProcessDecay: MinStep: gamma: " << gamma << endl; + cout << "ProcessDecay: MinStep: density: " << density << endl; + // return as column density + const double x0 = density * t0 * gamma * constants::c / kilogram * 1_cm * 1_cm; + cout << "ProcessDecay: MinStep: x0: " << x0 << endl; + int a = 1; + const double x = -x0 * log(s_rndm_(a)); + cout << "ProcessDecay: next decay: " << x << endl; + return x; + } + + template <typename Particle, typename Stack> + void DoDiscrete(Particle& p, Stack& s) const { + SibStack ss; + ss.Clear(); + // copy particle to sibyll stack + auto pin = ss.NewParticle(); + pin.SetPID(process::sibyll::ConvertToSibyllRaw(p.GetPID())); + pin.SetEnergy(p.GetEnergy()); + pin.SetMomentum(p.GetMomentum()); + // remove original particle from corsika stack + p.Delete(); + // set all particles/hadrons unstable + setHadronsUnstable(); + // call sibyll decay + std::cout << "ProcessDecay: calling Sibyll decay routine.." << std::endl; + decsib_(); + // print output + int print_unit = 6; + sib_list_(print_unit); + // copy particles from sibyll stack to corsika + int i = -1; + for (auto& psib : ss) { + ++i; + // FOR NOW: skip particles that have decayed in Sibyll, move to iterator? + if (abs(s_plist_.llist[i]) > 100) continue; + // add to corsika stack + // cout << "decay product: " << process::sibyll::ConvertFromSibyll( + // psib.GetPID() ) << endl; + auto pnew = s.NewParticle(); + pnew.SetEnergy(psib.GetEnergy()); + pnew.SetPID(process::sibyll::ConvertFromSibyll(psib.GetPID())); + pnew.SetMomentum(psib.GetMomentum()); + } + // empty sibyll stack + ss.Clear(); + } + + template <typename Particle, typename Stack> + EProcessReturn DoContinuous(Particle&, setup::Trajectory&, Stack&) const { + return EProcessReturn::eOk; + } + }; + } // namespace sibyll +} // namespace corsika::process + +#endif diff --git a/Processes/Sibyll/code_generator.py b/Processes/Sibyll/code_generator.py index 77c1f5dd8216ad48ebf5c4aa476ef57695bb7fea..a593a1f2ce5a5c3a281c758e2404c72347286ec0 100755 --- a/Processes/Sibyll/code_generator.py +++ b/Processes/Sibyll/code_generator.py @@ -159,8 +159,6 @@ if __name__ == "__main__": pythia_db = load_pythiadb(sys.argv[1]) read_sibyll_codes(sys.argv[2], pythia_db) - print (str(pythia_db)) - with open("Generated.inc", "w") as f: print("// this file is automatically generated\n// edit at your own risk!\n", file=f) print(generate_sibyll_enum(pythia_db), file=f) diff --git a/Processes/StackInspector/StackInspector.cc b/Processes/StackInspector/StackInspector.cc index 266005cde54295a790a8748e91614bf6f9d58b37..ad90442848976c4cc779977a2c2f1890cedb1091 100644 --- a/Processes/StackInspector/StackInspector.cc +++ b/Processes/StackInspector/StackInspector.cc @@ -10,9 +10,9 @@ */ #include <corsika/geometry/RootCoordinateSystem.h> +#include <corsika/particles/ParticleProperties.h> #include <corsika/process/stack_inspector/StackInspector.h> #include <corsika/units/PhysicalUnits.h> -#include <corsika/particles/ParticleProperties.h> #include <corsika/logging/Logger.h> @@ -28,7 +28,8 @@ using namespace corsika::process::stack_inspector; template <typename Stack> StackInspector<Stack>::StackInspector(const bool aReport) - : fReport(aReport) {} + : fReport(aReport) + , fCountStep(0) {} template <typename Stack> StackInspector<Stack>::~StackInspector() {} @@ -36,7 +37,6 @@ StackInspector<Stack>::~StackInspector() {} template <typename Stack> process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&, setup::Trajectory&, Stack& s) const { - static int countStep = 0; if (!fReport) return EProcessReturn::eOk; [[maybe_unused]] int i = 0; EnergyType Etot = 0_GeV; @@ -51,8 +51,8 @@ process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&, setup::Tr << iterP.GetPID() << " E=" << setw(15) << scientific << (E / 1_GeV) << " GeV, " << " pos=" << pos << endl; } - countStep++; - cout << "StackInspector: nStep=" << countStep << " stackSize=" << s.GetSize() + fCountStep++; + cout << "StackInspector: nStep=" << fCountStep << " stackSize=" << s.GetSize() << " Estack=" << Etot / 1_GeV << " GeV" << endl; return EProcessReturn::eOk; } @@ -63,7 +63,9 @@ double StackInspector<Stack>::MaxStepLength(Particle&, setup::Trajectory&) const } template <typename Stack> -void StackInspector<Stack>::Init() {} +void StackInspector<Stack>::Init() { + fCountStep = 0; +} #include <corsika/setup/SetupStack.h> diff --git a/Processes/StackInspector/StackInspector.h b/Processes/StackInspector/StackInspector.h index 58b9ec5ebd7652b127f719beafcedacbbf79d503..6032beac618b0941b01ffd76962c3bc13ad2300b 100644 --- a/Processes/StackInspector/StackInspector.h +++ b/Processes/StackInspector/StackInspector.h @@ -40,6 +40,7 @@ namespace corsika::process { private: bool fReport; + mutable int fCountStep = 0; }; } // namespace stack_inspector diff --git a/Processes/TrackingLine/testTrackingLine.cc b/Processes/TrackingLine/testTrackingLine.cc index ef44f2390a5071f645e383bff23373d8ec240993..a3df326480c9417b736f6ac058dd70f6e8cce253 100644 --- a/Processes/TrackingLine/testTrackingLine.cc +++ b/Processes/TrackingLine/testTrackingLine.cc @@ -13,8 +13,8 @@ #include <corsika/process/tracking_line/TrackingLine.h> #include <corsika/geometry/Point.h> -#include <corsika/geometry/Vector.h> #include <corsika/geometry/Sphere.h> +#include <corsika/geometry/Vector.h> #include <corsika/setup/SetupTrajectory.h> using corsika::setup::Trajectory; @@ -33,66 +33,80 @@ using namespace std; using namespace corsika::units::si; struct DummyParticle { - EnergyType fEnergy; - Vector<momentum_d> fMomentum; - Point fPosition; - - DummyParticle(EnergyType pEnergy, Vector<momentum_d> pMomentum, Point pPosition) : fEnergy(pEnergy), fMomentum(pMomentum), fPosition(pPosition) {} - - auto GetEnergy() const { return fEnergy; } - auto GetMomentum() const { return fMomentum; } - auto GetPosition() const { return fPosition; } + EnergyType fEnergy; + Vector<momentum_d> fMomentum; + Point fPosition; + + DummyParticle(EnergyType pEnergy, Vector<momentum_d> pMomentum, Point pPosition) + : fEnergy(pEnergy) + , fMomentum(pMomentum) + , fPosition(pPosition) {} + + auto GetEnergy() const { return fEnergy; } + auto GetMomentum() const { return fMomentum; } + auto GetPosition() const { return fPosition; } }; struct DummyStack { - using ParticleType = DummyParticle; + using ParticleType = DummyParticle; }; TEST_CASE("TrackingLine") { corsika::environment::Environment env; // dummy environment auto const& cs = env.GetCoordinateSystem(); - + tracking_line::TrackingLine<DummyStack> tracking(env); SECTION("intersection with sphere") { Point const origin(cs, {0_m, 0_m, 0_m}); Point const center(cs, {0_m, 0_m, 10_m}); Sphere const sphere(center, 1_m); - Vector<corsika::units::si::SpeedType::dimension_type> v(cs, 0_m/second, 0_m/second, 1_m/second); + Vector<corsika::units::si::SpeedType::dimension_type> v(cs, 0_m / second, + 0_m / second, 1_m / second); Line line(origin, v); - + geometry::Trajectory<Line> traj(line, 12345_s); - - auto const opt = tracking.TimeOfIntersection(traj, Sphere(Point(cs, {0_m, 0_m, 10_m}), 1_m)); + + auto const opt = + tracking.TimeOfIntersection(traj, Sphere(Point(cs, {0_m, 0_m, 10_m}), 1_m)); REQUIRE(opt.has_value()); - + auto [t1, t2] = opt.value(); REQUIRE(t1 / 9_s == Approx(1)); REQUIRE(t2 / 11_s == Approx(1)); - - auto const optNoIntersection = tracking.TimeOfIntersection(traj, Sphere(Point(cs, {5_m, 0_m, 10_m}), 1_m)); + + auto const optNoIntersection = + tracking.TimeOfIntersection(traj, Sphere(Point(cs, {5_m, 0_m, 10_m}), 1_m)); REQUIRE_FALSE(optNoIntersection.has_value()); } - + SECTION("maximally possible propagation") { - auto& universe = *(env.GetUniverse()); - - //~ std::cout << env.GetUniverse().get() << std::endl; - - DummyParticle p(1_J, Vector<momentum_d>(cs, 0*kilogram*meter/second, 0*kilogram*meter/second, 1*kilogram*meter/second), Point(cs, 0_m, 0_m,0_m)); - - auto const radius = 20_m; - - auto theMedium = corsika::environment::Environment::CreateNode<Sphere>( - Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, radius); - universe.AddChild(std::move(theMedium)); - - Point const origin(cs, {0_m, 0_m, 0_m}); - Vector<corsika::units::si::SpeedType::dimension_type> v(cs, 0_m/second, 0_m/second, 1_m/second); - Line line(origin, v); - - auto const traj = tracking.GetTrack(p); - - REQUIRE((traj.GetPosition(1.) - Point(cs, 0_m, 0_m, radius)).GetComponents(cs).norm().magnitude() == Approx(0).margin(1e-4)); + auto& universe = *(env.GetUniverse()); + + //~ std::cout << env.GetUniverse().get() << std::endl; + + DummyParticle p( + 1_J, + Vector<momentum_d>(cs, 0 * kilogram * meter / second, + 0 * kilogram * meter / second, 1 * kilogram * meter / second), + Point(cs, 0_m, 0_m, 0_m)); + + auto const radius = 20_m; + + auto theMedium = corsika::environment::Environment::CreateNode<Sphere>( + Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, radius); + universe.AddChild(std::move(theMedium)); + + Point const origin(cs, {0_m, 0_m, 0_m}); + Vector<corsika::units::si::SpeedType::dimension_type> v(cs, 0_m / second, + 0_m / second, 1_m / second); + Line line(origin, v); + + auto const traj = tracking.GetTrack(p); + + REQUIRE((traj.GetPosition(1.) - Point(cs, 0_m, 0_m, radius)) + .GetComponents(cs) + .norm() + .magnitude() == Approx(0).margin(1e-4)); } } diff --git a/Setup/SetupEnvironment.h b/Setup/SetupEnvironment.h index e822b64ec0dd4b393fd7285360c96879ce2ccc0f..c5de9d53c9e26d6f5afe88d9762ec88df3043a64 100644 --- a/Setup/SetupEnvironment.h +++ b/Setup/SetupEnvironment.h @@ -15,7 +15,7 @@ #include <corsika/environment/IMediumModel.h> namespace corsika::setup { - using IEnvironmentModel = corsika::environment::IMediumModel; + using IEnvironmentModel = corsika::environment::IMediumModel; } #endif diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h index 8c79934422420791c1d33395810e5b90afa4038e..a889d32a652753955ba2553012350e521b1d99dc 100644 --- a/Stack/SuperStupidStack/SuperStupidStack.h +++ b/Stack/SuperStupidStack/SuperStupidStack.h @@ -137,7 +137,7 @@ namespace corsika::stack { void IncrementSize() { fDataPID.push_back(Code::Unknown); fDataE.push_back(0 * joule); -#warning this here makes no sense: see issue #48 + //#TODO this here makes no sense: see issue #48 geometry::CoordinateSystem& dummyCS = geometry::RootCoordinateSystem::GetInstance().GetRootCS(); fMomentum.push_back(MomentumVector(