-
Maximilian Reininghaus authoredMaximilian Reininghaus authored
testFluka.cpp 7.53 KiB
/*
* (c) Copyright 2023 CORSIKA Project, corsika-project@lists.kit.edu
*
* 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/modules/FLUKA.hpp>
#include <corsika/modules/fluka/Random.hpp>
#include <corsika/framework/core/EnergyMomentumOperations.hpp>
#include <corsika/framework/geometry/Point.hpp>
#include <corsika/framework/geometry/FourVector.hpp>
#include <corsika/framework/geometry/CoordinateSystem.hpp>
#include <corsika/media/Environment.hpp>
#include <corsika/media/IMediumModel.hpp>
#include <corsika/media/HomogeneousMedium.hpp>
#include <catch2/catch.hpp>
#include <fstream>
#include <iomanip>
#include <SetupTestStack.hpp>
#include <SetupTestEnvironment.hpp>
using namespace corsika;
template <typename TStackView>
auto sumMomentum(TStackView const& view, CoordinateSystemPtr const& vCS) {
MomentumVector sum{vCS, 0_eV, 0_eV, 0_eV};
for (auto const& p : view) { sum += p.getMomentum(); }
return sum;
}
TEST_CASE("FLUKACodeConversion") {
REQUIRE(corsika::fluka::convertToFluka(Code::PiPlus) ==
corsika::fluka::FLUKACode::PiPlus);
REQUIRE(corsika::fluka::convertToFlukaRaw(Code::PiPlus) == 13);
REQUIRE(corsika::fluka::convertToFlukaRaw(Code::Proton) == 1);
REQUIRE(corsika::fluka::convertToFlukaRaw(Code::Lambda0) == 17);
REQUIRE_THROWS(corsika::fluka::convertToFluka(Code::WPlus));
}
auto setupEnvironment() {
using DummyEnvironmentInterface =
IMediumPropertyModel<IMagneticFieldModel<IMediumModel>>;
using DummyEnvironment = Environment<DummyEnvironmentInterface>;
using MyHomogeneousModel = MediumPropertyModel<
UniformMagneticField<HomogeneousMedium<DummyEnvironmentInterface>>>;
RNGManager<>::getInstance().registerRandomStream("fluka");
DummyEnvironment env;
auto& universe = *env.getUniverse();
CoordinateSystemPtr const& cs = env.getCoordinateSystem();
universe.setModelProperties<MyHomogeneousModel>(
Medium::AirDry1Atm, Vector(cs, 0_T, 0_T, 0_T), 1_kg / (1_m * 1_m * 1_m),
NuclearComposition{
std::vector<Code>{Code::Hydrogen, Code::Oxygen, Code::Nitrogen, Code::Argon},
std::vector<double>{.25, .25, .25, .25}});
return env;
}
static auto const env = setupEnvironment();
static corsika::fluka::InteractionModel flukaModel{env};
static auto const& cs = env.getCoordinateSystem();
TEST_CASE("FLUKA") {
//~ auto tup = setupFluka();
//~ corsika::fluka::InteractionModel& flukaModel = std::get<0>(tup);
//~ auto const env = std::get<1>(tup);
SECTION("getMaterialIndex") {
REQUIRE(flukaModel.getMaterialIndex(Code::Hydrogen) > 0);
REQUIRE(flukaModel.getMaterialIndex(Code::Oxygen) > 0);
REQUIRE(flukaModel.getMaterialIndex(Code::Nitrogen) > 0);
REQUIRE(flukaModel.getMaterialIndex(Code::Argon) > 0);
// not initialized
REQUIRE(flukaModel.getMaterialIndex(Code::Uranium) < 0);
}
SECTION("getCrossSection") {
auto const projectileCode = GENERATE(
Code::PiMinus, Code::PiMinus, Code::PiMinus, Code::KMinus, Code::K0Long,
Code::K0Short, Code::Lambda0, Code::SigmaPlus, Code::Proton, Code::AntiProton,
Code::KMinus, Code::K0Long, Code::K0Short, Code::Lambda0, Code::SigmaPlus,
Code::Proton, Code::AntiProton, Code::Photon);
auto const targetCode = GENERATE(Code::Oxygen, Code::Hydrogen);
HEPEnergyType const p = 100_GeV;
auto const projectile4mom =
FourVector{calculate_total_energy(p, get_mass(projectileCode)),
MomentumVector{cs, 0_eV, 0_eV, p}};
auto const target4mom =
FourVector{get_mass(targetCode), MomentumVector{cs, 0_eV, 0_eV, 0_eV}};
CHECK(flukaModel.getCrossSection(projectileCode, targetCode, projectile4mom,
target4mom) > 0_mb);
}
SECTION("getCrossSection invalid") {
auto const projectileCode = Code::Electron;
auto const targetCode = GENERATE(Code::Oxygen, Code::Hydrogen);
HEPEnergyType const p = 100_GeV;
auto const projectile4mom =
FourVector{calculate_total_energy(p, get_mass(projectileCode)),
MomentumVector{cs, 0_eV, 0_eV, p}};
auto const target4mom =
FourVector{get_mass(targetCode), MomentumVector{cs, 0_eV, 0_eV, 0_eV}};
CHECK(flukaModel.getCrossSection(projectileCode, targetCode, projectile4mom,
target4mom) == CrossSectionType::zero());
}
SECTION("doInteraction") {
auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Proton);
auto const& cs = *csPtr;
auto const projectileCode =
GENERATE(Code::PiPlus, Code::PiMinus, Code::KPlus, Code::K0Long, Code::Lambda0,
Code::SigmaPlus, Code::Photon);
auto const p = GENERATE(1_GeV, 20_GeV, 100_GeV, 1_TeV);
auto [stackPtr, secViewPtr] = setup::testing::setup_stack(
Code::Hydrogen, 1_GeV, (DummyEnvironment::BaseNodeType* const)nodePtr, *csPtr);
{ [[maybe_unused]] auto const& dummy_StackPtr = stackPtr; }
auto const targetCode = GENERATE(Code::Oxygen, Code::Nitrogen, Code::Argon);
auto const projectile4mom =
FourVector{calculate_total_energy(p, get_mass(projectileCode)),
MomentumVector{cs, 0_eV, 0_eV, p}};
auto const target4mom =
FourVector{get_mass(targetCode), MomentumVector{cs, 0_eV, 0_eV, 0_eV}};
flukaModel.doInteraction(*secViewPtr, projectileCode, targetCode, projectile4mom,
target4mom);
auto const pSum = sumMomentum(*secViewPtr, cs);
CHECK((pSum - projectile4mom.getSpaceLikeComponents()).getNorm() / p ==
Approx(0).margin(1e-4));
CHECK((pSum.getNorm() - p) / p == Approx(0).margin(1e-4));
CHECK(secViewPtr->getSize() > 1);
}
SECTION("doInteraction-invalid-projectile") {
auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Proton);
auto const& cs = *csPtr;
auto const projectileCode = GENERATE(Code::Electron, Code::MuPlus);
auto const p = 50_GeV;
auto [stackPtr, secViewPtr] = setup::testing::setup_stack(
Code::Hydrogen, 1_GeV, (DummyEnvironment::BaseNodeType* const)nodePtr, *csPtr);
{ [[maybe_unused]] auto const& dummy_StackPtr = stackPtr; }
auto const targetCode = Code::Oxygen;
auto const projectile4mom =
FourVector{calculate_total_energy(p, get_mass(projectileCode)),
MomentumVector{cs, 0_eV, 0_eV, p}};
auto const target4mom =
FourVector{get_mass(targetCode), MomentumVector{cs, 0_eV, 0_eV, 0_eV}};
REQUIRE_THROWS(flukaModel.doInteraction(*secViewPtr, projectileCode, targetCode,
projectile4mom, target4mom));
}
SECTION("doInteraction-invalid-target") {
auto [env, csPtr, nodePtr] = setup::testing::setup_environment(Code::Proton);
auto const& cs = *csPtr;
auto const projectileCode = Code::AntiNeutron;
auto const p = 50_GeV;
auto [stackPtr, secViewPtr] = setup::testing::setup_stack(
Code::Hydrogen, 1_GeV, (DummyEnvironment::BaseNodeType* const)nodePtr, *csPtr);
{ [[maybe_unused]] auto const& dummy_StackPtr = stackPtr; }
auto const targetCode = Code::Uranium;
auto const projectile4mom =
FourVector{calculate_total_energy(p, get_mass(projectileCode)),
MomentumVector{cs, 0_eV, 0_eV, p}};
auto const target4mom =
FourVector{get_mass(targetCode), MomentumVector{cs, 0_eV, 0_eV, 0_eV}};
REQUIRE_THROWS(flukaModel.doInteraction(*secViewPtr, projectileCode, targetCode,
projectile4mom, target4mom));
}
}