IAP GITLAB

Skip to content
Snippets Groups Projects
testProcessSequence.cc 11.9 KiB
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>

#include <corsika/process/ProcessSequence.h>
#include <corsika/process/SwitchProcessSequence.h>
#include <corsika/units/PhysicalUnits.h>
Ralf Ulrich's avatar
Ralf Ulrich committed
using namespace corsika;
using namespace corsika::units::si;
using namespace corsika::process;
Ralf Ulrich's avatar
Ralf Ulrich committed
using namespace std;
static const int nData = 10;

int checkDecay = 0;    // use this as a bit field
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
Ralf Ulrich's avatar
Ralf Ulrich committed

class ContinuousProcess1 : public ContinuousProcess<ContinuousProcess1> {
Ralf Ulrich's avatar
Ralf Ulrich committed
  int fV = 0;

public:
Ralf Ulrich's avatar
Ralf Ulrich committed
  ContinuousProcess1(const int v)
      : fV(v) {

    cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
Ralf Ulrich's avatar
Ralf Ulrich committed
    globalCount++;
  }
  template <typename D, typename T>
  inline EProcessReturn DoContinuous(D& d, T&) const {
    cout << "ContinuousProcess1::DoContinuous" << endl;
    checkCont |= 1;
    for (int i = 0; i < nData; ++i) d.data_[i] += 0.933;
    return EProcessReturn::eOk;
  }
};

