20 #include <momemta/MoMEMta.h> 27 #include <momemta/Configuration.h> 28 #include <momemta/Logging.h> 29 #include <momemta/ParameterSet.h> 30 #include <momemta/Utils.h> 31 #include <momemta/Unused.h> 34 #include <ModuleUtils.h> 35 #include <lua/utils.h> 38 #define CUBA_ABORT -999 46 void validateModules(
const std::vector<Configuration::ModuleDecl>& module_decls,
47 const momemta::ModuleList& available_modules) {
49 bool all_parameters_valid =
true;
51 for (
const auto& decl: module_decls) {
53 auto it = std::find_if(available_modules.begin(), available_modules.end(),
54 [&decl](
const momemta::ModuleList::value_type& available_module) {
57 return available_module.name == decl.type;
60 if (it == available_modules.end())
61 throw std::runtime_error(
"A module was declared with a type unknown to the registry. This is not supposed to " 64 const auto& def = *it;
70 all_parameters_valid &= momemta::validateModuleParameters(def, *decl.parameters);
73 if (! all_parameters_valid) {
76 "Check the log output for more details on how to fix your configuration file.");
78 LOG(fatal) << exception.what();
89 momemta::ModuleList available_modules;
93 std::vector<Configuration::ModuleDecl> module_instances_def = configuration.
getModules();
101 std::vector<InputTag> integrands = configuration.
getIntegrands();
102 if (!integrands.size()) {
104 <<
"No integrand found. Define which module's output you want to use as the integrand using the lua `integrand` function.";
105 throw integrands_output_error(
"No integrand found");
108 std::string export_graph_as;
114 m_computation_graph = builder.build();
116 if (! export_graph_as.empty())
117 builder.exportGraph(export_graph_as);
120 initPool(configuration);
123 m_computation_graph->initialize(m_pool);
125 for (
const auto& component: integrands) {
126 m_integrands.push_back(m_pool->get<
double>(component));
127 LOG(debug) <<
"Configuration declared integrand component using: " << component.toString();
129 m_n_components = m_integrands.size();
131 m_n_dimensions = m_computation_graph->getNDimensions();
132 LOG(info) <<
"Number of expected inputs: " << m_inputs_p4.size();
133 LOG(info) <<
"Number of dimensions for integration: " << m_n_dimensions;
136 m_ps_points->resize(m_n_dimensions);
143 m_computation_graph->configure();
146 cubalogging(MoMEMta::cuba_logging);
150 m_computation_graph->finish();
157 std::vector<std::pair<double, double>>
MoMEMta::computeWeights(
const std::vector<momemta::Particle>& particles,
const LorentzVector& met) {
159 if (particles.size() != m_inputs_p4.size()) {
160 auto exception = invalid_inputs(
"Some inputs are missing. " + std::to_string(m_inputs_p4.size()) +
" expected, " 161 + std::to_string(particles.size()) +
" provided.");
162 LOG(fatal) << exception.what();
166 std::vector<std::string> consumed_inputs;
167 for (
const auto& p: particles) {
168 checkIfPhysical(p.p4);
170 if (m_inputs_p4.count(p.name) == 0) {
171 auto exception = invalid_inputs(p.name +
" is not a declared input");
172 LOG(fatal) << exception.what();
176 if (std::find(consumed_inputs.begin(), consumed_inputs.end(), p.name) != consumed_inputs.end()) {
177 auto exception = invalid_inputs(
"Duplicated input " + p.name);
178 LOG(fatal) << exception.what();
182 *m_inputs_p4[p.name] = p.p4;
183 *m_inputs_type[p.name] = p.type;
185 consumed_inputs.push_back(p.name);
190 m_computation_graph->beginIntegration();
192 std::unique_ptr<double[]> mcResult(
new double[m_n_components]);
193 std::unique_ptr<double[]> error(
new double[m_n_components]);
195 for (
size_t i = 0; i < m_n_components; i++) {
200 if (m_n_dimensions > 0) {
204 std::string algorithm = m_cuba_configuration.get<std::string>(
"algorithm",
"vegas");
207 double relative_accuracy = m_cuba_configuration.get<
double>(
"relative_accuracy", 0.005);
208 double absolute_accuracy = m_cuba_configuration.get<
double>(
"absolute_accuracy", 0.);
209 int64_t seed = m_cuba_configuration.get<int64_t>(
"seed", 0);
210 int64_t min_eval = m_cuba_configuration.get<int64_t>(
"min_eval", 0);
211 int64_t max_eval = m_cuba_configuration.get<int64_t>(
"max_eval", 500000);
212 std::string grid_file = m_cuba_configuration.get<std::string>(
"grid_file",
"");
215 uint8_t verbosity = m_cuba_configuration.get<int64_t>(
"verbosity", 0);
216 bool subregion = m_cuba_configuration.get<
bool>(
"subregion",
false);
217 bool retainStateFile = m_cuba_configuration.get<
bool>(
"retainStateFile",
false);
218 uint64_t level = m_cuba_configuration.get<int64_t>(
"level", 0);
220 bool takeOnlyGridFromFile = m_cuba_configuration.get<
bool>(
"takeOnlyGridFromFile",
true);
222 bool smoothing = m_cuba_configuration.get<
bool>(
"smoothing",
true);
224 unsigned int flags = cuba::createFlagsBitset(verbosity, subregion, retainStateFile, level, smoothing, takeOnlyGridFromFile);
226 int64_t ncores = m_cuba_configuration.get<int64_t>(
"ncores", 0);
227 int64_t pcores = m_cuba_configuration.get<int64_t>(
"pcores", 1000000);
228 cubacores(ncores, pcores);
231 long long int neval = 0;
233 std::unique_ptr<double[]> prob(
new double[m_n_components]);
235 for (
size_t i = 0; i < m_n_components; i++) {
239 if (algorithm ==
"vegas") {
240 int64_t n_start = m_cuba_configuration.get<int64_t>(
"n_start", 25000);
241 int64_t n_increase = m_cuba_configuration.get<int64_t>(
"n_increase", 0);
242 int64_t batch_size = m_cuba_configuration.get<int64_t>(
"batch_size", std::min(n_start, 50000L));
243 int64_t grid_number = m_cuba_configuration.get<int64_t>(
"grid_number", 0);
248 (integrand_t) CUBAIntegrandWeighted,
269 }
else if (algorithm ==
"suave") {
270 int64_t n_new = m_cuba_configuration.get<int64_t>(
"n_new", 1000);
271 int64_t n_min = m_cuba_configuration.get<int64_t>(
"n_min", 2);
272 double flatness = m_cuba_configuration.get<
double>(
"flatness", 0.25);
279 (integrand_t) CUBAIntegrandWeighted,
300 }
else if (algorithm ==
"divonne") {
301 int64_t key1 = m_cuba_configuration.get<int64_t>(
"key1", 47);
302 int64_t key2 = m_cuba_configuration.get<int64_t>(
"key2", 1);
303 int64_t key3 = m_cuba_configuration.get<int64_t>(
"key3", 1);
304 int64_t maxpass = m_cuba_configuration.get<int64_t>(
"maxpass", 5);
305 double border = m_cuba_configuration.get<
double>(
"border", 0);
306 double maxchisq = m_cuba_configuration.get<
double>(
"maxchisq", 10.0);
307 double mindeviation = m_cuba_configuration.get<
double>(
"mindeviation", 0.25);
314 (integrand_t) CUBAIntegrand,
342 }
else if (algorithm ==
"cuhre") {
343 int64_t key = m_cuba_configuration.get<int64_t>(
"key", 0);
350 (integrand_t) CUBAIntegrand,
369 throw cuba_configuration_error(
"Integration algorithm " + algorithm +
" is not supported");
374 }
else if (nfail == -1) {
376 }
else if (nfail > 0) {
378 }
else if (nfail == -99) {
383 LOG(debug) <<
"No integration dimension requested, bypassing integration.";
386 int status = integrand(
nullptr, mcResult.get(),
nullptr);
388 if (status == CUBA_OK) {
396 m_computation_graph->logTimings();
399 m_computation_graph->endIntegration();
401 std::vector<std::pair<double, double>> result;
402 for (
size_t i = 0; i < m_n_components; i++) {
403 result.push_back( std::make_pair(mcResult[i], error[i]) );
409 int MoMEMta::integrand(
const double* psPoints,
double* results,
const double* weights=
nullptr) {
412 std::memcpy(m_ps_points->data(), psPoints,
sizeof(double) * m_n_dimensions);
414 if (weights !=
nullptr) {
416 *m_ps_weight = *weights;
419 auto status = m_computation_graph->execute();
421 int return_value = CUBA_OK;
422 if (status != Module::Status::OK) {
423 for (
size_t i = 0; i < m_n_components; i++)
426 if (status == Module::Status::ABORT)
427 return_value = CUBA_ABORT;
429 for (
size_t i = 0; i < m_n_components; i++) {
430 results[i] = *(m_integrands[i]);
431 if (!std::isfinite(results[i]))
432 throw integrands_nonfinite_error(
"Integrand component " + std::to_string(i) +
" is infinite or NaN!");
439 int MoMEMta::CUBAIntegrand(
const int *nDim,
const double* psPoint,
const int *nComp,
double *value,
void *inputs,
const int *nVec,
const int *core) {
445 return static_cast<MoMEMta*
>(inputs)->integrand(psPoint, value);
448 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) {
454 return static_cast<MoMEMta*
>(inputs)->integrand(psPoint, value, weight);
457 void MoMEMta::cuba_logging(
const char* s) {
458 std::stringstream ss(s);
461 while(std::getline(ss, line,
'\n')) {
462 if (line.length() > 0)
468 return integration_status;
471 void MoMEMta::checkIfPhysical(
const LorentzVector& p4) {
473 if ((p4.M2() < 0) || (p4.E() < 0)) {
474 auto exception = unphysical_lorentzvector_error(p4);
475 LOG(fatal) << exception.what();
482 m_pool.reset(
new Pool());
485 m_ps_points = m_pool->put<std::vector<double>>({
"cuba",
"ps_points"});
486 m_ps_weight = m_pool->put<
double>({
"cuba",
"ps_weight"});
490 for (
const auto& input: inputs) {
491 LOG(debug) <<
"Input declared: " << input;
492 m_inputs_p4.emplace(input, m_pool->put<LorentzVector>({input,
"p4"}));
493 m_inputs_type.emplace(input, m_pool->put<int64_t>({input,
"type"}));
497 m_met = m_pool->put<LorentzVector>({
"met",
"p4"});
501 MoMEMta::unphysical_lorentzvector_error::unphysical_lorentzvector_error(
const LorentzVector& p4) {
502 std::stringstream msg;
504 msg <<
"Unphysical lorentz vector: " << p4;
505 msg <<
". Please ensure that the energy and the mass are positive or null.";
510 const char* MoMEMta::unphysical_lorentzvector_error::what()
const noexcept {
511 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.
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 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.