diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 53f2e7b4ce54b88a9e45df329eb9a7348829330c..2ef93a896e2a7343746c270b20ea6e32834087c8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -249,7 +249,6 @@ test-clang-8: - if: $CI_MERGE_REQUEST_ID when: manual allow_failure: true - allow_failure: true artifacts: when: always expire_in: 3 days @@ -315,7 +314,6 @@ build_test-clang-8: - if: $CI_COMMIT_TAG when: manual allow_failure: true - allow_failure: true artifacts: when: always expire_in: 3 days @@ -373,7 +371,6 @@ build_test_example-clang-8: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_BRANCH when: manual - allow_failure: true cache: paths: - ${CI_PROJECT_DIR}/build/ diff --git a/.gitmodules b/.gitmodules index 5429f2d75f591d52f001615fddde188e8bd012de..9c4be8bab0ad06af04dab930d151388062890e83 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,13 +1,8 @@ [submodule "modules/data"] - path = modules/data - url = ../../AirShowerPhysics/corsika-data.git - branch = master - shallow = true -[submodule "modules/proposal"] - path = modules/proposal - url = https://github.com/tudo-astroparticlephysics/PROPOSAL.git - branch = restructure_parametrization - shallow = true + path = modules/data + url = ../../AirShowerPhysics/corsika-data.git + branch = master + shallow = true [submodule "modules/conex"] path = modules/conex url = ../../AirShowerPhysics/cxroot.git diff --git a/CMakeLists.txt b/CMakeLists.txt index d81de38f705fa7f6b5901a5643e74cb2f5f9ab93..7310df1c8f9af36fe354f22a90bdce58efb49d2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ project ( #+++++++++++++++++++++++++++++ # prevent in-source builds and give warning message # -if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") +if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") message (FATAL_ERROR "In-source builds are disabled. Please create a build-dir and use `cmake <source-dir>` inside it. NOTE: cmake will now create CMakeCache.txt and CMakeFiles/*. @@ -124,7 +124,7 @@ if (CMAKE_BUILD_TYPE STREQUAL Coverage) # compile coverage under -O0 to avoid any optimization, function elimation etc. add_compile_options ("-O0") - + set (GCOV gcov CACHE STRING "gcov executable" FORCE) set (LCOV_BIN_DIR "${PROJECT_SOURCE_DIR}/externals/lcov/bin") # collect coverage data @@ -158,7 +158,7 @@ endif () # CTest config # enable_testing () -if (${CMAKE_VERSION} VERSION_LESS "3.12.0") +if (${CMAKE_VERSION} VERSION_LESS "3.12.0") list (APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") else (${CMAKE_VERSION} VERSION_LESS "3.12.0") set (CTEST_OUTPUT_ON_FAILURE 1) # this is for new versions of cmake @@ -196,18 +196,19 @@ set_target_properties ( INTERFACE_CORSIKA8_MAJOR_VERSION 0 COMPATIBLE_INTERFACE_STRING CORSIKA8_MAJOR_VERSION ) -# +# target_include_directories ( CORSIKA8 INTERFACE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}> $<INSTALL_INTERFACE:include> - ) + ) # since CORSIKA8 is a header only library we must specify all link dependencies here: target_link_libraries ( CORSIKA8 INTERFACE + CONAN_PKG::proposal CONAN_PKG::eigen CONAN_PKG::spdlog CONAN_PKG::boost @@ -234,17 +235,10 @@ add_subdirectory (modules/sibyll) add_subdirectory (modules/qgsjetII) add_subdirectory (modules/urqmd) add_subdirectory (modules/conex) -# -# we really need a better proposal CMakeList.txt file: -set (ADD_PYTHON OFF) -file (READ modules/CMakeLists_PROPOSAL.txt overwrite_CMakeLists_PROPOSAL_txt) -file (WRITE modules/proposal/CMakeLists.txt ${overwrite_CMakeLists_PROPOSAL_txt}) -add_subdirectory (modules/proposal) -target_link_libraries (CORSIKA8 INTERFACE PROPOSAL) #+++++++++++++++++++++++++++++++ # unit testing -# +# add_subdirectory (tests) #+++++++++++++++++++++++++++++++ @@ -298,8 +292,8 @@ configure_package_config_file ( # config for install tree # overwrite with install location (if it was build as part of corsika) -set (Pythia8_INCDIR ${Pythia8_INCDIR_INSTALL}) -set (Pythia8_LIBDIR ${Pythia8_LIBDIR_INSTALL}) +set (Pythia8_INCDIR ${Pythia8_INCDIR_INSTALL}) +set (Pythia8_LIBDIR ${Pythia8_LIBDIR_INSTALL}) configure_package_config_file ( cmake/corsikaConfig.cmake.in ${PROJECT_BINARY_DIR}/cmake/corsikaConfig.cmake diff --git a/conanfile.txt b/conanfile.txt index 78cda273ada5bf3c944cb45f6f22df53d0567a8c..645158b384218cbb653f08842c32ea917c9cb1fc 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -5,7 +5,7 @@ catch2/2.13.3 eigen/3.3.8 boost/1.76.0 zlib/1.2.11 -proposal/7.0.2 +proposal/7.0.4 yaml-cpp/0.6.3 arrow/2.0.0 diff --git a/corsika/detail/modules/proposal/ContinuousProcess.inl b/corsika/detail/modules/proposal/ContinuousProcess.inl index 430d779c6062549b4e44d5142aca15c8dd85886b..91308390ba4f9b5b8e87bb0d94e79646e9a6f101 100644 --- a/corsika/detail/modules/proposal/ContinuousProcess.inl +++ b/corsika/detail/modules/proposal/ContinuousProcess.inl @@ -38,14 +38,19 @@ namespace corsika::proposal { get_mass(code); //! energy thresholds globally defined for individual particles auto c = p_cross->second(media.at(comp.getHash()), emCut); + // Use higland multiple scattering and deactivate stochastic deflection by + // passing an empty vector + static constexpr auto ms_type = PROPOSAL::MultipleScatteringType::Highland; + auto s_type = std::vector<PROPOSAL::InteractionType>(); + // Build displacement integral and scattering object and interpolate them too and // saved in the calc map by a key build out of a hash of composed of the component and // particle code. - auto disp = PROPOSAL::make_displacement(c, true); - auto scatter = - PROPOSAL::make_scattering("highland", particle[code], media.at(comp.getHash())); - calc[std::make_pair(comp.getHash(), code)] = - std::make_tuple(std::move(disp), std::move(scatter)); + auto calculator = + Calculator{PROPOSAL::make_displacement(c, true), + PROPOSAL::make_scattering(ms_type, s_type, particle[code], + media.at(comp.getHash()))}; + calc[std::make_pair(comp.getHash(), code)] = std::move(calculator); } template <> @@ -63,28 +68,25 @@ namespace corsika::proposal { // Cast corsika vector to proposal vector auto vP_dir = vP.getDirection(); auto d = vP_dir.getComponents(); - auto direction = PROPOSAL::Vector3D(d.getX().magnitude(), d.getY().magnitude(), - d.getZ().magnitude()); + auto direction = PROPOSAL::Cartesian3D(d.getX().magnitude(), d.getY().magnitude(), + d.getZ().magnitude()); auto E_f = vP.getEnergy() - loss; // draw random numbers required for scattering process std::uniform_real_distribution<double> distr(0., 1.); - auto rnd = array<double, 4>(); + auto rnd = std::array<double, 4>(); for (auto& it : rnd) it = distr(RNG_); // calculate deflection based on particle energy, loss - auto [mean_dir, final_dir] = get<eSCATTERING>(c->second)->Scatter( - grammage / 1_g * square(1_cm), vP.getEnergy() / 1_MeV, E_f / 1_MeV, direction, - rnd); - - // TODO: neglect mean direction deflection because Trajectory is a const ref - (void)mean_dir; + [[maybe_unused]] auto deflection = (c->second).scatter->CalculateMultipleScattering( + grammage / 1_g * square(1_cm), vP.getEnergy() / 1_MeV, E_f / 1_MeV, rnd); + // TODO: multiple scattering is temporary deactivated !!!!! // update particle direction after continuous loss caused by multiple // scattering - auto vec = QuantityVector(final_dir.GetX() * E_f, final_dir.GetY() * E_f, - final_dir.GetZ() * E_f); + auto vec = QuantityVector(direction.GetX() * E_f, direction.GetY() * E_f, + direction.GetZ() * E_f); vP.setMomentum(MomentumVector(vP_dir.getCoordinateSystem(), vec)); } @@ -103,7 +105,7 @@ namespace corsika::proposal { // get or build corresponding track integral calculator and solve the // integral auto c = getCalculator(vP, calc); - auto final_energy = get<eDISPLACEMENT>(c->second)->UpperLimitTrackIntegral( + auto final_energy = (c->second).disp->UpperLimitTrackIntegral( vP.getEnergy() / 1_MeV, dX / 1_g * 1_cm * 1_cm) * 1_MeV; auto dE = vP.getEnergy() - final_energy; @@ -126,20 +128,20 @@ namespace corsika::proposal { // hyper parameter which must be adjusted. // auto const energy = vP.getEnergy(); - auto const energy_lim = std::max( - energy * 0.9, // either 10% relative loss max., or - get_kinetic_energy_threshold(code) + - get_mass(code) // energy thresholds globally defined for individual particles - * 0.99 // need to go 1% below global e-cut to assure removal in - // ParticleCut. The 1% does not matter since at cut-time the entire - // energy is removed. - ); + auto const energy_lim = + std::max(energy * 0.9, // either 10% relative loss max., or + get_kinetic_energy_threshold( + code) // energy thresholds globally defined for individual particles + * 0.9999 // need to go slightly below global e-cut to assure removal + // in ParticleCut. This does not matter since at cut-time + // the entire energy is removed. + ); // solving the track integral for giving energy lim auto c = getCalculator(vP, calc); - auto grammage = get<eDISPLACEMENT>(c->second)->SolveTrackIntegral( - energy / 1_MeV, energy_lim / 1_MeV) * - 1_g / square(1_cm); + auto grammage = + (c->second).disp->SolveTrackIntegral(energy / 1_MeV, energy_lim / 1_MeV) * 1_g / + square(1_cm); // return it in distance aequivalent auto dist = vP.getNode()->getModelProperties().getArclengthFromGrammage(vT, grammage); diff --git a/corsika/detail/modules/proposal/Interaction.inl b/corsika/detail/modules/proposal/Interaction.inl index 26aa7904c6fce84c33046fe6c2505ab5071b407d..019d31270abeb1da6fe2a99121081363762dcac6 100644 --- a/corsika/detail/modules/proposal/Interaction.inl +++ b/corsika/detail/modules/proposal/Interaction.inl @@ -66,38 +66,41 @@ namespace corsika::proposal { std::uniform_real_distribution<double> distr(0., 1.); // sample a interaction-type, loss and component - auto rates = get<eINTERACTION>(c->second)->Rates(projectile.getEnergy() / 1_MeV); - auto [type, comp_ptr, v] = get<eINTERACTION>(c->second)->SampleLoss( + auto rates = + std::get<eINTERACTION>(c->second)->Rates(projectile.getEnergy() / 1_MeV); + auto [type, target_hash, v] = std::get<eINTERACTION>(c->second)->SampleLoss( projectile.getEnergy() / 1_MeV, rates, distr(RNG_)); // Read how much random numbers are required to calculate the secondaries. // Calculate the secondaries and deploy them on the corsika stack. - auto rnd = - vector<double>(get<eSECONDARIES>(c->second)->RequiredRandomNumbers(type)); + auto rnd = std::vector<double>( + std::get<eSECONDARIES>(c->second)->RequiredRandomNumbers(type)); for (auto& it : rnd) it = distr(RNG_); Point const& place = projectile.getPosition(); CoordinateSystemPtr const& labCS = place.getCoordinateSystem(); - auto point = PROPOSAL::Vector3D(place.getX(labCS) / 1_cm, place.getY(labCS) / 1_cm, - place.getZ(labCS) / 1_cm); + auto point = PROPOSAL::Cartesian3D( + place.getX(labCS) / 1_cm, place.getY(labCS) / 1_cm, place.getZ(labCS) / 1_cm); auto projectile_dir = projectile.getDirection(); auto d = projectile_dir.getComponents(labCS); - auto direction = PROPOSAL::Vector3D(d.getX().magnitude(), d.getY().magnitude(), - d.getZ().magnitude()); - auto loss = make_tuple(static_cast<int>(type), point, direction, - v * projectile.getEnergy() / 1_MeV, 0.); - auto sec = get<eSECONDARIES>(c->second)->CalculateSecondaries( - projectile.getEnergy() / 1_MeV, loss, *comp_ptr, rnd); + auto direction = PROPOSAL::Cartesian3D(d.getX().magnitude(), d.getY().magnitude(), + d.getZ().magnitude()); + + auto loss = PROPOSAL::StochasticLoss( + static_cast<int>(type), v * projectile.getEnergy() / 1_MeV, point, direction, + projectile.getTime() / 1_s, 0., projectile.getEnergy() / 1_MeV); + auto target = PROPOSAL::Component::component_map->operator[](target_hash); + auto sec = + std::get<eSECONDARIES>(c->second)->CalculateSecondaries(loss, target, rnd); for (auto& s : sec) { - auto E = get<PROPOSAL::Loss::ENERGY>(s) * 1_MeV; - auto vecProposal = get<PROPOSAL::Loss::DIRECTION>(s); + auto E = s.energy * 1_MeV; + auto vecProposal = s.direction; auto vec = QuantityVector(vecProposal.GetX() * E, vecProposal.GetY() * E, vecProposal.GetZ() * E); auto p = MomentumVector(labCS, vec); - auto sec_code = - convert_from_PDG(static_cast<PDGCode>(get<PROPOSAL::Loss::TYPE>(s))); + auto sec_code = convert_from_PDG(static_cast<PDGCode>(s.type)); view.addSecondary( - make_tuple(sec_code, p, projectile.getPosition(), projectile.getTime())); + std::make_tuple(sec_code, p, projectile.getPosition(), projectile.getTime())); } } return ProcessReturn::Ok; @@ -109,7 +112,8 @@ namespace corsika::proposal { if (canInteract(projectile.getPID())) { auto c = getCalculator(projectile, calc); - return get<eINTERACTION>(c->second)->MeanFreePath(projectile.getEnergy() / 1_MeV) * + return std::get<eINTERACTION>(c->second)->MeanFreePath(projectile.getEnergy() / + 1_MeV) * 1_g / (1_cm * 1_cm); } return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm); diff --git a/corsika/detail/modules/proposal/ProposalProcessBase.inl b/corsika/detail/modules/proposal/ProposalProcessBase.inl index 992d24e4d5feefc081ca658e6fd270c534ee5d25..7b07100888bbdb8c7ecd63fdbbc57bdc7668dd4b 100644 --- a/corsika/detail/modules/proposal/ProposalProcessBase.inl +++ b/corsika/detail/modules/proposal/ProposalProcessBase.inl @@ -38,7 +38,7 @@ namespace corsika::proposal { const auto& medium = mediumData( prop.getMedium(Point(_env.getCoordinateSystem(), 0_cm, 0_cm, 0_cm))); - auto comp_vec = std::vector<PROPOSAL::Components::Component>(); + auto comp_vec = std::vector<PROPOSAL::Component>(); const auto& comp = prop.getNuclearComposition(); auto frac_iter = comp.getFractions().cbegin(); for (auto& pcode : comp.getComponents()) { @@ -54,15 +54,11 @@ namespace corsika::proposal { } }); - PROPOSAL::InterpolationDef::order_of_interpolation = 2; - PROPOSAL::InterpolationDef::nodes_cross_section = 100; - PROPOSAL::InterpolationDef::nodes_propagate = 1000; - //! If corsika data exist store interpolation tables to the corresponding //! path, otherwise interpolation tables would only stored in main memory if //! no explicit intrpolation def is specified. if (auto data_path = std::getenv("CORSIKA_DATA")) { - PROPOSAL::InterpolationDef::path_to_tables = std::string(data_path) + "/PROPOSAL"; + PROPOSAL::InterpolationSettings::TABLES_PATH = std::string(data_path) + "/PROPOSAL"; } else { throw std::runtime_error( "It is not recommended to run PROPOSAL without its tables in " diff --git a/corsika/detail/modules/pythia8/Decay.inl b/corsika/detail/modules/pythia8/Decay.inl index 27fd2a31f43290a26e6c7807f22d29b3debf7e37..163ec37a7864fdd2b2c85022aaafce73e73d6739 100644 --- a/corsika/detail/modules/pythia8/Decay.inl +++ b/corsika/detail/modules/pythia8/Decay.inl @@ -62,8 +62,10 @@ namespace corsika::pythia8 { // Pythia8::Pythia::particleData.readString("59:m0 = 101.00"); + // LCOV_EXCL_START, we don't validate pythia8 internals if (!Pythia8::Pythia::init()) throw std::runtime_error("Pythia::Decay: Initialization failed!"); + // LCOV_EXCL_STOP } inline bool Decay::canHandleDecay(Code const vParticleCode) { @@ -74,7 +76,7 @@ namespace corsika::pythia8 { vParticleCode == Code::NuMuBar || vParticleCode == Code::NuTauBar || vParticleCode == Code::Electron || vParticleCode == Code::Positron) return false; - else if (canDecay(vParticleCode)) // non-zero for particles known to sibyll + else if (canDecay(vParticleCode)) // check pythia8 internal return true; else return false; @@ -207,15 +209,19 @@ namespace corsika::pythia8 { event.append(pdgCode, 1, 0, 0, // PID, status, col, acol px, py, pz, en, m); + // LCOV_EXCL_START, we don't validate pythia8 internals if (!Pythia8::Pythia::next()) throw std::runtime_error("Pythia::Decay: decay failed!"); - else - CORSIKA_LOG_DEBUG("Pythia::Decay: particles after decay: {} ", event.size()); + // LCOV_EXCL_STOP + + CORSIKA_LOG_DEBUG("Pythia::Decay: particles after decay: {} ", event.size()); + // LCOV_EXCL_START, we don't validate pythia8 internals if (print_listing_) { // list final state event.list(); } + // LCOV_EXCL_STOP // loop over final state for (int i = 0; i < event.size(); ++i) diff --git a/corsika/detail/modules/pythia8/Interaction.inl b/corsika/detail/modules/pythia8/Interaction.inl index 4f288918b4215eba6925c2ca70ea6160892628c2..74a910de769ff259aeafacc46e9b2d74d02e32e5 100644 --- a/corsika/detail/modules/pythia8/Interaction.inl +++ b/corsika/detail/modules/pythia8/Interaction.inl @@ -45,8 +45,10 @@ namespace corsika::pythia8 { Pythia8::Pythia::readString("HardQCD:all = on"); Pythia8::Pythia::readString("ProcessLevel:resonanceDecays = off"); + // we can't test this block, LCOV_EXCL_START if (!Pythia8::Pythia::init()) throw std::runtime_error("Pythia::Interaction: Initialization failed!"); + // LCOV_EXCL_STOP // any decays in pythia? if yes need to define which particles if (internalDecays_) { @@ -110,8 +112,10 @@ namespace corsika::pythia8 { Pythia8::Pythia::readString("Beams:eB = 0."); // initialize this config + // we can't test this block, LCOV_EXCL_START if (!Pythia8::Pythia::init()) throw std::runtime_error("Pythia::Interaction: Initialization failed!"); + // LCOV_EXCL_STOP } inline bool Interaction::canInteract(Code const pCode) { @@ -137,9 +141,11 @@ namespace corsika::pythia8 { return std::make_tuple(sigProd * (1_fm * 1_fm), sigEla * (1_fm * 1_fm)); - } else + } else { + // we can't test pythia8 internals, LCOV_EXCL_START throw std::runtime_error("pythia cross section init failed"); - + // we can't test pythia8 internals, LCOV_EXCL_STOP + } } else { return std::make_tuple(std::numeric_limits<double>::infinity() * 1_mb, std::numeric_limits<double>::infinity() * 1_mb); @@ -341,17 +347,20 @@ namespace corsika::pythia8 { configureLabFrameCollision(corsikaBeamId, corsikaTargetId, eProjectileLab); - // create event in pytia + // create event in pytia. LCOV_EXCL_START: we don't validate pythia8 internals if (!Pythia8::Pythia::next()) throw std::runtime_error("Pythia::DoInteraction: failed!"); + // LCOV_EXCL_STOP // link to pythia stack Pythia8::Event& event = Pythia8::Pythia::event; + // LCOV_EXCL_START, we don't validate pythia8 internals if (print_listing_) { // print final state event.list(); } + // LCOV_EXCL_STOP MomentumVector Plab_final(labCS, {0.0_GeV, 0.0_GeV, 0.0_GeV}); HEPEnergyType Elab_final = 0_GeV; diff --git a/corsika/detail/modules/sibyll/Interaction.inl b/corsika/detail/modules/sibyll/Interaction.inl index 78b237e9484aa3b76dc9395f3bbfe8b24fe1ba40..bbcacf4e5e7e90fca3fa5a21a0aa639848ccdc3c 100644 --- a/corsika/detail/modules/sibyll/Interaction.inl +++ b/corsika/detail/modules/sibyll/Interaction.inl @@ -81,8 +81,9 @@ namespace corsika::sibyll { BeamId); // 0 (can not interact, 1: proton-like, 2: pion-like, 3:kaon-like) if (!iBeam) throw std::runtime_error( - "Interaction: getCrossSection: interaction of beam hadron not defined in " - "Sibyll!"); + fmt::format("Interaction of beam {} not defined in " + "Sibyll!", + BeamId)); if (!isValidCoMEnergy(CoMenergy)) { throw std::runtime_error( "Interaction: getCrossSection: CoM energy outside range for Sibyll!"); diff --git a/corsika/modules/proposal/ContinuousProcess.hpp b/corsika/modules/proposal/ContinuousProcess.hpp index c8895c8aa752bcd3a3630d4876ace48578d232f3..bf421186c1e68c2522060f601fbc5116bfc2bc7b 100644 --- a/corsika/modules/proposal/ContinuousProcess.hpp +++ b/corsika/modules/proposal/ContinuousProcess.hpp @@ -14,6 +14,7 @@ #include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/process/ContinuousProcess.hpp> +#include <corsika/framework/process/ProcessReturn.hpp> #include <corsika/framework/random/RNGManager.hpp> #include <corsika/framework/random/UniformRealDistribution.hpp> @@ -32,11 +33,12 @@ namespace corsika::proposal { : public corsika::ContinuousProcess<proposal::ContinuousProcess>, ProposalProcessBase { - enum { eDISPLACEMENT, eSCATTERING }; - using calc_t = std::tuple<std::unique_ptr<PROPOSAL::Displacement>, - std::unique_ptr<PROPOSAL::Scattering>>; + struct Calculator { + std::unique_ptr<PROPOSAL::Displacement> disp; + std::unique_ptr<PROPOSAL::Scattering> scatter; + }; - std::unordered_map<calc_key_t, calc_t, hash> + std::unordered_map<calc_key_t, Calculator, hash> calc; //!< Stores the displacement and scattering calculators. HEPEnergyType energy_lost_ = 0 * electronvolt; diff --git a/corsika/modules/proposal/Interaction.hpp b/corsika/modules/proposal/Interaction.hpp index b492862f0b091aea23251ba449821caa4a8faf54..80a8a7864247e2bc798db5564aa8506869ce1525 100644 --- a/corsika/modules/proposal/Interaction.hpp +++ b/corsika/modules/proposal/Interaction.hpp @@ -12,6 +12,7 @@ #include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/process/InteractionProcess.hpp> +#include <corsika/framework/process/ProcessReturn.hpp> #include <corsika/framework/random/RNGManager.hpp> #include <corsika/framework/random/UniformRealDistribution.hpp> @@ -31,8 +32,8 @@ namespace corsika::proposal { class Interaction : public InteractionProcess<Interaction>, ProposalProcessBase { enum { eSECONDARIES, eINTERACTION }; - using calculator_t = tuple<unique_ptr<PROPOSAL::SecondariesCalculator>, - unique_ptr<PROPOSAL::Interaction>>; + using calculator_t = std::tuple<std::unique_ptr<PROPOSAL::SecondariesCalculator>, + std::unique_ptr<PROPOSAL::Interaction>>; std::unordered_map<calc_key_t, calculator_t, hash> calc; //!< Stores the secondaries and interaction calculators. diff --git a/corsika/modules/proposal/ProposalProcessBase.hpp b/corsika/modules/proposal/ProposalProcessBase.hpp index bb9e3b721c84d57fcaa8956042fbea99a221d91f..3edb90720f2346161f062c45ec79b8f9de85c639 100644 --- a/corsika/modules/proposal/ProposalProcessBase.hpp +++ b/corsika/modules/proposal/ProposalProcessBase.hpp @@ -48,19 +48,16 @@ namespace corsika::proposal { corsika::units::si::HEPEnergyType emCut) { //!< Stochastic losses smaller than the given cut //!< will be handeled continuously. - using namespace corsika::units::si; - auto p_cut = - std::make_shared<const PROPOSAL::EnergyCutSettings>(emCut / 1_MeV, 1, true); - return PROPOSAL::DefaultCrossSections<T>::template Get<std::false_type>( - T(), m, p_cut, true); + auto p_cut = std::make_shared<const PROPOSAL::EnergyCutSettings>( + 0.5 * emCut / 1_MeV, 1, false); + return PROPOSAL::GetStdCrossSections(T(), m, p_cut, true); }; //! //! PROPOSAL default crosssections are maped to corresponding corsika particle //! code. //! - static std::map<Code, std::function<PROPOSAL::crosssection_list_t<PROPOSAL::ParticleDef, - PROPOSAL::Medium>( + static std::map<Code, std::function<PROPOSAL::crosssection_list_t( PROPOSAL::Medium&, corsika::units::si::HEPEnergyType)>> cross = {{Code::Photon, cross_builder<PROPOSAL::GammaDef>}, {Code::Electron, cross_builder<PROPOSAL::EMinusDef>}, diff --git a/examples/vertical_EAS.cpp b/examples/vertical_EAS.cpp index a8916b55e67a245f7aac1f01cdf8d3a3c3a81689..21354adcfc31d8fec2ec28381a7aeb4ceb39e39e 100644 --- a/examples/vertical_EAS.cpp +++ b/examples/vertical_EAS.cpp @@ -160,7 +160,7 @@ int main(int argc, char** argv) { mass = get_mass(beamCode); } HEPEnergyType const E0 = 1_GeV * std::stof(std::string(argv[3])); - double theta = 20.; + double theta = 0.; double phi = 180.; auto const thetaRad = theta / 180. * M_PI; auto const phiRad = phi / 180. * M_PI; @@ -396,9 +396,10 @@ int main(int argc, char** argv) { // register the observation plane with the output output.add("particles", observationLevel); - auto sequence = - make_sequence(stackInspect, hadronSequence, reset_particle_mass, decaySequence, - emContinuous, cut, trackWriter, observationLevel, longprof); + auto sequence = make_sequence( // emCascadeCounted, + stackInspect, hadronSequence, reset_particle_mass, decaySequence, + // emContinuous, + BetheBlochPDG(showerAxis), cut, trackWriter, observationLevel, longprof); // define air shower object, run simulation setup::Tracking tracking; diff --git a/modules/CMakeLists_PROPOSAL.txt b/modules/CMakeLists_PROPOSAL.txt deleted file mode 100644 index c487b17cdb880e772e0ac7ccc723f1133fdf71f9..0000000000000000000000000000000000000000 --- a/modules/CMakeLists_PROPOSAL.txt +++ /dev/null @@ -1,215 +0,0 @@ -if(CMAKE_PROJECT_NAME STREQUAL corsika) - message(STATUS "Including PROPOSAL as part of CORSIKA8") - set (IN_CORSIKA8 ON) -else(CMAKE_PROJECT_NAME STREQUAL corsika) - set (IN_CORSIKA8 OFF) - - cmake_minimum_required(VERSION 3.8) - project(PROPOSAL VERSION 6.1.2 LANGUAGES CXX) - -endif(CMAKE_PROJECT_NAME STREQUAL corsika) - -project(PROPOSAL VERSION 6.1.2 LANGUAGES CXX) - -if (NOT IN_CORSIKA8) -IF(APPLE) - # In newer version of cmake this will be the default - SET(CMAKE_MACOSX_RPATH 1) -ENDIF(APPLE) - -# sets standard installtion paths -include(GNUInstallDirs) - -### full RPATH -### copied from https://cmake.org/Wiki/CMake_RPATH_handling -### set the RPATH so that for using PROPOSAL in python -### the DYLD_LIBRARY_PATH must not be set in the bashrc -### But for using PROPOSAL as c-Library, this path still -### has to be set - -# use, i.e. don't skip the full RPATH for the build tree -SET(CMAKE_SKIP_BUILD_RPATH FALSE) - -# when building, don't use the install RPATH already -# (but later on when installing) -OPTION(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -list(APPEND CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/lib64") -message(STATUS "CMAKE_INSTALL_RPATH=${CMAKE_INSTALL_RPATH}") - -# add the automatically determined parts of the RPATH -# which point to directories outside the build tree to the install RPATH -OPTION(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -### end full RPATH - -# Some additional options -OPTION(ADD_PYTHON "Choose to compile the python wrapper library" ON) -endif (NOT IN_CORSIKA8) - -################################################################# -#################### PROPOSAL ######################## -################################################################# -file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/src/PROPOSAL/*) -if (IN_CORSIKA8) - add_library(PROPOSAL STATIC ${SRC_FILES}) -else (IN_CORSIKA8) - add_library(PROPOSAL SHARED ${SRC_FILES}) -endif (IN_CORSIKA8) - -add_library(PROPOSAL::PROPOSAL ALIAS PROPOSAL) -#target_compile_features(PROPOSAL PUBLIC cxx_std_11) -#set_target_properties(PROPOSAL PROPERTIES CXX_EXTENSIONS OFF) -target_include_directories( - PROPOSAL PUBLIC - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> - $<INSTALL_INTERFACE:include> -) -target_compile_options(PROPOSAL PRIVATE -Wall -Wextra -Wnarrowing -Wpedantic -fdiagnostics-show-option -Wno-format-security) -if (NOT IN_CORSIKA8) -install( - TARGETS PROPOSAL - EXPORT PROPOSALTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) -else (NOT IN_CORSIKA8) -install( - TARGETS PROPOSAL - EXPORT CORSIKA8PublicTargets - LIBRARY DESTINATION lib/corsika - ARCHIVE DESTINATION lib/corsika -) -endif (NOT IN_CORSIKA8) - -# input version from the project call, so the library knows its own version -configure_file( - "${PROJECT_SOURCE_DIR}/include/PROPOSAL/version.h.in" - "${PROJECT_BINARY_DIR}/include/PROPOSAL/version.h" -) -if (NOT IN_CORSIKA8) -install( - FILES ${PROJECT_BINARY_DIR}/include/PROPOSAL/version.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/include/PROPOSAL -) -target_include_directories( - PROPOSAL PUBLIC - $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include> - $<INSTALL_INTERFACE:include> -) -else (NOT IN_CORSIKA8) -install( - FILES ${PROJECT_BINARY_DIR}/include/PROPOSAL/version.h - DESTINATION include/corsika_modules/PROPOSAL -) -target_include_directories( - PROPOSAL PUBLIC - $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include> - $<INSTALL_INTERFACE:include/corsika_modules> -) -endif (NOT IN_CORSIKA8) - -# install header files -file(GLOB_RECURSE INC_FILES ${PROJECT_SOURCE_DIR}/include/*) -if (NOT IN_CORSIKA8) -foreach(INC_FILE ${INC_FILES}) - file(RELATIVE_PATH REL_FILE ${PROJECT_SOURCE_DIR}/include ${INC_FILE}) - get_filename_component(DIR ${REL_FILE} DIRECTORY) - install(FILES include/${REL_FILE} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${DIR}) -endforeach() -else (NOT IN_CORSIKA8) -foreach(INC_FILE ${INC_FILES}) - file(RELATIVE_PATH REL_FILE ${PROJECT_SOURCE_DIR}/include/ ${INC_FILE}) - get_filename_component(DIR ${REL_FILE} DIRECTORY) - install(FILES include/${REL_FILE} DESTINATION include/corsika_modules/${DIR}) -endforeach() -endif (NOT IN_CORSIKA8) - - -if(NOT IS_SYMLINK ${CMAKE_BINARY_DIR}/resources) - execute_process(COMMAND ln -sv ${CMAKE_CURRENT_SOURCE_DIR}/resources ${CMAKE_BINARY_DIR}/resources OUTPUT_VARIABLE link_msg OUTPUT_STRIP_TRAILING_WHITESPACE) - message(STATUS "Symlink to resources created:") - message(STATUS " ${link_msg}") -endif() - - -################################################################# -################# spdlog ####################### -################################################################# - -if (NOT IN_CORSIKA8) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -add_subdirectory("vendor/spdlog") -target_link_libraries(PROPOSAL PRIVATE spdlog::spdlog) -else (NOT IN_CORSIKA8) -target_link_libraries(PROPOSAL PRIVATE CONAN_PKG::spdlog) -endif (NOT IN_CORSIKA8) - - -################################################################# -################# Tests ######################## -################################################################# - -if (NOT IN_CORSIKA8) -if(CMAKE_PROJECT_NAME STREQUAL PROPOSAL) - include(CTest) -endif() -if(CMAKE_PROJECT_NAME STREQUAL PROPOSAL AND BUILD_TESTING) - add_subdirectory(tests) -else() - MESSAGE(STATUS "No tests will be build.") -endif() -endif (NOT IN_CORSIKA8) - -################################################################# -################# Documentation ######################## -################################################################# -if (NOT IN_CORSIKA8) -add_subdirectory(doc) -endif (NOT IN_CORSIKA8) - - -################################################################# -################# python ######################### -################################################################# -if (NOT IN_CORSIKA8) -IF(ADD_PYTHON) - message(STATUS "Building the python wrapper library.") - find_package(PythonLibs REQUIRED) - add_subdirectory("vendor/pybind11") - file(GLOB_RECURSE PYTHON_SRC_FILES ${PROJECT_SOURCE_DIR}/interface/python/*) - - pybind11_add_module(pyproposal SHARED ${PYTHON_SRC_FILES}) - set_target_properties(pyproposal PROPERTIES OUTPUT_NAME proposal) - target_include_directories(pyproposal PRIVATE ${PYTHON_INCLUDE_DIRS}) - target_include_directories(pyproposal PRIVATE ${PROJECT_SOURCE_DIR}/interface/python) - target_link_libraries(pyproposal PRIVATE PROPOSAL) - target_compile_options(pyproposal PRIVATE -fvisibility=hidden) - install(TARGETS pyproposal EXPORT PROPOSALTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}) -ELSE(ADD_PYTHON) - MESSAGE(STATUS "No python wrapper library will be build.") -ENDIF(ADD_PYTHON) -endif (NOT IN_CORSIKA8) - - - -################################################################# -################# INSTALLATION ################### -################################################################# -if (NOT IN_CORSIKA8) -install( - EXPORT PROPOSALTargets - FILE PROPOSALConfig.cmake - NAMESPACE PROPOSAL:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/PROPOSAL -) - -include(CMakePackageConfigHelpers) -write_basic_package_version_file( - "PROPOSALConfigVersion.cmake" - VERSION ${PACKAGE_VERSION} - COMPATIBILITY SameMajorVersion -) -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/PROPOSALConfigVersion.cmake" - DESTINATION lib/cmake/PROPOSAL -) -endif (NOT IN_CORSIKA8) diff --git a/modules/proposal b/modules/proposal deleted file mode 160000 index 92b9b9ca20826725cb805d135a1a5d5b29a7e06a..0000000000000000000000000000000000000000 --- a/modules/proposal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 92b9b9ca20826725cb805d135a1a5d5b29a7e06a diff --git a/tests/modules/testPythia8.cpp b/tests/modules/testPythia8.cpp index b2d683a88bbcff787753d434f46b4cc601657ab1..846c734877badaaa8cbb508f30da1716ed24b78d 100644 --- a/tests/modules/testPythia8.cpp +++ b/tests/modules/testPythia8.cpp @@ -20,7 +20,7 @@ using namespace corsika; -TEST_CASE("Pythia", "[processes]") { +TEST_CASE("Pythia8", "modules") { logging::set_level(logging::level::info); @@ -64,7 +64,7 @@ TEST_CASE("Pythia", "[processes]") { std::set<Code> const particleList = {Code::PiPlus, Code::PiMinus, Code::KPlus, Code::KMinus, Code::K0Long, Code::K0Short}; RNGManager::getInstance().registerRandomStream("pythia"); - corsika::pythia8::Decay model(particleList); + corsika::pythia8::Decay decay(particleList); } } @@ -91,10 +91,9 @@ auto sumMomentum(TStackView const& view, CoordinateSystemPtr const& vCS) { return sum; } -TEST_CASE("PythiaInterface", "[processes]") { +TEST_CASE("Pythia8Interface", "modules") { logging::set_level(logging::level::info); - auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Proton); auto const& cs = *csPtr; [[maybe_unused]] auto const& env_dummy = env; @@ -115,14 +114,12 @@ TEST_CASE("PythiaInterface", "[processes]") { RNGManager::getInstance().registerRandomStream("pythia"); - corsika::pythia8::Decay model(particleList); + corsika::pythia8::Decay decay(particleList); - CORSIKA_LOG_INFO("stack: {} {}", stack.asString(), particle.asString()); - [[maybe_unused]] const TimeType time = model.getLifetime(particle); + [[maybe_unused]] const TimeType time = decay.getLifetime(particle); double const gamma = particle.getEnergy() / get_mass(Code::PiPlus); CHECK(time == get_lifetime(Code::PiPlus) * gamma); - model.doDecay(*secViewPtr); - CORSIKA_LOG_INFO("piplus->{}", stack.asString()); + decay.doDecay(*secViewPtr); CHECK(stack.getEntries() == 3); // piplus, muplu, numu auto const pSum = sumMomentum(view, cs); CHECK((pSum - plab).getNorm() / 1_GeV == Approx(0).margin(1e-4)); @@ -130,26 +127,33 @@ TEST_CASE("PythiaInterface", "[processes]") { } SECTION("pythia decay config") { - corsika::pythia8::Decay model({Code::PiPlus, Code::PiMinus}); - CHECK(model.isDecayHandled(Code::PiPlus)); - CHECK(model.isDecayHandled(Code::PiMinus)); - CHECK_FALSE(model.isDecayHandled(Code::KPlus)); + corsika::pythia8::Decay decay({Code::PiPlus, Code::PiMinus}); + CHECK(decay.isDecayHandled(Code::PiPlus)); + CHECK(decay.isDecayHandled(Code::PiMinus)); + CHECK_FALSE(decay.isDecayHandled(Code::KPlus)); const std::vector<Code> particleTestList = {Code::PiPlus, Code::PiMinus, Code::KPlus, Code::Lambda0Bar, Code::D0Bar}; // setup decays - model.setHandleDecay(particleTestList); - for (auto& pCode : particleTestList) CHECK(model.isDecayHandled(pCode)); + decay.setHandleDecay(particleTestList); + for (auto& pCode : particleTestList) CHECK(decay.isDecayHandled(pCode)); // individually - model.setHandleDecay(Code::KMinus); + decay.setHandleDecay(Code::KMinus); + + // impossible + CHECK_THROWS(decay.setHandleDecay(Code::Photon)); + + CHECK(decay.isDecayHandled(Code::PiPlus)); + CHECK_FALSE(decay.isDecayHandled(Code::Photon)); // possible decays - CHECK_FALSE(model.canHandleDecay(Code::Proton)); - CHECK_FALSE(model.canHandleDecay(Code::Electron)); - CHECK(model.canHandleDecay(Code::PiPlus)); - CHECK(model.canHandleDecay(Code::MuPlus)); + CHECK_FALSE(decay.canHandleDecay(Code::Photon)); + CHECK_FALSE(decay.canHandleDecay(Code::Proton)); + CHECK_FALSE(decay.canHandleDecay(Code::Electron)); + CHECK(decay.canHandleDecay(Code::PiPlus)); + CHECK(decay.canHandleDecay(Code::MuPlus)); } SECTION("pythia interaction") { @@ -161,10 +165,81 @@ TEST_CASE("PythiaInterface", "[processes]") { auto& view = *secViewPtr; auto particle = stackPtr->first(); - corsika::pythia8::Interaction model; - model.doInteraction(view); - [[maybe_unused]] const GrammageType length = model.getInteractionLength(particle); + corsika::pythia8::Interaction collision; + + CHECK(collision.canInteract(Code::Proton)); + CHECK(collision.canInteract(Code::AntiProton)); + CHECK(collision.canInteract(Code::Neutron)); + CHECK(collision.canInteract(Code::AntiNeutron)); + CHECK(collision.canInteract(Code::PiMinus)); + CHECK(collision.canInteract(Code::PiPlus)); + CHECK_FALSE(collision.canInteract(Code::Electron)); + + // nuclei not supported + CHECK_THROWS(collision.getCrossSection(Code::Proton, Code::Helium, 1_TeV)); + std::tuple<CrossSectionType, CrossSectionType> xs_test = + collision.getCrossSection(Code::Iron, Code::Hydrogen, 1_GeV); + CHECK(std::get<0>(xs_test) == std::numeric_limits<double>::infinity() * 1_mb); + CHECK(std::get<1>(xs_test) == std::numeric_limits<double>::infinity() * 1_mb); + + collision.getInteractionLength(particle); + + collision.doInteraction(view); + [[maybe_unused]] const GrammageType length = collision.getInteractionLength(particle); CHECK(length / 1_kg * square(1_m) == Approx(43.04).margin(5e-1)); CHECK(view.getSize() == 38); } + + SECTION("pythia nucleus projectile") { + + // this is a projectile nucleus with very little energy + auto [stackPtr, secViewPtr] = setup::testing::setup_stack( + Code::Oxygen, 0, 0, 17_GeV, (setup::Environment::BaseNodeType* const)nodePtr, + *csPtr); + auto& view = *secViewPtr; + auto particle = stackPtr->first(); + + corsika::pythia8::Interaction collision; + + GrammageType lambda_test = collision.getInteractionLength(particle); + CHECK(lambda_test == std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm)); + + CHECK_THROWS(collision.doInteraction(view)); + } + + SECTION("pythia too low energy") { + + // this is a projectile neutron with very little energy + auto [stackPtr, secViewPtr] = setup::testing::setup_stack( + Code::Neutron, 0, 0, 1_GeV, (setup::Environment::BaseNodeType* const)nodePtr, + *csPtr); + auto& view = *secViewPtr; + auto particle = stackPtr->first(); + + corsika::pythia8::Interaction collision; + + GrammageType lambda_test = collision.getInteractionLength(particle); + CHECK(lambda_test == std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm)); + + CHECK_THROWS(collision.doInteraction(view)); + } + + SECTION("pythia wrong target") { + + // incompatible target + auto [env_Fe, csPtr_Fe, nodePtr_Fe] = setup::testing::setup_environment(Code::Iron); + [[maybe_unused]] auto const& cs_Fe = *csPtr_Fe; + [[maybe_unused]] auto const& env_dummy_Fe = env_Fe; + [[maybe_unused]] auto const& node_dummy_Fe = nodePtr_Fe; + + // resonable projectile, but tool low energy + auto [stackPtr, secViewPtr] = setup::testing::setup_stack( + Code::Proton, 0, 0, 1_GeV, (setup::Environment::BaseNodeType* const)nodePtr_Fe, + *csPtr_Fe); + auto& view = *secViewPtr; + + corsika::pythia8::Interaction collision; + + CHECK_THROWS(collision.doInteraction(view)); + } }