gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
ColliderBit_eventloop.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
36 
39 
40 // #define COLLIDERBIT_DEBUG
41 #define DEBUG_PREFIX "DEBUG: OMP thread " << omp_get_thread_num() << ": "
42 
43 namespace Gambit
44 {
45 
46  namespace ColliderBit
47  {
48 
50  void operateLHCLoop(MCLoopInfo& result)
51  {
52  using namespace Pipes::operateLHCLoop;
53  static std::streambuf *coutbuf = std::cout.rdbuf(); // save cout buffer for running the loop quietly
54 
55  #ifdef COLLIDERBIT_DEBUG
56  cout << DEBUG_PREFIX << endl;
57  cout << DEBUG_PREFIX << "~~~~ New point! ~~~~" << endl;
58  #endif
59 
60  // Retrieve run options from the YAML file (or standalone code)
61  static bool first = true;
62  static bool silenceLoop;
63  static std::map<str,int> min_nEvents;
64  static std::map<str,int> max_nEvents;
65  static std::map<str,int> stoppingres;
66  if (first)
67  {
68  // Should we silence stdout during the loop?
69  silenceLoop = runOptions->getValueOrDef<bool>(true, "silenceLoop");
70 
71  // Retrieve all the names of all entries in the yaml options node.
72  std::vector<str> vec = runOptions->getNames();
73  // Step though the names, and accept only those with a "min_nEvents" sub-entry as colliders.
74  for (str& name : vec)
75  {
76  YAML::Node node = runOptions->getNode(name);
77  if (not node.IsScalar() and node["min_nEvents"]) result.collider_names.push_back(name);
78  }
79 
80  // Retrieve the options for each collider.
81  for (auto& collider : result.collider_names)
82  {
83  Options colOptions(runOptions->getValue<YAML::Node>(collider));
84  min_nEvents[collider] = colOptions.getValue<int>("min_nEvents");
85  max_nEvents[collider] = colOptions.getValue<int>("max_nEvents");
86  result.convergence_options[collider].target_stat = colOptions.getValue<double>("target_fractional_uncert");
87  result.convergence_options[collider].stop_at_sys = colOptions.getValueOrDef<bool>(true, "halt_when_systematic_dominated");
88  result.convergence_options[collider].all_analyses_must_converge = colOptions.getValueOrDef<bool>(false, "all_analyses_must_converge");
89  result.convergence_options[collider].all_SR_must_converge = colOptions.getValueOrDef<bool>(false, "all_SR_must_converge");
90  result.maxFailedEvents[collider] = colOptions.getValueOrDef<int>(1, "maxFailedEvents");
91  result.invalidate_failed_points[collider] = colOptions.getValueOrDef<bool>(false, "invalidate_failed_points");
92  stoppingres[collider] = colOptions.getValueOrDef<int>(200, "events_between_convergence_checks");
93  result.analyses[collider] = colOptions.getValueOrDef<std::vector<str>>(std::vector<str>(), "analyses");
94  result.event_count[collider] = 0;
95  // Check that the nEvents options given make sense.
96  if (min_nEvents.at(collider) > max_nEvents.at(collider))
97  ColliderBit_error().raise(LOCAL_INFO,"Option min_nEvents is greater than corresponding max_nEvents for collider "
98  +collider+". Please correct your YAML file.");
99  // Check that the analyses all correspond to actual ColliderBit analyses, and sort them into separate maps for each detector.
100  for (str& analysis : result.analyses.at(collider))
101  {
102  result.detector_analyses[collider][getDetector(analysis)].push_back(analysis);
103  }
104  }
105  first = false;
106  }
107 
108  // Do the base-level initialisation
109  Loop::executeIteration(BASE_INIT);
110 
111  // Mute stdout during the loop if requested
112  if (silenceLoop) std::cout.rdbuf(0);
113 
114  // For every collider requested in the yaml file:
115  for (auto& collider : result.collider_names)
116  {
117 
118  // Reset the event_generation_began and exceeded_maxFailedEvents flags
119  result.reset_flags();
120 
121  // Update the collider
122  result.set_current_collider(collider);
123 
124  // Initialise the count of the number of generated events.
125  result.current_event_count() = 0;
126 
127  #ifdef COLLIDERBIT_DEBUG
128  cout << DEBUG_PREFIX << "operateLHCLoop: Current collider is " << collider << "." << endl;
129  #endif
130 
132  Loop::reset();
133 
134  // Do the single-thread part of the collider initialization
135  #ifdef COLLIDERBIT_DEBUG
136  cout << DEBUG_PREFIX << "operateLHCLoop: Will execute COLLIDER_INIT" << endl;
137  #endif
138  Loop::executeIteration(COLLIDER_INIT);
139  // Any problem during COLLIDER_INIT step?
140  piped_warnings.check(ColliderBit_warning());
141  piped_errors.check(ColliderBit_error());
142 
143  // Do the OMP parallelized part of the collider initialization
144  #ifdef COLLIDERBIT_DEBUG
145  cout << DEBUG_PREFIX << "operateLHCLoop: Will execute COLLIDER_INIT_OMP" << endl;
146  #endif
147  #pragma omp parallel
148  {
149  Loop::executeIteration(COLLIDER_INIT_OMP);
150  }
151  // Any problems during the COLLIDER_INIT_OMP step?
152  piped_warnings.check(ColliderBit_warning());
153  piped_errors.check(ColliderBit_error());
154 
155  // Execute the sigle-thread iteration XSEC_CALCULATION
156  #ifdef COLLIDERBIT_DEBUG
157  cout << DEBUG_PREFIX << "operateLHCLoop: Will execute XSEC_CALCULATION" << endl;
158  #endif
159  Loop::executeIteration(XSEC_CALCULATION);
160  // Any problems during the XSEC_CALCULATION step?
161  piped_warnings.check(ColliderBit_warning());
162  piped_errors.check(ColliderBit_error());
163 
164  //
165  // The main OMP parallelized sections begin here
166  //
167  #ifdef COLLIDERBIT_DEBUG
168  cout << DEBUG_PREFIX << "operateLHCLoop: Will execute START_SUBPROCESS" << endl;
169  #endif
170  result.current_event_count() = 0;
171  #pragma omp parallel
172  {
173  Loop::executeIteration(START_SUBPROCESS);
174  }
175  // Any problems during the START_SUBPROCESS step?
176  piped_warnings.check(ColliderBit_warning());
177  piped_errors.check(ColliderBit_error());
178 
179  // Convergence loop
180  while(result.current_event_count() < max_nEvents.at(collider) and not *Loop::done)
181  {
182  int eventCountBetweenConvergenceChecks = 0;
183  #ifdef COLLIDERBIT_DEBUG
184  cout << DEBUG_PREFIX << "Starting main event loop. Will do " << stoppingres.at(collider) << " events before testing convergence." << endl;
185  #endif
186 
187  // Main event loop
188  result.event_generation_began = true;
189  #pragma omp parallel
190  {
191  while(eventCountBetweenConvergenceChecks < stoppingres.at(collider) and
192  result.current_event_count() < max_nEvents.at(collider) and
193  not *Loop::done and
194  not result.end_of_event_file and
195  not result.exceeded_maxFailedEvents and
196  not piped_errors.inquire()
197  )
198  {
199  bool thread_do_iteration = true;
200  int thread_my_iteration;
201 
202  // Increment counters before executing the corresponding event loop iteration,
203  // to stop other threads from starting any event iterations beyond max_nEvents.
204  #pragma omp critical
205  {
206  if(result.current_event_count() < max_nEvents.at(collider))
207  {
208  result.current_event_count()++;
209  thread_my_iteration = result.current_event_count();
210  eventCountBetweenConvergenceChecks++;
211  }
212  else
213  {
214  thread_do_iteration = false;
215  }
216  }
217 
218  if(thread_do_iteration)
219  {
220  try
221  {
222  // Execute event loop iteration
223  Loop::executeIteration(thread_my_iteration);
224  }
225  catch (std::domain_error& e)
226  {
227  cout << "\n Caught std::domain_error. Continuing to the next event...\n\n";
228  // Decrement counters since the event iteration failed
229  #pragma omp critical
230  {
231  result.current_event_count()--;
232  eventCountBetweenConvergenceChecks--;
233  }
234  }
235  }
236 
237  } // end while loop
238 
239  } // end omp parallel block
240 
241  // Any problems during the main event loop?
242  piped_warnings.check(ColliderBit_warning());
243  piped_errors.check(ColliderBit_error());
244 
245  #ifdef COLLIDERBIT_DEBUG
246  cout << DEBUG_PREFIX << "Did " << eventCountBetweenConvergenceChecks << " events of " << result.current_event_count() << " simulated so far." << endl;
247  #endif
248 
249  // Break convergence loop if too many events fail
250  if(result.exceeded_maxFailedEvents) break;
251 
252  // Don't bother with convergence stuff if we haven't passed the minimum number of events yet
253  if (result.current_event_count() >= min_nEvents.at(collider))
254  {
255  #pragma omp parallel
256  {
257  Loop::executeIteration(COLLECT_CONVERGENCE_DATA);
258  }
259  // Any problems during the COLLECT_CONVERGENCE_DATA step?
260  piped_warnings.check(ColliderBit_warning());
261  piped_errors.check(ColliderBit_error());
262 
263  Loop::executeIteration(CHECK_CONVERGENCE);
264  // Any problems during the CHECK_CONVERGENCE step?
265  piped_warnings.check(ColliderBit_warning());
266  piped_errors.check(ColliderBit_error());
267  }
268 
269  }
270 
271  #ifdef COLLIDERBIT_DEBUG
272  cerr << DEBUG_PREFIX << "Final event count: current_event_count() = " << result.current_event_count() << endl;
273  #endif
274 
275  // Skip to next collider if too many events fail
276  if(result.exceeded_maxFailedEvents) continue;
277 
278  #pragma omp parallel
279  {
280  Loop::executeIteration(END_SUBPROCESS);
281  }
282  // Any problems during the END_SUBPROCESS step?
283  piped_warnings.check(ColliderBit_warning());
284  piped_errors.check(ColliderBit_error());
285 
286  //
287  // OMP parallelized sections end here
288  //
289 
290  Loop::executeIteration(COLLIDER_FINALIZE);
291  }
292 
293  // Nicely thank the loop for being quiet, and restore everyone's vocal chords
294  if (silenceLoop) std::cout.rdbuf(coutbuf);
295 
296  // Check for exceptions
298 
299  Loop::executeIteration(BASE_FINALIZE);
300  }
301 
302 
305  {
306  using namespace Pipes::getLHCEventLoopInfo;
307  result.clear();
308  result["did_event_generation"] = double(Dep::RunMC->event_generation_began);
309  result["too_many_failed_events"] = double(Dep::RunMC->exceeded_maxFailedEvents);
310  for (auto& name : Dep::RunMC->collider_names)
311  {
312  result["event_count_" + name] = Dep::RunMC->event_count.at(name);
313  }
314  }
315 
316 
319  {
320  using namespace Pipes::CollectAnalyses;
321  static bool first = true;
322 
323  // Start with an empty vector
324  result.clear();
325 
326  #ifdef COLLIDERBIT_DEBUG
327  cout << DEBUG_PREFIX << "CollectAnalyses: Dep::ATLASAnalysisNumbers->size() = " << Dep::ATLASAnalysisNumbers->size() << endl;
328  cout << DEBUG_PREFIX << "CollectAnalyses: Dep::CMSAnalysisNumbers->size() = " << Dep::CMSAnalysisNumbers->size() << endl;
329  cout << DEBUG_PREFIX << "CollectAnalyses: Dep::IdentityAnalysisNumbers->size() = " << Dep::IdentityAnalysisNumbers->size() << endl;
330  #endif
331 
332  // Add results
333  if (Dep::ATLASAnalysisNumbers->size() != 0) result.insert(result.end(), Dep::ATLASAnalysisNumbers->begin(), Dep::ATLASAnalysisNumbers->end());
334  if (Dep::CMSAnalysisNumbers->size() != 0) result.insert(result.end(), Dep::CMSAnalysisNumbers->begin(), Dep::CMSAnalysisNumbers->end());
335  if (Dep::IdentityAnalysisNumbers->size() != 0) result.insert(result.end(), Dep::IdentityAnalysisNumbers->begin(), Dep::IdentityAnalysisNumbers->end());
336 
337  // When first called, check that all analyses contain at least one signal region.
338  if (first)
339  {
340  // Loop over all AnalysisData pointers
341  for (auto& adp : result)
342  {
343  if (adp->size() == 0)
344  {
345  str errmsg;
346  errmsg = "The analysis " + adp->analysis_name + " has no signal regions.";
347  ColliderBit_error().raise(LOCAL_INFO, errmsg);
348  }
349  }
350  first = false;
351  }
352 
353 
354  // #ifdef COLLIDERBIT_DEBUG
355  // cout << DEBUG_PREFIX << "CollectAnalyses: Current size of 'result': " << result.size() << endl;
356  // if (result.size() > 0)
357  // {
358  // cout << DEBUG_PREFIX << "CollectAnalyses: Will loop through 'result'..." << endl;
359  // for (auto& adp : result)
360  // {
361  // cout << DEBUG_PREFIX << "CollectAnalyses: 'result' contains AnalysisData pointer to " << adp << endl;
362  // cout << DEBUG_PREFIX << "CollectAnalyses: -- Will now loop over all signal regions in " << adp << endl;
363  // for (auto& sr : adp->srdata)
364  // {
365  // cout << DEBUG_PREFIX << "CollectAnalyses: -- " << adp << " contains signal region: " << sr.sr_label << ", n_sig_MC = " << sr.n_sig_MC << ", n_sig_scaled = " << n_sig_scaled << endl;
366  // }
367  // cout << DEBUG_PREFIX << "CollectAnalyses: -- Done looping over signal regions in " << adp << endl;
368  // }
369  // cout << DEBUG_PREFIX << "CollectAnalyses: ...Done looping through 'result'." << endl;
370  // }
371  // #endif
372  }
373 
374 
375  }
376 
377 }
std::map< str, int > event_count
Number of events generated for each collider.
Definition: MCLoopInfo.hpp:52
DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry double
Piped_exceptions piped_errors
Global instance of Piped_exceptions class for errors.
void operateLHCLoop(MCLoopInfo &result)
LHC Loop Manager.
void getLHCEventLoopInfo(map_str_dbl &result)
Store some information about the event generation.
bool end_of_event_file
Maximum allowed number of failed events has been reached and MC loop terminated.
Definition: MCLoopInfo.hpp:40
#define LOCAL_INFO
Definition: local_info.hpp:34
const int & current_event_count() const
Get the number of events generated for the current collider.
Definition: MCLoopInfo.cpp:135
Piped_exceptions piped_warnings
Global instance of Piped_exceptions class for warnings.
bool exceeded_maxFailedEvents
Maximum allowed number of failed events has been reached.
Definition: MCLoopInfo.hpp:37
bool inquire()
Check whether any exceptions were requested without handling them.
Definition: exceptions.cpp:607
std::map< str, convergence_settings > convergence_options
Convergence options for each collider.
Definition: MCLoopInfo.hpp:55
std::map< str, bool > invalidate_failed_points
Invalidate points where number of failed events > maxFailedEvents? One bool for each collider...
Definition: MCLoopInfo.hpp:49
Piped_invalid_point piped_invalid_point
Global instance of piped invalid point class.
Definition: exceptions.cpp:544
Declarations common to all ColliderBit event loop functions.
void CollectAnalyses(AnalysisDataPointers &result)
Loop over all analyses and collect them in one place.
TYPE getValue(const args &... keys) const
bool event_generation_began
Event generation has started.
Definition: MCLoopInfo.hpp:34
#define DEBUG_PREFIX
void reset_flags()
Reset flags.
Definition: MCLoopInfo.cpp:51
std::map< str, int > maxFailedEvents
Maximum allowable number of failed events before MC loop is terminated for each collider.
Definition: MCLoopInfo.hpp:46
std::vector< str > collider_names
The names of all colliders.
Definition: MCLoopInfo.hpp:43
std::map< str, std::map< str, std::vector< str > > > detector_analyses
Analysis list for each detector of each collider.
Definition: MCLoopInfo.hpp:61
Header file that includes all GAMBIT headers required for a module source file.
void set_current_collider(str &)
Set the current collider.
Definition: MCLoopInfo.cpp:59
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
TYPE getValueOrDef(TYPE def, const args &... keys) const
str getDetector(const str &name)
Return the detector to be used for a given analysis name, checking that the analysis exists...
void check(exception &excep)
Check whether any exceptions were requested, and raise them.
Definition: exceptions.cpp:564
void check()
Check whether an exception was requested, and throw it if necessary.
Definition: exceptions.cpp:481
std::map< std::string, double > map_str_dbl
Shorthand for a string-to-double map.
std::vector< T > vec(std::vector< T > vector)
Definition: daFunk.hpp:142
std::vector< const AnalysisData * > AnalysisDataPointers
TODO: see if we can use this one:
Definition: Analysis.hpp:33
A small wrapper object for &#39;options&#39; nodes.
Container for event loop status data and settings.
Definition: MCLoopInfo.hpp:31
std::map< str, std::vector< str > > analyses
Analysis list for each collider.
Definition: MCLoopInfo.hpp:58