diff --git a/Documentation/Examples/CMakeLists.txt b/Documentation/Examples/CMakeLists.txt index 6529b5153565a74ddc39fc16b3e7c90f882f7aac..ffc14426f790c8c760d77fdc056d782836bc1a94 100644 --- a/Documentation/Examples/CMakeLists.txt +++ b/Documentation/Examples/CMakeLists.txt @@ -47,8 +47,8 @@ CORSIKA_ADD_TEST (cascade_example) add_executable (boundary_example boundary_example.cc) target_compile_options(boundary_example PRIVATE -g) # do not skip asserts target_link_libraries (boundary_example SuperStupidStack CORSIKAunits CORSIKAlogging - CORSIKArandom - ProcessSibyll + CORSIKArandom + ProcessSibyll CORSIKAcascade ProcessTrackWriter ProcessTrackingLine @@ -70,11 +70,12 @@ target_link_libraries (cascade_proton_example SuperStupidStack CORSIKAunits ProcessSibyll ProcessPythia CORSIKAcascade - ProcessStackInspector + ProcessEnergyLoss ProcessTrackWriter ProcessTrackingLine ProcessHadronicElasticModel CORSIKAprocesses + CORSIKAcascade CORSIKAparticles CORSIKAgeometry CORSIKAenvironment @@ -84,6 +85,28 @@ target_link_libraries (cascade_proton_example SuperStupidStack CORSIKAunits install (TARGETS cascade_proton_example DESTINATION share/examples) CORSIKA_ADD_TEST (cascade_proton_example) +add_executable (vertical_EAS vertical_EAS.cc) +target_compile_options(vertical_EAS PRIVATE -g) # do not skip asserts +target_link_libraries (vertical_EAS SuperStupidStack CORSIKAunits + CORSIKAlogging + CORSIKArandom + ProcessSibyll + ProcessPythia + CORSIKAcascade + ProcessEnergyLoss + ProcessTrackWriter + ProcessTrackingLine + ProcessHadronicElasticModel + CORSIKAprocesses + CORSIKAcascade + CORSIKAparticles + CORSIKAgeometry + CORSIKAenvironment + CORSIKAprocesssequence + ) +install (TARGETS vertical_EAS DESTINATION share/examples) +# CORSIKA_ADD_TEST (vertical_EAS) not yet... + add_executable (staticsequence_example staticsequence_example.cc) target_compile_options(staticsequence_example PRIVATE -g) # do not skip asserts target_link_libraries (staticsequence_example diff --git a/Documentation/Examples/boundary_example.cc b/Documentation/Examples/boundary_example.cc index 98e01b89f0aaeaa556e8d0364b2be3fff4498ecc..b1d540eebb540c10063ef79648086f749d779ba9 100644 --- a/Documentation/Examples/boundary_example.cc +++ b/Documentation/Examples/boundary_example.cc @@ -51,7 +51,7 @@ using namespace corsika::environment; using namespace std; using namespace corsika::units::si; -class ProcessCut : public process::ContinuousProcess<ProcessCut> { +class ProcessCut : public process::SecondariesProcess<ProcessCut> { HEPEnergyType fECut; @@ -145,47 +145,38 @@ public: return is_inv; } - template <typename Particle> - LengthType MaxStepLength(Particle& p, setup::Trajectory&) const { - cout << "ProcessCut: MinStep: pid: " << p.GetPID() << endl; - cout << "ProcessCut: MinStep: energy (GeV): " << p.GetEnergy() / 1_GeV << endl; - const Code pid = p.GetPID(); - if (isEmParticle(pid) || isInvisible(pid) || isBelowEnergyCut(p)) { - cout << "ProcessCut: MinStep: next cut: " << 0. << endl; - return 0_m; - } else { - LengthType next_step = 1_m * std::numeric_limits<double>::infinity(); - cout << "ProcessCut: MinStep: next cut: " << next_step << endl; - return next_step; - } - } - - template <typename Particle, typename Stack> - EProcessReturn DoContinuous(Particle& p, setup::Trajectory&, Stack&) { - const Code pid = p.GetPID(); - HEPEnergyType energy = p.GetEnergy(); - cout << "ProcessCut: DoContinuous: " << pid << " E= " << energy - << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" << endl; - EProcessReturn ret = EProcessReturn::eOk; - if (isEmParticle(pid)) { - cout << "removing em. particle..." << endl; - fEmEnergy += energy; - fEmCount += 1; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; - } else if (isInvisible(pid)) { - cout << "removing inv. particle..." << endl; - fInvEnergy += energy; - fInvCount += 1; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; - } else if (isBelowEnergyCut(p)) { - cout << "removing low en. particle..." << endl; - fEnergy += energy; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; + template <typename TSecondaries> + EProcessReturn DoSecondaries(TSecondaries& vS) { + auto p = vS.begin(); + while (p != vS.end()) { + const Code pid = p.GetPID(); + HEPEnergyType energy = p.GetEnergy(); + cout << "ProcessCut: DoSecondaries: " << pid << " E= " << energy + << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" + << endl; + if (isEmParticle(pid)) { + cout << "removing em. particle..." << endl; + fEmEnergy += energy; + fEmCount += 1; + p.Delete(); + } else if (isInvisible(pid)) { + cout << "removing inv. particle..." << endl; + fInvEnergy += energy; + fInvCount += 1; + p.Delete(); + } else if (isBelowEnergyCut(p)) { + cout << "removing low en. particle..." << endl; + fEnergy += energy; + p.Delete(); + } else if (p.GetTime() > 10_ms) { + cout << "removing OLD particle..." << endl; + fEnergy += energy; + p.Delete(); + } else { + ++p; // next entry in SecondaryView + } } - return ret; + return EProcessReturn::eOk; } void Init() { @@ -251,7 +242,7 @@ int main() { random::RNGManager::GetInstance().RegisterRandomStream("cascade"); // setup environment, geometry - using EnvType = environment::Environment<setup::IEnvironmentModel>; + using EnvType = Environment<setup::IEnvironmentModel>; EnvType env; auto& universe = *(env.GetUniverse()); @@ -266,7 +257,7 @@ int main() { ->SetModelProperties<environment::HomogeneousMedium<setup::IEnvironmentModel>>( 1_kg / (1_m * 1_m * 1_m), environment::NuclearComposition( - std::vector<particles::Code>{particles::Code::Oxygen}, + std::vector<particles::Code>{particles::Code::Proton}, std::vector<float>{1.f})); auto innerMedium = EnvType::CreateNode<Sphere>(Point{rootCS, 0_m, 0_m, 0_m}, 5_km); diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc index 9855dfcb8bfa227c1b5da8487d73fe0d64b4941f..03feb8f6eb88b8d5f023bbcaec7ede771e9fadfd 100644 --- a/Documentation/Examples/cascade_example.cc +++ b/Documentation/Examples/cascade_example.cc @@ -41,7 +41,6 @@ #include <iostream> #include <limits> -#include <typeinfo> using namespace corsika; using namespace corsika::process; @@ -55,7 +54,7 @@ using namespace corsika::environment; using namespace std; using namespace corsika::units::si; -class ProcessCut : public process::ContinuousProcess<ProcessCut> { +class ProcessCut : public process::SecondariesProcess<ProcessCut> { HEPEnergyType fECut; @@ -149,47 +148,38 @@ public: return is_inv; } - template <typename Particle> - LengthType MaxStepLength(Particle& p, setup::Trajectory&) const { - cout << "ProcessCut: MinStep: pid: " << p.GetPID() << endl; - cout << "ProcessCut: MinStep: energy (GeV): " << p.GetEnergy() / 1_GeV << endl; - const Code pid = p.GetPID(); - if (isEmParticle(pid) || isInvisible(pid) || isBelowEnergyCut(p)) { - cout << "ProcessCut: MinStep: next cut: " << 0. << endl; - return 0_m; - } else { - LengthType next_step = 1_m * std::numeric_limits<double>::infinity(); - cout << "ProcessCut: MinStep: next cut: " << next_step << endl; - return next_step; - } - } - - template <typename Particle, typename Stack> - EProcessReturn DoContinuous(Particle& p, setup::Trajectory&, Stack&) { - const Code pid = p.GetPID(); - HEPEnergyType energy = p.GetEnergy(); - cout << "ProcessCut: DoContinuous: " << pid << " E= " << energy - << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" << endl; - EProcessReturn ret = EProcessReturn::eOk; - if (isEmParticle(pid)) { - cout << "removing em. particle..." << endl; - fEmEnergy += energy; - fEmCount += 1; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; - } else if (isInvisible(pid)) { - cout << "removing inv. particle..." << endl; - fInvEnergy += energy; - fInvCount += 1; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; - } else if (isBelowEnergyCut(p)) { - cout << "removing low en. particle..." << endl; - fEnergy += energy; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; + template <typename TSecondaries> + EProcessReturn DoSecondaries(TSecondaries& vS) { + auto p = vS.begin(); + while (p != vS.end()) { + const Code pid = p.GetPID(); + HEPEnergyType energy = p.GetEnergy(); + cout << "ProcessCut: DoSecondaries: " << pid << " E= " << energy + << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" + << endl; + if (isEmParticle(pid)) { + cout << "removing em. particle..." << endl; + fEmEnergy += energy; + fEmCount += 1; + p.Delete(); + } else if (isInvisible(pid)) { + cout << "removing inv. particle..." << endl; + fInvEnergy += energy; + fInvCount += 1; + p.Delete(); + } else if (isBelowEnergyCut(p)) { + cout << "removing low en. particle..." << endl; + fEnergy += energy; + p.Delete(); + } else if (p.GetTime() > 10_ms) { + cout << "removing OLD particle..." << endl; + fEnergy += energy; + p.Delete(); + } else { + ++p; // next entry in SecondaryView + } } - return ret; + return EProcessReturn::eOk; } void Init() { @@ -217,10 +207,14 @@ public: HEPEnergyType GetEmEnergy() const { return fEmEnergy; } }; + // // The example main program for a particle cascade // int main() { + + const LengthType height_atmosphere = 112.8_km; + feenableexcept(FE_INVALID); // initialize random number sequence(s) random::RNGManager::GetInstance().RegisterRandomStream("cascade"); @@ -256,7 +250,7 @@ int main() { // setup processes, decays and interactions tracking_line::TrackingLine tracking; - stack_inspector::StackInspector<setup::Stack> stackInspect(true); + stack_inspector::StackInspector<setup::Stack> stackInspect(1, true); const std::vector<particles::Code> trackedHadrons = { particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus, @@ -273,7 +267,8 @@ int main() { process::EnergyLoss::EnergyLoss eLoss; // assemble all processes into an ordered process list - auto sequence = sibyll << sibyllNuc << decay << cut << trackWriter; + auto sequence = stackInspect << sibyll << sibyllNuc << decay << eLoss << cut + << trackWriter; // setup particle stack, and add primary particle setup::Stack stack; @@ -282,7 +277,7 @@ int main() { const int nuclA = 4; const int nuclZ = int(nuclA / 2.15 + 0.7); const HEPMassType mass = GetNucleusMass(nuclA, nuclZ); - const HEPEnergyType E0 = nuclA * 10_TeV; + const HEPEnergyType E0 = nuclA * 1_TeV; double theta = 0.; double phi = 0.; @@ -301,7 +296,8 @@ int main() { cout << "input particle: " << beamCode << endl; cout << "input angles: theta=" << theta << " phi=" << phi << endl; cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl; - Point pos(rootCS, 0_m, 0_m, 0_m); + Point pos(rootCS, 0_m, 0_m, + height_atmosphere); // this is the CORSIKA 7 start of atmosphere/universe stack.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType, unsigned short, unsigned short>{ diff --git a/Documentation/Examples/cascade_proton_example.cc b/Documentation/Examples/cascade_proton_example.cc index 97e6c40ac5f4b80fd2a64430eec8b19fe81867ed..743f8f007b0fbfd594cb209d1d580444a25aba21 100644 --- a/Documentation/Examples/cascade_proton_example.cc +++ b/Documentation/Examples/cascade_proton_example.cc @@ -12,7 +12,6 @@ #include <corsika/cascade/Cascade.h> #include <corsika/process/ProcessSequence.h> #include <corsika/process/hadronic_elastic_model/HadronicElasticModel.h> -#include <corsika/process/stack_inspector/StackInspector.h> #include <corsika/process/tracking_line/TrackingLine.h> #include <corsika/setup/SetupStack.h> @@ -58,7 +57,7 @@ using namespace corsika::environment; using namespace std; using namespace corsika::units::si; -class ProcessCut : public process::ContinuousProcess<ProcessCut> { +class ProcessCut : public process::SecondariesProcess<ProcessCut> { HEPEnergyType fECut; @@ -152,47 +151,38 @@ public: return is_inv; } - template <typename Particle> - LengthType MaxStepLength(Particle& p, setup::Trajectory&) const { - cout << "ProcessCut: MinStep: pid: " << p.GetPID() << endl; - cout << "ProcessCut: MinStep: energy (GeV): " << p.GetEnergy() / 1_GeV << endl; - const Code pid = p.GetPID(); - if (isEmParticle(pid) || isInvisible(pid) || isBelowEnergyCut(p)) { - cout << "ProcessCut: MinStep: next cut: " << 0. << endl; - return 0_m; - } else { - LengthType next_step = 1_m * std::numeric_limits<double>::infinity(); - cout << "ProcessCut: MinStep: next cut: " << next_step << endl; - return next_step; - } - } - - template <typename Particle, typename Stack> - EProcessReturn DoContinuous(Particle& p, setup::Trajectory&, Stack&) { - const Code pid = p.GetPID(); - HEPEnergyType energy = p.GetEnergy(); - cout << "ProcessCut: DoContinuous: " << pid << " E= " << energy - << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" << endl; - EProcessReturn ret = EProcessReturn::eOk; - if (isEmParticle(pid)) { - cout << "removing em. particle..." << endl; - fEmEnergy += energy; - fEmCount += 1; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; - } else if (isInvisible(pid)) { - cout << "removing inv. particle..." << endl; - fInvEnergy += energy; - fInvCount += 1; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; - } else if (isBelowEnergyCut(p)) { - cout << "removing low en. particle..." << endl; - fEnergy += energy; - // p.Delete(); - ret = EProcessReturn::eParticleAbsorbed; + template <typename TSecondaries> + EProcessReturn DoSecondaries(TSecondaries& vS) { + auto p = vS.begin(); + while (p != vS.end()) { + const Code pid = p.GetPID(); + HEPEnergyType energy = p.GetEnergy(); + cout << "ProcessCut: DoSecondaries: " << pid << " E= " << energy + << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" + << endl; + if (isEmParticle(pid)) { + cout << "removing em. particle..." << endl; + fEmEnergy += energy; + fEmCount += 1; + p.Delete(); + } else if (isInvisible(pid)) { + cout << "removing inv. particle..." << endl; + fInvEnergy += energy; + fInvCount += 1; + p.Delete(); + } else if (isBelowEnergyCut(p)) { + cout << "removing low en. particle..." << endl; + fEnergy += energy; + p.Delete(); + } else if (p.GetTime() > 10_ms) { + cout << "removing OLD particle..." << endl; + fEnergy += energy; + p.Delete(); + } else { + ++p; // next entry in SecondaryView + } } - return ret; + return EProcessReturn::eOk; } void Init() { @@ -229,7 +219,7 @@ int main() { random::RNGManager::GetInstance().RegisterRandomStream("cascade"); // setup environment, geometry - using EnvType = environment::Environment<setup::IEnvironmentModel>; + using EnvType = Environment<setup::IEnvironmentModel>; EnvType env; auto& universe = *(env.GetUniverse()); @@ -237,12 +227,11 @@ int main() { EnvType::CreateNode<Sphere>(Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); - using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>; + using MyHomogeneousModel = HomogeneousMedium<IMediumModel>; theMedium->SetModelProperties<MyHomogeneousModel>( 1_kg / (1_m * 1_m * 1_m), - environment::NuclearComposition( - std::vector<particles::Code>{particles::Code::Hydrogen}, - std::vector<float>{(float)1.})); + NuclearComposition(std::vector<particles::Code>{particles::Code::Hydrogen}, + std::vector<float>{(float)1.})); universe.AddChild(std::move(theMedium)); @@ -250,7 +239,6 @@ int main() { // setup processes, decays and interactions tracking_line::TrackingLine tracking; - stack_inspector::StackInspector<setup::Stack> stackInspect(true); const std::vector<particles::Code> trackedHadrons = { particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus, @@ -272,10 +260,8 @@ int main() { process::TrackWriter::TrackWriter trackWriter("tracks.dat"); // assemble all processes into an ordered process list - // auto sequence = p0 << sibyll << decay << hadronicElastic << cut << trackWriter; - // auto sequence = p0 << sibyll << sibyllNuc << decay << cut << trackWriter; - - auto sequence = stackInspect << pythia << decay << cut << trackWriter; + // auto sequence = sibyll << decay << hadronicElastic << cut << trackWriter; + auto sequence = pythia << decay << cut << trackWriter; // cout << "decltype(sequence)=" << type_id_with_cvr<decltype(sequence)>().pretty_name() // << "\n"; diff --git a/Documentation/Examples/staticsequence_example.cc b/Documentation/Examples/staticsequence_example.cc index 5e881ebbe3e38ae028d2c263ff27bcc41b0490b5..0cd2901c3520d203371a7103f3dff96243328f9f 100644 --- a/Documentation/Examples/staticsequence_example.cc +++ b/Documentation/Examples/staticsequence_example.cc @@ -88,12 +88,11 @@ void modular() { auto sequence = m1 << m2 << m3 << m4; - DummyData p; - DummyStack s; - DummyTrajectory t; + DummyData particle; + DummyTrajectory track; const int n = 1000; - for (int i = 0; i < n; ++i) { sequence.DoContinuous(p, t, s); } + for (int i = 0; i < n; ++i) { sequence.DoContinuous(particle, track); } for (int i = 0; i < nData; ++i) { // cout << p.p[i] << endl; diff --git a/Documentation/Examples/vertical_EAS.cc b/Documentation/Examples/vertical_EAS.cc new file mode 100644 index 0000000000000000000000000000000000000000..e2d381914668b83431cccac1c2a51caa117ed22f --- /dev/null +++ b/Documentation/Examples/vertical_EAS.cc @@ -0,0 +1,322 @@ + +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#include <corsika/cascade/Cascade.h> +#include <corsika/process/ProcessSequence.h> +#include <corsika/process/energy_loss/EnergyLoss.h> +#include <corsika/process/hadronic_elastic_model/HadronicElasticModel.h> +#include <corsika/process/tracking_line/TrackingLine.h> + +#include <corsika/setup/SetupStack.h> +#include <corsika/setup/SetupTrajectory.h> + +#include <corsika/environment/Environment.h> +#include <corsika/environment/HomogeneousMedium.h> +#include <corsika/environment/NuclearComposition.h> + +#include <corsika/geometry/Sphere.h> + +#include <corsika/process/sibyll/Decay.h> +#include <corsika/process/sibyll/Interaction.h> +#include <corsika/process/sibyll/NuclearInteraction.h> + +#include <corsika/process/pythia/Decay.h> + +#include <corsika/process/track_writer/TrackWriter.h> + +#include <corsika/units/PhysicalUnits.h> + +#include <corsika/random/RNGManager.h> + +#include <corsika/utl/CorsikaFenv.h> + +#include <boost/type_index.hpp> +using boost::typeindex::type_id_with_cvr; + +#include <iostream> +#include <limits> +#include <typeinfo> + +using namespace corsika; +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; + +using namespace std; +using namespace corsika::units::si; + +class ProcessCut : public process::SecondariesProcess<ProcessCut> { + + HEPEnergyType fECut; + + HEPEnergyType fEnergy = 0_GeV; + HEPEnergyType fEmEnergy = 0_GeV; + int fEmCount = 0; + HEPEnergyType fInvEnergy = 0_GeV; + int fInvCount = 0; + +public: + ProcessCut(const HEPEnergyType cut) + : fECut(cut) {} + + template <typename Particle> + bool isBelowEnergyCut(Particle& p) const { + // nuclei + if (p.GetPID() == particles::Code::Nucleus) { + auto const ElabNuc = p.GetEnergy() / p.GetNuclearA(); + auto const EcmNN = sqrt(2. * ElabNuc * 0.93827_GeV); + if (ElabNuc < fECut || EcmNN < 10_GeV) + return true; + else + return false; + } else { + // TODO: center-of-mass energy hard coded + const HEPEnergyType Ecm = sqrt(2. * p.GetEnergy() * 0.93827_GeV); + if (p.GetEnergy() < fECut || 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::Positron: + 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; + + case Code::Neutron: + is_inv = true; + break; + + case Code::AntiNeutron: + is_inv = true; + break; + + default: + break; + } + return is_inv; + } + + template <typename TSecondaries> + EProcessReturn DoSecondaries(TSecondaries& vS) { + auto p = vS.begin(); + while (p != vS.end()) { + const Code pid = p.GetPID(); + HEPEnergyType energy = p.GetEnergy(); + cout << "ProcessCut: DoSecondaries: " << pid << " E= " << energy + << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" + << endl; + if (isEmParticle(pid)) { + cout << "removing em. particle..." << endl; + fEmEnergy += energy; + fEmCount += 1; + p.Delete(); + } else if (isInvisible(pid)) { + cout << "removing inv. particle..." << endl; + fInvEnergy += energy; + fInvCount += 1; + p.Delete(); + } else if (isBelowEnergyCut(p)) { + cout << "removing low en. particle..." << endl; + fEnergy += energy; + p.Delete(); + } else if (p.GetTime() > 10_ms) { + cout << "removing OLD particle..." << endl; + fEnergy += energy; + p.Delete(); + } else { + ++p; // next entry in SecondaryView + } + } + return EProcessReturn::eOk; + } + + 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 + << " energy below particle cut (GeV): " << fEnergy / 1_GeV << endl + << " ******************************" << endl; + } + + HEPEnergyType GetInvEnergy() const { return fInvEnergy; } + HEPEnergyType GetCutEnergy() const { return fEnergy; } + HEPEnergyType GetEmEnergy() const { return fEmEnergy; } +}; + + +// +// The example main program for a particle cascade +// +int main() { + feenableexcept(FE_INVALID); + // initialize random number sequence(s) + random::RNGManager::GetInstance().RegisterRandomStream("cascade"); + + // setup environment, geometry + using EnvType = Environment<setup::IEnvironmentModel>; + EnvType env; + auto& universe = *(env.GetUniverse()); + + auto theMedium = + EnvType::CreateNode<Sphere>(Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, + 1_km * std::numeric_limits<double>::infinity()); + + // fraction of oxygen + const float fox = 0.20946; + using MyHomogeneousModel = HomogeneousMedium<environment::IMediumModel>; + theMedium->SetModelProperties<MyHomogeneousModel>( + 1_kg / (1_m * 1_m * 1_m), + environment::NuclearComposition( + std::vector<particles::Code>{particles::Code::Nitrogen, + particles::Code::Oxygen}, + std::vector<float>{(float)1. - fox, fox})); + + universe.AddChild(std::move(theMedium)); + + const CoordinateSystem& rootCS = env.GetCoordinateSystem(); + + // setup processes, decays and interactions + tracking_line::TrackingLine tracking; + + const std::vector<particles::Code> trackedHadrons = { + particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus, + particles::Code::KMinus, particles::Code::K0Long, particles::Code::K0Short}; + + random::RNGManager::GetInstance().RegisterRandomStream("s_rndm"); + process::sibyll::Interaction sibyll; + process::sibyll::NuclearInteraction sibyllNuc(sibyll, env); + process::sibyll::Decay decay(trackedHadrons); + // random::RNGManager::GetInstance().RegisterRandomStream("pythia"); + // process::pythia::Decay decay(trackedHadrons); + ProcessCut cut(20_GeV); + + // random::RNGManager::GetInstance().RegisterRandomStream("HadronicElasticModel"); + // process::HadronicElasticModel::HadronicElasticInteraction + // hadronicElastic(env); + + process::TrackWriter::TrackWriter trackWriter("tracks.dat"); + process::EnergyLoss::EnergyLoss eLoss; + + // assemble all processes into an ordered process list + // cut << trackWriter; + auto sequence = sibyll << sibyllNuc << decay << eLoss << cut; + + // cout << "decltype(sequence)=" << type_id_with_cvr<decltype(sequence)>().pretty_name() + // << "\n"; + + // setup particle stack, and add primary particle + setup::Stack stack; + stack.Clear(); + const Code beamCode = Code::Nucleus; + const int nuclA = 4; + const int nuclZ = int(nuclA / 2.15 + 0.7); + const HEPMassType mass = GetNucleusMass(nuclA, nuclZ); + const HEPEnergyType E0 = nuclA * 10_TeV; + double theta = 0.; + double phi = 0.; + + { + auto elab2plab = [](HEPEnergyType Elab, HEPMassType m) { + return sqrt((Elab - m) * (Elab + m)); + }; + HEPMomentumType P0 = elab2plab(E0, mass); + auto momentumComponents = [](double theta, double phi, HEPMomentumType ptot) { + return std::make_tuple(ptot * sin(theta) * cos(phi), ptot * sin(theta) * sin(phi), + -ptot * cos(theta)); + }; + auto const [px, py, pz] = + momentumComponents(theta / 180. * M_PI, phi / 180. * M_PI, P0); + auto plab = corsika::stack::MomentumVector(rootCS, {px, py, pz}); + cout << "input particle: " << beamCode << endl; + cout << "input angles: theta=" << theta << " phi=" << phi << endl; + cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl; + Point pos(rootCS, 0_m, 0_m, + 112.8_km); // this is the CORSIKA 7 start of atmosphere/universe + stack.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, + units::si::TimeType, unsigned short, unsigned short>{ + beamCode, E0, plab, pos, 0_ns, nuclA, nuclZ}); + } + + // define air shower object, run simulation + cascade::Cascade EAS(env, tracking, sequence, stack); + EAS.Init(); + EAS.Run(); + + eLoss.PrintProfile(); // print longitudinal profile + + cut.ShowResults(); + const HEPEnergyType Efinal = + cut.GetCutEnergy() + cut.GetInvEnergy() + cut.GetEmEnergy(); + cout << "total cut energy (GeV): " << Efinal / 1_GeV << endl + << "relative difference (%): " << (Efinal / E0 - 1) * 100 << endl; + cout << "total dEdX energy (GeV): " << eLoss.GetTotal() / 1_GeV << endl + << "relative difference (%): " << eLoss.GetTotal() / E0 * 100 << endl; +} diff --git a/Environment/FlatExponential.h b/Environment/FlatExponential.h index 19e42c725c4b5204dc9c6fc166f9be00f44bdb7a..61fa2dced76357946bccfc9fc2951752361c9a42 100644 --- a/Environment/FlatExponential.h +++ b/Environment/FlatExponential.h @@ -1,5 +1,6 @@ + /* - * (c) Copyright 2019 CORSIKA Project, corsika-project@lists.kit.edu + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu * * See file AUTHORS for a list of contributors. * diff --git a/Environment/VolumeTreeNode.h b/Environment/VolumeTreeNode.h index faadc94c6a070876d34653fcf5cdebfb9482b7af..7a8b2e785f134ba59546e5622366a03c8f7554a4 100644 --- a/Environment/VolumeTreeNode.h +++ b/Environment/VolumeTreeNode.h @@ -108,7 +108,7 @@ namespace corsika::environment { auto const& GetModelProperties() const { return *fModelProperties; } - auto HasModelProperties() const { return fModelProperties != nullptr; } + bool HasModelProperties() const { return fModelProperties.get() != nullptr; } template <typename ModelProperties, typename... Args> auto SetModelProperties(Args&&... args) { diff --git a/Framework/Cascade/CMakeLists.txt b/Framework/Cascade/CMakeLists.txt index 3e294b214dd325ee9c082c32e2e0d46cdd70de3b..cce178637582bb48a8b17d1017bc489802c192aa 100644 --- a/Framework/Cascade/CMakeLists.txt +++ b/Framework/Cascade/CMakeLists.txt @@ -45,6 +45,7 @@ target_link_libraries ( CORSIKAcascade ProcessStackInspector ProcessTrackingLine + ProcessNullModel CORSIKAstackinterface CORSIKAprocesses CORSIKAparticles diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index c7a187447a5d3f6034600a05bffe09e3543cd7f0..75f29e4ed51bc70d7d31d4917ef4c186baee4bef 100644 --- a/Framework/Cascade/Cascade.h +++ b/Framework/Cascade/Cascade.h @@ -17,15 +17,28 @@ #include <corsika/random/ExponentialDistribution.h> #include <corsika/random/RNGManager.h> #include <corsika/random/UniformRealDistribution.h> -#include <corsika/setup/SetupTrajectory.h> +#include <corsika/stack/SecondaryView.h> #include <corsika/units/PhysicalUnits.h> +#include <corsika/setup/SetupTrajectory.h> + +/* see Issue 161, we need to include SetupStack only because we need + to globally define StackView. This is clearly not nice and should + be changed, when possible. It might be that StackView needs to be + templated in Cascade, but this would be even worse... so we don't + do that until it is really needed. + */ +#include <corsika/setup/SetupStack.h> + #include <cassert> #include <cmath> #include <iostream> #include <limits> #include <type_traits> +#include <boost/type_index.hpp> +using boost::typeindex::type_id_with_cvr; + /** * The cascade namespace assembles all objects needed to simulate full particles cascades. */ @@ -39,23 +52,27 @@ namespace corsika::cascade { * it very versatile. Via the template arguments physics models are * plugged into the cascade simulation. * - * <b>Tracking</b> must be a class according to the + * <b>TTracking</b> must be a class according to the * TrackingInterface providing the functions: * <code>auto GetTrack(Particle const& p)</auto>, * with the return type <code>geometry::Trajectory<corsika::geometry::Line> * </code> * - * <b>ProcessList</b> must be a ProcessSequence. * + * <b>TProcessList</b> must be a ProcessSequence. * * <b>Stack</b> is the storage object for particle data, i.e. with * Particle class type <code>Stack::ParticleType</code> * * - */ - template <typename Tracking, typename ProcessList, typename Stack> + template <typename TTracking, typename TProcessList, typename TStack, + /* + TStackView is needed as template parameter because of issue 161 and the + inability of clang to understand "MakeView" so far. + */ + typename TStackView = corsika::setup::StackView> class Cascade { - using Particle = typename Stack::ParticleType; + using Particle = typename TStack::ParticleType; using VolumeTreeNode = std::remove_pointer_t<decltype(((Particle*)nullptr)->GetNode())>; using MediumInterface = typename VolumeTreeNode::IModelProperties; @@ -68,8 +85,8 @@ namespace corsika::cascade { * Cascade class cannot be default constructed, but needs a valid * list of physics processes for configuration at construct time. */ - Cascade(corsika::environment::Environment<MediumInterface> const& env, Tracking& tr, - ProcessList& pl, Stack& stack) + Cascade(corsika::environment::Environment<MediumInterface> const& env, TTracking& tr, + TProcessList& pl, TStack& stack) : fEnvironment(env) , fTracking(tr) , fProcessSequence(pl) @@ -107,6 +124,7 @@ namespace corsika::cascade { while (!fStack.IsEmpty()) { auto pNext = fStack.GetNextParticle(); Step(pNext); + fProcessSequence.DoStack(fStack); } // do cascade equations, which can put new particles on Stack, // thus, the double loop @@ -125,15 +143,17 @@ namespace corsika::cascade { * New particles produced in one step are subject to further * processing, e.g. thinning, etc. */ - void Step(Particle& particle) { + void Step(Particle& vParticle) { + using namespace corsika; using namespace corsika::units::si; // determine geometric tracking - auto [step, geomMaxLength, nextVol] = fTracking.GetTrack(particle); + auto [step, geomMaxLength, nextVol] = fTracking.GetTrack(vParticle); + [[maybe_unused]] auto const& dummy_nextVol = nextVol; // determine combined total interaction length (inverse) InverseGrammageType const total_inv_lambda = - fProcessSequence.GetTotalInverseInteractionLength(particle, step); + fProcessSequence.GetTotalInverseInteractionLength(vParticle, step); // sample random exponential step length in grammage corsika::random::ExponentialDistribution expDist(1 / total_inv_lambda); @@ -142,7 +162,7 @@ namespace corsika::cascade { std::cout << "total_inv_lambda=" << total_inv_lambda << ", next_interact=" << next_interact << std::endl; - auto const* currentLogicalNode = particle.GetNode(); + auto const* currentLogicalNode = vParticle.GetNode(); // assert that particle stays outside void Universe if it has no // model properties set @@ -155,12 +175,12 @@ namespace corsika::cascade { next_interact); // determine the maximum geometric step length - LengthType const distance_max = fProcessSequence.MaxStepLength(particle, step); + LengthType const distance_max = fProcessSequence.MaxStepLength(vParticle, step); std::cout << "distance_max=" << distance_max << std::endl; // determine combined total inverse decay time InverseTimeType const total_inv_lifetime = - fProcessSequence.GetTotalInverseLifetime(particle); + fProcessSequence.GetTotalInverseLifetime(vParticle); // sample random exponential decay time corsika::random::ExponentialDistribution expDistDecay(1 / total_inv_lifetime); @@ -169,9 +189,8 @@ namespace corsika::cascade { << ", next_decay=" << next_decay << std::endl; // convert next_decay from time to length [m] - LengthType const distance_decay = next_decay * particle.GetMomentum().norm() / - particle.GetEnergy() * - corsika::units::constants::c; + LengthType const distance_decay = next_decay * vParticle.GetMomentum().norm() / + vParticle.GetEnergy() * units::constants::c; // take minimum of geometry, interaction, decay for next step auto const min_distance = @@ -180,73 +199,98 @@ namespace corsika::cascade { std::cout << " move particle by : " << min_distance << std::endl; // here the particle is actually moved along the trajectory to new position: - // std::visit(corsika::setup::ParticleUpdate<Particle>{particle}, step); - particle.SetPosition(step.PositionFromArclength(min_distance)); + // std::visit(setup::ParticleUpdate<Particle>{vParticle}, step); + vParticle.SetPosition(step.PositionFromArclength(min_distance)); // .... also update time, momentum, direction, ... + vParticle.SetTime(vParticle.GetTime() + min_distance / units::constants::c); step.LimitEndTo(min_distance); // apply all continuous processes on particle + track - corsika::process::EProcessReturn status = - fProcessSequence.DoContinuous(particle, step, fStack); + process::EProcessReturn status = fProcessSequence.DoContinuous(vParticle, step); - if (status == corsika::process::EProcessReturn::eParticleAbsorbed) { - std::cout << "Cascade: delete absorbed particle " << particle.GetPID() << " " - << particle.GetEnergy() / 1_GeV << "GeV" << std::endl; - particle.Delete(); + if (status == process::EProcessReturn::eParticleAbsorbed) { + std::cout << "Cascade: delete absorbed particle " << vParticle.GetPID() << " " + << vParticle.GetEnergy() / 1_GeV << "GeV" << std::endl; + vParticle.Delete(); return; } std::cout << "sth. happening before geometric limit ? " << ((min_distance < geomMaxLength) ? "yes" : "no") << std::endl; + /* + Create SecondaryView object on Stack. The data container + remains untouched and identical, and 'projectil' is identical + to 'vParticle' above this line. However, + projectil.AddSecondaries populate the SecondaryView, which can + then be used afterwards for further processing. Thus: it is + important to use projectle (and not vParticle) for Interaction, + and Decay! + */ + + TStackView secondaries(vParticle); + [[maybe_unused]] auto projectile = secondaries.GetProjectile(); + if (min_distance < geomMaxLength) { // interaction to happen within geometric limit + + // check whether decay or interaction limits this step the + // outcome of decay or interaction MAY be a) new particles in + // secondaries, b) the projectile particle deleted (or + // changed) + if (min_distance == distance_interact) { std::cout << "collide" << std::endl; InverseGrammageType const actual_inv_length = - fProcessSequence.GetTotalInverseInteractionLength(particle, step); + fProcessSequence.GetTotalInverseInteractionLength(vParticle, step); - corsika::random::UniformRealDistribution<InverseGrammageType> uniDist( - actual_inv_length); + random::UniformRealDistribution<InverseGrammageType> uniDist(actual_inv_length); const auto sample_process = uniDist(fRNG); InverseGrammageType inv_lambda_count = 0. * meter * meter / gram; - fProcessSequence.SelectInteraction(particle, step, fStack, sample_process, + fProcessSequence.SelectInteraction(vParticle, projectile, step, sample_process, inv_lambda_count); } else if (min_distance == distance_decay) { std::cout << "decay" << std::endl; InverseTimeType const actual_decay_time = - fProcessSequence.GetTotalInverseLifetime(particle); + fProcessSequence.GetTotalInverseLifetime(vParticle); - corsika::random::UniformRealDistribution<InverseTimeType> uniDist( - actual_decay_time); + random::UniformRealDistribution<InverseTimeType> uniDist(actual_decay_time); const auto sample_process = uniDist(fRNG); InverseTimeType inv_decay_count = 0 / second; - fProcessSequence.SelectDecay(particle, fStack, sample_process, inv_decay_count); + fProcessSequence.SelectDecay(vParticle, projectile, sample_process, + inv_decay_count); } else { // step-length limitation within volume std::cout << "step-length limitation" << std::endl; } + fProcessSequence.DoSecondaries(secondaries); + vParticle.Delete(); // todo: this should be reviewed. Where + // exactly are particles best deleted, and + // where they should NOT be + // deleted... maybe Delete function should + // be "protected" and not accessible to physics + auto const assertion = [&] { auto const* numericalNodeAfterStep = - fEnvironment.GetUniverse()->GetContainingNode(particle.GetPosition()); + fEnvironment.GetUniverse()->GetContainingNode(vParticle.GetPosition()); return numericalNodeAfterStep == currentLogicalNode; }; assert(assertion()); // numerical and logical nodes don't match } else { // boundary crossing, step is limited by volume boundary std::cout << "boundary crossing! next node = " << nextVol << std::endl; - particle.SetNode(nextVol); + vParticle.SetNode(nextVol); // DoBoundary may delete the particle (or not) - fProcessSequence.DoBoundaryCrossing(particle, *currentLogicalNode, *nextVol); + fProcessSequence.DoBoundaryCrossing(vParticle, *currentLogicalNode, *nextVol); } } private: corsika::environment::Environment<MediumInterface> const& fEnvironment; - Tracking& fTracking; - ProcessList& fProcessSequence; - Stack& fStack; + TTracking& fTracking; + TProcessList& fProcessSequence; + TStack& fStack; corsika::random::RNG& fRNG = corsika::random::RNGManager::GetInstance().GetRandomStream("cascade"); }; // namespace corsika::cascade diff --git a/Framework/Cascade/testCascade.cc b/Framework/Cascade/testCascade.cc index 5ec522a670de7ea048d33397e868590ea9e6faed..89fd65ef42150149a9c0ffbd7183fed865ba659d 100644 --- a/Framework/Cascade/testCascade.cc +++ b/Framework/Cascade/testCascade.cc @@ -9,13 +9,12 @@ * the license. */ -#include <limits> - #include <corsika/cascade/testCascade.h> #include <corsika/cascade/Cascade.h> #include <corsika/process/ProcessSequence.h> +#include <corsika/process/null_model/NullModel.h> #include <corsika/process/stack_inspector/StackInspector.h> #include <corsika/process/tracking_line/TrackingLine.h> @@ -28,10 +27,6 @@ #include <corsika/environment/HomogeneousMedium.h> #include <corsika/environment/NuclearComposition.h> -#include <corsika/setup/SetupStack.h> -#include <corsika/setup/SetupTrajectory.h> -using corsika::setup::Trajectory; - #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one // cpp file #include <catch2/catch.hpp> @@ -43,6 +38,7 @@ using namespace corsika::units::si; using namespace corsika::geometry; #include <iostream> +#include <limits> using namespace std; auto MakeDummyEnv() { @@ -51,11 +47,11 @@ auto MakeDummyEnv() { auto theMedium = TestEnvironmentType::CreateNode<Sphere>( Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, - 1_km * std::numeric_limits<double>::infinity()); + 100_km * std::numeric_limits<double>::infinity()); using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>; theMedium->SetModelProperties<MyHomogeneousModel>( - 1_g / (1_m * 1_m * 1_m), + 1_g / (1_cm * 1_cm * 1_cm), environment::NuclearComposition( std::vector<particles::Code>{particles::Code::Proton}, std::vector<float>{1.})); @@ -64,47 +60,75 @@ auto MakeDummyEnv() { return env; } -class ProcessSplit : public process::ContinuousProcess<ProcessSplit> { +class ProcessSplit : public process::InteractionProcess<ProcessSplit> { + + int fCalls = 0; + GrammageType fX0; + +public: + ProcessSplit(GrammageType const X0) + : fX0(X0) {} + + template <typename Particle, typename Track> + corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&) const { + return fX0; + } + + template <typename TProjectile> + corsika::process::EProcessReturn DoInteraction(TProjectile& vP) { + fCalls++; + const HEPEnergyType E = vP.GetEnergy(); + vP.AddSecondary( + std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ + vP.GetPID(), E / 2, vP.GetMomentum(), vP.GetPosition(), vP.GetTime()}); + vP.AddSecondary( + std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ + vP.GetPID(), E / 2, vP.GetMomentum(), vP.GetPosition(), vP.GetTime()}); + return EProcessReturn::eInteracted; + } + + void Init() { fCalls = 0; } + + int GetCalls() const { return fCalls; } +}; + +class ProcessCut : public process::SecondariesProcess<ProcessCut> { int fCount = 0; int fCalls = 0; HEPEnergyType fEcrit; public: - ProcessSplit(HEPEnergyType e) + ProcessCut(HEPEnergyType e) : fEcrit(e) {} - template <typename Particle, typename T> - LengthType MaxStepLength(Particle&, T&) const { - return 1_m; - } - - template <typename Particle, typename T, typename Stack> - EProcessReturn DoContinuous(Particle& p, T&, Stack&) { + template <typename TStack> + EProcessReturn DoSecondaries(TStack& vS) { fCalls++; - HEPEnergyType E = p.GetEnergy(); - if (E < fEcrit) { - p.Delete(); - fCount++; - } else { - p.SetEnergy(E / 2); - p.AddSecondary(std::tuple<particles::Code, units::si::HEPEnergyType, - corsika::stack::MomentumVector, geometry::Point, - units::si::TimeType>{p.GetPID(), E / 2, p.GetMomentum(), - p.GetPosition(), p.GetTime()}); + auto p = vS.begin(); + while (p != vS.end()) { + HEPEnergyType E = p.GetEnergy(); + if (E < fEcrit) { + p.Delete(); + fCount++; + } else { + ++p; // next particle + } } + cout << "ProcessCut::DoSecondaries size=" << vS.GetSize() << " count=" << fCount + << endl; return EProcessReturn::eOk; } void Init() { - fCount = 0; fCalls = 0; + fCount = 0; } int GetCount() const { return fCount; } int GetCalls() const { return fCalls; } - -private: }; TEST_CASE("Cascade", "[Cascade]") { @@ -114,14 +138,19 @@ TEST_CASE("Cascade", "[Cascade]") { auto env = MakeDummyEnv(); tracking_line::TrackingLine tracking; - stack_inspector::StackInspector<TestCascadeStack> p0(true); + stack_inspector::StackInspector<TestCascadeStack> stackInspect(1, true); + null_model::NullModel nullModel; + const GrammageType X0 = 20_g / square(1_cm); const HEPEnergyType Ecrit = 85_MeV; - ProcessSplit p1(Ecrit); - auto sequence = p0 << p1; + ProcessSplit split(X0); + ProcessCut cut(Ecrit); + auto sequence = nullModel << stackInspect << split << cut; TestCascadeStack stack; - cascade::Cascade EAS(env, tracking, sequence, stack); + cascade::Cascade<tracking_line::TrackingLine, decltype(sequence), TestCascadeStack, + TestCascadeStackView> + EAS(env, tracking, sequence, stack); CoordinateSystem const& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); @@ -136,6 +165,7 @@ TEST_CASE("Cascade", "[Cascade]") { EAS.Init(); EAS.Run(); - CHECK(p1.GetCount() == 2048); - CHECK(p1.GetCalls() == 4095); + CHECK(cut.GetCount() == 2048); + CHECK(cut.GetCalls() == 2047); + CHECK(split.GetCalls() == 2047); } diff --git a/Framework/Cascade/testCascade.h b/Framework/Cascade/testCascade.h index c84d1e14bff303274e648a4d018e711c4ff9dfd5..386a7281f429ad1b9a8ce83de4ed1e5e830ef040 100644 --- a/Framework/Cascade/testCascade.h +++ b/Framework/Cascade/testCascade.h @@ -26,8 +26,20 @@ template <typename StackIter> using StackWithGeometryInterface = corsika::stack::CombinedParticleInterface< corsika::setup::detail::ParticleDataStack::PIType, SetupGeometryDataInterface, StackIter>; + using TestCascadeStack = corsika::stack::CombinedStack< typename corsika::setup::detail::ParticleDataStack::StackImpl, GeometryData<TestEnvironmentType>, StackWithGeometryInterface>; +/* + See also Issue 161 +*/ +#if defined(__clang__) +using TestCascadeStackView = + corsika::stack::SecondaryView<typename TestCascadeStack::StackImpl, + StackWithGeometryInterface>; +#elif defined(__GNUC__) || defined(__GNUG__) +using TestCascadeStackView = corsika::stack::MakeView<TestCascadeStack>::type; +#endif + #endif diff --git a/Framework/Geometry/Point.h b/Framework/Geometry/Point.h index f05bd31d1ca628f1f32834a9e6d6300e6ef2578c..55dfa2950a1d5452bb9065ca4a814d4ee7562dee 100644 --- a/Framework/Geometry/Point.h +++ b/Framework/Geometry/Point.h @@ -37,6 +37,9 @@ namespace corsika::geometry { // TODO: this should be private or protected, we don NOT want to expose numbers // without reference to outside: auto GetCoordinates() const { return BaseVector<length_d>::qVector; } + auto GetX() const { return BaseVector<length_d>::qVector.GetX(); } + auto GetY() const { return BaseVector<length_d>::qVector.GetY(); } + auto GetZ() const { return BaseVector<length_d>::qVector.GetZ(); } /// this always returns a QuantityVector as triple auto GetCoordinates(CoordinateSystem const& pCS) const { diff --git a/Framework/Geometry/QuantityVector.h b/Framework/Geometry/QuantityVector.h index 2712c188d8daf8c65f354bf416711c7d4d71e32c..c606a2934d6415aecefc541c71d2e0335be02948 100644 --- a/Framework/Geometry/QuantityVector.h +++ b/Framework/Geometry/QuantityVector.h @@ -55,6 +55,12 @@ namespace corsika::geometry { return Quantity(phys::units::detail::magnitude_tag, eVector[index]); } + auto GetX() const { return Quantity(phys::units::detail::magnitude_tag, eVector[0]); } + + auto GetY() const { return Quantity(phys::units::detail::magnitude_tag, eVector[1]); } + + auto GetZ() const { return Quantity(phys::units::detail::magnitude_tag, eVector[2]); } + auto norm() const { return Quantity(phys::units::detail::magnitude_tag, eVector.norm()); } diff --git a/Framework/ProcessSequence/BaseProcess.h b/Framework/ProcessSequence/BaseProcess.h index 8b4014478f5ebef33e4acd76f6b7315f2c1e5041..6733fcf9a9f66a53c3a4d55326cdc37eabbcc314 100644 --- a/Framework/ProcessSequence/BaseProcess.h +++ b/Framework/ProcessSequence/BaseProcess.h @@ -13,6 +13,7 @@ #define _include_corsika_baseprocess_h_ #include <corsika/process/ProcessReturn.h> // for convenience +#include <type_traits> namespace corsika::process { diff --git a/Framework/ProcessSequence/CMakeLists.txt b/Framework/ProcessSequence/CMakeLists.txt index 9ec9072dabb1dab6ecb17213ddc84a45bb73cd5f..33aad8236f6b2943d083fd95addcea1698700d43 100644 --- a/Framework/ProcessSequence/CMakeLists.txt +++ b/Framework/ProcessSequence/CMakeLists.txt @@ -13,7 +13,9 @@ set ( BaseProcess.h BoundaryCrossingProcess.h ContinuousProcess.h + SecondariesProcess.h InteractionProcess.h + StackProcess.h DecayProcess.h ProcessSequence.h ProcessReturn.h diff --git a/Framework/ProcessSequence/ContinuousProcess.h b/Framework/ProcessSequence/ContinuousProcess.h index 9a3424a35d4637a9e21212a0909f2456f71b3597..58d378aa3eb5bdad5f8029555ea8825afa450007 100644 --- a/Framework/ProcessSequence/ContinuousProcess.h +++ b/Framework/ProcessSequence/ContinuousProcess.h @@ -33,8 +33,8 @@ namespace corsika::process { // here starts the interface part // -> enforce derived to implement DoContinuous... - template <typename Particle, typename Track, typename Stack> - EProcessReturn DoContinuous(Particle&, Track&, Stack&) const; + template <typename Particle, typename Track> + EProcessReturn DoContinuous(Particle&, Track&) const; // -> enforce derived to implement MaxStepLength... template <typename Particle, typename Track> diff --git a/Framework/ProcessSequence/DecayProcess.h b/Framework/ProcessSequence/DecayProcess.h index 82be572d6fc8e19260fa50a5267f1171c20e042b..16d63ae667775848db49076d242fa451f38060e6 100644 --- a/Framework/ProcessSequence/DecayProcess.h +++ b/Framework/ProcessSequence/DecayProcess.h @@ -34,15 +34,15 @@ namespace corsika::process { /// here starts the interface-definition part // -> enforce derived to implement DoDecay... - template <typename Particle, typename Stack> - EProcessReturn DoDecay(Particle&, Stack&); + template <typename Particle> + EProcessReturn DoDecay(Particle&); template <typename Particle> corsika::units::si::TimeType GetLifetime(Particle& p); template <typename Particle> - corsika::units::si::InverseTimeType GetInverseLifetime(Particle& p) { - return 1. / GetRef().GetLifetime(p); + corsika::units::si::InverseTimeType GetInverseLifetime(Particle& vP) { + return 1. / GetRef().GetLifetime(vP); } }; diff --git a/Framework/ProcessSequence/InteractionProcess.h b/Framework/ProcessSequence/InteractionProcess.h index 723cbf02fcc7ce443d968300293ccc44d1b40811..27ad9c222d5ce644d6b344a469edaf8e717fcf87 100644 --- a/Framework/ProcessSequence/InteractionProcess.h +++ b/Framework/ProcessSequence/InteractionProcess.h @@ -35,8 +35,8 @@ namespace corsika::process { /// here starts the interface-definition part // -> enforce derived to implement DoInteraction... - template <typename P, typename S> - EProcessReturn DoInteraction(P&, S&); + template <typename Particle> + EProcessReturn DoInteraction(Particle&); template <typename Particle, typename Track> corsika::units::si::GrammageType GetInteractionLength(Particle& p, Track& t); diff --git a/Framework/ProcessSequence/ProcessSequence.h b/Framework/ProcessSequence/ProcessSequence.h index c697d09f416d49025a0d4763f00851c047cedb62..3bd759c04a97e55360c87473cc4457159bd967fa 100644 --- a/Framework/ProcessSequence/ProcessSequence.h +++ b/Framework/ProcessSequence/ProcessSequence.h @@ -18,6 +18,8 @@ #include <corsika/process/DecayProcess.h> #include <corsika/process/InteractionProcess.h> #include <corsika/process/ProcessReturn.h> +#include <corsika/process/SecondariesProcess.h> +#include <corsika/process/StackProcess.h> #include <corsika/units/PhysicalUnits.h> #include <cmath> @@ -89,78 +91,120 @@ namespace corsika::process { return ret; } - template <typename Particle, typename Track, typename Stack> - EProcessReturn DoContinuous(Particle& p, Track& t, Stack& s) { + template <typename TParticle, typename TTrack> + EProcessReturn DoContinuous(TParticle& vP, TTrack& vT) { EProcessReturn ret = EProcessReturn::eOk; if constexpr (std::is_base_of<ContinuousProcess<T1type>, T1type>::value || is_process_sequence<T1>::value) { - ret |= A.DoContinuous(p, t, s); + ret |= A.DoContinuous(vP, vT); } if constexpr (std::is_base_of<ContinuousProcess<T2type>, T2type>::value || is_process_sequence<T2>::value) { - ret |= B.DoContinuous(p, t, s); + ret |= B.DoContinuous(vP, vT); } return ret; } - template <typename Particle, typename Track> - corsika::units::si::LengthType MaxStepLength(Particle& p, Track& track) { + template <typename TSecondaries> + EProcessReturn DoSecondaries(TSecondaries& vS) { + EProcessReturn ret = EProcessReturn::eOk; + if constexpr (std::is_base_of<SecondariesProcess<T1type>, T1type>::value || + is_process_sequence<T1>::value) { + ret |= A.DoSecondaries(vS); + } + if constexpr (std::is_base_of<SecondariesProcess<T2type>, T2type>::value || + is_process_sequence<T2>::value) { + ret |= B.DoSecondaries(vS); + } + return ret; + } + + bool CheckStep() { + bool ret = false; + if constexpr (std::is_base_of<StackProcess<T1type>, T1type>::value || + is_process_sequence<T1>::value) { + ret |= A.CheckStep(); + } + if constexpr (std::is_base_of<StackProcess<T2type>, T2type>::value || + is_process_sequence<T2>::value) { + ret |= B.CheckStep(); + } + return ret; + } + + template <typename TStack> + EProcessReturn DoStack(TStack& vS) { + EProcessReturn ret = EProcessReturn::eOk; + if constexpr (std::is_base_of<StackProcess<T1type>, T1type>::value || + is_process_sequence<T1>::value) { + if (A.CheckStep()) { ret |= A.DoStack(vS); } + } + if constexpr (std::is_base_of<StackProcess<T2type>, T2type>::value || + is_process_sequence<T2>::value) { + if (B.CheckStep()) { ret |= B.DoStack(vS); } + } + return ret; + } + + template <typename TParticle, typename TTrack> + corsika::units::si::LengthType MaxStepLength(TParticle& vP, TTrack& vTrack) { corsika::units::si::LengthType max_length = // if no other process in the sequence implements it std::numeric_limits<double>::infinity() * corsika::units::si::meter; if constexpr (std::is_base_of<ContinuousProcess<T1type>, T1type>::value || is_process_sequence<T1>::value) { - corsika::units::si::LengthType const len = A.MaxStepLength(p, track); + corsika::units::si::LengthType const len = A.MaxStepLength(vP, vTrack); max_length = std::min(max_length, len); } if constexpr (std::is_base_of<ContinuousProcess<T2type>, T2type>::value || is_process_sequence<T2>::value) { - corsika::units::si::LengthType const len = B.MaxStepLength(p, track); + corsika::units::si::LengthType const len = B.MaxStepLength(vP, vTrack); max_length = std::min(max_length, len); } return max_length; } - template <typename Particle, typename Track> - corsika::units::si::GrammageType GetTotalInteractionLength(Particle& p, Track& t) { - return 1. / GetInverseInteractionLength(p, t); + template <typename TParticle, typename TTrack> + corsika::units::si::GrammageType GetTotalInteractionLength(TParticle& vP, + TTrack& vT) { + return 1. / GetInverseInteractionLength(vP, vT); } - template <typename Particle, typename Track> - corsika::units::si::InverseGrammageType GetTotalInverseInteractionLength(Particle& p, - Track& t) { - return GetInverseInteractionLength(p, t); + template <typename TParticle, typename TTrack> + corsika::units::si::InverseGrammageType GetTotalInverseInteractionLength( + TParticle& vP, TTrack& vT) { + return GetInverseInteractionLength(vP, vT); } - template <typename Particle, typename Track> - corsika::units::si::InverseGrammageType GetInverseInteractionLength(Particle& p, - Track& t) { + template <typename TParticle, typename TTrack> + corsika::units::si::InverseGrammageType GetInverseInteractionLength(TParticle& vP, + TTrack& vT) { using namespace corsika::units::si; InverseGrammageType tot = 0 * meter * meter / gram; if constexpr (std::is_base_of<InteractionProcess<T1type>, T1type>::value || is_process_sequence<T1>::value) { - tot += A.GetInverseInteractionLength(p, t); + tot += A.GetInverseInteractionLength(vP, vT); } if constexpr (std::is_base_of<InteractionProcess<T2type>, T2type>::value || is_process_sequence<T2>::value) { - tot += B.GetInverseInteractionLength(p, t); + tot += B.GetInverseInteractionLength(vP, vT); } return tot; } - template <typename Particle, typename Track, typename Stack> + template <typename TParticle, typename TSecondaries, typename TTrack> EProcessReturn SelectInteraction( - Particle& vP, Track& vT, Stack& vS, + TParticle& vP, TSecondaries& vS, TTrack& vT, [[maybe_unused]] corsika::units::si::InverseGrammageType lambda_select, corsika::units::si::InverseGrammageType& lambda_inv_count) { if constexpr (is_process_sequence<T1type>::value) { // if A is a process sequence --> check inside const EProcessReturn ret = - A.SelectInteraction(vP, vT, vS, lambda_select, lambda_inv_count); + A.SelectInteraction(vP, vS, vT, lambda_select, lambda_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<InteractionProcess<T1type>, T1type>::value) { @@ -168,7 +212,7 @@ namespace corsika::process { lambda_inv_count += A.GetInverseInteractionLength(vP, vT); // check if we should execute THIS process and then EXIT if (lambda_select < lambda_inv_count) { - A.DoInteraction(vP, vS); + A.DoInteraction(vS); return EProcessReturn::eInteracted; } } // end branch A @@ -176,7 +220,7 @@ namespace corsika::process { if constexpr (is_process_sequence<T2>::value) { // if A is a process sequence --> check inside const EProcessReturn ret = - B.SelectInteraction(vP, vT, vS, lambda_select, lambda_inv_count); + B.SelectInteraction(vP, vS, vT, lambda_select, lambda_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<InteractionProcess<T2type>, T2type>::value) { @@ -184,25 +228,25 @@ namespace corsika::process { lambda_inv_count += B.GetInverseInteractionLength(vP, vT); // check if we should execute THIS process and then EXIT if (lambda_select < lambda_inv_count) { - B.DoInteraction(vP, vS); + B.DoInteraction(vS); return EProcessReturn::eInteracted; } } // end branch A return EProcessReturn::eOk; } - template <typename Particle> - corsika::units::si::TimeType GetTotalLifetime(Particle& p) { + template <typename TParticle> + corsika::units::si::TimeType GetTotalLifetime(TParticle& p) { return 1. / GetInverseLifetime(p); } - template <typename Particle> - corsika::units::si::InverseTimeType GetTotalInverseLifetime(Particle& p) { + template <typename TParticle> + corsika::units::si::InverseTimeType GetTotalInverseLifetime(TParticle& p) { return GetInverseLifetime(p); } - template <typename Particle> - corsika::units::si::InverseTimeType GetInverseLifetime(Particle& p) { + template <typename TParticle> + corsika::units::si::InverseTimeType GetInverseLifetime(TParticle& p) { using namespace corsika::units::si; corsika::units::si::InverseTimeType tot = 0 / second; @@ -219,38 +263,38 @@ namespace corsika::process { } // select decay process - template <typename Particle, typename Stack> + template <typename TParticle, typename TSecondaries> EProcessReturn SelectDecay( - Particle& p, Stack& s, + TParticle& vP, TSecondaries& vS, [[maybe_unused]] corsika::units::si::InverseTimeType decay_select, corsika::units::si::InverseTimeType& decay_inv_count) { if constexpr (is_process_sequence<T1>::value) { // if A is a process sequence --> check inside - const EProcessReturn ret = A.SelectDecay(p, s, decay_select, decay_inv_count); + const EProcessReturn ret = A.SelectDecay(vP, vS, decay_select, decay_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<DecayProcess<T1type>, T1type>::value) { // if this is not a ContinuousProcess --> evaluate probability - decay_inv_count += A.GetInverseLifetime(p); + decay_inv_count += A.GetInverseLifetime(vP); // check if we should execute THIS process and then EXIT if (decay_select < decay_inv_count) { // more pedagogical: rndm_select < // decay_inv_count / decay_inv_tot - A.DoDecay(p, s); + A.DoDecay(vS); return EProcessReturn::eDecayed; } } // end branch A if constexpr (is_process_sequence<T2>::value) { // if A is a process sequence --> check inside - const EProcessReturn ret = B.SelectDecay(p, s, decay_select, decay_inv_count); + const EProcessReturn ret = B.SelectDecay(vP, vS, decay_select, decay_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<DecayProcess<T2type>, T2type>::value) { // if this is not a ContinuousProcess --> evaluate probability - decay_inv_count += B.GetInverseLifetime(p); + decay_inv_count += B.GetInverseLifetime(vP); // check if we should execute THIS process and then EXIT if (decay_select < decay_inv_count) { - B.DoDecay(p, s); + B.DoDecay(vS); return EProcessReturn::eDecayed; } } // end branch B @@ -272,8 +316,8 @@ namespace corsika::process { typename P1, typename P2, typename std::enable_if<is_process<typename std::decay<P1>::type>::value && is_process<typename std::decay<P2>::type>::value>::type...> - inline auto operator<<(P1&& A, P2&& B) -> ProcessSequence<P1, P2> { - return ProcessSequence<P1, P2>(A.GetRef(), B.GetRef()); + inline auto operator<<(P1&& vA, P2&& vB) -> ProcessSequence<P1, P2> { + return ProcessSequence<P1, P2>(vA.GetRef(), vB.GetRef()); } /// marker to identify objectas ProcessSequence diff --git a/Framework/ProcessSequence/SecondariesProcess.h b/Framework/ProcessSequence/SecondariesProcess.h new file mode 100644 index 0000000000000000000000000000000000000000..7e4f11e442e39ecfdde376332ceb276095fc8484 --- /dev/null +++ b/Framework/ProcessSequence/SecondariesProcess.h @@ -0,0 +1,48 @@ + +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#ifndef _include_corsika_secondariesprocess_h_ +#define _include_corsika_secondariesprocess_h_ + +#include <corsika/process/ProcessReturn.h> // for convenience +#include <corsika/setup/SetupTrajectory.h> +#include <corsika/units/PhysicalUnits.h> + +namespace corsika::process { + + /** + \class SecondariesProcess + + The structural base type of a process object in a + ProcessSequence. Both, the ProcessSequence and all its elements + are of type SecondariesProcess<T> + + */ + + template <typename derived> + struct SecondariesProcess { + + derived& GetRef() { return static_cast<derived&>(*this); } + const derived& GetRef() const { return static_cast<const derived&>(*this); } + + /// here starts the interface-definition part + // -> enforce derived to implement DoSecondaries... + template <typename TSecondaries> + inline EProcessReturn DoSecondaries(TSecondaries&); + }; + + // overwrite the default trait class, to mark BaseProcess<T> as useful process + template <class T> + std::true_type is_process_impl(const SecondariesProcess<T>* impl); + +} // namespace corsika::process + +#endif diff --git a/Framework/ProcessSequence/SecondaryProcess.h b/Framework/ProcessSequence/SecondaryProcess.h new file mode 100644 index 0000000000000000000000000000000000000000..523ce4d88ff4b2a3684958f6015540ab415682d3 --- /dev/null +++ b/Framework/ProcessSequence/SecondaryProcess.h @@ -0,0 +1,48 @@ + +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#ifndef _include_corsika_secondariesprocess_h_ +#define _include_corsika_secondariesprocess_h_ + +#include <corsika/process/ProcessReturn.h> // for convenience +#include <corsika/setup/SetupTrajectory.h> +#include <corsika/units/PhysicalUnits.h> + +namespace corsika::process { + + /** + \class SecondariesProcess + + The structural base type of a process object in a + ProcessSequence. Both, the ProcessSequence and all its elements + are of type SecondariesProcess<T> + + */ + + template <typename derived> + struct SecondariesProcess { + + derived& GetRef() { return static_cast<derived&>(*this); } + const derived& GetRef() const { return static_cast<const derived&>(*this); } + + /// here starts the interface-definition part + // -> enforce derived to implement DoSecondaries... + template <typename Particle> + inline EProcessReturn DoSecondaries(Particle&); + }; + + // overwrite the default trait class, to mark BaseProcess<T> as useful process + template <class T> + std::true_type is_process_impl(const SecondariesProcess<T>* impl); + +} // namespace corsika::process + +#endif diff --git a/Framework/ProcessSequence/StackProcess.h b/Framework/ProcessSequence/StackProcess.h new file mode 100644 index 0000000000000000000000000000000000000000..1458fa75ca5938cdd42d50d0b4d22af46f641302 --- /dev/null +++ b/Framework/ProcessSequence/StackProcess.h @@ -0,0 +1,66 @@ + +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#ifndef _include_corsika_stackprocess_h_ +#define _include_corsika_stackprocess_h_ + +#include <corsika/process/ProcessReturn.h> // for convenience +#include <corsika/setup/SetupTrajectory.h> +#include <corsika/units/PhysicalUnits.h> + +namespace corsika::process { + + /** + \class StackProcess + + The structural base type of a process object in a + ProcessSequence. Both, the ProcessSequence and all its elements + are of type StackProcess<T> + + */ + + template <typename derived> + class StackProcess { + + public: + StackProcess() = delete; + StackProcess(const unsigned int nStep) + : fNStep(nStep) {} + + derived& GetRef() { return static_cast<derived&>(*this); } + const derived& GetRef() const { return static_cast<const derived&>(*this); } + + /// here starts the interface-definition part + // -> enforce derived to implement DoStack... + template <typename TStack> + inline EProcessReturn DoStack(TStack&); + + bool CheckStep() { return !((++fIStep) % fNStep); } + + private: + /** + @name The number of "steps" during the cascade processing after + which this StackProcess is going to be executed. The logic is + "fIStep modulo fNStep" + @{ + */ + unsigned int fNStep = 0; + unsigned long int fIStep = 0; + //! @} + }; + + // overwrite the default trait class, to mark BaseProcess<T> as useful process + template <class T> + std::true_type is_process_impl(const StackProcess<T>* impl); + +} // namespace corsika::process + +#endif diff --git a/Framework/ProcessSequence/testProcessSequence.cc b/Framework/ProcessSequence/testProcessSequence.cc index 8fd46418ac838ca1af0f2beb3691bf599a40eb05..aa78ee89c4c012eb2df3d322b6b1ddf6fa44ba1e 100644 --- a/Framework/ProcessSequence/testProcessSequence.cc +++ b/Framework/ProcessSequence/testProcessSequence.cc @@ -39,8 +39,8 @@ public: assert(globalCount == fV); globalCount++; } - template <typename D, typename T, typename S> - inline EProcessReturn DoContinuous(D& d, T&, S&) const { + template <typename D, typename T> + inline EProcessReturn DoContinuous(D& d, T&) const { cout << "ContinuousProcess1::DoContinuous" << endl; for (int i = 0; i < nData; ++i) d.p[i] += 0.933; return EProcessReturn::eOk; @@ -58,8 +58,8 @@ public: assert(globalCount == fV); globalCount++; } - template <typename D, typename T, typename S> - inline EProcessReturn DoContinuous(D& d, T&, S&) const { + template <typename D, typename T> + inline EProcessReturn DoContinuous(D& d, T&) const { cout << "ContinuousProcess2::DoContinuous" << endl; for (int i = 0; i < nData; ++i) d.p[i] += 0.933; return EProcessReturn::eOk; @@ -95,8 +95,8 @@ public: assert(globalCount == fV); globalCount++; } - template <typename Particle, typename Stack> - inline EProcessReturn DoInteraction(Particle&, Stack&) const { + template <typename Particle> + inline EProcessReturn DoInteraction(Particle&) const { cout << "Process2::DoInteraction" << endl; return EProcessReturn::eOk; } @@ -118,8 +118,8 @@ public: assert(globalCount == fV); globalCount++; } - template <typename Particle, typename Stack> - inline EProcessReturn DoInteraction(Particle&, Stack&) const { + template <typename Particle> + inline EProcessReturn DoInteraction(Particle&) const { cout << "Process3::DoInteraction" << endl; return EProcessReturn::eOk; } @@ -141,14 +141,14 @@ public: assert(globalCount == fV); globalCount++; } - template <typename D, typename T, typename S> - inline EProcessReturn DoContinuous(D& d, T&, S&) const { + template <typename D, typename T> + inline EProcessReturn DoContinuous(D& d, T&) const { for (int i = 0; i < nData; ++i) { d.p[i] /= 1.2; } return EProcessReturn::eOk; } // inline double MinStepLength(D& d) { - template <typename Particle, typename Stack> - EProcessReturn DoInteraction(Particle&, Stack&) const { + template <typename Particle> + EProcessReturn DoInteraction(Particle&) const { return EProcessReturn::eOk; } }; @@ -168,16 +168,30 @@ public: TimeType GetLifetime(Particle&) const { return 1_s; } - template <typename Particle, typename Stack> - EProcessReturn DoDecay(Particle&, Stack&) const { + template <typename Particle> + EProcessReturn DoDecay(Particle&) const { + return EProcessReturn::eOk; + } +}; + +class Stack1 : public StackProcess<Stack1> { + int fCount = 0; + +public: + Stack1(const int n) + : StackProcess(n) {} + template <typename TStack> + EProcessReturn DoStack(TStack&) { + fCount++; return EProcessReturn::eOk; } + int GetCount() const { return fCount; } }; +struct DummyStack {}; struct DummyData { double p[nData] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; }; -struct DummyStack {}; struct DummyTrajectory {}; TEST_CASE("Process Sequence", "[Process Sequence]") { @@ -205,12 +219,13 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { Process2 m2(1); Process3 m3(2); - DummyStack s; - DummyTrajectory t; + DummyData particle; + DummyTrajectory track; auto sequence2 = cp1 << m2 << m3; - GrammageType const tot = sequence2.GetTotalInteractionLength(s, t); - InverseGrammageType const tot_inv = sequence2.GetTotalInverseInteractionLength(s, t); + GrammageType const tot = sequence2.GetTotalInteractionLength(particle, track); + InverseGrammageType const tot_inv = + sequence2.GetTotalInverseInteractionLength(particle, track); cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl; } @@ -220,11 +235,11 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { Process3 m3(2); Decay1 d3(2); - DummyStack s; + DummyData particle; auto sequence2 = cp1 << m2 << m3 << d3; - TimeType const tot = sequence2.GetTotalLifetime(s); - InverseTimeType const tot_inv = sequence2.GetTotalInverseLifetime(s); + TimeType const tot = sequence2.GetTotalLifetime(particle); + InverseTimeType const tot_inv = sequence2.GetTotalInverseLifetime(particle); cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl; } @@ -237,27 +252,44 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { auto sequence2 = cp1 << m2 << m3 << cp2; - DummyData p; - DummyStack s; - DummyTrajectory t; + DummyData particle; + DummyTrajectory track; cout << "-->init sequence2" << endl; globalCount = 0; sequence2.Init(); cout << "-->docont" << endl; - sequence2.DoContinuous(p, t, s); + sequence2.DoContinuous(particle, track); cout << "-->dodisc" << endl; - // sequence2.DoInteraction(p, s); cout << "-->done" << endl; const int nLoop = 5; cout << "Running loop with n=" << nLoop << endl; - for (int i = 0; i < nLoop; ++i) { - sequence2.DoContinuous(p, t, s); - // sequence2.DoInteraction(p, s); + for (int i = 0; i < nLoop; ++i) { sequence2.DoContinuous(particle, track); } + for (int i = 0; i < nData; i++) { + cout << "data[" << i << "]=" << particle.p[i] << endl; } - for (int i = 0; i < nData; i++) { cout << "data[" << i << "]=" << p.p[i] << endl; } cout << "done" << endl; } + + SECTION("StackProcess") { + + ContinuousProcess1 cp1(0); + ContinuousProcess2 cp2(3); + Process2 m2(1); + Process3 m3(2); + Stack1 s1(1); + Stack1 s2(2); + + auto sequence = s1 << s2; + + DummyStack stack; + + const int nLoop = 20; + for (int i = 0; i < nLoop; ++i) { sequence.DoStack(stack); } + + CHECK(s1.GetCount() == 20); + CHECK(s2.GetCount() == 10); + } } diff --git a/Framework/StackInterface/CombinedStack.h b/Framework/StackInterface/CombinedStack.h index 44a29a6280bbf7aa61e05301d3bd9fd9adc8dd5b..8b987d5100732a7a339a23d6fadd3530870bb2ef 100644 --- a/Framework/StackInterface/CombinedStack.h +++ b/Framework/StackInterface/CombinedStack.h @@ -19,51 +19,92 @@ namespace corsika::stack { /** + * @class CombinedParticleInterface * + * You may combine two StackData object, see class CombinedStackImpl + * below, into one Stack, using a combined StackIterator (aka + * CombinedParticleInterface) interface class. + * + * This allows to add specific information to a given Stack, could + * be special information on a subset of entries + * (e.g. NuclearStackExtension) or also (multi) thinning weights for + * all particles. + * + * Many Stacks can be combined into more complex object. + * + * The two sub-stacks must both provide their independent + * ParticleInterface classes. * */ - template <template <typename> typename ParticleInterface, - template <typename> typename ParticleInterfaceAdd, typename StackIterator> + template <template <typename> typename ParticleInterfaceA, + template <typename> typename ParticleInterfaceB, typename StackIterator> class CombinedParticleInterface - : public ParticleInterfaceAdd<ParticleInterface<StackIterator>> { + : public ParticleInterfaceB<ParticleInterfaceA<StackIterator>> { + + // template<template <typename> typename _PI> + // template <typename StackDataType, template <typename> typename ParticleInterface> + // template<typename T1, template <typename> typename T2> friend class Stack<T1, T2>; - using C = - CombinedParticleInterface<ParticleInterface, ParticleInterfaceAdd, StackIterator>; - using T = ParticleInterfaceAdd<ParticleInterface<StackIterator>>; - using I = ParticleInterface<StackIterator>; + using PI_C = + CombinedParticleInterface<ParticleInterfaceA, ParticleInterfaceB, StackIterator>; + using PI_A = ParticleInterfaceA<StackIterator>; + using PI_B = ParticleInterfaceB<ParticleInterfaceA<StackIterator>>; protected: - using T::GetIndex; - using T::GetStackData; + using PI_B::GetIndex; // choose B, A would also work + using PI_B::GetStackData; // choose B, A would also work public: + /** + * @name wrapper for user functions + * @{ + * + * In this set of functions we call the user-provide + * ParticleInterface SetParticleData(...) methods, either with + * parent particle reference, or w/o. + * + * There is one implicit assumption here: if only one data tuple + * is provided for SetParticleData, the data is passed on to + * ParticleInterfaceA and the ParticleInterfaceB is + * default-initialized. There are many occasions where this is the + * desired behaviour, e.g. for thinning etc. + * + */ + template <typename... Args1> void SetParticleData(const std::tuple<Args1...> vA) { - I::SetParticleData(vA); - T::SetParticleData(); + PI_A::SetParticleData(vA); + PI_B::SetParticleData(); } template <typename... Args1, typename... Args2> void SetParticleData(const std::tuple<Args1...> vA, const std::tuple<Args2...> vB) { - I::SetParticleData(vA); - T::SetParticleData(vB); + PI_A::SetParticleData(vA); + PI_B::SetParticleData(vB); } template <typename... Args1> - void SetParticleData(C& p, const std::tuple<Args1...> vA) { + void SetParticleData(PI_C& p, const std::tuple<Args1...> vA) { // static_assert(MT<I>::has_not, "error"); - I::SetParticleData(static_cast<I&>(p), vA); // original stack - T::SetParticleData(static_cast<T&>(p)); // addon stack + PI_A::SetParticleData(static_cast<PI_A&>(p), vA); // original stack + PI_B::SetParticleData(static_cast<PI_B&>(p)); // addon stack } template <typename... Args1, typename... Args2> - void SetParticleData(C& p, const std::tuple<Args1...> vA, + void SetParticleData(PI_C& p, const std::tuple<Args1...> vA, const std::tuple<Args2...> vB) { - I::SetParticleData(static_cast<I&>(p), vA); - T::SetParticleData(static_cast<T&>(p), vB); + PI_A::SetParticleData(static_cast<PI_A&>(p), vA); + PI_B::SetParticleData(static_cast<PI_B&>(p), vB); } + ///@} }; /** - * Memory implementation of the most simple (stupid) particle stack object. + * @class CombinedStackImpl + * + * Memory implementation of a combined data stack. + * + * The two stack data user objects Stack1Impl and Stack2Impl are + * merged into one consistent Stack container object providing + * access to the combined number of data entries. */ template <typename Stack1Impl, typename Stack2Impl> class CombinedStackImpl : public Stack1Impl, public Stack2Impl { @@ -118,11 +159,17 @@ namespace corsika::stack { Stack2Impl::DecrementSize(); } - private: - /// the actual memory to store particle data - }; // end class CombinedStackImpl + /** + * Helper template alias `CombinedStack` to construct new combined + * stack from two stack data objects and a particle readout interface. + * + * Note that the Stack2Impl provides only /additional/ data to + * Stack1Impl. This is important (see above) since tuple data for + * initialization are forwarded to Stack1Impl (first). + */ + template <typename Stack1Impl, typename Stack2Impl, template <typename> typename _PI> using CombinedStack = Stack<CombinedStackImpl<Stack1Impl, Stack2Impl>, _PI>; diff --git a/Framework/StackInterface/ParticleBase.h b/Framework/StackInterface/ParticleBase.h index b5704e762a667b8ff7d4c7442a068f561d2dee8a..04c9184ba5187111e44ffae0902a7352950498da 100644 --- a/Framework/StackInterface/ParticleBase.h +++ b/Framework/StackInterface/ParticleBase.h @@ -52,7 +52,6 @@ namespace corsika::stack { ParticleBase() = default; private: - /* // those copy constructors and assigments should never be implemented ParticleBase(ParticleBase&) = delete; ParticleBase operator=(ParticleBase&) = delete; @@ -60,7 +59,7 @@ namespace corsika::stack { ParticleBase operator=(ParticleBase&&) = delete; ParticleBase(const ParticleBase&) = delete; ParticleBase operator=(const ParticleBase&) = delete; - */ + public: /** * Delete this particle on the stack. The corresponding iterator @@ -73,8 +72,8 @@ namespace corsika::stack { * args is a variadic list of input data that has to match the * function description in the user defined ParticleInterface::AddSecondary(...) */ - template <typename... Args> - StackIterator AddSecondary(const Args... args) { + template <typename... TArgs> + StackIterator AddSecondary(const TArgs... args) { return GetStack().AddSecondary(GetIterator(), args...); } @@ -88,7 +87,7 @@ namespace corsika::stack { return static_cast<const StackIterator&>(*this); } - // protected: + protected: /** @name Access to underlying stack fData, these are service function for user classes. User code can only rely on GetIndex @@ -107,26 +106,6 @@ namespace corsika::stack { ///@} }; - template <typename T> - class ParticleBaseAdd { - - public: - ParticleBaseAdd() = default; - - using T::GetIndex; - using T::GetStackData; - - public: - /* - template <typename... Args1, typename... Args2> - void SetParticleData(Args1... args1, Args2... args2) { - T::SetParticleData(args1...); - } - template <typename... Args1, typename... Args2> - void SetParticleData(T& p, Args1... args1, Args2... args2) {} - */ - }; - } // namespace corsika::stack #endif diff --git a/Framework/StackInterface/SecondaryView.h b/Framework/StackInterface/SecondaryView.h index ac2e3ed19e462ecaca7e7def0bfd2abcb58e31ac..1bbbe02ccaad07fcc533d5782c753427c0dddbf1 100644 --- a/Framework/StackInterface/SecondaryView.h +++ b/Framework/StackInterface/SecondaryView.h @@ -14,6 +14,7 @@ #include <corsika/stack/Stack.h> +#include <stdexcept> #include <vector> namespace corsika::stack { @@ -68,10 +69,10 @@ namespace corsika::stack { * the constructor of the SecondaryView class * @{ */ - using InnerStackTypeV = Stack<StackDataType, ParticleInterface>; - typedef StackIteratorInterface<typename std::remove_reference<StackDataType>::type, - ParticleInterface, InnerStackTypeV> - StackIteratorV; + using InnerStackTypeValue = Stack<StackDataType, ParticleInterface>; + using StackIteratorValue = + StackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, InnerStackTypeValue>; /// @} public: @@ -85,7 +86,8 @@ namespace corsika::stack { /** * this is the full type of the declared ParticleInterface: typedef typename */ - using ParticleType = typename StackIterator::ParticleInterfaceType; + using ParticleType = StackIterator; + using ParticleInterfaceType = typename StackIterator::ParticleInterfaceType; friend class StackIteratorInterface< typename std::remove_reference<StackDataType>::type, ParticleInterface, ViewType>; @@ -99,25 +101,34 @@ namespace corsika::stack { * new stack. */ template <typename... Args> - SecondaryView(Args... args); + SecondaryView(Args... args) = delete; public: - SecondaryView(StackIteratorV& vP) - : Stack<StackDataType&, ParticleInterface>(vP.GetStackData()) - , fProjectileIndex(vP.GetIndex()) {} - - auto GetProjectile() { + /** + SecondaryView can only be constructed passing it a valid + StackIterator to another Stack object + **/ + SecondaryView(StackIteratorValue& vI) + : Stack<StackDataType&, ParticleInterface>(vI.GetStackData()) + , fProjectileIndex(vI.GetIndex()) {} + + StackIterator GetProjectile() { // NOTE: 0 is special marker here for PROJECTILE, see GetIndexFromIterator return StackIterator(*this, 0); } template <typename... Args> auto AddSecondary(const Args... v) { + StackIterator proj = GetProjectile(); + return AddSecondary(proj, v...); + } + + template <typename... Args> + auto AddSecondary(StackIterator& proj, const Args... v) { InnerStackType::GetStackData().IncrementSize(); const unsigned int idSec = GetSize(); const unsigned int index = InnerStackType::GetStackData().GetSize() - 1; fIndices.push_back(index); - StackIterator proj = GetProjectile(); // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see // GetIndexFromIterator return StackIterator(*this, idSec + 1, proj, v...); @@ -164,7 +175,7 @@ namespace corsika::stack { /** * need overwrite Stack::Delete, since we want to call SecondaryView::DeleteLast */ - void Delete(ParticleType p) { Delete(p.GetIterator()); } + void Delete(ParticleInterfaceType p) { Delete(p.GetIterator()); } /** * delete last particle on stack by decrementing stack size @@ -201,6 +212,21 @@ namespace corsika::stack { std::vector<unsigned int> fIndices; }; + /* + See Issue 161 + + unfortunately clang does not support this in the same way (yet) as + gcc, so we have to distinguish here. If clang cataches up, we + could remove the #if here and elsewhere. The gcc code is much more + generic and universal. + */ +#if not defined(__clang__) && defined(__GNUC__) || defined(__GNUG__) + template <typename S, template <typename> typename _PIType = S::template PIType> + struct MakeView { + using type = corsika::stack::SecondaryView<typename S::StackImpl, _PIType>; + }; +#endif + } // namespace corsika::stack #endif diff --git a/Framework/StackInterface/Stack.h b/Framework/StackInterface/Stack.h index 72f3a72fe2d9c5078f893b3f815ed880fd515118..2f183af2a9d7b64def393ea698966cfdabe0d413 100644 --- a/Framework/StackInterface/Stack.h +++ b/Framework/StackInterface/Stack.h @@ -13,12 +13,12 @@ #define _include_Stack_h__ #include <corsika/stack/StackIteratorInterface.h> +// must be after StackIteratorInterface +#include <corsika/stack/SecondaryView.h> #include <stdexcept> #include <type_traits> -#include <corsika/stack/SecondaryView.h> - /** All classes around management of particles on a stack. */ @@ -85,6 +85,10 @@ namespace corsika::stack { * This constructor takes any argument and passes it on to the * StackDataType user class. If the user did not provide a suited * constructor this will fail with an error message. + * + * Furthermore, this is disabled with enable_if for SecondaryView + * stacks, where the inner data container is always a reference + * and cannot be initialized here. */ template < typename... Args, typename _StackDataType = StackDataType, diff --git a/Framework/StackInterface/StackIteratorInterface.h b/Framework/StackInterface/StackIteratorInterface.h index cf1b6d7b53efb14f3fbdd4283831e1f34fe751de..03c59cb44c1d9b7cc74f18fce20cd0ceaaac687f 100644 --- a/Framework/StackInterface/StackIteratorInterface.h +++ b/Framework/StackInterface/StackIteratorInterface.h @@ -14,8 +14,6 @@ #include <corsika/stack/ParticleBase.h> -#include <type_traits> - namespace corsika::stack { template <typename StackDataType, template <typename> typename ParticleInterface> @@ -58,20 +56,20 @@ namespace corsika::stack { ParticleInterface, in this example StackDataType::GetData(const unsigned int vIndex). - For an example see stack_example.cc, or the + For two examples see stack_example.cc, or the corsika::processes::sibyll::SibStack class */ template <typename StackDataType, template <typename> typename ParticleInterface, - typename StackType = - Stack<StackDataType, ParticleInterface>> //, bool IsBase=true > + typename StackType = Stack<StackDataType, ParticleInterface>> class StackIteratorInterface - : public ParticleInterface<StackIteratorInterface<StackDataType, ParticleInterface, - StackType>> { //,IsBase> { + : public ParticleInterface< + StackIteratorInterface<StackDataType, ParticleInterface, StackType>> { public: - using ParticleInterfaceType = ParticleInterface< - StackIteratorInterface<StackDataType, ParticleInterface, StackType>>; //,IsBase>; + using ParticleInterfaceType = + ParticleInterface<corsika::stack::StackIteratorInterface< + StackDataType, ParticleInterface, StackType>>; // friends are needed for access to protected methods friend class Stack<StackDataType, @@ -91,10 +89,20 @@ namespace corsika::stack { StackIteratorInterface() = delete; public: + StackIteratorInterface(StackIteratorInterface const& vR) + : fIndex(vR.fIndex) + , fData(vR.fData) {} + + StackIteratorInterface& operator=(StackIteratorInterface const& vR) { + fIndex = vR.fIndex; + fData = vR.fData; + return *this; + } + /** iterator must always point to data, with an index: - @param data reference to the stack [rw] - @param index index on stack - */ + @param data reference to the stack [rw] + @param index index on stack + */ StackIteratorInterface(StackType& data, const unsigned int index) : fIndex(index) , fData(&data) {} @@ -110,8 +118,7 @@ namespace corsika::stack { StackIteratorInterface(StackType& data, const unsigned int index, const Args... args) : fIndex(index) , fData(&data) { - ParticleInterfaceType& p = **this; - p.SetParticleData(args...); + (**this).SetParticleData(args...); } /** constructor that also sets new values on particle data object, including reference @@ -129,9 +136,7 @@ namespace corsika::stack { StackIteratorInterface& parent, const Args... args) : fIndex(index) , fData(&data) { - ParticleInterfaceType& p = **this; - ParticleInterfaceType& pa = *parent; - p.SetParticleData(pa, args...); + (**this).SetParticleData(*parent, args...); } public: @@ -200,12 +205,12 @@ namespace corsika::stack { template <typename StackDataType, template <typename> typename ParticleInterface, typename StackType = Stack<StackDataType, ParticleInterface>> class ConstStackIteratorInterface - : public ParticleInterface<ConstStackIteratorInterface< - StackDataType, ParticleInterface, StackType>> { //,IsBase> { + : public ParticleInterface< + ConstStackIteratorInterface<StackDataType, ParticleInterface, StackType>> { public: - typedef ParticleInterface<ConstStackIteratorInterface< - StackDataType, ParticleInterface, StackType>> //,IsBase> + typedef ParticleInterface< + ConstStackIteratorInterface<StackDataType, ParticleInterface, StackType>> ParticleInterfaceType; friend class Stack<StackDataType, ParticleInterface>; // for access to GetIndex diff --git a/Framework/StackInterface/testCombinedStack.cc b/Framework/StackInterface/testCombinedStack.cc index 11a3314a2e60a517b9c1b197f913ffec1e7cc421..fbe4a031c928da4ea5a6c326ad1a98c903933972 100644 --- a/Framework/StackInterface/testCombinedStack.cc +++ b/Framework/StackInterface/testCombinedStack.cc @@ -10,6 +10,7 @@ */ #include <corsika/stack/CombinedStack.h> +#include <corsika/stack/SecondaryView.h> #include <corsika/stack/Stack.h> #include <testTestStack.h> // for testing: simple stack. This is a @@ -31,6 +32,10 @@ using namespace corsika; using namespace corsika::stack; using namespace std; +//////////////////////////////////////////////////////////// +// first level test: combine two stacks: +// StackTest = (TestStackData + TestStackData2) + // definition of stack-data object class TestStackData2 { @@ -82,7 +87,7 @@ public: double GetData2() const { return GetStackData().GetData2(GetIndex()); } }; -// combined stack +// combined stack: StackTest = (TestStackData + TestStackData2) template <typename StackIter> using CombinedTestInterfaceType = corsika::stack::CombinedParticleInterface<TestParticleInterface, @@ -196,6 +201,8 @@ TEST_CASE("Combined Stack", "[stack]") { } //////////////////////////////////////////////////////////// +// next level: combine three stacks: +// combined stack: StackTest2 = ((TestStackData + TestStackData2) + TestStackData3) // definition of stack-data object class TestStackData3 { @@ -228,6 +235,7 @@ private: std::vector<double> fData3; }; +// --------------------------------------- // defintion of a stack-readout object, the iteractor dereference // operator will deliver access to these function template <typename T> @@ -248,7 +256,7 @@ public: double GetData3() const { return GetStackData().GetData3(GetIndex()); } }; -// double combined stack +// double combined stack: // combined stack template <typename StackIter> using CombinedTestInterfaceType2 = @@ -264,12 +272,14 @@ TEST_CASE("Combined Stack - multi", "[stack]") { StackTest2 s; REQUIRE(s.GetSize() == 0); + // add new particle, only provide tuple data for StackTest auto p1 = s.AddParticle(std::tuple{9.9}); + // add new particle, provide tuple data for both StackTest and TestStackData3 auto p2 = s.AddParticle(std::tuple{8.8}, std::tuple{0.1}); + // examples to explicitly change data on stack p2.SetData2(0.1); // not clear why this is needed, need to check // SetParticleData workflow for more complicated // settings - // auto p3 = s.AddParticle( std::tuple {8.8}, std::tuple{1.}, std::tuple{0.1} ); p1.SetData3(20.2); p2.SetData3(10.3); @@ -301,3 +311,47 @@ TEST_CASE("Combined Stack - multi", "[stack]") { REQUIRE(s.GetSize() == 0); } } + +//////////////////////////////////////////////////////////// + +// final level test, create SecondaryView on StackTest2 + +/* + See Issue 161 + + unfortunately clang does not support this in the same way (yet) as + gcc, so we have to distinguish here. If clang cataches up, we could + remove the clang branch here and also in corsika::Cascade. The gcc + code is much more generic and universal. + */ +template <typename StackIter> +using CombinedTestInterfaceType2 = + corsika::stack::CombinedParticleInterface<StackTest::PIType, TestParticleInterface3, + StackIter>; + +using StackTest2 = CombinedStack<typename StackTest::StackImpl, TestStackData3, + CombinedTestInterfaceType2>; + +#if defined(__clang__) +using StackTestView = SecondaryView<TestStackData, TestParticleInterface>; +#elif defined(__GNUC__) || defined(__GNUG__) +using StackTestView = corsika::stack::MakeView<StackTest2>::type; +#endif + +using Particle2 = typename StackTest2::ParticleType; + +TEST_CASE("Combined Stack - secondary view") { + + SECTION("create secondaries via secondaryview") { + + StackTest2 stack; + auto particle = stack.AddParticle(std::tuple{9.9}); + // cout << boost::typeindex::type_id_runtime(particle).pretty_name() << endl; + StackTestView view(particle); + + auto projectile = view.GetProjectile(); + projectile.AddSecondary(std::tuple{8.8}); + + REQUIRE(stack.GetSize() == 2); + } +} diff --git a/Framework/StackInterface/testSecondaryView.cc b/Framework/StackInterface/testSecondaryView.cc index 08d27c169bfa6144abd203603eae74dc1e134c98..2d2064b64e2e09c96ec5f77ebbf25d50f5d60e9e 100644 --- a/Framework/StackInterface/testSecondaryView.cc +++ b/Framework/StackInterface/testSecondaryView.cc @@ -33,6 +33,22 @@ using namespace std; typedef Stack<TestStackData, TestParticleInterface> StackTest; +/* + See Issue 161 + + unfortunately clang does not support this in the same way (yet) as + gcc, so we have to distinguish here. If clang cataches up, we could + remove the clang branch here and also in corsika::Cascade. The gcc + code is much more generic and universal. + */ +#if defined(__clang__) +using StackTestView = SecondaryView<TestStackData, TestParticleInterface>; +#elif defined(__GNUC__) || defined(__GNUG__) +using StackTestView = MakeView<StackTest>::type; +#endif + +using Particle = typename StackTest::ParticleType; + TEST_CASE("SecondaryStack", "[stack]") { // helper function for sum over stack data @@ -51,55 +67,71 @@ TEST_CASE("SecondaryStack", "[stack]") { auto particle = s.GetNextParticle(); - typedef SecondaryView<TestStackData, TestParticleInterface> StackTestView; - StackTestView v(particle); - REQUIRE(v.GetSize() == 0); + StackTestView view(particle); + REQUIRE(view.GetSize() == 0); { - auto proj = v.GetProjectile(); + auto proj = view.GetProjectile(); REQUIRE(proj.GetData() == particle.GetData()); + proj.AddSecondary(std::tuple{4.4}); } - v.AddSecondary(std::tuple{4.4}); - v.AddSecondary(std::tuple{4.5}); - v.AddSecondary(std::tuple{4.6}); + view.AddSecondary(std::tuple{4.5}); + view.AddSecondary(std::tuple{4.6}); - REQUIRE(v.GetSize() == 3); + REQUIRE(view.GetSize() == 3); REQUIRE(s.GetSize() == 5); - REQUIRE(!v.IsEmpty()); + REQUIRE(!view.IsEmpty()); auto sumView = [](const StackTestView& stack) { - double v = 0; - for (const auto& p : stack) { v += p.GetData(); } - return v; + double value = 0; + for (const auto& p : stack) { value += p.GetData(); } + return value; }; REQUIRE(sum(s) == sumS + 4.4 + 4.5 + 4.6); - REQUIRE(sumView(v) == 4.4 + 4.5 + 4.6); + REQUIRE(sumView(view) == 4.4 + 4.5 + 4.6); - v.DeleteLast(); - REQUIRE(v.GetSize() == 2); + view.DeleteLast(); + REQUIRE(view.GetSize() == 2); REQUIRE(s.GetSize() == 4); REQUIRE(sum(s) == sumS + 4.4 + 4.5); - REQUIRE(sumView(v) == 4.4 + 4.5); + REQUIRE(sumView(view) == 4.4 + 4.5); - auto pDel = v.GetNextParticle(); - v.Delete(pDel); - REQUIRE(v.GetSize() == 1); + auto pDel = view.GetNextParticle(); + view.Delete(pDel); + REQUIRE(view.GetSize() == 1); REQUIRE(s.GetSize() == 3); REQUIRE(sum(s) == sumS + 4.4 + 4.5 - pDel.GetData()); - REQUIRE(sumView(v) == 4.4 + 4.5 - pDel.GetData()); + REQUIRE(sumView(view) == 4.4 + 4.5 - pDel.GetData()); - v.Delete(v.GetNextParticle()); + view.Delete(view.GetNextParticle()); REQUIRE(sum(s) == sumS); - REQUIRE(sumView(v) == 0); - REQUIRE(v.IsEmpty()); + REQUIRE(sumView(view) == 0); + REQUIRE(view.IsEmpty()); { - auto proj = v.GetProjectile(); + auto proj = view.GetProjectile(); REQUIRE(proj.GetData() == particle.GetData()); } } + + SECTION("secondary view, construct from ParticleType") { + StackTest s; + REQUIRE(s.GetSize() == 0); + s.AddParticle(std::tuple{9.9}); + s.AddParticle(std::tuple{8.8}); + + auto iterator = s.GetNextParticle(); + typename StackTest::ParticleType& particle = iterator; // as in corsika::Cascade + + StackTestView view(particle); + REQUIRE(view.GetSize() == 0); + + view.AddSecondary(std::tuple{4.4}); + + REQUIRE(view.GetSize() == 1); + } } diff --git a/Processes/EnergyLoss/EnergyLoss.cc b/Processes/EnergyLoss/EnergyLoss.cc index 960bbd3235e0de25b4898d5a68dd84813ca27ea4..dde5cf442c175d167cd14f605a04f4e5fd288736 100644 --- a/Processes/EnergyLoss/EnergyLoss.cc +++ b/Processes/EnergyLoss/EnergyLoss.cc @@ -148,7 +148,7 @@ namespace corsika::process::EnergyLoss { (0.5 * log(aux) - beta2 - Cadj / Z - delta / 2 + barkas + bloch) * dX; } - process::EProcessReturn EnergyLoss::DoContinuous(Particle& p, Track& t, Stack&) { + process::EProcessReturn EnergyLoss::DoContinuous(Particle& p, Track& t) { if (p.GetChargeNumber() == 0) return process::EProcessReturn::eOk; GrammageType const dX = p.GetNode()->GetModelProperties().IntegratedGrammage(t, t.GetLength()); @@ -178,16 +178,16 @@ namespace corsika::process::EnergyLoss { return units::si::meter * std::numeric_limits<double>::infinity(); } - void EnergyLoss::MomentumUpdate(corsika::setup::Stack::ParticleType& p, + void EnergyLoss::MomentumUpdate(corsika::setup::Stack::ParticleType& vP, corsika::units::si::HEPEnergyType Enew) { - HEPMomentumType Pnew = elab2plab(Enew, p.GetMass()); - auto pnew = p.GetMomentum(); - p.SetMomentum(pnew * Pnew / pnew.GetNorm()); + HEPMomentumType Pnew = elab2plab(Enew, vP.GetMass()); + auto pnew = vP.GetMomentum(); + vP.SetMomentum(pnew * Pnew / pnew.GetNorm()); } #include <corsika/geometry/CoordinateSystem.h> - int EnergyLoss::GetXbin(corsika::setup::Stack::ParticleType& p, + int EnergyLoss::GetXbin(corsika::setup::Stack::ParticleType& vP, const HEPEnergyType dE) { using namespace corsika::geometry; @@ -195,12 +195,12 @@ namespace corsika::process::EnergyLoss { CoordinateSystem const& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); Point pos1(rootCS, 0_m, 0_m, 0_m); - Point pos2(rootCS, 0_m, 0_m, p.GetPosition().GetCoordinates()[2]); + Point pos2(rootCS, 0_m, 0_m, vP.GetPosition().GetCoordinates()[2]); Vector delta = (pos2 - pos1) / 1_s; Trajectory t(Line(pos1, delta), 1_s); GrammageType const grammage = - p.GetNode()->GetModelProperties().IntegratedGrammage(t, t.GetLength()); + vP.GetNode()->GetModelProperties().IntegratedGrammage(t, t.GetLength()); const int bin = grammage / fdX; diff --git a/Processes/EnergyLoss/EnergyLoss.h b/Processes/EnergyLoss/EnergyLoss.h index 5eb2a6b6782b12bb7b336e67d43e2882d666b80a..323ef85735eb1525ef3514329bbc112d7c44cf97 100644 --- a/Processes/EnergyLoss/EnergyLoss.h +++ b/Processes/EnergyLoss/EnergyLoss.h @@ -35,8 +35,7 @@ namespace corsika::process::EnergyLoss { void Init() {} corsika::process::EProcessReturn DoContinuous(corsika::setup::Stack::ParticleType&, - corsika::setup::Trajectory&, - corsika::setup::Stack&); + corsika::setup::Trajectory&); corsika::units::si::LengthType MaxStepLength(corsika::setup::Stack::ParticleType&, corsika::setup::Trajectory&); diff --git a/Processes/HadronicElasticModel/HadronicElasticModel.cc b/Processes/HadronicElasticModel/HadronicElasticModel.cc index 289968645c4c758d10f7230dbcf99babba40838c..33f162e41531bf4008f91b21bb98e8afc13a7abb 100644 --- a/Processes/HadronicElasticModel/HadronicElasticModel.cc +++ b/Processes/HadronicElasticModel/HadronicElasticModel.cc @@ -79,7 +79,7 @@ namespace corsika::process::HadronicElasticModel { } template <> - process::EProcessReturn HadronicElasticInteraction::DoInteraction(Particle& p, Stack&) { + process::EProcessReturn HadronicElasticInteraction::DoInteraction(Particle& p) { if (p.GetPID() != particles::Code::Proton) { return process::EProcessReturn::eOk; } using namespace units::si; diff --git a/Processes/HadronicElasticModel/HadronicElasticModel.h b/Processes/HadronicElasticModel/HadronicElasticModel.h index fae8c97242bac32426eca9089ac8a8ff611b631e..4180c04c514d00089fd044ab39027b9128a853ff 100644 --- a/Processes/HadronicElasticModel/HadronicElasticModel.h +++ b/Processes/HadronicElasticModel/HadronicElasticModel.h @@ -59,8 +59,8 @@ namespace corsika::process::HadronicElasticModel { template <typename Particle, typename Track> corsika::units::si::GrammageType GetInteractionLength(Particle const& p, Track&); - template <typename Particle, typename Stack> - corsika::process::EProcessReturn DoInteraction(Particle& p, Stack&); + template <typename Particle> + corsika::process::EProcessReturn DoInteraction(Particle&); }; } // namespace corsika::process::HadronicElasticModel diff --git a/Processes/NullModel/NullModel.cc b/Processes/NullModel/NullModel.cc index c99a464b4dd4eca06e288df524202ec8016bd3e3..802ee5b4a669f824ac94c717e0bd61b3a0cfd3a3 100644 --- a/Processes/NullModel/NullModel.cc +++ b/Processes/NullModel/NullModel.cc @@ -14,21 +14,23 @@ #include <corsika/setup/SetupTrajectory.h> using namespace corsika; -using namespace corsika::process::null_model; +namespace corsika::process::null_model { -void corsika::process::null_model::NullModel::Init() {} + void NullModel::Init() {} -NullModel::NullModel(units::si::LengthType maxStepLength) - : fMaxStepLength(maxStepLength) {} + NullModel::NullModel(units::si::LengthType maxStepLength) + : fMaxStepLength(maxStepLength) {} -template <> -process::EProcessReturn NullModel::DoContinuous(setup::Stack::ParticleType&, - setup::Trajectory&, setup::Stack&) const { - return process::EProcessReturn::eOk; -} + template <> + process::EProcessReturn NullModel::DoContinuous(setup::Stack::ParticleType&, + setup::Trajectory&) const { + return process::EProcessReturn::eOk; + } -template <> -units::si::LengthType NullModel::MaxStepLength(setup::Stack::ParticleType&, - setup::Trajectory&) const { - return fMaxStepLength; -} + template <> + units::si::LengthType NullModel::MaxStepLength(setup::Stack::ParticleType&, + setup::Trajectory&) const { + return fMaxStepLength; + } + +} // namespace corsika::process::null_model diff --git a/Processes/NullModel/NullModel.h b/Processes/NullModel/NullModel.h index 5579d69f8a1ec08348e242e4d5bb8d012a21feb5..d3a820da41ede79dfd40669e7da6d15faaa8cf79 100644 --- a/Processes/NullModel/NullModel.h +++ b/Processes/NullModel/NullModel.h @@ -12,11 +12,12 @@ #ifndef _Physics_NullModel_NullModel_h_ #define _Physics_NullModel_NullModel_h_ -#include <corsika/process/ContinuousProcess.h> +#include <corsika/process/BaseProcess.h> +#include <corsika/units/PhysicalUnits.h> namespace corsika::process::null_model { - class NullModel : public corsika::process::ContinuousProcess<NullModel> { + class NullModel : public corsika::process::BaseProcess<NullModel> { corsika::units::si::LengthType const fMaxStepLength; public: @@ -25,8 +26,8 @@ namespace corsika::process::null_model { void Init(); - template <typename Particle, typename Track, typename Stack> - process::EProcessReturn DoContinuous(Particle&, Track&, Stack&) const; + template <typename Particle, typename Track> + process::EProcessReturn DoContinuous(Particle&, Track&) const; template <typename Particle, typename Track> corsika::units::si::LengthType MaxStepLength(Particle&, Track&) const; diff --git a/Processes/NullModel/testNullModel.cc b/Processes/NullModel/testNullModel.cc index ed639eca4cb54fa3f1f6a676a27c01eb37663b6c..930d5979fec7bbcc728212b74e944f7dd11599cf 100644 --- a/Processes/NullModel/testNullModel.cc +++ b/Processes/NullModel/testNullModel.cc @@ -39,23 +39,19 @@ TEST_CASE("NullModel", "[processes]") { geometry::Trajectory<geometry::Line> track(line, 10_s); setup::Stack stack; - setup::Stack::ParticleType - // auto - particle = stack.AddParticle( - std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType, - corsika::stack::MomentumVector, corsika::geometry::Point, - corsika::units::si::TimeType>{ - particles::Code::Electron, 1.5_GeV, - stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), - geometry::Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s}); - + setup::Stack::ParticleType particle = stack.AddParticle( + std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ + particles::Code::Electron, 100_GeV, + corsika::stack::MomentumVector(dummyCS, {0_GeV, 0_GeV, -1_GeV}), + geometry::Point(dummyCS, {0_m, 0_m, 10_km}), 0_ns}); SECTION("interface") { NullModel model(10_m); model.Init(); [[maybe_unused]] const process::EProcessReturn ret = - model.DoContinuous(particle, track, stack); + model.DoContinuous(particle, track); LengthType const length = model.MaxStepLength(particle, track); CHECK((length / 10_m) == Approx(1)); diff --git a/Processes/Pythia/Decay.cc b/Processes/Pythia/Decay.cc index 77241b106dff5d6f674f60ec9a2acfe763ca09be..222c68c8dd57d7fd57c453b62f53777e85ad062a 100644 --- a/Processes/Pythia/Decay.cc +++ b/Processes/Pythia/Decay.cc @@ -22,7 +22,8 @@ using std::vector; using namespace corsika; using namespace corsika::setup; -using Particle = Stack::StackIterator; // ParticleType; +using Projectile = corsika::setup::StackView::ParticleType; +using Particle = corsika::setup::Stack::ParticleType; using Track = Trajectory; namespace corsika::process::pythia { @@ -84,13 +85,13 @@ namespace corsika::process::pythia { } template <> - void Decay::DoDecay(Particle& p, Stack&) { + void Decay::DoDecay(Projectile& vP) { using geometry::Point; using namespace units; using namespace units::si; - auto const decayPoint = p.GetPosition(); - auto const t0 = p.GetTime(); + auto const decayPoint = vP.GetPosition(); + auto const t0 = vP.GetTime(); // coordinate system, get global frame of reference geometry::CoordinateSystem& rootCS = @@ -103,17 +104,17 @@ namespace corsika::process::pythia { event.reset(); // set particle unstable - Decay::SetUnstable(p.GetPID()); + Decay::SetUnstable(vP.GetPID()); // input particle PDG - auto const pdgCode = static_cast<int>(particles::GetPDG(p.GetPID())); + auto const pdgCode = static_cast<int>(particles::GetPDG(vP.GetPID())); - auto const pcomp = p.GetMomentum().GetComponents(); + auto const pcomp = vP.GetMomentum().GetComponents(); double px = pcomp[0] / 1_GeV; double py = pcomp[1] / 1_GeV; double pz = pcomp[2] / 1_GeV; - double en = p.GetEnergy() / 1_GeV; - double m = particles::GetMass(p.GetPID()) / 1_GeV; + double en = vP.GetEnergy() / 1_GeV; + double m = particles::GetMass(vP.GetPID()) / 1_GeV; // add particle to pythia stack event.append(pdgCode, 1, 0, 0, px, py, pz, en, m); @@ -138,17 +139,17 @@ namespace corsika::process::pythia { cout << "particle: id=" << pyId << " momentum=" << pyP.GetComponents() / 1_GeV << " energy=" << pyEn << endl; - p.AddSecondary( + vP.AddSecondary( tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ pyId, pyEn, pyP, decayPoint, t0}); } // set particle stable - Decay::SetStable(p.GetPID()); + Decay::SetStable(vP.GetPID()); // remove original particle from corsika stack - p.Delete(); + vP.Delete(); // if (fCount>10) throw std::runtime_error("stop here"); } diff --git a/Processes/Pythia/Decay.h b/Processes/Pythia/Decay.h index fc76137160177afabe0d6624b2bc1b708f545ab4..6506625b07a04ec076919bafcbf0e8c92395aaf4 100644 --- a/Processes/Pythia/Decay.h +++ b/Processes/Pythia/Decay.h @@ -35,11 +35,11 @@ namespace corsika::process { void SetUnstable(const corsika::particles::Code); void SetStable(const corsika::particles::Code); - template <typename Particle> - corsika::units::si::TimeType GetLifetime(Particle const& p); + template <typename TParticle> + corsika::units::si::TimeType GetLifetime(TParticle const&); - template <typename Particle, typename Stack> - void DoDecay(Particle& p, Stack&); + template <typename TProjectile> + void DoDecay(TProjectile&); private: Pythia8::Pythia fPythia; diff --git a/Processes/Pythia/Interaction.cc b/Processes/Pythia/Interaction.cc index 092563e52bb66cf8130604100ed6a3f7e5b1c18d..ae8104350086f5cfda94b174305d0f0366faa2ce 100644 --- a/Processes/Pythia/Interaction.cc +++ b/Processes/Pythia/Interaction.cc @@ -26,7 +26,8 @@ using std::tuple; using namespace corsika; using namespace corsika::setup; -using Particle = Stack::StackIterator; // ParticleType; +using Projectile = corsika::setup::StackView::ParticleType; +using Particle = corsika::setup::Stack::ParticleType; using Track = Trajectory; namespace corsika::process::pythia { @@ -224,8 +225,9 @@ namespace corsika::process::pythia { i++; cout << "Interaction: get interaction length for target: " << targetId << endl; - [[maybe_unused]] auto const [productionCrossSection, elaCrossSection] = + auto const [productionCrossSection, elaCrossSection] = GetCrossSection(corsikaBeamId, targetId, ECoM); + [[maybe_unused]] const auto& dummy_elaCrossSection = elaCrossSection; cout << "Interaction: IntLength: pythia return (mb): " << productionCrossSection / 1_mb << endl @@ -257,14 +259,14 @@ namespace corsika::process::pythia { */ template <> - process::EProcessReturn Interaction::DoInteraction(Particle& p, Stack&) { + process::EProcessReturn Interaction::DoInteraction(Projectile& vP) { using namespace units; using namespace utl; using namespace units::si; using namespace geometry; - const auto corsikaBeamId = p.GetPID(); + const auto corsikaBeamId = vP.GetPID(); cout << "Pythia::Interaction: " << "DoInteraction: " << corsikaBeamId << " interaction? " << process::pythia::Interaction::CanInteract(corsikaBeamId) << endl; @@ -280,8 +282,8 @@ namespace corsika::process::pythia { RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); // position and time of interaction, not used in Sibyll - Point pOrig = p.GetPosition(); - TimeType tOrig = p.GetTime(); + Point pOrig = vP.GetPosition(); + TimeType tOrig = vP.GetTime(); // define target // FOR NOW: target is always at rest @@ -290,8 +292,8 @@ namespace corsika::process::pythia { const FourVector PtargLab(eTargetLab, pTargetLab); // define projectile - HEPEnergyType const eProjectileLab = p.GetEnergy(); - auto const pProjectileLab = p.GetMomentum(); + HEPEnergyType const eProjectileLab = vP.GetEnergy(); + auto const pProjectileLab = vP.GetMomentum(); cout << "Interaction: ebeam lab: " << eProjectileLab / 1_GeV << endl << "Interaction: pbeam lab: " << pProjectileLab.GetComponents() / 1_GeV @@ -326,12 +328,12 @@ namespace corsika::process::pythia { cout << "Interaction: time: " << tOrig << endl; HEPEnergyType Etot = eProjectileLab + eTargetLab; - MomentumVector Ptot = p.GetMomentum(); + MomentumVector Ptot = vP.GetMomentum(); // invariant mass, i.e. cm. energy HEPEnergyType Ecm = sqrt(Etot * Etot - Ptot.squaredNorm()); // sample target mass number - const auto* currentNode = p.GetNode(); + const auto* currentNode = vP.GetNode(); const auto& mediumComposition = currentNode->GetModelProperties().GetNuclearComposition(); // get cross sections for target materials @@ -345,8 +347,8 @@ namespace corsika::process::pythia { for (size_t i = 0; i < compVec.size(); ++i) { auto const targetId = compVec[i]; - [[maybe_unused]] const auto [sigProd, sigEla] = - GetCrossSection(corsikaBeamId, targetId, Ecm); + const auto [sigProd, sigEla] = GetCrossSection(corsikaBeamId, targetId, Ecm); + [[maybe_unused]] const auto& dummy_sigEla = sigEla; cross_section_of_components[i] = sigProd; } @@ -385,19 +387,19 @@ namespace corsika::process::pythia { MomentumVector Plab_final(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV}); HEPEnergyType Elab_final = 0_GeV; for (int i = 0; i < event.size(); ++i) { - Pythia8::Particle& pp = event[i]; + Pythia8::Particle& p8p = event[i]; // skip particles that have decayed in pythia - if (!pp.isFinal()) continue; + if (!p8p.isFinal()) continue; auto const pyId = - particles::ConvertFromPDG(static_cast<particles::PDGCode>(pp.id())); + particles::ConvertFromPDG(static_cast<particles::PDGCode>(p8p.id())); const MomentumVector pyPlab( - rootCS, {pp.px() * 1_GeV, pp.py() * 1_GeV, pp.pz() * 1_GeV}); - HEPEnergyType const pyEn = pp.e() * 1_GeV; + rootCS, {p8p.px() * 1_GeV, p8p.py() * 1_GeV, p8p.pz() * 1_GeV}); + HEPEnergyType const pyEn = p8p.e() * 1_GeV; // add to corsika stack - auto pnew = p.AddSecondary( + auto pnew = vP.AddSecondary( tuple<particles::Code, units::si::HEPEnergyType, stack::MomentumVector, geometry::Point, units::si::TimeType>{pyId, pyEn, pyPlab, pOrig, tOrig}); @@ -410,7 +412,7 @@ namespace corsika::process::pythia { << ", Plab_final=" << (Plab_final / 1_GeV).GetComponents() << endl; } // delete current particle - p.Delete(); + vP.Delete(); } return process::EProcessReturn::eOk; } diff --git a/Processes/Pythia/Interaction.h b/Processes/Pythia/Interaction.h index 3e1d8813b22a55ffef913ea8298414a8d441ec7d..ac27825acf0561d0d9e7e8e8b66961bdfc674e2f 100644 --- a/Processes/Pythia/Interaction.h +++ b/Processes/Pythia/Interaction.h @@ -51,16 +51,16 @@ namespace corsika::process::pythia { const corsika::particles::Code TargetId, const corsika::units::si::HEPEnergyType CoMenergy); - template <typename Particle, typename Track> - corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&); + template <typename TParticle, typename TTrack> + corsika::units::si::GrammageType GetInteractionLength(TParticle&, TTrack&); /** In this function PYTHIA is called to produce one event. The event is copied (and boosted) into the shower lab frame. */ - template <typename Particle, typename Stack> - corsika::process::EProcessReturn DoInteraction(Particle&, Stack&); + template <typename TProjctile> + corsika::process::EProcessReturn DoInteraction(TProjctile&); private: corsika::random::RNG& fRNG = diff --git a/Processes/Pythia/testPythia.cc b/Processes/Pythia/testPythia.cc index 1e6c57cca49e7fb53017776a8d4fb69790c9b278..3fb2df13ecd1c24e674997a3c3aa468164f21d06 100644 --- a/Processes/Pythia/testPythia.cc +++ b/Processes/Pythia/testPythia.cc @@ -145,11 +145,12 @@ TEST_CASE("pythia process") { random::RNGManager::GetInstance().RegisterRandomStream("pythia"); - process::pythia::Decay model(particleList); + corsika::stack::SecondaryView view(particle); + auto projectile = view.GetProjectile(); + process::pythia::Decay model(particleList); model.Init(); - /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(particle, - stack); + /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(projectile); [[maybe_unused]] const TimeType time = model.GetLifetime(particle); } @@ -166,11 +167,12 @@ TEST_CASE("pythia process") { corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ particles::Code::PiPlus, E0, plab, pos, 0_ns}); particle.SetNode(nodePtr); - process::pythia::Interaction model; + corsika::stack::SecondaryView view(particle); + auto projectile = view.GetProjectile(); + process::pythia::Interaction model; model.Init(); - /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoInteraction(particle, - stack); + [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(projectile); [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle, track); } diff --git a/Processes/Sibyll/Decay.cc b/Processes/Sibyll/Decay.cc index 3cd009c580d10845ea2219b59322dc1855a88295..7a865e92fa08d606c68c5bad782e0a70e826f101 100644 --- a/Processes/Sibyll/Decay.cc +++ b/Processes/Sibyll/Decay.cc @@ -24,7 +24,8 @@ using std::vector; using namespace corsika; using namespace corsika::setup; -using Particle = Stack::StackIterator; // ParticleType; +using Projectile = corsika::setup::StackView::ParticleType; +using Particle = corsika::setup::Stack::ParticleType; using Track = Trajectory; namespace corsika::process::sibyll { @@ -103,27 +104,27 @@ namespace corsika::process::sibyll { } template <> - units::si::TimeType Decay::GetLifetime(Particle const& p) { + units::si::TimeType Decay::GetLifetime(Particle const& vP) { using namespace units::si; - HEPEnergyType E = p.GetEnergy(); - HEPMassType m = p.GetMass(); + HEPEnergyType E = vP.GetEnergy(); + HEPMassType m = vP.GetMass(); const double gamma = E / m; - const TimeType t0 = particles::GetLifetime(p.GetPID()); + const TimeType t0 = particles::GetLifetime(vP.GetPID()); auto const lifetime = gamma * t0; const auto mkin = - (E * E - p.GetMomentum().squaredNorm()); // delta_mass(p.GetMomentum(), E, m); - cout << "Decay: code: " << p.GetPID() << endl; + (E * E - vP.GetMomentum().squaredNorm()); // delta_mass(vP.GetMomentum(), E, m); + cout << "Decay: code: " << vP.GetPID() << endl; cout << "Decay: MinStep: t0: " << t0 << endl; cout << "Decay: MinStep: energy: " << E / 1_GeV << " GeV" << endl; - cout << "Decay: momentum: " << p.GetMomentum().GetComponents() / 1_GeV << " GeV" + cout << "Decay: momentum: " << vP.GetMomentum().GetComponents() / 1_GeV << " GeV" << endl; cout << "Decay: momentum: shell mass-kin. inv. mass " << mkin / 1_GeV / 1_GeV << " " << m / 1_GeV * m / 1_GeV << endl; - auto sib_id = process::sibyll::ConvertToSibyllRaw(p.GetPID()); + auto sib_id = process::sibyll::ConvertToSibyllRaw(vP.GetPID()); cout << "Decay: sib mass: " << get_sibyll_mass2(sib_id) << endl; cout << "Decay: MinStep: gamma: " << gamma << endl; cout << "Decay: MinStep: tau: " << lifetime << endl; @@ -132,23 +133,23 @@ namespace corsika::process::sibyll { } template <> - void Decay::DoDecay(Particle& p, Stack&) { + void Decay::DoDecay(Projectile& vP) { using geometry::Point; using namespace units::si; fCount++; SibStack ss; ss.Clear(); - const particles::Code pCode = p.GetPID(); + const particles::Code pCode = vP.GetPID(); // copy particle to sibyll stack - ss.AddParticle(process::sibyll::ConvertToSibyllRaw(pCode), p.GetEnergy(), - p.GetMomentum(), + ss.AddParticle(process::sibyll::ConvertToSibyllRaw(pCode), vP.GetEnergy(), + vP.GetMomentum(), // setting particle mass with Corsika values, may be inconsistent // with sibyll internal values particles::GetMass(pCode)); // remember position - Point const decayPoint = p.GetPosition(); - TimeType const t0 = p.GetTime(); + Point const decayPoint = vP.GetPosition(); + TimeType const t0 = vP.GetTime(); // set all particles/hadrons unstable // setHadronsUnstable(); SetUnstable(pCode); @@ -166,7 +167,7 @@ namespace corsika::process::sibyll { // FOR NOW: skip particles that have decayed in Sibyll, move to iterator? if (psib.HasDecayed()) continue; // add to corsika stack - p.AddSecondary( + vP.AddSecondary( tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ process::sibyll::ConvertFromSibyll(psib.GetPID()), psib.GetEnergy(), @@ -174,8 +175,6 @@ namespace corsika::process::sibyll { } // empty sibyll stack ss.Clear(); - // remove original particle from corsika stack - p.Delete(); } } // namespace corsika::process::sibyll diff --git a/Processes/Sibyll/Decay.h b/Processes/Sibyll/Decay.h index 7e7a202e7c3172577c6a5662d09eb67bbb9433f2..5dc06bd0cfc6db1a59c74f04dd78971b3f01a748 100644 --- a/Processes/Sibyll/Decay.h +++ b/Processes/Sibyll/Decay.h @@ -37,10 +37,10 @@ namespace corsika::process { void SetHadronsUnstable(); template <typename Particle> - corsika::units::si::TimeType GetLifetime(Particle const& p); + corsika::units::si::TimeType GetLifetime(Particle const&); - template <typename Particle, typename Stack> - void DoDecay(Particle& p, Stack&); + template <typename Projectile> + void DoDecay(Projectile&); }; } // namespace sibyll } // namespace corsika::process diff --git a/Processes/Sibyll/Interaction.cc b/Processes/Sibyll/Interaction.cc index 333b6c9894a9f1e7e84a77fecaa283afe9afe047..ed550a012d63df6b89586198933ce10c4d01b8d2 100644 --- a/Processes/Sibyll/Interaction.cc +++ b/Processes/Sibyll/Interaction.cc @@ -27,8 +27,11 @@ using std::cout; using std::endl; using std::tuple; -using SetupParticle = corsika::setup::Stack::StackIterator; // SetupParticleType; -using Track = corsika::setup::Trajectory; +using namespace corsika; +using namespace corsika::setup; +using Particle = Stack::StackIterator; // ParticleType; +using Projectile = StackView::StackIterator; // ParticleType; +using Track = Trajectory; namespace corsika::process::sibyll { @@ -115,8 +118,7 @@ namespace corsika::process::sibyll { } template <> - units::si::GrammageType Interaction::GetInteractionLength(SetupParticle& p, - Track&) const { + units::si::GrammageType Interaction::GetInteractionLength(Particle& vP, Track&) const { using namespace units; using namespace units::si; @@ -126,7 +128,7 @@ namespace corsika::process::sibyll { CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - const particles::Code corsikaBeamId = p.GetPID(); + const particles::Code corsikaBeamId = vP.GetPID(); // beam particles for sibyll : 1, 2, 3 for p, pi, k // read from cross section code table @@ -136,9 +138,9 @@ namespace corsika::process::sibyll { MomentumVector pTarget(rootCS, {0_GeV, 0_GeV, 0_GeV}); // total momentum and energy - HEPEnergyType Elab = p.GetEnergy() + constants::nucleonMass; + HEPEnergyType Elab = vP.GetEnergy() + constants::nucleonMass; MomentumVector pTotLab(rootCS, {0_GeV, 0_GeV, 0_GeV}); - pTotLab += p.GetMomentum(); + pTotLab += vP.GetMomentum(); pTotLab += pTarget; auto const pTotLabNorm = pTotLab.norm(); // calculate cm. energy @@ -146,9 +148,9 @@ namespace corsika::process::sibyll { (Elab + pTotLabNorm) * (Elab - pTotLabNorm)); // binomial for numerical accuracy cout << "Interaction: LambdaInt: \n" - << " input energy: " << p.GetEnergy() / 1_GeV << endl + << " input energy: " << vP.GetEnergy() / 1_GeV << endl << " beam can interact:" << kInteraction << endl - << " beam pid:" << p.GetPID() << endl; + << " beam pid:" << vP.GetPID() << endl; // TODO: move limits into variables // FR: removed && Elab >= 8.5_GeV @@ -160,7 +162,7 @@ namespace corsika::process::sibyll { ideally as full particle object so that the four momenta and the boosts can be defined.. */ - auto const* currentNode = p.GetNode(); + auto const* currentNode = vP.GetNode(); const auto mediumComposition = currentNode->GetModelProperties().GetNuclearComposition(); // determine average interaction length @@ -174,8 +176,9 @@ namespace corsika::process::sibyll { i++; cout << "Interaction: get interaction length for target: " << targetId << endl; - [[maybe_unused]] auto const [productionCrossSection, elaCrossSection] = + auto const [productionCrossSection, elaCrossSection] = GetCrossSection(corsikaBeamId, targetId, ECoM); + [[maybe_unused]] const auto& dummy_elaCX = elaCrossSection; cout << "Interaction: " << " IntLength: sibyll return (mb): " << productionCrossSection / 1_mb @@ -206,14 +209,14 @@ namespace corsika::process::sibyll { */ template <> - process::EProcessReturn Interaction::DoInteraction(SetupParticle& p, setup::Stack&) { + process::EProcessReturn Interaction::DoInteraction(Projectile& vP) { using namespace units; using namespace utl; using namespace units::si; using namespace geometry; - const auto corsikaBeamId = p.GetPID(); + const auto corsikaBeamId = vP.GetPID(); cout << "ProcessSibyll: " << "DoInteraction: " << corsikaBeamId << " interaction? " << process::sibyll::CanInteract(corsikaBeamId) << endl; @@ -228,8 +231,8 @@ namespace corsika::process::sibyll { RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); // position and time of interaction, not used in Sibyll - Point pOrig = p.GetPosition(); - TimeType tOrig = p.GetTime(); + Point pOrig = vP.GetPosition(); + TimeType tOrig = vP.GetTime(); // define target // for Sibyll is always a single nucleon @@ -239,8 +242,8 @@ namespace corsika::process::sibyll { const FourVector PtargLab(eTargetLab, pTargetLab); // define projectile - HEPEnergyType const eProjectileLab = p.GetEnergy(); - auto const pProjectileLab = p.GetMomentum(); + HEPEnergyType const eProjectileLab = vP.GetEnergy(); + auto const pProjectileLab = vP.GetMomentum(); cout << "Interaction: ebeam lab: " << eProjectileLab / 1_GeV << endl << "Interaction: pbeam lab: " << pProjectileLab.GetComponents() / 1_GeV @@ -275,12 +278,12 @@ namespace corsika::process::sibyll { cout << "Interaction: time: " << tOrig << endl; HEPEnergyType Etot = eProjectileLab + eTargetLab; - MomentumVector Ptot = p.GetMomentum(); + MomentumVector Ptot = vP.GetMomentum(); // invariant mass, i.e. cm. energy HEPEnergyType Ecm = sqrt(Etot * Etot - Ptot.squaredNorm()); // sample target mass number - auto const* currentNode = p.GetNode(); + auto const* currentNode = vP.GetNode(); auto const& mediumComposition = currentNode->GetModelProperties().GetNuclearComposition(); // get cross sections for target materials @@ -294,8 +297,8 @@ namespace corsika::process::sibyll { for (size_t i = 0; i < compVec.size(); ++i) { auto const targetId = compVec[i]; - [[maybe_unsused]] const auto [sigProd, sigEla] = - GetCrossSection(corsikaBeamId, targetId, Ecm); + const auto [sigProd, sigEla] = GetCrossSection(corsikaBeamId, targetId, Ecm); + [[maybe_unused]] const auto& dummy_sigEla = sigEla; cross_section_of_components[i] = sigProd; } @@ -330,7 +333,6 @@ namespace corsika::process::sibyll { << " DoInteraction: should have dropped particle.. " << "THIS IS AN ERROR" << endl; throw std::runtime_error("energy too low for SIBYLL"); - // p.Delete(); delete later... different process } else { fCount++; // Sibyll does not know about units.. @@ -361,7 +363,7 @@ namespace corsika::process::sibyll { auto const Plab = boost.fromCoM(FourVector(eCoM, pCoM)); // add to corsika stack - auto pnew = p.AddSecondary( + auto pnew = vP.AddSecondary( tuple<particles::Code, units::si::HEPEnergyType, stack::MomentumVector, geometry::Point, units::si::TimeType>{ process::sibyll::ConvertFromSibyll(psib.GetPID()), @@ -378,7 +380,7 @@ namespace corsika::process::sibyll { } } // delete current particle - p.Delete(); + vP.Delete(); return process::EProcessReturn::eOk; } diff --git a/Processes/Sibyll/Interaction.h b/Processes/Sibyll/Interaction.h index d2274d428e7819bb929b5a199e20ae2743da5a02..4e1899f685e9254c3207850c227328340a051e94 100644 --- a/Processes/Sibyll/Interaction.h +++ b/Processes/Sibyll/Interaction.h @@ -61,8 +61,8 @@ namespace corsika::process::sibyll { event is copied (and boosted) into the shower lab frame. */ - template <typename Particle, typename Stack> - corsika::process::EProcessReturn DoInteraction(Particle&, Stack&); + template <typename TProjectile> + corsika::process::EProcessReturn DoInteraction(TProjectile&); private: corsika::random::RNG& fRNG = diff --git a/Processes/Sibyll/NuclearInteraction.cc b/Processes/Sibyll/NuclearInteraction.cc index 52c585916e5b274f5700d2e8cde726a4c664117f..31abd9da350e1c80c24868eb2313e860b51bd821 100644 --- a/Processes/Sibyll/NuclearInteraction.cc +++ b/Processes/Sibyll/NuclearInteraction.cc @@ -29,10 +29,11 @@ using std::endl; using std::tuple; using std::vector; -using corsika::setup::SetupEnvironment; -using SetupStack = corsika::setup::Stack; -using Particle = SetupStack::StackIterator; // ParticleType; -using Track = corsika::setup::Trajectory; +using namespace corsika; +using namespace corsika::setup; +using Particle = Stack::ParticleType; // StackIterator; // ParticleType; +using Projectile = StackView::StackIterator; // StackView::ParticleType; +using Track = Trajectory; namespace corsika::process::sibyll { @@ -177,15 +178,15 @@ namespace corsika::process::sibyll { template <> template <> tuple<units::si::CrossSectionType, units::si::CrossSectionType> - NuclearInteraction<SetupEnvironment>::GetCrossSection(Particle& p, + NuclearInteraction<SetupEnvironment>::GetCrossSection(Particle& vP, const particles::Code TargetId) { using namespace units::si; - if (p.GetPID() != particles::Code::Nucleus) + if (vP.GetPID() != particles::Code::Nucleus) throw std::runtime_error( "NuclearInteraction: GetCrossSection: particle not a nucleus!"); - auto const iBeamA = p.GetNuclearA(); - HEPEnergyType LabEnergyPerNuc = p.GetEnergy() / iBeamA; + auto const iBeamA = vP.GetNuclearA(); + HEPEnergyType LabEnergyPerNuc = vP.GetEnergy() / iBeamA; cout << "NuclearInteraction: GetCrossSection: called with: beamNuclA= " << iBeamA << " TargetId= " << TargetId << " LabEnergyPerNuc= " << LabEnergyPerNuc / 1_GeV << endl; @@ -216,7 +217,7 @@ namespace corsika::process::sibyll { template <> template <> units::si::GrammageType NuclearInteraction<SetupEnvironment>::GetInteractionLength( - Particle& p, Track&) { + Particle& vP, Track&) { using namespace units; using namespace units::si; @@ -226,7 +227,7 @@ namespace corsika::process::sibyll { CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - const particles::Code corsikaBeamId = p.GetPID(); + const particles::Code corsikaBeamId = vP.GetPID(); if (!particles::IsNucleus(corsikaBeamId)) { // no nuclear interaction return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm); @@ -243,12 +244,12 @@ namespace corsika::process::sibyll { corsika::stack::MomentumVector pTarget(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV}); // total momentum and energy - HEPEnergyType Elab = p.GetEnergy() + constants::nucleonMass; - int const nuclA = p.GetNuclearA(); - auto const ElabNuc = p.GetEnergy() / nuclA; + HEPEnergyType Elab = vP.GetEnergy() + constants::nucleonMass; + int const nuclA = vP.GetNuclearA(); + auto const ElabNuc = vP.GetEnergy() / nuclA; corsika::stack::MomentumVector pTotLab(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV}); - pTotLab += p.GetMomentum(); + pTotLab += vP.GetMomentum(); pTotLab += pTarget; auto const pTotLabNorm = pTotLab.norm(); // calculate cm. energy @@ -275,7 +276,7 @@ namespace corsika::process::sibyll { ideally as full particle object so that the four momenta and the boosts can be defined.. */ - auto const* const currentNode = p.GetNode(); + auto const* const currentNode = vP.GetNode(); auto const& mediumComposition = currentNode->GetModelProperties().GetNuclearComposition(); // determine average interaction length @@ -289,8 +290,9 @@ namespace corsika::process::sibyll { i++; cout << "NuclearInteraction: get interaction length for target: " << targetId << endl; - [[maybe_unused]] auto const [productionCrossSection, elaCrossSection] = - GetCrossSection(p, targetId); + auto const [productionCrossSection, elaCrossSection] = + GetCrossSection(vP, targetId); + [[maybe_unused]] auto& dummy_elaCrossSection = elaCrossSection; cout << "NuclearInteraction: " << "IntLength: nuclib return (mb): " << productionCrossSection / 1_mb @@ -317,7 +319,7 @@ namespace corsika::process::sibyll { template <> template <> process::EProcessReturn NuclearInteraction<SetupEnvironment>::DoInteraction( - Particle& p, SetupStack& s) { + Projectile& vP) { // this routine superimposes different nucleon-nucleon interactions // in a nucleus-nucleus interaction, based the SIBYLL routine SIBNUC @@ -327,9 +329,9 @@ namespace corsika::process::sibyll { using namespace units::si; using namespace geometry; - const auto ProjId = p.GetPID(); + const auto ProjId = vP.GetPID(); // TODO: calculate projectile mass in nuclearStackExtension - // const auto ProjMass = p.GetMass(); + // const auto ProjMass = vP.GetMass(); cout << "NuclearInteraction: DoInteraction: called with:" << ProjId << endl; if (!IsNucleus(ProjId)) { @@ -346,8 +348,8 @@ namespace corsika::process::sibyll { "should use NuclearStackExtension!"); auto const ProjMass = - p.GetNuclearZ() * particles::Proton::GetMass() + - (p.GetNuclearA() - p.GetNuclearZ()) * particles::Neutron::GetMass(); + vP.GetNuclearZ() * particles::Proton::GetMass() + + (vP.GetNuclearA() - vP.GetNuclearZ()) * particles::Neutron::GetMass(); cout << "NuclearInteraction: projectile mass: " << ProjMass / 1_GeV << endl; fCount++; @@ -356,21 +358,21 @@ namespace corsika::process::sibyll { RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); // position and time of interaction, not used in NUCLIB - Point pOrig = p.GetPosition(); - TimeType tOrig = p.GetTime(); + Point pOrig = vP.GetPosition(); + TimeType tOrig = vP.GetTime(); cout << "Interaction: position of interaction: " << pOrig.GetCoordinates() << endl; cout << "Interaction: time: " << tOrig << endl; // projectile nucleon number - const int kAProj = p.GetNuclearA(); // GetNucleusA(ProjId); + const int kAProj = vP.GetNuclearA(); // GetNucleusA(ProjId); if (kAProj > GetMaxNucleusAProjectile()) throw std::runtime_error("Projectile nucleus too large for NUCLIB!"); // kinematics // define projectile nucleus - HEPEnergyType const eProjectileLab = p.GetEnergy(); - auto const pProjectileLab = p.GetMomentum(); + HEPEnergyType const eProjectileLab = vP.GetEnergy(); + auto const pProjectileLab = vP.GetMomentum(); const FourVector PprojLab(eProjectileLab, pProjectileLab); cout << "NuclearInteraction: eProj lab: " << eProjectileLab / 1_GeV << endl @@ -378,8 +380,8 @@ namespace corsika::process::sibyll { << endl; // define projectile nucleon - HEPEnergyType const eProjectileNucLab = p.GetEnergy() / kAProj; - auto const pProjectileNucLab = p.GetMomentum() / kAProj; + HEPEnergyType const eProjectileNucLab = vP.GetEnergy() / kAProj; + auto const pProjectileNucLab = vP.GetMomentum() / kAProj; const FourVector PprojNucLab(eProjectileNucLab, pProjectileNucLab); cout << "NuclearInteraction: eProjNucleon lab: " << eProjectileNucLab / 1_GeV << endl @@ -431,7 +433,7 @@ namespace corsika::process::sibyll { // // proton stand-in for nucleon const auto beamId = particles::Proton::GetCode(); - auto const* const currentNode = p.GetNode(); + auto const* const currentNode = vP.GetNode(); const auto& mediumComposition = currentNode->GetModelProperties().GetNuclearComposition(); cout << "get nucleon-nucleus cross sections for target materials.." << endl; @@ -556,15 +558,16 @@ namespace corsika::process::sibyll { if (nuclA == 1) // add nucleon - p.AddSecondary(tuple<particles::Code, units::si::HEPEnergyType, - stack::MomentumVector, geometry::Point, units::si::TimeType>{ - specCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(), pOrig, - tOrig}); + vP.AddSecondary( + tuple<particles::Code, units::si::HEPEnergyType, stack::MomentumVector, + geometry::Point, units::si::TimeType>{ + specCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(), + pOrig, tOrig}); else // add nucleus - p.AddSecondary(tuple<particles::Code, units::si::HEPEnergyType, - corsika::stack::MomentumVector, geometry::Point, - units::si::TimeType, unsigned short, unsigned short>{ + vP.AddSecondary(tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, + units::si::TimeType, unsigned short, unsigned short>{ specCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(), pOrig, tOrig, nuclA, nuclZ}); } @@ -583,7 +586,7 @@ namespace corsika::process::sibyll { const double mass_ratio = particles::GetMass(elaNucCode) / ProjMass; auto const Plab = PprojLab * mass_ratio; - p.AddSecondary( + vP.AddSecondary( tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ elaNucCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(), @@ -597,19 +600,16 @@ namespace corsika::process::sibyll { auto pCode = particles::Proton::GetCode(); // temporarily add to stack, will be removed after interaction in DoInteraction cout << "inelastic interaction no. " << j << endl; - auto inelasticNucleon = p.AddSecondary( + auto inelasticNucleon = vP.AddSecondary( tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ pCode, PprojNucLab.GetTimeLikeComponent(), PprojNucLab.GetSpaceLikeComponents(), pOrig, tOrig}); // create inelastic interaction cout << "calling HadronicInteraction..." << endl; - fHadronicInteraction.DoInteraction(inelasticNucleon, s); + fHadronicInteraction.DoInteraction(inelasticNucleon); } - // delete parent particle - p.Delete(); - cout << "NuclearInteraction: DoInteraction: done" << endl; return process::EProcessReturn::eOk; diff --git a/Processes/Sibyll/NuclearInteraction.h b/Processes/Sibyll/NuclearInteraction.h index b04bba538ec9cf2472f8d102fe4ec3bce070578d..6bee9ba7a7964e74112c2bf60e5cbd4b1c23c2fa 100644 --- a/Processes/Sibyll/NuclearInteraction.h +++ b/Processes/Sibyll/NuclearInteraction.h @@ -54,10 +54,10 @@ namespace corsika::process::sibyll { GetCrossSection(Particle& p, const corsika::particles::Code TargetId); template <typename Particle, typename Track> - corsika::units::si::GrammageType GetInteractionLength(Particle& p, Track&); + corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&); - template <typename Particle, typename Stack> - corsika::process::EProcessReturn DoInteraction(Particle& p, Stack& s); + template <typename Projectle> + corsika::process::EProcessReturn DoInteraction(Projectle&); private: TEnvironment const& fEnvironment; diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc index 6acb2b4938282453a94997f69f9cdc01ad99e475..d5f5d9bc8e39ac775de3fb9d541a18b596941bad 100644 --- a/Processes/Sibyll/testSibyll.cc +++ b/Processes/Sibyll/testSibyll.cc @@ -119,12 +119,13 @@ TEST_CASE("SibyllInterface", "[processes]") { corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ particles::Code::Proton, E0, plab, pos, 0_ns}); particle.SetNode(nodePtr); + corsika::stack::SecondaryView view(particle); + auto projectile = view.GetProjectile(); Interaction model; model.Init(); - [[maybe_unused]] const process::EProcessReturn ret = - model.DoInteraction(particle, stack); + [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(projectile); [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle, track); } @@ -144,13 +145,14 @@ TEST_CASE("SibyllInterface", "[processes]") { units::si::TimeType, unsigned short, unsigned short>{ particles::Code::Nucleus, E0, plab, pos, 0_ns, 4, 2}); particle.SetNode(nodePtr); + corsika::stack::SecondaryView view(particle); + auto projectile = view.GetProjectile(); Interaction hmodel; NuclearInteraction model(hmodel, env); model.Init(); - [[maybe_unused]] const process::EProcessReturn ret = - model.DoInteraction(particle, stack); + [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(projectile); [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle, track); } @@ -167,6 +169,8 @@ TEST_CASE("SibyllInterface", "[processes]") { std::tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ particles::Code::Proton, E0, plab, pos, 0_ns}); + corsika::stack::SecondaryView view(particle); + auto projectile = view.GetProjectile(); const std::vector<particles::Code> particleList = { particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus, @@ -175,8 +179,7 @@ TEST_CASE("SibyllInterface", "[processes]") { Decay model(particleList); model.Init(); - /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(particle, - stack); + /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(projectile); [[maybe_unused]] const TimeType time = model.GetLifetime(particle); } } diff --git a/Processes/StackInspector/CMakeLists.txt b/Processes/StackInspector/CMakeLists.txt index f00f44c2ab6b5513630f5344545f988b8e78dc3f..f8297639672f215e7a34e2330bd8e8387454d185 100644 --- a/Processes/StackInspector/CMakeLists.txt +++ b/Processes/StackInspector/CMakeLists.txt @@ -57,7 +57,6 @@ add_executable (testStackInspector testStackInspector.cc) target_link_libraries ( testStackInspector ProcessStackInspector - CORSIKAsetup CORSIKAgeometry CORSIKAunits CORSIKAthirdparty # for catch2 diff --git a/Processes/StackInspector/StackInspector.cc b/Processes/StackInspector/StackInspector.cc index a22742165bec0a6f4a9bfe3b06e33e25ca2e9c3c..814763d5cbfcbc0bd4201db70f220dc4e8ea123f 100644 --- a/Processes/StackInspector/StackInspector.cc +++ b/Processes/StackInspector/StackInspector.cc @@ -16,7 +16,6 @@ #include <corsika/logging/Logger.h> -#include <corsika/cascade/testCascade.h> #include <corsika/setup/SetupTrajectory.h> #include <iostream> @@ -28,23 +27,22 @@ using namespace corsika::particles; using namespace corsika::units::si; using namespace corsika::process::stack_inspector; -template <typename Stack> -StackInspector<Stack>::StackInspector(const bool aReport) - : fReport(aReport) +template <typename TStack> +StackInspector<TStack>::StackInspector(const int nStep, const bool aReport) + : StackProcess<StackInspector<TStack>>(nStep) + , fReport(aReport) , fCountStep(0) {} -template <typename Stack> -StackInspector<Stack>::~StackInspector() {} - -template <typename Stack> -process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&, setup::Trajectory&, - Stack& s) { +template <typename TStack> +StackInspector<TStack>::~StackInspector() {} +template <typename TStack> +process::EProcessReturn StackInspector<TStack>::DoStack(TStack& vS) { if (!fReport) return process::EProcessReturn::eOk; [[maybe_unused]] int i = 0; HEPEnergyType Etot = 0_GeV; - for (auto& iterP : s) { + for (auto& iterP : vS) { HEPEnergyType E = iterP.GetEnergy(); Etot += E; geometry::CoordinateSystem& rootCS = geometry::RootCoordinateSystem::GetInstance() @@ -53,27 +51,21 @@ process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&, setup::Tr cout << "StackInspector: i=" << setw(5) << fixed << (i++) << ", id=" << setw(30) << iterP.GetPID() << " E=" << setw(15) << scientific << (E / 1_GeV) << " GeV, " << " pos=" << pos << " node = " << iterP.GetNode(); - // if (iterP.GetPID()==Code::Nucleus) - // cout << " nuc_ref=" << iterP.GetNucleusRef(); + if (iterP.GetPID() == Code::Nucleus) cout << " nuc_ref=" << iterP.GetNucleusRef(); cout << endl; } fCountStep++; - cout << "StackInspector: nStep=" << fCountStep << " stackSize=" << s.GetSize() + cout << "StackInspector: nStep=" << fCountStep << " stackSize=" << vS.GetSize() << " Estack=" << Etot / 1_GeV << " GeV" << endl; return process::EProcessReturn::eOk; } -template <typename Stack> -corsika::units::si::LengthType StackInspector<Stack>::MaxStepLength(Particle&, - setup::Trajectory&) { - return std::numeric_limits<double>::infinity() * meter; -} - -template <typename Stack> -void StackInspector<Stack>::Init() { +template <typename TStack> +void StackInspector<TStack>::Init() { fCountStep = 0; } +#include <corsika/cascade/testCascade.h> #include <corsika/setup/SetupStack.h> template class process::stack_inspector::StackInspector<setup::Stack>; diff --git a/Processes/StackInspector/StackInspector.h b/Processes/StackInspector/StackInspector.h index 9488767d780c9b2747ace740a14b21aa7da341a4..57a929dd2362b302d43d05175878a257c5c8a832 100644 --- a/Processes/StackInspector/StackInspector.h +++ b/Processes/StackInspector/StackInspector.h @@ -12,7 +12,7 @@ #ifndef _Physics_StackInspector_StackInspector_h_ #define _Physics_StackInspector_StackInspector_h_ -#include <corsika/process/ContinuousProcess.h> +#include <corsika/process/StackProcess.h> #include <corsika/setup/SetupTrajectory.h> #include <corsika/units/PhysicalUnits.h> @@ -20,20 +20,17 @@ namespace corsika::process { namespace stack_inspector { - template <typename Stack> - class StackInspector - : public corsika::process::ContinuousProcess<StackInspector<Stack>> { + template <typename TStack> + class StackInspector : public corsika::process::StackProcess<StackInspector<TStack>> { - typedef typename Stack::ParticleType Particle; + typedef typename TStack::ParticleType Particle; public: - StackInspector(const bool aReport); + StackInspector(const int nStep, const bool aReport); ~StackInspector(); void Init(); - EProcessReturn DoContinuous(Particle&, corsika::setup::Trajectory&, Stack& s); - corsika::units::si::LengthType MaxStepLength(Particle&, - corsika::setup::Trajectory&); + EProcessReturn DoStack(TStack&); private: bool fReport; diff --git a/Processes/StackInspector/testStackInspector.cc b/Processes/StackInspector/testStackInspector.cc index 11e9cff3e4eae58513694dd3b64ba6a6ea64bead..832bea00a8074214ef9f3a235a6a574f7286cf02 100644 --- a/Processes/StackInspector/testStackInspector.cc +++ b/Processes/StackInspector/testStackInspector.cc @@ -21,12 +21,12 @@ #include <corsika/units/PhysicalUnits.h> -#include <corsika/setup/SetupStack.h> -#include <corsika/setup/SetupTrajectory.h> +#include <corsika/cascade/testCascade.h> using namespace corsika::units::si; using namespace corsika::process::stack_inspector; using namespace corsika; +using namespace corsika::geometry; TEST_CASE("StackInspector", "[processes]") { @@ -38,21 +38,21 @@ TEST_CASE("StackInspector", "[processes]") { geometry::Line line(origin, v); geometry::Trajectory<geometry::Line> track(line, 10_s); - setup::Stack stack; - auto particle = stack.AddParticle( + TestCascadeStack stack; + stack.Clear(); + HEPEnergyType E0 = 100_GeV; + stack.AddParticle( std::tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ - particles::Code::Electron, 10_GeV, + particles::Code::Electron, E0, corsika::stack::MomentumVector(rootCS, {0_GeV, 0_GeV, -1_GeV}), - geometry::Point(rootCS, {0_m, 0_m, 10_km}), 0_ns}); + Point(rootCS, {0_m, 0_m, 10_km}), 0_ns}); SECTION("interface") { - StackInspector<setup::Stack> model(true); + StackInspector<TestCascadeStack> model(1, true); model.Init(); - [[maybe_unused]] const process::EProcessReturn ret = - model.DoContinuous(particle, track, stack); - [[maybe_unused]] const LengthType length = model.MaxStepLength(particle, track); + [[maybe_unused]] const process::EProcessReturn ret = model.DoStack(stack); } } diff --git a/Processes/TrackWriter/TrackWriter.cc b/Processes/TrackWriter/TrackWriter.cc index b58a40fbbeca28b8e295ea246901253d674bef8a..5ea8588d9f19aca5f430aa7e749e7d3a51005e59 100644 --- a/Processes/TrackWriter/TrackWriter.cc +++ b/Processes/TrackWriter/TrackWriter.cc @@ -33,13 +33,13 @@ namespace corsika::process::TrackWriter { } template <> - process::EProcessReturn TrackWriter::DoContinuous(Particle& p, Track& t, Stack&) { + process::EProcessReturn TrackWriter::DoContinuous(Particle& vP, Track& vT) { using namespace units::si; - auto const start = t.GetPosition(0).GetCoordinates(); - auto const delta = t.GetPosition(1).GetCoordinates() - start; - auto const& name = particles::GetName(p.GetPID()); + auto const start = vT.GetPosition(0).GetCoordinates(); + auto const delta = vT.GetPosition(1).GetCoordinates() - start; + auto const& name = particles::GetName(vP.GetPID()); - fFile << name << " " << p.GetEnergy() / 1_eV << ' ' << start[0] / 1_m << ' ' + fFile << name << " " << vP.GetEnergy() / 1_eV << ' ' << start[0] / 1_m << ' ' << start[1] / 1_m << ' ' << start[2] / 1_m << " " << delta[0] / 1_m << ' ' << delta[1] / 1_m << ' ' << delta[2] / 1_m << '\n'; diff --git a/Processes/TrackWriter/TrackWriter.h b/Processes/TrackWriter/TrackWriter.h index fa2430569240b159f0c8cb94dd06bc314472be05..51fd5a157da9955aed9a06c69a1b6270626cfb5d 100644 --- a/Processes/TrackWriter/TrackWriter.h +++ b/Processes/TrackWriter/TrackWriter.h @@ -28,8 +28,8 @@ namespace corsika::process::TrackWriter { void Init(); - template <typename Particle, typename Track, typename Stack> - corsika::process::EProcessReturn DoContinuous(Particle& p, Track& t, Stack&); + template <typename Particle, typename Track> + corsika::process::EProcessReturn DoContinuous(Particle&, Track&); template <typename Particle, typename Track> corsika::units::si::LengthType MaxStepLength(Particle&, Track&); diff --git a/Processes/TrackingLine/TrackingLine.h b/Processes/TrackingLine/TrackingLine.h index e847a3fd7ebef23583c632cc5b71af474c883428..a801a2ee2baa206424211151c6a7fb9a616d0b70 100644 --- a/Processes/TrackingLine/TrackingLine.h +++ b/Processes/TrackingLine/TrackingLine.h @@ -105,7 +105,8 @@ namespace corsika::process { currentLogicalVolumeNode->GetVolume()); // for the moment we are a bit bold here and assume // everything is a sphere, crashes with exception if not - auto const [t1, t2] = *TimeOfIntersection(line, sphere); + [[maybe_unused]] auto const [t1, t2] = *TimeOfIntersection(line, sphere); + [[maybe_unused]] auto dummy_t1 = t1; intersections.emplace_back(t2, currentLogicalVolumeNode->GetParent()); } diff --git a/Processes/TrackingLine/testTrackingLine.cc b/Processes/TrackingLine/testTrackingLine.cc index fb213f9d8e3729015a8ad2f19c092e3d476bf9dc..1acff46eec0d810138203856b0bb6900e153ce87 100644 --- a/Processes/TrackingLine/testTrackingLine.cc +++ b/Processes/TrackingLine/testTrackingLine.cc @@ -91,6 +91,8 @@ TEST_CASE("TrackingLine") { Line line(origin, v); auto const [traj, geomMaxLength, nextVol] = tracking.GetTrack(p); + [[maybe_unused]] auto dummy_geomMaxLength = geomMaxLength; + [[maybe_unused]] auto dummy_nextVol = nextVol; REQUIRE((traj.GetPosition(1.) - Point(cs, 0_m, 0_m, radius)) .GetComponents(cs) diff --git a/Setup/SetupStack.h b/Setup/SetupStack.h index dfcfa757dc2d0ad183a1ae9919bd603fbe8bb250..a59ca2aa3815b5a956e17a07faabf61e2834d972 100644 --- a/Setup/SetupStack.h +++ b/Setup/SetupStack.h @@ -29,6 +29,12 @@ // definition of stack-data object to store geometry information template <typename TEnvType> + +/** + * @class GeometryData + * + * definition of stack-data object to store geometry information + */ class GeometryData { public: @@ -57,8 +63,14 @@ private: std::vector<const BaseNodeType*> fNode; }; +/** + * @class GeometryDataInterface + * + * corresponding defintion of a stack-readout object, the iteractor + * dereference operator will deliver access to these function // defintion of a stack-readout object, the iteractor dereference // operator will deliver access to these function + */ template <typename T, typename TEnvType> class GeometryDataInterface : public T { @@ -120,6 +132,25 @@ namespace corsika::setup { // this is the REAL stack we use: using Stack = detail::StackWithGeometry; + /* + See Issue 161 + + unfortunately clang does not support this in the same way (yet) as + gcc, so we have to distinguish here. If clang cataches up, we + could remove the clang branch here and also in + corsika::Cascade. The gcc code is much more generic and + universal. If we could do the gcc version, we won't had to define + StackView globally, we could do it with MakeView whereever it is + actually needed. Keep an eye on this! + */ +#if defined(__clang__) + using StackView = + corsika::stack::SecondaryView<typename corsika::setup::Stack::StackImpl, + corsika::setup::detail::StackWithGeometryInterface>; +#elif defined(__GNUC__) || defined(__GNUG__) + using StackView = corsika::stack::MakeView<corsika::setup::Stack>::type; +#endif + } // namespace corsika::setup #endif diff --git a/Stack/NuclearStackExtension/CMakeLists.txt b/Stack/NuclearStackExtension/CMakeLists.txt index f2f34cfcfa4cf6108651282b464c476de9c125a5..6032c0b90218790d6622a0474af371c62687b711 100644 --- a/Stack/NuclearStackExtension/CMakeLists.txt +++ b/Stack/NuclearStackExtension/CMakeLists.txt @@ -40,8 +40,7 @@ target_link_libraries ( testNuclearStackExtension SuperStupidStack NuclearStackExtension - # CORSIKAutls - ProcessStackInspector + CORSIKAparticles CORSIKAgeometry CORSIKAunits CORSIKAthirdparty # for catch2 diff --git a/Stack/NuclearStackExtension/NuclearStackExtension.h b/Stack/NuclearStackExtension/NuclearStackExtension.h index 6c1fd2b801120bbe0c22c6c76d22ccadc652f4af..40eb5e0e672883e58cc207324e99d11afdd6be18 100644 --- a/Stack/NuclearStackExtension/NuclearStackExtension.h +++ b/Stack/NuclearStackExtension/NuclearStackExtension.h @@ -178,6 +178,8 @@ namespace corsika::stack { return InnerParticleInterface<StackIteratorInterface>::GetChargeNumber(); } + int GetNucleusRef() const { return GetStackData().GetNucleusRef(GetIndex()); } + protected: void SetNucleusRef(const int vR) { GetStackData().SetNucleusRef(GetIndex(), vR); } }; diff --git a/Stack/NuclearStackExtension/testNuclearStackExtension.cc b/Stack/NuclearStackExtension/testNuclearStackExtension.cc index 5185c3538f7b915dd825b8fe1ec98c751903c2a2..c92e5471fdf53e74aa6fdf3e0312e8f0492ae07e 100644 --- a/Stack/NuclearStackExtension/testNuclearStackExtension.cc +++ b/Stack/NuclearStackExtension/testNuclearStackExtension.cc @@ -29,10 +29,11 @@ using namespace corsika::units::si; // this is an auxiliary help typedef, which I don't know how to put // into NuclearStackExtension.h where it belongs... template <typename StackIter> -using ExtendedParticleInterfaceType = stack::nuclear_extension::NuclearParticleInterface< - stack::super_stupid::SuperStupidStack::PIType, StackIter>; +using ExtendedParticleInterfaceType = + corsika::stack::nuclear_extension::NuclearParticleInterface< + corsika::stack::super_stupid::SuperStupidStack::template PIType, StackIter>; -using ExtStack = NuclearStackExtension<stack::super_stupid::SuperStupidStack, +using ExtStack = NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack, ExtendedParticleInterfaceType>; #include <iostream> diff --git a/Stack/SuperStupidStack/CMakeLists.txt b/Stack/SuperStupidStack/CMakeLists.txt index de96527d4a0fb757ac3e79b61ef4ff7481981fa1..d787f0d033ce0977a96c875412685c4dc1f1d38c 100644 --- a/Stack/SuperStupidStack/CMakeLists.txt +++ b/Stack/SuperStupidStack/CMakeLists.txt @@ -38,9 +38,8 @@ add_executable ( target_link_libraries ( testSuperStupidStack -# CORSIKAutls - ProcessStackInspector CORSIKAgeometry + CORSIKAparticles CORSIKAunits CORSIKAthirdparty # for catch2 ) diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h index 1610aede7ec0cad53a8e5e92d14ffba5ce1ab973..0b67b95f184bba24358e10980ededdf1dc86c551 100644 --- a/Stack/SuperStupidStack/SuperStupidStack.h +++ b/Stack/SuperStupidStack/SuperStupidStack.h @@ -39,6 +39,8 @@ namespace corsika::stack { protected: using corsika::stack::ParticleBase<StackIteratorInterface>::GetStack; using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData; + + public: using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex; public: