1#ifndef AMPGEN_GENERATOR_H
2#define AMPGEN_GENERATOR_H
20 template <
typename phaseSpace_t = PhaseSpace>
32 size_t m_generatorBlock = {5000000};
33 TRandom* m_rnd = {gRandom};
34 bool m_normalise = {
true};
37 template <
typename... ARGS>
explicit Generator(
const ARGS&... args ) : m_gps(args...)
39 m_eventType = m_gps.eventType();
40 if( m_rnd != gRandom )
setRandom( m_rnd );
43 phaseSpace_t
phsp() {
return m_gps; }
48 m_gps.setRandom( m_rnd );
50 void setBlockSize(
const size_t& blockSize ) { m_generatorBlock = blockSize; }
51 void setNormFlag(
const bool& normSetting ) { m_normalise = normSetting; }
55 if constexpr( std::is_same<phaseSpace_t, PhaseSpace>::value )
58 for(
unsigned i = 0 ; i != N ; ++i ){
59 double* addr =
reinterpret_cast<double*
>( events.
block( i/w ))+ i % w;
64 auto it = events.
begin();
65 while( it != events.
end() )
67 *it = m_gps.makeEvent();
72 template <
typename pdf_t>
73 double getMax(
const eventlist_t& events, pdf_t& pdf )
const
76 for (
const auto& evt : events )
78 auto value = evt.genPdf();
79 if( std::isnan(value) ){
80 ERROR(
"PDF for event is nan: " << value );
84 else if ( value > max ) max = value;
86 DEBUG(
"Returning normalisation constant = " << max );
90 template <
typename eventList_t,
typename pdf_t>
void fillEventList( pdf_t& pdf, eventList_t& list,
const size_t& N)
92 if ( m_rnd ==
nullptr )
94 ERROR(
"Random generator not set!" );
97 double maxProb = m_normalise ? 0 : 1;
98 auto size0 = list.size();
99 double totalGenerated = 0;
103 std::vector<bool> efficiencyReport(m_generatorBlock,
false);
105 while ( list.size() - size0 < N ) {
106 eventlist_t mc( m_eventType );
107 mc.
resize(m_generatorBlock);
114 auto previousSize = list.size();
116 #pragma omp parallel for
118 for (
size_t block=0; block < mc.
nBlocks(); ++block )
122 maxProb = maxProb == 0 ? 1.5 *
getMax(mc, pdf) : maxProb;
123 DEBUG(
"Norm: " << maxProb );
127 t_acceptReject.
start();
128 totalGenerated += mc.
size();
129 for(
const auto& event : mc)
131 if ( event.genPdf() > maxProb ) {
132 std::cout << std::endl;
133 WARNING(
"PDF value exceeds norm value: " << event.genPdf() <<
" > " << maxProb );
136 if ( event.genPdf() > maxProb * m_rnd->Rndm() ){
137 list.push_back(event);
138 list.rbegin()->setGenPdf( pdf(event) );
139 efficiencyReport[
event.index()] =
true;
141 else efficiencyReport[
event.index()] =
false;
142 if ( list.size() - size0 == N )
break;
145 t_acceptReject.
stop();
146 double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock;
147 pb.
print(
double(list.size()) /
double(N),
" ε[gen] = " +
mysprintf(
"%.4f",efficiency) +
"% , " + std::to_string(
int(t_total.
count()/1000.)) +
" seconds" );
148 if ( list.size() == previousSize ) {
155 INFO(
"Generated " << N <<
" events in " << t_total <<
" ms");
156 INFO(
"Generating phase space : " << t_phsp <<
" ms");
157 INFO(
"Evaluating PDF : " << t_eval <<
" ms");
158 INFO(
"Accept/reject : " << t_acceptReject <<
" ms");
159 INFO(
"Efficiency = " <<
double(N) * 100. / totalGenerated <<
" %");
161 template <typename pdf_t, typename = typename std::enable_if<!std::is_integral<pdf_t>::value>::type>
164 eventlist_t evts( m_eventType );
167 for(
const auto& event : evts ) output.
emplace_back( event );
172 eventlist_t evts( m_eventType );
176 for(
const auto& event : evts ) output.
emplace_back( event );
188 size_t size()
const {
return 0; }
189 void reset(
const bool& =
false ){};
201 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)
Generator(const ARGS &... args)
void setRandom(TRandom *rand)
void fillEventListPhaseSpace(eventlist_t &events, const size_t &N)
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 mysprintf(const std::string &format, ARGS &&... args)
std::string type_string()
Utility classes for compile-time metaprogramming, such as identifying the types of arguments for gene...
PDFWrapper< FCN > make_pdf(const FCN &fcn)
static constexpr unsigned value