cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
Generator.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2013-2024 Laurent Forthomme
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <chrono>
20
27#include "CepGen/Generator.h"
34#include "CepGen/Utils/String.h"
36
37namespace cepgen {
38 Generator::Generator(bool safe_mode) : parameters_(new RunParameters) {
39 static bool init = false;
40 if (!init) {
41 cepgen::initialise(safe_mode);
42 init = true;
43 CG_DEBUG("Generator:init") << "Generator initialised";
44 }
45 //--- random number initialization
46 std::chrono::system_clock::time_point time = std::chrono::system_clock::now();
47 srandom(time.time_since_epoch().count());
48 }
49
50 Generator::Generator(RunParameters* ip) : parameters_(ip) {}
51
53 if (parameters_->timeKeeper())
54 CG_INFO("Generator:destructor") << parameters_->timeKeeper()->summary();
55 }
56
57 void Generator::clearRun() {
58 CG_DEBUG("Generator:clearRun") << "Run is set to be cleared.";
59 worker_ = GeneratorWorkerFactory::get().build(parameters_->generation().parameters().get<ParametersList>("worker"));
60 CG_DEBUG("Generator:clearRun") << "Initialised a generator worker with parameters: " << worker_->parameters()
61 << ".";
62 // destroy and recreate the integrator instance
63 resetIntegrator();
64
65 worker_->setRunParameters(const_cast<const RunParameters*>(parameters_.get()));
66 worker_->setIntegrator(integrator_.get());
67 xsect_ = Value{-1., -1.};
68 parameters_->prepareRun();
69 initialised_ = false;
70 }
71
72 void Generator::parseRunParameters(const std::string& filename) {
73 setRunParameters(CardsHandlerFactory::get().buildFromFilename(filename)->parseFile(filename).runParameters());
74 }
75
77 if (!parameters_)
78 throw CG_FATAL("Generator:runParameters") << "Run parameters object is not yet initialised.";
79 return *parameters_;
80 }
81
83 if (!parameters_)
84 throw CG_FATAL("Generator:runParameters") << "Run parameters object is not yet initialised.";
85 return *parameters_;
86 }
87
88 void Generator::setRunParameters(std::unique_ptr<RunParameters>& ip) { parameters_ = std::move(ip); }
89
90 double Generator::computePoint(const std::vector<double>& coord) {
91 if (!worker_)
92 clearRun();
93 if (!parameters_->hasProcess())
94 throw CG_FATAL("Generator:computePoint") << "Trying to compute a point with no process specified!";
95 const size_t ndim = worker_->integrand().process().ndim();
96 if (coord.size() != ndim)
97 throw CG_FATAL("Generator:computePoint")
98 << "Invalid phase space dimension (ndim=" << ndim << ", given=" << coord.size() << ").";
99 double res = worker_->integrand().eval(coord);
100 CG_DEBUG("Generator:computePoint") << "Result for x[" << ndim << "] = " << coord << ":\n\t" << res << ".";
101 return res;
102 }
103
104 void Generator::computeXsection(double& cross_section, double& err) {
105 const auto xsec = computeXsection();
106 cross_section = xsec;
107 err = xsec.uncertainty();
108 }
109
111 CG_INFO("Generator") << "Starting the computation of the process cross-section.";
112
113 integrate(); // run is cleared here
114
115 if (xsect_ < 1.e-2)
116 CG_INFO("Generator") << "Total cross section: " << xsect_ * 1.e3 << " fb.";
117 else if (xsect_ < 0.5e3)
118 CG_INFO("Generator") << "Total cross section: " << xsect_ << " pb.";
119 else if (xsect_ < 0.5e6)
120 CG_INFO("Generator") << "Total cross section: " << xsect_ * 1.e-3 << " nb.";
121 else if (xsect_ < 0.5e9)
122 CG_INFO("Generator") << "Total cross section: " << xsect_ * 1.e-6 << " µb.";
123 else
124 CG_INFO("Generator") << "Total cross section: " << xsect_ * 1.e-9 << " mb.";
125
126 return xsect_;
127 }
128
129 void Generator::resetIntegrator() {
130 CG_TICKER(parameters_->timeKeeper());
131 // create a spec-defined integrator in the current scope
132 setIntegrator(IntegratorFactory::get().build(parameters_->integrator()));
133 }
134
135 void Generator::setIntegrator(std::unique_ptr<Integrator> integ) {
136 CG_TICKER(parameters_->timeKeeper());
137 // copy the integrator instance (or create it if unspecified) in the current scope
138 if (!integ)
139 resetIntegrator();
140 else
141 integrator_ = std::move(integ);
142 CG_INFO("Generator:integrator") << "Generator will use a " << integrator_->name() << "-type integrator.";
143 }
144
146 CG_TICKER(parameters_->timeKeeper());
147
148 clearRun();
149
150 if (!parameters_->hasProcess())
151 throw CG_FATAL("Generator:integrate") << "Trying to integrate while no process is specified!";
152 const size_t ndim = worker_->integrand().process().ndim();
153 if (ndim == 0)
154 throw CG_FATAL("Generator:integrate") << "Invalid phase space dimension. "
155 << "At least one integration variable is required!";
156
157 CG_DEBUG("Generator:integrate") << "New integrator instance created for " << ndim << "-dimensional integration.";
158
159 if (!integrator_)
160 throw CG_FATAL("Generator:integrate") << "No integrator object was declared for the generator!";
161
162 xsect_ = integrator_->integrate(worker_->integrand());
163
164 CG_DEBUG("Generator:integrate") << "Computed cross section: (" << xsect_ << ") pb.";
165
166 // now that the cross section has been computed, feed it to the event modification algorithms...
167 for (auto& mod : parameters_->eventModifiersSequence())
168 mod->setCrossSection(xsect_);
169 // ...and to the event storage algorithms
170 for (auto& mod : parameters_->eventExportersSequence())
171 mod->setCrossSection(xsect_);
172 }
173
174 void Generator::initialise() {
175 if (!parameters_)
176 throw CG_FATAL("Generator:generate") << "No steering parameters specified!";
177
178 CG_TICKER(parameters_->timeKeeper());
179
180 // if no worker is found, launch a new integration/run preparation
181 if (!worker_)
182 integrate();
183
184 // prepare the run parameters for event generation
185 parameters_->initialiseModules();
186 worker_->initialise();
187
188 initialised_ = true;
189 }
190
192 if (!worker_ || !initialised_)
193 initialise();
194 size_t num_try = 0;
195 while (!worker_->next()) {
196 if (num_try++ > 5)
197 throw CG_FATAL("Generator:next") << "Failed to generate the next event!";
198 }
199 return worker_->integrand().process().event();
200 }
201
202 void Generator::generate(size_t num_events, const std::function<void(const proc::Process&)>& callback) {
203 CG_TICKER(parameters_->timeKeeper());
204
205 if (!worker_ || !initialised_)
206 initialise();
207
208 //--- if invalid argument, retrieve from runtime parameters
209 if (num_events < 1) {
210 if (parameters_->generation().targetLuminosity() > 0.) {
211 num_events = std::ceil(parameters_->generation().targetLuminosity() * xsect_);
212 CG_INFO("Generator") << "Target luminosity: " << parameters_->generation().targetLuminosity() << " pb-1.";
213 } else
214 num_events = parameters_->generation().maxGen();
215 }
216
217 CG_INFO("Generator") << utils::s("event", num_events, true) << " will be generated.";
218
219 const utils::Timer tmr;
220
221 //--- launch the event generation
222
223 worker_->generate(num_events, callback);
224
225 const double gen_time_s = tmr.elapsed();
226 const double rate_ms =
227 (parameters_->numGeneratedEvents() > 0) ? gen_time_s / parameters_->numGeneratedEvents() * 1.e3 : 0.;
228 const double equiv_lumi = parameters_->numGeneratedEvents() / crossSection();
229 CG_INFO("Generator") << utils::s("event", parameters_->numGeneratedEvents()) << " generated in " << gen_time_s
230 << " s "
231 << "(" << rate_ms << " ms/event).\n\t"
232 << "Equivalent luminosity: " << utils::format("%g", equiv_lumi) << " pb^-1.";
233 }
234
235 void Generator::generate(size_t num_events, const std::function<void(const Event&, size_t)>& callback) {
236 generate(num_events, [&](const proc::Process& proc) {
237 if (callback)
238 callback(proc.event(), parameters_->numGeneratedEvents());
239 });
240 }
241} // namespace cepgen
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_DEBUG(mod)
Definition Message.h:220
#define CG_INFO(mod)
Definition Message.h:216
#define CG_TICKER(tmr)
Definition TimeKeeper.h:30
Container for the information on the in- and outgoing particles' kinematics.
Definition Event.h:28
void generate(size_t num_events, const std::function< void(const Event &, size_t)> &)
Generate events.
double computePoint(const std::vector< double > &x)
Compute one single point from the total phase space.
Definition Generator.cpp:90
void integrate()
Integrate the functional over the phase space of interest.
void parseRunParameters(const std::string &)
Read a steering card to populate the run parameters block.
Definition Generator.cpp:72
void setIntegrator(std::unique_ptr< Integrator >)
Specify an integrator algorithm configuration.
const Event & next()
Generate one single event.
Generator(bool safe_mode=false)
Initialise the Monte Carlo integrator and event generator.
Definition Generator.cpp:38
void setRunParameters(std::unique_ptr< RunParameters > &)
Feed the generator with a RunParameters object.
Definition Generator.cpp:88
double crossSection() const
Last cross section computed by the generator.
Definition Generator.h:69
const RunParameters & runParameters() const
Pointer to the parameters block.
Definition Generator.cpp:76
Value computeXsection()
Compute the cross section and uncertainty, in pb, for the run parameters Compute the cross section fo...
List of parameters used to start and run the simulation job.
A scalar value with its uncertainty.
Definition Value.h:26
Class template to define any process to compute using this MC integrator/events generator.
Definition Process.h:34
const Event & event() const
Handled particles objects and their relationships.
Definition Process.cpp:267
A generic timer to extract the processing time between two steps in this software's flow.
Definition Timer.h:30
double elapsed() const
Time elapsed since the last reset call (or class construction)
Definition Timer.h:37
std::string format(const std::string &fmt, Args... args)
Format a string using a printf style format descriptor.
Definition String.h:61
std::string s(const std::string &word, float num, bool show_number)
Add a trailing "s" when needed.
Definition String.cpp:228
Common namespace for this Monte Carlo generator.
void initialise(bool safe_mode)
static CardsHandlerFactory & get()