IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 097c01c1 authored by ralfulrich's avatar ralfulrich
Browse files

allow more specific types of processes

parent 11d3010d
No related branches found
No related tags found
No related merge requests found
......@@ -62,7 +62,7 @@ namespace corsika::cascade {
// DoCascadeEquations(); //
}
}
void Step(Particle& particle) {
[[maybe_unused]] double nextStep = fProcesseList.MinStepLength(particle);
// corsika::utls::ignore(nextStep);
......@@ -80,7 +80,7 @@ namespace corsika::cascade {
fProcesseList.DoDiscrete(particle, fStack);
}
}
private:
ProcessList& fProcesseList;
Stack& fStack;
......
......@@ -20,6 +20,15 @@ namespace corsika::process {
const derived& GetRef() const { return static_cast<const derived&>(*this); }
};
}
template <typename T>
struct is_base {
static const bool value = false;
};
template <typename T>
struct is_base<BaseProcess<T>> {
static const bool value = true;
};
} // namespace corsika::process
#endif
......@@ -11,6 +11,8 @@ set (
set (
CORSIKAprocesssequence_HEADERS
BaseProcess.h
ContinuousProcess.h
DiscreteProcess.h
ProcessSequence.h
ProcessReturn.h
)
......
#ifndef _include_corsika_continuousprocess_h_
#define _include_corsika_continuousprocess_h_
#include <corsika/process/ProcessReturn.h> // for convenience
namespace corsika::process {
/**
\class ContinuousProcess
The structural base type of a process object in a
ProcessSequence. Both, the ProcessSequence and all its elements
are of type ContinuousProcess<T>
*/
template <typename derived>
struct ContinuousProcess {
derived& GetRef() { return static_cast<derived&>(*this); }
const derived& GetRef() const { return static_cast<const derived&>(*this); }
};
} // namespace corsika::process
#endif
#ifndef _include_corsika_discreteprocess_h_
#define _include_corsika_discreteprocess_h_
#include <corsika/process/ProcessReturn.h> // for convenience
#include <iostream> // debug
namespace corsika::process {
/**
\class DiscreteProcess
The structural base type of a process object in a
ProcessSequence. Both, the ProcessSequence and all its elements
are of type DiscreteProcess<T>
*/
template <typename derived>
struct DiscreteProcess {
// DiscreteProcess() {
// static_assert(mustProvide<derived>::mustProvide, "");
//}
derived& GetRef() { return static_cast<derived&>(*this); }
const derived& GetRef() const { return static_cast<const derived&>(*this); }
// here starts the interface part
// -> enforce derived to implement DoDiscrete...
template <typename Particle, typename Stack>
inline EProcessReturn DoDiscrete(Particle&, Stack&) const; // {}
// private:
template <typename D, typename T, typename S>
inline EProcessReturn DoContinuous(D& d, T&, S&) const {
std::cout << "yeah" << std::endl;
return EProcessReturn::eOk;
} // find out how to make this FINAL
// void DoContinuous;
};
} // namespace corsika::process
#endif
......@@ -13,14 +13,112 @@
#define _include_ProcessSequence_h_
#include <corsika/process/BaseProcess.h>
#include <corsika/process/ContinuousProcess.h>
#include <corsika/process/DiscreteProcess.h>
#include <corsika/process/ProcessReturn.h>
#include <cmath>
#include <iostream>
#include <typeinfo>
//#include <type_traits> // still needed ?
namespace corsika::process {
/* namespace detail { */
/* /\* template<typename TT1, typename TT2, typename Type = void> *\/ */
/* /\* struct CallHello { *\/ */
/* /\* static void Call(const TT1&, const TT2&) { *\/ */
/* /\* std::cout << "normal" << std::endl; *\/ */
/* /\* } *\/ */
/* /\* }; *\/ */
/* /\* template<typename TT1, typename TT2> *\/ */
/* /\* struct CallHello<TT1, TT2, typename
* std::enable_if<std::is_base_of<ContinuousProcess<TT2>, TT2>::value>::type> *\/ */
/* /\* { *\/ */
/* /\* static void Call(const TT1&, const TT2&) { *\/ */
/* /\* std::cout << "special" << std::endl; *\/ */
/* /\* } *\/ */
/* /\* }; *\/ */
/* template<typename T1, typename T2, typename Particle, typename Trajectory, typename
* Stack> //, typename Type = void> */
/* struct DoContinuous { */
/* static EProcessReturn Call(const T1& A, const T2& B, Particle& p, Trajectory& t,
* Stack& s) { */
/* EProcessReturn ret = EProcessReturn::eOk; */
/* if constexpr (!std::is_base_of<DiscreteProcess<T1>, T1>::value) { */
/* A.DoContinuous(p, t, s); */
/* } */
/* if constexpr (!std::is_base_of<DiscreteProcess<T2>, T2>::value) { */
/* B.DoContinuous(p, t, s); */
/* } */
/* return ret; */
/* } */
/* }; */
/* /\* */
/* template<typename T1, typename T2, typename Particle, typename Trajectory, typename
* Stack> */
/* struct DoContinuous<T1,T2,Particle,Trajectory,Stack, typename
* std::enable_if<std::is_base_of<DiscreteProcess<T1>, T1>::value>::type> { */
/* static EProcessReturn Call(const T1& A, const T2& B, Particle& p, Trajectory& t,
* Stack& s) { */
/* EProcessReturn ret = EProcessReturn::eOk; */
/* A.DoContinuous(p, t, s); */
/* B.DoContinuous(p, t, s); */
/* return ret; */
/* } */
/* }; */
/* template<typename T1, typename T2, typename Particle, typename Trajectory,
* typename Stack> */
/* struct DoContinuous<T1,T2,Particle,Trajectory,Stack, typename
* std::enable_if<std::is_base_of<DiscreteProcess<T2>, T2>::value>::type> { */
/* static EProcessReturn Call(const T1& A, const T2&, Particle& p, Trajectory& t,
* Stack& s) { */
/* EProcessReturn ret = EProcessReturn::eOk; */
/* A.DoContinuous(p, t, s); */
/* B.DoContinuous(p, t, s); */
/* return ret; */
/* } */
/* }; */
/* *\/ */
/* template<typename T1, typename T2, typename Particle, typename Stack>//, typename
* Type = void> */
/* struct DoDiscrete { */
/* static EProcessReturn Call(const T1& A, const T2& B, Particle& p, Stack& s) { */
/* if constexpr (!std::is_base_of<ContinuousProcess<T1>, T1>::value) { */
/* A.DoDiscrete(p, s); */
/* } */
/* if constexpr (!std::is_base_of<ContinuousProcess<T2>, T2>::value) { */
/* B.DoDiscrete(p, s); */
/* } */
/* return EProcessReturn::eOk; */
/* } */
/* }; */
/* /\* */
/* template<typename T1, typename T2, typename Particle, typename Stack> */
/* struct DoDiscrete<T1,T2,Particle,Stack, typename
* std::enable_if<std::is_base_of<ContinuousProcess<T1>, T1>::value>::type> { */
/* static EProcessReturn Call(const T1&, const T2& B, Particle& p, Stack& s) { */
/* // A.DoDiscrete(p, s); */
/* B.DoDiscrete(p, s); */
/* return EProcessReturn::eOk; */
/* } */
/* }; */
/* template<typename T1, typename T2, typename Particle, typename Stack> */
/* struct DoDiscrete<T1,T2,Particle,Stack, typename
* std::enable_if<std::is_base_of<ContinuousProcess<T2>, T2>::value>::type> { */
/* static EProcessReturn Call(const T1& A, const T2&, Particle& p, Stack& s) { */
/* A.DoDiscrete(p, s); */
/* //B.DoDiscrete(p, s); */
/* return EProcessReturn::eOk; */
/* } */
/* }; */
/* *\/ */
/* } // end namespace detail */
/**
\class ProcessSequence
......@@ -42,13 +140,20 @@ namespace corsika::process {
: A(in_A)
, B(in_B) {}
// example for a trait-based call:
// void Hello() const { detail::CallHello<T1,T2>::Call(A, B); }
template <typename Particle, typename Trajectory, typename Stack>
inline EProcessReturn DoContinuous(Particle& p, Trajectory& t, Stack& s) const {
EProcessReturn ret = EProcessReturn::eOk;
/*ret |=*/A.DoContinuous(p, t, s);
/*ret |=*/B.DoContinuous(p, t, s);
if constexpr (!std::is_base_of<DiscreteProcess<T1>, T1>::value) {
A.DoContinuous(p, t, s);
}
if constexpr (!std::is_base_of<DiscreteProcess<T2>, T2>::value) {
B.DoContinuous(p, t, s);
}
return ret;
} // add trajectory
}
template <typename D>
inline double MinStepLength(D& d) const {
......@@ -64,11 +169,16 @@ namespace corsika::process {
p, length); // need to do this also to decide which Trajectory to return!!!!
}
*/
template <typename Particle, typename Stack>
void DoDiscrete(Particle& p, Stack& s) const {
A.DoDiscrete(p, s);
B.DoDiscrete(p, s);
inline EProcessReturn DoDiscrete(Particle& p, Stack& s) const {
if constexpr (!std::is_base_of<ContinuousProcess<T1>, T1>::value) {
A.DoDiscrete(p, s);
}
if constexpr (!std::is_base_of<ContinuousProcess<T2>, T2>::value) {
B.DoDiscrete(p, s);
}
return EProcessReturn::eOk;
}
/// TODO the const_cast is not nice, think about the constness here
......@@ -78,13 +188,27 @@ namespace corsika::process {
}
};
/// the + operator that assembles more BaseProcess objects into a ProcessSequence
template <typename T1, typename T2>
inline const ProcessSequence<T1, T2> operator+(const BaseProcess<T1>& A,
const BaseProcess<T2>& B) {
return ProcessSequence<T1, T2>(A.GetRef(), B.GetRef());
/// the +operator assembles many BaseProcess, ContinuousProcess, and
/// DiscreteProcess objects into a ProcessSequence, all combinatoris
/// must be allowed, this is why we define a macro to define all
/// combinations here:
#define OPSEQ(C1, C2) \
template <typename T1, typename T2> \
inline const ProcessSequence<T1, T2> operator+(const C1<T1>& A, const C2<T2>& B) { \
return ProcessSequence<T1, T2>(A.GetRef(), B.GetRef()); \
}
OPSEQ(BaseProcess, BaseProcess)
OPSEQ(BaseProcess, DiscreteProcess)
OPSEQ(BaseProcess, ContinuousProcess)
OPSEQ(ContinuousProcess, BaseProcess)
OPSEQ(ContinuousProcess, DiscreteProcess)
OPSEQ(ContinuousProcess, ContinuousProcess)
OPSEQ(DiscreteProcess, BaseProcess)
OPSEQ(DiscreteProcess, DiscreteProcess)
OPSEQ(DiscreteProcess, ContinuousProcess)
/*
template <typename T1>
struct depth_lhs
......
#ifndef _include_process_processsignature_h_
#define _include_process_processsignature_h_
#define FORCE_SIGNATURE(nameTrait, nameMethod, signatureMethod) \
template <typename U> \
class nameTrait { \
private: \
template <typename T, T> \
struct helper; \
template <typename T> \
static std::uint8_t check(helper<signatureMethod, &nameMethod>*); \
template <typename T> \
static std::uint16_t check(...); \
\
public: \
static constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
}
// FORCE_SIGNATURE(thisMustBeDefined, T::thisMustBeDefined, int(*)(void));
#endif
......@@ -22,43 +22,94 @@
using namespace std;
using namespace corsika::process;
class Process1 : public BaseProcess<Process1> {
class ContinuousProcess1 : public ContinuousProcess<ContinuousProcess1> {
public:
ContinuousProcess1() {}
void Init() { cout << "ContinuousProcess1::Init" << endl; }
template <typename D, typename T, typename S>
inline EProcessReturn DoContinuous(D& d, T&, S&) const {
cout << "ContinuousProcess1::DoContinuous" << endl;
for (int i = 0; i < 10; ++i) d.p[i] += 0.933;
return EProcessReturn::eOk;
}
template <typename Particle, typename Stack>
inline EProcessReturn DoDiscrete(Particle&, Stack&) const {
cout << "ContinuousProcess1::DoDiscrete" << endl;
return EProcessReturn::eOk;
}
};
class ContinuousProcess2 : public ContinuousProcess<ContinuousProcess2> {
public:
ContinuousProcess2() {}
void Init() { cout << "ContinuousProcess2::Init" << endl; }
template <typename D, typename T, typename S>
inline EProcessReturn DoContinuous(D& d, T&, S&) const {
cout << "ContinuousProcess2::DoContinuous" << endl;
for (int i = 0; i < 20; ++i) d.p[i] += 0.933;
return EProcessReturn::eOk;
}
template <typename Particle, typename Stack>
inline EProcessReturn DoDiscrete(Particle&, Stack&) const {
cout << "ContinuousProcess2::DoDiscrete" << endl;
return EProcessReturn::eOk;
}
};
class Process1 : public DiscreteProcess<Process1> {
public:
Process1() {}
void Init() {} // cout << "Process1::Init" << endl; }
void Init() { cout << "Process1::Init" << endl; }
template <typename D, typename T, typename S>
inline EProcessReturn DoContinuous(D& d, T&, S&) const {
for (int i = 0; i < 10; ++i) d.p[i] += 1 + i;
return EProcessReturn::eOk;
}
template <typename Particle, typename Stack>
inline EProcessReturn DoDiscrete(Particle&, Stack&) const {
cout << "Process1::DoDiscrete" << endl;
return EProcessReturn::eOk;
}
};
class Process2 : public BaseProcess<Process2> {
class Process2 : public DiscreteProcess<Process2> {
public:
Process2() {}
void Init() {} // cout << "Process2::Init" << endl; }
void Init() { cout << "Process2::Init" << endl; }
template <typename D, typename T, typename S>
inline EProcessReturn DoContinuous(D& d, T&, S&) const {
for (int i = 0; i < 10; ++i) d.p[i] *= 0.7;
return EProcessReturn::eOk;
}
template <typename Particle, typename Stack>
inline EProcessReturn DoDiscrete(Particle&, Stack&) const {
cout << "Process2::DoDiscrete" << endl;
return EProcessReturn::eOk;
}
};
class Process3 : public BaseProcess<Process3> {
class Process3 : public DiscreteProcess<Process3> {
public:
Process3() {}
void Init() {} // cout << "Process3::Init" << endl; }
void Init() { cout << "Process3::Init" << endl; }
template <typename D, typename T, typename S>
inline EProcessReturn DoContinuous(D& d, T&, S&) const {
for (int i = 0; i < 10; ++i) d.p[i] += 0.933;
return EProcessReturn::eOk;
}
template <typename Particle, typename Stack>
inline EProcessReturn DoDiscrete(Particle&, Stack&) const {
cout << "Process3::DoDiscrete" << endl;
return EProcessReturn::eOk;
}
};
class Process4 : public BaseProcess<Process4> {
public:
Process4() {}
void Init() {} // cout << "Process4::Init" << endl; }
void Init() { cout << "Process4::Init" << endl; }
template <typename D, typename T, typename S>
inline EProcessReturn DoContinuous(D& d, T&, S&) const {
for (int i = 0; i < 10; ++i) d.p[i] /= 1.2;
......@@ -85,17 +136,30 @@ TEST_CASE("Cascade", "[Cascade]") {
const auto sequence = m1 + m2 + m3 + m4;
ContinuousProcess1 cp1;
ContinuousProcess2 cp2;
const auto sequence2 = cp1 + m2 + m3 + cp2;
DummyData p;
DummyTrajectory t;
DummyStack s;
cout << "-->init" << endl;
sequence2.Init();
cout << "-->docont" << endl;
sequence2.DoContinuous(p, t, s);
cout << "-->dodisc" << endl;
sequence2.DoDiscrete(p, s);
cout << "-->done" << endl;
sequence.Init();
const int n = 100;
INFO("Running loop with n=" << n);
cout << "Running loop with n=" << n << endl;
for (int i = 0; i < n; ++i) { sequence.DoContinuous(p, t, s); }
for (int i = 0; i < 10; i++) { INFO("data[" << i << "]=" << p.p[i]); }
for (int i = 0; i < 10; i++) { cout << "data[" << i << "]=" << p.p[i] << endl; }
}
SECTION("sectionThree") {}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment