Newer
Older
* (c) Copyright 2018 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 <catch2/catch.hpp>
#include <array>
#include <iomanip>
#include <iostream>
ralfulrich
committed
#include <typeinfo>
#include <corsika/framework/sequence/ProcessSequence.hpp>
//#include <corsika/process/SwitchProcess.hpp>
using namespace corsika;
ralfulrich
committed
int globalCount = 0; // simple counter
ralfulrich
committed
int checkInteract = 0; // use this as a bit field
int checkSec = 0; // use this as a bit field
int checkCont = 0; // use this as a bit field
class ContinuousProcess1 : public ContinuousProcess<ContinuousProcess1> {
: fV(v) {
cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const {
cout << "ContinuousProcess1::DoContinuous" << endl;
ralfulrich
committed
checkCont |= 1;
for (int i = 0; i < nData; ++i) d.data_[i] += 0.933;
return EProcessReturn::eOk;
}
};
class ContinuousProcess2 : public ContinuousProcess<ContinuousProcess2> {
: fV(v) {
cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const {
cout << "ContinuousProcess2::DoContinuous" << endl;
ralfulrich
committed
checkCont |= 2;
ralfulrich
committed
return EProcessReturn::eOk;
}
};
class ContinuousProcess3 : public ContinuousProcess<ContinuousProcess3> {
int fV = 0;
public:
ContinuousProcess3(const int v)
: fV(v) {
cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
globalCount++;
}
template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const {
cout << "ContinuousProcess3::DoContinuous" << endl;
checkCont |= 4;
return EProcessReturn::eOk;
}
};
class Process1 : public InteractionProcess<Process1> {
: fV(v) {
cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
ralfulrich
committed
template <typename TView>
inline EProcessReturn DoInteraction(TView& v) const {
checkInteract |= 1;
for (int i = 0; i < nData; ++i) v.parent().data_[i] += 1 + i;
ralfulrich
committed
template <typename TParticle>
corsika::units::si::GrammageType GetInteractionLength(TParticle&) const {
return 10_g / square(1_cm);
}
class Process2 : public InteractionProcess<Process2> {
: fV(v) {
cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
ralfulrich
committed
template <typename TView>
ralfulrich
committed
checkInteract |= 2;
for (int i = 0; i < nData; ++i) v.parent().data_[i] /= 1.1;
cout << "Process2::DoInteraction" << endl;
template <typename Particle>
GrammageType GetInteractionLength(Particle&) const {
ralfulrich
committed
return 20_g / (1_cm * 1_cm);
class Process3 : public InteractionProcess<Process3> {
: fV(v) {
cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
ralfulrich
committed
template <typename TView>
ralfulrich
committed
checkInteract |= 4;
for (int i = 0; i < nData; ++i) v.parent().data_[i] *= 1.01;
cout << "Process3::DoInteraction" << endl;
template <typename Particle>
GrammageType GetInteractionLength(Particle&) const {
ralfulrich
committed
return 30_g / (1_cm * 1_cm);
};
class Process4 : public BaseProcess<Process4> {
: fV(v) {
cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
template <typename D, typename T>
inline EProcessReturn DoContinuous(D& d, T&) const {
ralfulrich
committed
std::cout << "Base::DoContinuous" << std::endl;
checkCont |= 8;
for (int i = 0; i < nData; ++i) { d.data_[i] /= 1.2; }
ralfulrich
committed
template <typename TView>
EProcessReturn DoInteraction(TView&) const {
checkInteract |= 8;
return EProcessReturn::eOk;
}
};
class Decay1 : public DecayProcess<Decay1> {
public:
ralfulrich
committed
template <typename TView>
EProcessReturn DoDecay(TView&) const {
checkDecay |= 1;
return EProcessReturn::eOk;
}
};
class Decay2 : public DecayProcess<Decay2> {
public:
Decay2(const int) {
cout << "Decay2()" << endl;
globalCount++;
}
template <typename Particle>
ralfulrich
committed
TimeType GetLifetime(Particle&) const {
return 2_s;
}
template <typename TView>
EProcessReturn DoDecay(TView&) const {
checkDecay |= 2;
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;
}
};
struct DummyStack {};
ralfulrich
committed
double data_[nData] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
ralfulrich
committed
struct DummyView {
DummyView(DummyData& p)
: p_(p) {}
DummyData& p_;
DummyData& parent() { return p_; }
};
SECTION("Check construction") {
ralfulrich
committed
auto sequence1 = process::sequence(m1, m2, m3, m4);
CHECK(is_process_sequence_v<decltype(sequence1)> == true);
ralfulrich
committed
CHECK(is_process_sequence_v<decltype(m2)> == false);
CHECK(is_switch_process_sequence_v<decltype(sequence1)> == false);
CHECK(is_switch_process_sequence_v<decltype(m2)> == false);
ralfulrich
committed
auto sequence2 = process::sequence(m1, m2, m3);
CHECK(is_process_sequence_v<decltype(sequence2)> == true);
auto sequence3 = process::sequence(m4);
CHECK(is_process_sequence_v<decltype(sequence3)> == true);
ContinuousProcess1 cp1(0);
Process2 m2(1);
Process3 m3(2);
ralfulrich
committed
auto sequence2 = sequence(cp1, m2, m3);
ralfulrich
committed
GrammageType const tot = sequence2.GetInteractionLength(particle);
InverseGrammageType const tot_inv = sequence2.GetInverseInteractionLength(particle);
cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;
CHECK(tot / 1_g * square(1_cm) == 12);
CHECK(tot_inv * 1_g / square(1_cm) == 1. / 12);
ContinuousProcess1 cp1(0);
Process2 m2(1);
Process3 m3(2);
ralfulrich
committed
auto sequence2 = sequence(cp1, m2, m3, d3);
ralfulrich
committed
TimeType const tot = sequence2.GetLifetime(particle);
InverseTimeType const tot_inv = sequence2.GetInverseLifetime(particle);
cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;
CHECK(tot / 1_s == 1);
CHECK(tot_inv * 1_s == 1.);
ContinuousProcess1 cp1(0); // += 0.933
ContinuousProcess2 cp2(1); // += 0.111
Process2 m2(2); // /= 1.1
Process3 m3(3); // *= 1.01
ralfulrich
committed
auto sequence2 = sequence(cp1, m2, m3, cp2);
DummyData particle;
DummyTrajectory track;
const int nLoop = 5;
cout << "Running loop with n=" << nLoop << endl;
for (int i = 0; i < nData; ++i) { test_data[i] += 0.933 + 0.111; }
for (int i = 0; i < nData; i++) {
ralfulrich
committed
cout << "data_[" << i << "]=" << particle.data_[i] << endl;
CHECK(particle.data_[i] == Approx(test_data[i]).margin(1e-9));
SECTION("StackProcess") {
Stack1 s1(1);
Stack1 s2(2);
ralfulrich
committed
auto sequence = process::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);
ContinuousProcess2 cp2(1); // += 0.111
Process2 m2(2); // /= 1.1
auto sequence2 = process::sequence(cp2, m2);
auto sequence3 = process::sequence(cp2, m2, s1);
CHECK(is_process_sequence_v<decltype(sequence2)> == true);
CHECK(is_process_sequence_v<decltype(sequence3)> == true);
CHECK(contains_stack_process_v<decltype(sequence2)> == false);
CHECK(contains_stack_process_v<decltype(sequence3)> == true);
/*
Note: there is a fine-grained dedicated test-suite for SwitchProcess
in Processes/SwitchProcess/testSwtichProcess
*/
/*
TEST_CASE("SwitchProcess") {
Process1 p1(0);
Process2 p2(0);
switch_process::SwitchProcess s(p1, p2, 10_GeV);
REQUIRE(is_switch_process_v<decltype(s)>);
}*/