20 #include <momemta/MoMEMta.h> 28 #include <momemta/Configuration.h> 29 #include <momemta/Logging.h> 30 #include <momemta/ParameterSet.h> 31 #include <momemta/Utils.h> 32 #include <momemta/Unused.h> 35 #include <ModuleUtils.h> 36 #include <lua/utils.h> 39 #define CUBA_ABORT -999 47 void validateModules(
const std::vector<Configuration::ModuleDecl>& module_decls,
48 const momemta::ModuleList& available_modules) {
50 bool all_parameters_valid =
true;
52 for (
const auto& decl: module_decls) {
54 auto it = std::find_if(available_modules.begin(), available_modules.end(),
55 [&decl](
const momemta::ModuleList::value_type& available_module) {
58 return available_module.name == decl.type;
61 if (it == available_modules.end())
62 throw std::runtime_error(
"A module was declared with a type unknown to the registry. This is not supposed to " 65 const auto& def = *it;
71 all_parameters_valid &= momemta::validateModuleParameters(def, *decl.parameters);
74 if (! all_parameters_valid) {
77 "Check the log output for more details on how to fix your configuration file.");
79 LOG(fatal) << exception.what();
90 momemta::ModuleList available_modules;
94 std::vector<Configuration::ModuleDecl> module_instances_def = configuration.
getModules();
102 std::vector<InputTag> integrands = configuration.
getIntegrands();
103 if (!integrands.size()) {
105 <<
"No integrand found. Define which module's output you want to use as the integrand using the lua `integrand` function.";
106 throw integrands_output_error(
"No integrand found");
109 std::string export_graph_as;
115 m_computation_graph = builder.build();
117 if (! export_graph_as.empty())
118 builder.exportGraph(export_graph_as);
121 initPool(configuration);
124 m_computation_graph->initialize(m_pool);
126 for (
const auto& component: integrands) {
127 m_integrands.push_back(m_pool->get<
double>(component));
128 LOG(debug) <<
"Configuration declared integrand component using: " << component.toString();
130 m_n_components = m_integrands.size();
132 m_n_dimensions = m_computation_graph->getNDimensions();
133 LOG(info) <<
"Number of expected inputs: " << m_inputs_p4.size();
134 LOG(info) <<
"Number of dimensions for integration: " << m_n_dimensions;
137 m_ps_points->resize(m_n_dimensions);
144 m_computation_graph->configure();
147 cubalogging(MoMEMta::cuba_logging);
151 m_computation_graph->finish();
159 void MoMEMta::setEvent(
const std::vector<momemta::Particle>& particles,
const LorentzVector& met) {
160 if (particles.size() != m_inputs_p4.size()) {
161 auto exception = invalid_inputs(
"Some inputs are missing. " + std::to_string(m_inputs_p4.size()) +
" expected, " 162 + std::to_string(particles.size()) +
" provided.");
163 LOG(fatal) << exception.what();
167 std::vector<std::string> consumed_inputs;
168 for (
const auto& p: particles) {
169 checkIfPhysical(p.p4);
171 if (m_inputs_p4.count(p.name) == 0) {
172 auto exception = invalid_inputs(p.name +
" is not a declared input");
173 LOG(fatal) << exception.what();
177 if (std::find(consumed_inputs.begin(), consumed_inputs.end(), p.name) != consumed_inputs.end()) {
178 auto exception = invalid_inputs(
"Duplicated input " + p.name);
179 LOG(fatal) << exception.what();
183 *m_inputs_p4[p.name] = p.p4;
184 *m_inputs_type[p.name] = p.type;
186 consumed_inputs.push_back(p.name);
192 std::vector<std::pair<double, double>>
MoMEMta::computeWeights(
const std::vector<momemta::Particle>& particles,
const LorentzVector& met) {
195 m_computation_graph->beginIntegration();
197 std::unique_ptr<double[]> mcResult(
new double[m_n_components]);
198 std::unique_ptr<double[]> error(
new double[m_n_components]);
200 for (
size_t i = 0; i < m_n_components; i++) {
205 if (m_n_dimensions > 0) {
209 std::string algorithm = m_cuba_configuration.get<std::string>(
"algorithm",
"vegas");
212 double relative_accuracy = m_cuba_configuration.get<
double>(
"relative_accuracy", 0.005);
213 double absolute_accuracy = m_cuba_configuration.get<
double>(
"absolute_accuracy", 0.);
214 int64_t seed = m_cuba_configuration.get<int64_t>(
"seed", 0);
215 int64_t min_eval = m_cuba_configuration.get<int64_t>(
"min_eval", 0);
216 int64_t max_eval = m_cuba_configuration.get<int64_t>(
"max_eval", 500000);
217 std::string grid_file = m_cuba_configuration.get<std::string>(
"grid_file",
"");
220 uint8_t verbosity = m_cuba_configuration.get<int64_t>(
"verbosity", 0);
221 bool subregion = m_cuba_configuration.get<
bool>(
"subregion",
false);
222 bool retainStateFile = m_cuba_configuration.get<
bool>(
"retainStateFile",
false);
223 uint64_t level = m_cuba_configuration.get<int64_t>(
"level", 0);
225 bool takeOnlyGridFromFile = m_cuba_configuration.get<
bool>(
"takeOnlyGridFromFile",
true);
227 bool smoothing = m_cuba_configuration.get<
bool>(
"smoothing",
true);
229 unsigned int flags = cuba::createFlagsBitset(verbosity, subregion, retainStateFile, level, smoothing, takeOnlyGridFromFile);
231 int64_t ncores = m_cuba_configuration.get<int64_t>(
"ncores", 0);
232 int64_t pcores = m_cuba_configuration.get<int64_t>(
"pcores", 1000000);
233 cubacores(ncores, pcores);
236 long long int neval = 0;
238 std::unique_ptr<double[]> prob(
new double[m_n_components]);
240 for (
size_t i = 0; i < m_n_components; i++) {
244 if (algorithm ==
"vegas") {
245 int64_t n_start = m_cuba_configuration.get<int64_t>(
"n_start", 25000);
246 int64_t n_increase = m_cuba_configuration.get<int64_t>(
"n_increase", 0);
247 int64_t batch_size = m_cuba_configuration.get<int64_t>(
"batch_size", std::min(n_start, INT64_C(50000)));
248 int64_t grid_number = m_cuba_configuration.get<int64_t>(
"grid_number", 0);
253 reinterpret_cast<integrand_t>(CUBAIntegrandWeighted),
274 }
else if (algorithm ==
"suave") {
275 int64_t n_new = m_cuba_configuration.get<int64_t>(
"n_new", 1000);
276 int64_t n_min = m_cuba_configuration.get<int64_t>(
"n_min", 2);
277 double flatness = m_cuba_configuration.get<
double>(
"flatness", 0.25);
284 reinterpret_cast<integrand_t>(CUBAIntegrandWeighted),
305 }
else if (algorithm ==
"divonne") {
306 int64_t key1 = m_cuba_configuration.get<int64_t>(
"key1", 47);
307 int64_t key2 = m_cuba_configuration.get<int64_t>(
"key2", 1);
308 int64_t key3 = m_cuba_configuration.get<int64_t>(
"key3", 1);
309 int64_t maxpass = m_cuba_configuration.get<int64_t>(
"maxpass", 5);
310 double border = m_cuba_configuration.get<
double>(
"border", 0);
311 double maxchisq = m_cuba_configuration.get<
double>(
"maxchisq", 10.0);
312 double mindeviation = m_cuba_configuration.get<
double>(
"mindeviation", 0.25);
319 reinterpret_cast<integrand_t>(CUBAIntegrand),
347 }
else if (algorithm ==
"cuhre") {
348 int64_t key = m_cuba_configuration.get<int64_t>(
"key", 0);
355 reinterpret_cast<integrand_t>(CUBAIntegrand),
374 throw cuba_configuration_error(
"Integration algorithm " + algorithm +
" is not supported");
379 }
else if (nfail == -1) {
381 }
else if (nfail > 0) {
383 }
else if (nfail == -99) {
388 LOG(debug) <<
"No integration dimension requested, bypassing integration.";
391 int status = integrand(
nullptr, mcResult.get(),
nullptr);
393 if (status == CUBA_OK) {
401 m_computation_graph->logTimings();
404 m_computation_graph->endIntegration();
406 std::vector<std::pair<double, double>> result;
407 for (
size_t i = 0; i < m_n_components; i++) {
408 result.push_back( std::make_pair(mcResult[i], error[i]) );
416 if (psPoints.size() != m_n_dimensions) {
417 throw invalid_inputs(
"Dimensionality of the phase-space point is incorrect.");
420 std::vector<double> results(m_n_components);
422 integrand(static_cast<const double*>(&psPoints[0]), &results[0]);
427 int MoMEMta::integrand(
const double* psPoints,
double* results,
const double* weights) {
430 std::memcpy(m_ps_points->data(), psPoints,
sizeof(double) * m_n_dimensions);
432 if (weights !=
nullptr) {
434 *m_ps_weight = *weights;
437 auto status = m_computation_graph->execute();
439 int return_value = CUBA_OK;
440 if (status != Module::Status::OK) {
441 for (
size_t i = 0; i < m_n_components; i++)
444 if (status == Module::Status::ABORT)
445 return_value = CUBA_ABORT;
447 for (
size_t i = 0; i < m_n_components; i++) {
448 results[i] = *(m_integrands[i]);
449 if (!std::isfinite(results[i]))
450 throw integrands_nonfinite_error(
"Integrand component " + std::to_string(i) +
" is infinite or NaN!");
457 int MoMEMta::CUBAIntegrand(
const int *nDim,
const double* psPoint,
const int *nComp,
double *value,
void *inputs,
const int *nVec,
const int *core) {
463 return static_cast<MoMEMta*
>(inputs)->integrand(psPoint, value);
466 int MoMEMta::CUBAIntegrandWeighted(
const int *nDim,
const double* psPoint,
const int *nComp,
double *value,
void *inputs,
const int *nVec,
const int *core,
const double *weight) {
472 return static_cast<MoMEMta*
>(inputs)->integrand(psPoint, value, weight);
475 void MoMEMta::cuba_logging(
const char* s) {
476 std::stringstream ss(s);
479 while(std::getline(ss, line,
'\n')) {
480 if (line.length() > 0)
486 return integration_status;
489 void MoMEMta::checkIfPhysical(
const LorentzVector& p4) {
491 if ((p4.M2() < 0) || (p4.E() < 0)) {
492 auto exception = unphysical_lorentzvector_error(p4);
493 LOG(fatal) << exception.what();
500 m_pool.reset(
new Pool());
503 m_ps_points = m_pool->put<std::vector<double>>({
"cuba",
"ps_points"});
504 m_ps_weight = m_pool->put<
double>({
"cuba",
"ps_weight"});
508 for (
const auto& input: inputs) {
509 LOG(debug) <<
"Input declared: " << input;
510 m_inputs_p4.emplace(input, m_pool->put<LorentzVector>({input,
"p4"}));
511 m_inputs_type.emplace(input, m_pool->put<int64_t>({input,
"type"}));
515 m_met = m_pool->put<LorentzVector>({
"met",
"p4"});
519 MoMEMta::unphysical_lorentzvector_error::unphysical_lorentzvector_error(
const LorentzVector& p4) {
520 std::stringstream msg;
522 msg <<
"Unphysical lorentz vector: " << p4;
523 msg <<
". Please ensure that the energy and the mass are positive or null.";
528 const char* MoMEMta::unphysical_lorentzvector_error::what()
const noexcept {
529 return _what.c_str();
const ParameterSet & getGlobalParameters() const
const Pool & getPool() const
Read-only access to the global memory pool.
IntegrationStatus getIntegrationStatus() const
Return the status of the integration.
std::vector< double > evaluateIntegrand(const std::vector< double > &psPoints)
Evaluate the integrand on a single phase-space point.
static ModuleRegistry & get()
A singleton available at startup.
virtual ~MoMEMta()
Destructor.
MoMEMta(const Configuration &configuration)
Create a new MoMEMta instance.
const ParameterSet & getCubaConfiguration() const
std::vector< InputTag > getIntegrands() const
std::vector< std::string > getInputs() const
Integration was successful.
< Thrown if the configuration file is not valid
A frozen snapshot of the configuration file.
void setEvent(const std::vector< momemta::Particle > &particles, const LorentzVector &met=LorentzVector())
Set the event particles' momenta.
void exportList(bool ignore_internal, ModuleList &list) const
Integration was stopped before desired accuracy was reached.
std::vector< std::pair< double, double > > computeWeights(const std::vector< momemta::Particle > &particles, const LorentzVector &met=LorentzVector())
Compute the weights in the current configuration.
const std::vector< ModuleDecl > & getModules() const
IntegrationStatus
Status of the integration.