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/process/ProcessSequence.h>
ralfulrich
committed
#include <corsika/process/SwitchProcessSequence.h>
#include <corsika/units/PhysicalUnits.h>
using namespace corsika::process;
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;
for (int i = 0; i < nData; ++i) d.data_[i] += 0.933;
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;
for (int i = 0; i < nData; ++i) d.data_[i] += 0.933;
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>
inline EProcessReturn DoInteraction(TView&) const {
checkInteract |= 2;
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>
inline EProcessReturn DoInteraction(TView&) const {
checkInteract |= 4;
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 sequence = m1 % m2 % m3 % m4;
CHECK(is_process_sequence_v<decltype(sequence)> == true);
CHECK(is_process_sequence_v<decltype(m2)> == false);
ContinuousProcess1 cp1(0);
Process2 m2(1);
Process3 m3(2);
ralfulrich
committed
auto sequence2 = cp1 % m2 % m3;
GrammageType const tot = sequence2.GetInteractionLength(particle);
InverseGrammageType const tot_inv = sequence2.GetInverseInteractionLength(particle);
cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;
ContinuousProcess1 cp1(0);
Process2 m2(1);
Process3 m3(2);
ralfulrich
committed
auto sequence2 = cp1 % m2 % m3 % d3;
TimeType const tot = sequence2.GetLifetime(particle);
InverseTimeType const tot_inv = sequence2.GetInverseLifetime(particle);
cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;
ContinuousProcess2 cp2(1);
Process2 m2(2);
Process3 m3(3);
ralfulrich
committed
auto sequence2 = cp1 % m2 % m3 % cp2;
DummyData particle;
DummyTrajectory track;
sequence2.DoContinuous(particle, track);
cout << "-->dodisc" << endl;
cout << "-->done" << endl;
const int nLoop = 5;
cout << "Running loop with n=" << nLoop << endl;
for (int i = 0; i < nLoop; ++i) { sequence2.DoContinuous(particle, track); }
for (int i = 0; i < nData; i++) {
ralfulrich
committed
cout << "data_[" << i << "]=" << particle.data_[i] << endl;
SECTION("StackProcess") {
Stack1 s1(1);
Stack1 s2(2);
ralfulrich
committed
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);
}
ralfulrich
committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
TEST_CASE("Switch Process Sequence", "[Process Sequence]") {
SECTION("Check construction") {
struct TestSelect {
corsika::process::SwitchResult select(const DummyData& p) const {
std::cout << "TestSelect data=" << p.data_[0] << std::endl;
if (p.data_[0] > 0) return corsika::process::SwitchResult::First;
return corsika::process::SwitchResult::Second;
}
};
TestSelect select;
auto sequence1 = Process1(0) % ContinuousProcess2(0) % Decay1(0);
auto sequence2 = ContinuousProcess3(0) % Process2(0) % Decay2(0);
auto sequence = ContinuousProcess1(0) % Process3(0) %
SwitchProcessSequence(sequence1, sequence2, select);
auto sequence_alt =
(ContinuousProcess1(0) % Process3(0)) %
process::select(Process1(0) % ContinuousProcess2(0) % Decay1(0),
ContinuousProcess3(0) % Process2(0) % Decay2(0), select);
// check that same process sequence can be build in different ways
CHECK(typeid(sequence) == typeid(sequence_alt));
CHECK(is_process_sequence_v<decltype(sequence)> == true);
CHECK(is_process_sequence_v<decltype(
SwitchProcessSequence(sequence1, sequence2, select))> == true);
DummyData particle;
DummyTrajectory track;
DummyView view(particle);
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = 100; // data positive
sequence.DoContinuous(particle, track);
CHECK(checkInteract == 0);
CHECK(checkDecay == 0);
CHECK(checkCont == 0b011);
CHECK(checkSec == 0);
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = -100; // data negative
sequence_alt.DoContinuous(particle, track);
CHECK(checkInteract == 0);
CHECK(checkDecay == 0);
CHECK(checkCont == 0b101);
CHECK(checkSec == 0);
// 1/(30g/cm2) is Process3
corsika::units::si::InverseGrammageType lambda_select = .9 / 30. * square(1_cm) / 1_g;
ralfulrich
committed
corsika::units::si::InverseTimeType time_select = 0.1 / second;
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = 100; // data positive
sequence.SelectInteraction(view, lambda_select);
sequence.SelectDecay(view, time_select);
CHECK(checkInteract == 0b100); // this is Process3
ralfulrich
committed
CHECK(checkCont == 0);
CHECK(checkSec == 0);
lambda_select = 1.01 / 30. * square(1_cm) / 1_g;
ralfulrich
committed
checkInteract = 0;
sequence.SelectInteraction(view, lambda_select);
CHECK(checkInteract == 0b001); // this is Process1
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = -100; // data negative
sequence.SelectInteraction(view, lambda_select);
sequence.SelectDecay(view, time_select);
CHECK(checkInteract == 0b010); // this is Process2
ralfulrich
committed
CHECK(checkCont == 0);
CHECK(checkSec == 0);
checkDecay = 0;
checkInteract = 0;
checkSec = 0;
checkCont = 0;
particle.data_[0] = -100; // data negative
sequence.DoSecondaries(view);
Stack1 stack(0);
sequence.DoStack(stack);
CHECK(checkInteract == 0);
CHECK(checkDecay == 0);
CHECK(checkCont == 0);
CHECK(checkSec == 0);
}