1#ifndef AMPGEN_GENERATOR_H
2#define AMPGEN_GENERATOR_H
18 template <
typename phaseSpace_t = PhaseSpace>
class Generator {
28 size_t m_generatorBlock = {5000000};
29 TRandom *m_rnd = {gRandom};
30 bool m_normalise = {
true};
33 template <
typename... ARGS>
explicit Generator(
const ARGS &...args) : m_gps(args...) {
34 m_eventType = m_gps.eventType();
38 phaseSpace_t
phsp() {
return m_gps; }
42 m_gps.setRandom(m_rnd);
44 void setBlockSize(
const size_t &blockSize) { m_generatorBlock = blockSize; }
45 void setNormFlag(
const bool &normSetting) { m_normalise = normSetting; }
48 if constexpr(std::is_same<phaseSpace_t, PhaseSpace>::value) {
50 for(
unsigned i = 0; i != N; ++i) {
51 double *addr =
reinterpret_cast<double *
>(events.
block(i / w)) + i % w;
55 auto it = events.
begin();
56 while(it != events.
end()) {
57 *it = m_gps.makeEvent();
62 template <
typename pdf_t>
double getMax(
const eventlist_t &events, pdf_t &pdf)
const {
64 for(
const auto &evt : events) {
65 auto value = evt.genPdf();
66 if(std::isnan(value)) {
67 ERROR(
"PDF for event is nan: " << value);
70 }
else if(value > max)
73 DEBUG(
"Returning normalisation constant = " << max);
77 template <
typename eventList_t,
typename pdf_t>
void fillEventList(pdf_t &pdf, eventList_t &list,
const size_t &N) {
78 if(m_rnd ==
nullptr) {
79 ERROR(
"Random generator not set!");
82 double maxProb = m_normalise ? 0 : 1;
83 auto size0 = list.size();
84 double totalGenerated = 0;
88 std::vector<bool> efficiencyReport(m_generatorBlock,
false);
90 while(list.size() - size0 < N) {
91 eventlist_t mc(m_eventType);
92 mc.
resize(m_generatorBlock);
99 auto previousSize = list.size();
101#pragma omp parallel for
104 maxProb = maxProb == 0 ? 1.5 *
getMax(mc, pdf) : maxProb;
105 DEBUG(
"Norm: " << maxProb);
109 t_acceptReject.
start();
110 totalGenerated += mc.
size();
111 for(
const auto &event : mc) {
112 if(event.genPdf() > maxProb) {
113 std::cout << std::endl;
114 WARNING(
"PDF value exceeds norm value: " << event.genPdf() <<
" > " << maxProb);
117 if(event.genPdf() > maxProb * m_rnd->Rndm()) {
118 list.push_back(event);
119 list.rbegin()->setGenPdf(pdf(event));
120 efficiencyReport[
event.index()] =
true;
122 efficiencyReport[
event.index()] =
false;
123 if(list.size() - size0 == N)
break;
126 t_acceptReject.
stop();
127 double efficiency = 100. * (list.size() - previousSize) / (double)m_generatorBlock;
128 pb.
print(
double(list.size()) /
double(N),
129 " ε[gen] = " +
mysprintf(
"%.4f", efficiency) +
"% , " + std::to_string(
int(t_total.
count() / 1000.)) +
" seconds");
130 if(list.size() == previousSize) {
137 INFO(
"Generated " << N <<
" events in " << t_total <<
" ms");
138 INFO(
"Generating phase space : " << t_phsp <<
" ms");
139 INFO(
"Evaluating PDF : " << t_eval <<
" ms");
140 INFO(
"Accept/reject : " << t_acceptReject <<
" ms");
141 INFO(
"Efficiency = " <<
double(N) * 100. / totalGenerated <<
" %");
143 template <typename pdf_t, typename = typename std::enable_if<!std::is_integral<pdf_t>::value>::type>
EventList generate(pdf_t &pdf,
const size_t &nEvents) {
144 eventlist_t evts(m_eventType);
147 for(
const auto &event : evts) output.
emplace_back(event);
151 eventlist_t evts(m_eventType);
155 for(
const auto &event : evts) output.
emplace_back(event);
166 size_t size()
const {
return 0; }
167 void reset(
const bool & =
false) {};
179 extern "C" void python__generate(
const char *eventType,
double *out,
const unsigned int size);
Encapsulates the final state particles of a single event.
double * block(const unsigned pos)
std::vector< Event >::iterator begin()
void setGenPDF(const unsigned int &pos, const double &g)
void emplace_back(const Event &evt)
std::vector< Event >::iterator end()
void resize(const size_t &size)
real_t genPDF(const size_t &pos) const
Deals with final state configuration of events, specifically dealing with the ordering of particles i...
void fillEventList(pdf_t &pdf, eventList_t &list, const size_t &N)
EventList generate(const size_t &nEvents)
EventList generate(pdf_t &pdf, const size_t &nEvents)
void setBlockSize(const size_t &blockSize)
void setRandom(TRandom *rand)
void fillEventListPhaseSpace(eventlist_t &events, const size_t &N)
Generator(const ARGS &...args)
double getMax(const eventlist_t &events, pdf_t &pdf) const
void setNormFlag(const bool &normSetting)
void setEvents(AmpGen::EventList &)
PDFWrapper(const FCN &fcn)
double prob_unnormalised(const AmpGen::Event &evt) const
void reset(const bool &=false)
void print(const double &percentage, const std::string &message="")
#define ERROR(X)
Used for printing errors messages, and will always be printed.
#define INFO(X)
Used for printing information messages, and will always be printed.
#define WARNING(X)
Used for printing warning messages, can be switched off using WARNINGLEVEL.
#define DEBUG(X)
Used for printing verbose debugging messages, only if DEBUGLEVEL is defined.
std::string trimmedString(std::string thing, const unsigned int &length=FCNNAMELENGTH)
void python__generate(const char *eventType, double *out, const unsigned int size)
@function PyGenerate
std::string type_string()
Utility classes for compile-time metaprogramming, such as identifying the types of arguments for gene...
std::string mysprintf(const std::string &format, ARGS &&...args)
PDFWrapper< FCN > make_pdf(const FCN &fcn)
static constexpr unsigned value