class ContinuousProcess2 : public ContinuousProcess<ContinuousProcess2> {
Ralf Ulrich's avatar
Ralf Ulrich committed
  int fV = 0;

public:
Ralf Ulrich's avatar
Ralf Ulrich committed
  ContinuousProcess2(const int v)
      : fV(v) {
    cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
Ralf Ulrich's avatar
Ralf Ulrich committed
    globalCount++;
  }
  template <typename D, typename T>
  inline EProcessReturn DoContinuous(D& d, T&) const {
    cout << "ContinuousProcess2::DoContinuous" << endl;
    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> {
Ralf Ulrich's avatar
Ralf Ulrich committed
  Process1(const int v)
      : fV(v) {
    cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
Ralf Ulrich's avatar
Ralf Ulrich committed
    globalCount++;
  }
  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's avatar
ralfulrich committed
    return EProcessReturn::eOk;
  template <typename TParticle>
  corsika::units::si::GrammageType GetInteractionLength(TParticle&) const {
    return 10_g / square(1_cm);
  }

Ralf Ulrich's avatar
Ralf Ulrich committed
  int fV;
class Process2 : public InteractionProcess<Process2> {
Ralf Ulrich's avatar
Ralf Ulrich committed
  int fV = 0;

Ralf Ulrich's avatar
Ralf Ulrich committed
  Process2(const int v)
      : fV(v) {
    cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
Ralf Ulrich's avatar
Ralf Ulrich committed
    globalCount++;
  template <typename TView>
  inline EProcessReturn DoInteraction(TView&) const {
    checkInteract |= 2;
    cout << "Process2::DoInteraction" << endl;
    return EProcessReturn::eOk;
  }
  template <typename Particle>
  GrammageType GetInteractionLength(Particle&) const {
ralfulrich's avatar
ralfulrich committed
    cout << "Process2::GetInteractionLength" << endl;
ralfulrich's avatar
ralfulrich committed
  }
class Process3 : public InteractionProcess<Process3> {
Ralf Ulrich's avatar
Ralf Ulrich committed
  int fV = 0;

Ralf Ulrich's avatar
Ralf Ulrich committed
  Process3(const int v)
      : fV(v) {
    cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
Ralf Ulrich's avatar
Ralf Ulrich committed
    globalCount++;
  template <typename TView>
  inline EProcessReturn DoInteraction(TView&) const {
    checkInteract |= 4;
    cout << "Process3::DoInteraction" << endl;
    return EProcessReturn::eOk;
  }
  template <typename Particle>
  GrammageType GetInteractionLength(Particle&) const {
ralfulrich's avatar
ralfulrich committed
    cout << "Process3::GetInteractionLength" << endl;
ralfulrich's avatar
ralfulrich committed
  }
};

class Process4 : public BaseProcess<Process4> {
Ralf Ulrich's avatar
Ralf Ulrich committed
  int fV = 0;

Ralf Ulrich's avatar
Ralf Ulrich committed
  Process4(const int v)
      : fV(v) {
    cout << "globalCount: " << globalCount << ", fV: " << fV << std::endl;
Ralf Ulrich's avatar
Ralf Ulrich committed
    globalCount++;
  }
  template <typename D, typename T>
  inline EProcessReturn DoContinuous(D& d, T&) const {
    std::cout << "Base::DoContinuous" << std::endl;
    checkCont |= 8;
    for (int i = 0; i < nData; ++i) { d.data_[i] /= 1.2; }
ralfulrich's avatar
ralfulrich committed
    return EProcessReturn::eOk;
  }
  template <typename TView>
  EProcessReturn DoInteraction(TView&) const {
    checkInteract |= 8;
    return EProcessReturn::eOk;
  }
};

class Decay1 : public DecayProcess<Decay1> {

public:
  Decay1(const int) {
    cout << "Decay1()" << endl;
    globalCount++;
  }
  template <typename Particle>
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
  TimeType GetLifetime(Particle&) const {
    return 1_s;
  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>
  TimeType GetLifetime(Particle&) const {
    return 2_s;
  }
  template <typename TView>
  EProcessReturn DoDecay(TView&) const {
    checkDecay |= 2;
Ralf Ulrich's avatar
Ralf Ulrich committed
    return EProcessReturn::eOk;
  }
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;
  }
  int GetCount() const { return fCount; }
struct DummyData {
  double data_[nData] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Ralf Ulrich's avatar
Ralf Ulrich committed
struct DummyTrajectory {};
struct DummyView {
  DummyView(DummyData& p)
      : p_(p) {}
  DummyData& p_;
  DummyData& parent() { return p_; }
};

Ralf Ulrich's avatar
Ralf Ulrich committed
TEST_CASE("Process Sequence", "[Process Sequence]") {
  SECTION("Check construction") {
    globalCount = 0;
Ralf Ulrich's avatar
Ralf Ulrich committed
    Process1 m1(0);
    CHECK(globalCount == 1);
Ralf Ulrich's avatar
Ralf Ulrich committed
    Process2 m2(1);
    CHECK(globalCount == 2);
Ralf Ulrich's avatar
Ralf Ulrich committed
    Process3 m3(2);
    CHECK(globalCount == 3);
Ralf Ulrich's avatar
Ralf Ulrich committed
    Process4 m4(3);
    CHECK(globalCount == 4);
    auto sequence1 = process::sequence(m1, m2, m3, m4);
    CHECK(is_process_sequence_v<decltype(sequence1)> == true);
    CHECK(is_process_sequence_v<decltype(m2)> == false);

    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);
Ralf Ulrich's avatar
Ralf Ulrich committed
  }

ralfulrich's avatar
ralfulrich committed
  SECTION("interaction length") {
    globalCount = 0;
ralfulrich's avatar
ralfulrich committed
    ContinuousProcess1 cp1(0);
    Process2 m2(1);
    Process3 m3(2);

    DummyData particle;
    GrammageType const tot = sequence2.GetInteractionLength(particle);
    InverseGrammageType const tot_inv = sequence2.GetInverseInteractionLength(particle);
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
    cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;
    globalCount = 0;
ralfulrich's avatar
ralfulrich committed
  }

  SECTION("lifetime") {
    globalCount = 0;
    ContinuousProcess1 cp1(0);
    Process2 m2(1);
    Process3 m3(2);
    Decay1 d3(3);
    DummyData particle;
    auto sequence2 = sequence(cp1, m2, m3, d3);
    TimeType const tot = sequence2.GetLifetime(particle);
    InverseTimeType const tot_inv = sequence2.GetInverseLifetime(particle);
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
    cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl;

    globalCount = 0;
Ralf Ulrich's avatar
Ralf Ulrich committed
  SECTION("sectionTwo") {
    globalCount = 0;
Ralf Ulrich's avatar
Ralf Ulrich committed
    ContinuousProcess1 cp1(0);
    ContinuousProcess2 cp2(1);
    Process2 m2(2);
    Process3 m3(3);
    auto sequence2 = sequence(cp1, m2, m3, cp2);
    DummyData particle;
    DummyTrajectory track;
ralfulrich's avatar
ralfulrich committed

Ralf Ulrich's avatar
Ralf Ulrich committed
    cout << "-->init sequence2" << endl;
    globalCount = 0;
    cout << "-->docont" << endl;
    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++) {
      cout << "data_[" << i << "]=" << particle.data_[i] << endl;
Ralf Ulrich's avatar
Ralf Ulrich committed
    }
    cout << "done" << endl;
    globalCount = 0;

    DummyStack stack;

    const int nLoop = 20;
    for (int i = 0; i < nLoop; ++i) { sequence.DoStack(stack); }

    CHECK(s1.GetCount() == 20);
    CHECK(s2.GetCount() == 10);
  }
TEST_CASE("Switch Process Sequence", "[Process Sequence]") {

  SECTION("Check construction") {

    struct TestSelect {
      corsika::process::SwitchResult operator()(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 = process::sequence(Process1(0), ContinuousProcess2(0), Decay1(0));
    auto sequence2 = process::sequence(ContinuousProcess3(0), Process2(0), Decay2(0));
    auto sequence =
        process::sequence(ContinuousProcess1(0), Process3(0),
                          SwitchProcessSequence(sequence1, sequence2, select));
    auto sequence_alt = process::sequence(
        ContinuousProcess1(0), Process3(0),
        process::select(process::sequence(Process1(0), ContinuousProcess2(0), Decay1(0)),
                        process::sequence(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;
    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
    CHECK(checkDecay == 0b001);    // this is Decay1
    lambda_select = 1.01 / 30. * square(1_cm) / 1_g;
    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
    CHECK(checkDecay == 0b010);    // this is Decay2
    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);
  }