diff --git a/Processes/CMakeLists.txt b/Processes/CMakeLists.txt index 6afe1cc51acdc689b97a90dec334d727b61c7f60..b54f76d8fd3d16d37de019ffb202015ab15bd663 100644 --- a/Processes/CMakeLists.txt +++ b/Processes/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory (HadronicElasticModel) add_subdirectory (EnergyLoss) add_subdirectory (UrQMD) add_subdirectory (SwitchProcess) +add_subdirectory (ParticleCut) #add_custom_target(CORSIKAprocesses) add_library (CORSIKAprocesses INTERFACE) @@ -23,3 +24,4 @@ add_dependencies(CORSIKAprocesses ProcessStackInspector) add_dependencies(CORSIKAprocesses ProcessTrackingLine) add_dependencies(CORSIKAprocesses ProcessEnergyLoss) add_dependencies(CORSIKAprocesses ProcessUrQMD) +add_dependencies(CORSIKAprocesses ProcessParticleCut) diff --git a/Processes/ParticleCut/CMakeLists.txt b/Processes/ParticleCut/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..48b539b47d273f0c1e359cb3f2d4f68cc07f1ea9 --- /dev/null +++ b/Processes/ParticleCut/CMakeLists.txt @@ -0,0 +1,67 @@ +set ( + MODEL_SOURCES + ParticleCut.cc +) + +set ( + MODEL_HEADERS + ParticleCut.h + ) + +set ( + MODEL_NAMESPACE + corsika/process/particle_cut + ) + +add_library (ProcessParticleCut STATIC ${MODEL_SOURCES}) +CORSIKA_COPY_HEADERS_TO_NAMESPACE (ProcessParticleCut ${MODEL_NAMESPACE} ${MODEL_HEADERS}) + +set_target_properties ( + ProcessParticleCut + PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 1 +# PUBLIC_HEADER "${MODEL_HEADERS}" + ) + +# target dependencies on other libraries (also the header onlys) +target_link_libraries ( + ProcessParticleCut + CORSIKAunits + CORSIKAparticles + CORSIKAsetup + ) + +target_include_directories ( + ProcessParticleCut + INTERFACE + $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include> + $<INSTALL_INTERFACE:include/include> + ) + +install ( + TARGETS ProcessParticleCut + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +# PUBLIC_HEADER DESTINATION include/${MODEL_NAMESPACE} + ) + +# -------------------- +# code unit testing +add_executable (testParticleCut + testParticleCut.cc + ${MODEL_HEADERS} + ) + +target_link_libraries ( + testParticleCut + ProcessParticleCut + CORSIKAunits + CORSIKAstackinterface + CORSIKAprocesssequence + CORSIKAsetup + CORSIKAgeometry + CORSIKAenvironment + CORSIKAthirdparty # for catch2 + ) +CORSIKA_ADD_TEST(testParticleCut) diff --git a/Processes/ParticleCut/ParticleCut.cc b/Processes/ParticleCut/ParticleCut.cc new file mode 100644 index 0000000000000000000000000000000000000000..455a9b8e66ea53e455b797e914ef931d2ff50f47 --- /dev/null +++ b/Processes/ParticleCut/ParticleCut.cc @@ -0,0 +1,156 @@ + +/* + * (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/process/particle_cut/ParticleCut.h> + +using namespace std; + +using namespace corsika; +using namespace corsika::process; +using namespace corsika::units::si; +using namespace corsika::particles; +using namespace corsika::setup; + +namespace corsika::process { + namespace particle_cut { + + template <typename Particle> + bool ParticleCut::ParticleIsBelowEnergyCut(Particle& vP) const { + auto const energyLab = vP.GetEnergy(); + // nuclei + if (vP.GetPID() == particles::Code::Nucleus) { + auto const ElabNuc = energyLab / vP.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. * energyLab * 0.93827_GeV); + if (energyLab < fECut || Ecm < 10_GeV) + return true; + else + return false; + } + } + + bool ParticleCut::ParticleIsEmParticle(Code vCode) const { + bool is_em = false; + // FOR NOW: switch + switch (vCode) { + 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; + } + + bool ParticleCut::ParticleIsInvisible(Code vCode) const { + bool is_inv = false; + // FOR NOW: switch + switch (vCode) { + 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 ParticleCut::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 (ParticleIsEmParticle(pid)) { + cout << "removing em. particle..." << endl; + fEmEnergy += energy; + fEmCount += 1; + p.Delete(); + } else if (ParticleIsInvisible(pid)) { + cout << "removing inv. particle..." << endl; + fInvEnergy += energy; + fInvCount += 1; + p.Delete(); + } else if (ParticleIsBelowEnergyCut(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 ParticleCut::Init() { + fEmEnergy = 0. * 1_GeV; + fEmCount = 0; + fInvEnergy = 0. * 1_GeV; + fInvCount = 0; + fEnergy = 0. * 1_GeV; + // defineEmParticles(); + } + + void ParticleCut::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; + } + } // namespace particle_cut +} // namespace corsika::process diff --git a/Processes/ParticleCut/ParticleCut.h b/Processes/ParticleCut/ParticleCut.h new file mode 100644 index 0000000000000000000000000000000000000000..e715d85c453969da44b3bdd8a72c95933537267d --- /dev/null +++ b/Processes/ParticleCut/ParticleCut.h @@ -0,0 +1,57 @@ +/* + * (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 _corsika_process_particle_cut_ParticleCut_h_ +#define _corsika_process_particle_cut_ParticleCut_h_ + +#include <corsika/particles/ParticleProperties.h> +#include <corsika/process/SecondariesProcess.h> +#include <corsika/units/PhysicalUnits.h> + +using namespace corsika; +using namespace corsika::units; +using namespace corsika::units::si; + +namespace corsika::process { + namespace particle_cut { + class ParticleCut : public process::SecondariesProcess<ParticleCut> { + + HEPEnergyType fECut; + + HEPEnergyType fEnergy = 0_GeV; + HEPEnergyType fEmEnergy = 0_GeV; + int fEmCount = 0; + HEPEnergyType fInvEnergy = 0_GeV; + int fInvCount = 0; + + public: + ParticleCut(const HEPEnergyType vCut) + : fECut(vCut) {} + + bool ParticleIsInvisible(particles::Code) const; + template <typename TSecondaries> + EProcessReturn DoSecondaries(TSecondaries&); + + template <typename Particle> + bool ParticleIsBelowEnergyCut(Particle&) const; + + bool ParticleIsEmParticle(particles::Code) const; + + void Init(); + void ShowResults(); + + HEPEnergyType GetInvEnergy() const { return fInvEnergy; } + HEPEnergyType GetCutEnergy() const { return fEnergy; } + HEPEnergyType GetEmEnergy() const { return fEmEnergy; } + }; + } // namespace particlecut +} // namespace corsika::process + +#endif diff --git a/Processes/ParticleCut/testParticleCut.cc b/Processes/ParticleCut/testParticleCut.cc new file mode 100644 index 0000000000000000000000000000000000000000..f315cb17e98d6a51f9a653ab4a39d976ab685f75 --- /dev/null +++ b/Processes/ParticleCut/testParticleCut.cc @@ -0,0 +1,72 @@ + +/* + * (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/process/particle_cut/ParticleCut.h> + +#include <corsika/environment/Environment.h> +#include <corsika/geometry/Point.h> +#include <corsika/geometry/RootCoordinateSystem.h> +#include <corsika/geometry/Vector.h> +#include <corsika/units/PhysicalUnits.h> +#include <corsika/utl/CorsikaFenv.h> + +#include <corsika/setup/SetupStack.h> + +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one + // cpp file +#include <catch2/catch.hpp> + +using namespace corsika; +using namespace corsika::process::particle_cut; +using namespace corsika::units; +using namespace corsika::units::si; + +TEST_CASE("ParticleCut", "[processes]") { + feenableexcept(FE_INVALID); + using EnvType = environment::Environment<setup::IEnvironmentModel>; + EnvType env; + const geometry::CoordinateSystem& rootCS = env.GetCoordinateSystem(); + SECTION("cut") { + + ParticleCut cut(20_GeV); + + // setup particle stack, and add primary particle + setup::Stack stack; + stack.Clear(); + const HEPEnergyType Eabove = 1_TeV; + const HEPEnergyType Ebelow = 10_GeV; + std::vector<particles::Code> particleList = { + particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus, + particles::Code::KMinus, particles::Code::K0Long, particles::Code::K0Short, + particles::Code::Electron, particles::Code::MuPlus, particles::Code::NuE, + particles::Code::Neutron}; + auto particle = stack.AddParticle( + std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ + particles::Code::Proton, Eabove, + corsika::stack::MomentumVector(rootCS, {0_GeV, 0_GeV, 0_GeV}), + geometry::Point(rootCS, 0_m, 0_m, 0_m), 0_ns}); + + for (auto proType : particleList) + + particle.AddSecondary(std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, + units::si::TimeType>{ + proType, Eabove, corsika::stack::MomentumVector(rootCS, {0_GeV, 0_GeV, 0_GeV}), + geometry::Point(rootCS, 0_m, 0_m, 0_m), 0_ns}); + + // auto secViewPtr = corsika::stack::SecondaryView(particle); + corsika::stack::SecondaryView view(particle); + cut.DoSecondaries(view); + REQUIRE(stack.GetSize() == 1); + + } +}