Classes | Public Types | Public Member Functions | Static Public Attributes | Private Member Functions | Private Attributes | Friends | List of all members
art::RandomNumberGenerator Class Reference

#include <RandomNumberGenerator.h>

Classes

struct  Config
 
struct  ScheduleData
 

Public Types

enum  EngineSource { EngineSource::Seed = 1, EngineSource::File = 2, EngineSource::Product = 3 }
 
using base_engine_t = CLHEP::HepRandomEngine
 
using seed_t = long
 
using Parameters = ServiceTable< Config >
 

Public Member Functions

 RandomNumberGenerator (Parameters const &, ActivityRegistry &)
 
 RandomNumberGenerator (RandomNumberGenerator const &)=delete
 
 RandomNumberGenerator (RandomNumberGenerator &&)=delete
 
RandomNumberGeneratoroperator= (RandomNumberGenerator const &)=delete
 
RandomNumberGeneratoroperator= (RandomNumberGenerator &&)=delete
 
std::string const & defaultEngineKind () const noexcept
 

Static Public Attributes

static long constexpr maxCLHEPSeed {900000000}
 
static long constexpr useDefaultSeed {-1}
 

Private Member Functions

CLHEP::HepRandomEngine & createEngine (ScheduleID sid, std::string const &module_label, long seed, std::string const &kind_of_engine_to_make, std::string const &engine_label={})
 
void validate_ (std::string const &user_specified_engine_kind, long user_specified_seed) noexcept(false)
 
void takeSnapshot_ (ScheduleID)
 
void restoreSnapshot_ (ScheduleID, Event const &)
 
std::vector< RNGsnapshot > const & accessSnapshot_ (ScheduleID) const
 
void saveToFile_ ()
 
void restoreFromFile_ ()
 
void print_ () const
 
bool invariant_holds_ (ScheduleID)
 
void preProcessEvent (Event const &, ScheduleContext)
 
void postProcessEvent (Event const &, ScheduleContext)
 
void postBeginJob ()
 
void postEndJob ()
 

Private Attributes

std::recursive_mutex mutex_ {}
 
std::string const defaultEngineKind_
 
std::string const restoreStateLabel_
 
std::string const saveToFilename_
 
std::string const restoreFromFilename_
 
bool const debug_
 
unsigned const nPrint_
 
bool engine_creation_is_okay_ {true}
 
PerScheduleContainer< ScheduleDatadata_
 

Friends

class EventProcessor
 
class detail::EngineCreator
 
class RandomNumberSaver
 

Detailed Description

Definition at line 158 of file RandomNumberGenerator.h.

Member Typedef Documentation

using art::RandomNumberGenerator::base_engine_t = CLHEP::HepRandomEngine

Definition at line 170 of file RandomNumberGenerator.h.

Definition at line 229 of file RandomNumberGenerator.h.

Definition at line 171 of file RandomNumberGenerator.h.

Member Enumeration Documentation

Enumerator
Seed 
File 
Product 

Definition at line 166 of file RandomNumberGenerator.h.

166 { Seed = 1, File = 2, Product = 3 };

Constructor & Destructor Documentation

art::RandomNumberGenerator::RandomNumberGenerator ( Parameters const &  config,
ActivityRegistry actReg 
)

Definition at line 118 of file RandomNumberGenerator.cc.

124  , debug_{config().debug()}
125  , nPrint_{config().nPrint()}
126  {
127  actReg.sPostBeginJob.watch(this, &RandomNumberGenerator::postBeginJob);
128  actReg.sPostEndJob.watch(this, &RandomNumberGenerator::postEndJob);
129  actReg.sPreProcessEvent.watch(this,
131  data_.resize(Globals::instance()->nschedules());
132  }
std::string const restoreFromFilename_
PerScheduleContainer< ScheduleData > data_
static Config * config
Definition: config.cpp:1054
void preProcessEvent(Event const &, ScheduleContext)
static Globals * instance()
Definition: Globals.cc:17
art::RandomNumberGenerator::RandomNumberGenerator ( RandomNumberGenerator const &  )
delete
art::RandomNumberGenerator::RandomNumberGenerator ( RandomNumberGenerator &&  )
delete

Member Function Documentation

vector< RNGsnapshot > const & art::RandomNumberGenerator::accessSnapshot_ ( ScheduleID  sid) const
private

Definition at line 259 of file RandomNumberGenerator.cc.

260  {
261  std::lock_guard sentry{mutex_};
262  return data_[sid].snapshot_;
263  }
PerScheduleContainer< ScheduleData > data_
CLHEP::HepRandomEngine & art::RandomNumberGenerator::createEngine ( ScheduleID  sid,
std::string const &  module_label,
long  seed,
std::string const &  kind_of_engine_to_make,
std::string const &  engine_label = {} 
)
private

Definition at line 135 of file RandomNumberGenerator.cc.

140  {
141  std::lock_guard sentry{mutex_};
143  throw cet::exception("RANDOM")
144  << "RNGservice::createEngine():\n"
145  << "Attempt to create engine \"" << engine_label << "\" is too late.\n";
146  }
147  if (sid.id() >= data_.size()) {
148  throw cet::exception("RANDOM")
149  << "RNGservice::createEngine():\n"
150  << "Attempt to create engine with out-of-range ScheduleID: " << sid
151  << "\n";
152  }
153  string const& label = qualify_engine_label(sid, module_label, engine_label);
154  if (data_[sid].tracker_.find(label) != data_[sid].tracker_.cend()) {
155  throw cet::exception("RANDOM")
156  << "RNGservice::createEngine():\n"
157  << "Engine \"" << label << "\" has already been created.\n";
158  }
159  string engineKind{requested_engine_kind};
160  if (requested_engine_kind.empty()) {
161  engineKind = defaultEngineKind_;
162  }
163 
164  validate_(engineKind, seed);
165 
166  shared_ptr<CLHEP::HepRandomEngine> eptr;
167  if (engineKind == "G4Engine"s) {
168  eptr = engine_factory(defaultEngineKind_, seed);
169  // We set CLHEP's random-number engine to be of type
170  // defaultEngineKind_.
171  CLHEP::HepRandom::setTheEngine(eptr.get());
173  CLHEP::HepRandom::setTheSeed(seed);
174  }
175  } else if (engineKind == "NonRandomEngine"s) {
176  eptr = std::make_shared<CLHEP::NonRandomEngine>();
177  } else {
178  eptr = engine_factory(engineKind, seed);
179  }
180  if (!eptr) {
181  throw cet::exception("RANDOM")
182  << "RNGservice::createEngine():\n"
183  << "Engine \"" << label << "\" could not be created.\n";
184  }
185  data_[sid].dict_[label] = eptr;
186  data_[sid].tracker_[label] = EngineSource::Seed;
187  data_[sid].kind_[label] = engineKind;
188  mf::LogInfo{"RANDOM"} << "Instantiated " << engineKind << " engine \""
189  << label << "\" with "
190  << ((seed == useDefaultSeed) ? "default seed " :
191  "seed ")
192  << seed << '.';
193  assert(invariant_holds_(sid) &&
194  "RNGservice::createEngine() invariant failed");
195  return *eptr;
196  }
PerScheduleContainer< ScheduleData > data_
static long constexpr useDefaultSeed
void validate_(std::string const &user_specified_engine_kind, long user_specified_seed) noexcept(false)
static QCString * s
Definition: config.cpp:1042
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::string const& art::RandomNumberGenerator::defaultEngineKind ( ) const
inlinenoexcept

Definition at line 239 of file RandomNumberGenerator.h.

240  {
241  return defaultEngineKind_;
242  }
bool art::RandomNumberGenerator::invariant_holds_ ( ScheduleID  sid)
private

Definition at line 111 of file RandomNumberGenerator.cc.

112  {
113  std::lock_guard sentry{mutex_};
114  return (data_[sid].dict_.size() == data_[sid].tracker_.size()) &&
115  (data_[sid].dict_.size() == data_[sid].kind_.size());
116  }
PerScheduleContainer< ScheduleData > data_
RandomNumberGenerator& art::RandomNumberGenerator::operator= ( RandomNumberGenerator const &  )
delete
RandomNumberGenerator& art::RandomNumberGenerator::operator= ( RandomNumberGenerator &&  )
delete
void art::RandomNumberGenerator::postBeginJob ( )
private

Definition at line 420 of file RandomNumberGenerator.cc.

421  {
422  std::lock_guard sentry{mutex_};
424  engine_creation_is_okay_ = false;
425  }
void art::RandomNumberGenerator::postEndJob ( )
private

Definition at line 438 of file RandomNumberGenerator.cc.

439  {
440  // For normal termination, we wish to save the state at the *end* of
441  // processing, not at the beginning of the last event.
442  std::lock_guard sentry{mutex_};
443  ScheduleIteration iteration(data_.size());
444  iteration.for_each_schedule(
445  [this](ScheduleID const sid) { takeSnapshot_(sid); });
446  saveToFile_();
447  }
PerScheduleContainer< ScheduleData > data_
void art::RandomNumberGenerator::postProcessEvent ( Event const &  ,
ScheduleContext   
)
private
void art::RandomNumberGenerator::preProcessEvent ( Event const &  e,
ScheduleContext  sc 
)
private

Definition at line 428 of file RandomNumberGenerator.cc.

430  {
431  auto const sid = sc.id();
432  std::lock_guard sentry{mutex_};
433  takeSnapshot_(sid);
434  restoreSnapshot_(sid, e);
435  }
void restoreSnapshot_(ScheduleID, Event const &)
const double e
void art::RandomNumberGenerator::print_ ( ) const
private

Definition at line 235 of file RandomNumberGenerator.cc.

236  {
237  std::lock_guard sentry{mutex_};
238  static unsigned ncalls = 0;
239  if (!debug_ || (++ncalls > nPrint_)) {
240  return;
241  }
242  auto print_per_stream = [](size_t const i, auto const& d) {
243  mf::LogInfo log{"RANDOM"};
244  if (d.snapshot_.empty()) {
245  log << "No snapshot has yet been made.\n";
246  return;
247  }
248  log << "Snapshot information:";
249  for (auto const& ss : d.snapshot_) {
250  log << "\nEngine: " << ss.label() << " Kind: " << ss.ekind()
251  << " Schedule ID: " << i << " State size: " << ss.state().size();
252  }
253  log << "\n";
254  };
255  cet::for_all_with_index(data_, print_per_stream);
256  }
void for_all_with_index(FwdCont &, Func)
PerScheduleContainer< ScheduleData > data_
void art::RandomNumberGenerator::restoreFromFile_ ( )
private

Definition at line 359 of file RandomNumberGenerator.cc.

360  {
361  std::lock_guard sentry{mutex_};
362  if (restoreFromFilename_.empty()) {
363  return;
364  }
365  HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
366  // access the file:
367  ifstream infile{restoreFromFilename_.c_str()};
368  if (!infile) {
369  throw cet::exception("RANDOM")
370  << "RNGservice::restoreFromFile_():\n"
371  << "Can't open file \"" << restoreFromFilename_
372  << "\" to initialize engines\n";
373  }
374  // restore engines:
375  for (string label{}; infile >> label;) {
376  // Get schedule ID from engine label
377  assert(count(label.cbegin(), label.cend(), ':') == 2u);
378  auto const p1 = label.find_first_of(':');
379  auto const p2 = label.find_last_of(':');
380  ScheduleID const sid{
381  static_cast<ScheduleID::size_type>(stoi(label.substr(p1 + 1, p2)))};
382  auto d = data_[sid].dict_.find(label);
383  if (d == data_[sid].dict_.end()) {
384  throw Exception(errors::Configuration, "RANDOM")
385  << "Attempt to restore an engine with label " << label
386  << " not configured in this job.\n";
387  }
388  assert((data_[sid].tracker_.find(label) != data_[sid].tracker_.cend()) &&
389  "RNGservice::restoreFromFile_()");
390  EngineSource& how{data_[sid].tracker_[label]};
391  if (how == EngineSource::Seed) {
392  auto& eptr = d->second;
393  assert(eptr && "RNGservice::restoreFromFile_()");
394  if (!eptr->get(infile)) {
395  throw cet::exception("RANDOM")
396  << "RNGservice::restoreFromFile_():\n"
397  << "Failed during restore of state of engine for label " << label
398  << "from file \"" << restoreFromFilename_ << "\"\n";
399  }
400  how = EngineSource::File;
401  } else if (how == EngineSource::File) {
402  throw Exception(errors::Configuration, "RANDOM")
403  << "Engine state file contains two engine states with the same "
404  "label: "
405  << label << "\n.";
406  } else {
407  throw Exception(errors::LogicError, "RANDOM")
408  << "Internal error: attempt to restore an engine state " << label
409  << " from file\n"
410  << "which was originally initialized via an unknown or impossible "
411  "method.\n";
412  }
413  assert(invariant_holds_(sid) &&
414  "RNGservice::restoreFromFile_() invariant failure");
415  }
416  }
std::string const restoreFromFilename_
PerScheduleContainer< ScheduleData > data_
string infile
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
id_type size_type
Definition: ScheduleID.h:25
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void art::RandomNumberGenerator::restoreSnapshot_ ( ScheduleID  sid,
Event const &  event 
)
private

Definition at line 284 of file RandomNumberGenerator.cc.

286  {
287  std::lock_guard sentry{mutex_};
288  if (restoreStateLabel_.empty()) {
289  return;
290  }
291  // access the saved-states product:
292  auto const& saved =
293  event.getProduct<vector<RNGsnapshot>>(restoreStateLabel_);
294  // restore engines from saved-states product:
295  for (auto const& snapshot : saved) {
296  string const& label = snapshot.label();
297  mf::LogInfo log("RANDOM");
298  log << "RNGservice::restoreSnapshot_(): label \"" << label << "\"";
299  auto t = data_[sid].tracker_.find(label);
300  if (t == data_[sid].tracker_.end()) {
301  log << " could not be restored;\n"
302  << "no established engine bears this label.\n";
303  continue;
304  }
305  if (t->second == EngineSource::File) {
306  throw cet::exception("RANDOM")
307  << "RNGservice::restoreSnapshot_():\n"
308  << "The state of engine \"" << label
309  << "\" has been previously read from a file;\n"
310  << "it is therefore not restorable from a snapshot product.\n";
311  }
312  shared_ptr<CLHEP::HepRandomEngine> ep{data_[sid].dict_[label]};
313  assert(ep && "RNGservice::restoreSnapshot_()");
314  data_[sid].tracker_[label] = EngineSource::Product;
315  auto const& est = snapshot.restoreState();
316  if (ep->get(est)) {
317  log << " successfully restored.\n";
318  } else {
319  throw cet::exception("RANDOM")
320  << "RNGservice::restoreSnapshot_():\n"
321  << "Failed during restore of state of engine for \"" << label
322  << "\"\n";
323  }
324  }
325  assert(invariant_holds_(sid) && "RNGsnapshot::restoreSnapshot_()");
326  }
PerScheduleContainer< ScheduleData > data_
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void art::RandomNumberGenerator::saveToFile_ ( )
private

Definition at line 329 of file RandomNumberGenerator.cc.

330  {
331  std::lock_guard sentry{mutex_};
332  if (saveToFilename_.empty()) {
333  return;
334  }
335  HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
336  // access the file:
337  ofstream outfile{saveToFilename_.c_str()};
338  if (!outfile) {
339  mf::LogWarning("RANDOM")
340  << "Can't create/access file \"" << saveToFilename_ << "\"\n";
341  }
342  // save each engine:
343  for (auto const& d : data_) {
344  for (auto const& pr : d.dict_) {
345  outfile << pr.first << '\n';
346  auto const& eptr = pr.second;
347  assert(eptr && "RNGservice::saveToFile_()");
348  eptr->put(outfile);
349  if (!outfile) {
350  mf::LogWarning("RANDOM")
351  << "This module's engine has not been saved;\n"
352  << "file \"" << saveToFilename_ << "\" is likely now corrupted.\n";
353  }
354  }
355  }
356  }
PerScheduleContainer< ScheduleData > data_
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void art::RandomNumberGenerator::takeSnapshot_ ( ScheduleID  sid)
private

Definition at line 266 of file RandomNumberGenerator.cc.

267  {
268  std::lock_guard sentry{mutex_};
269  mf::LogDebug log{"RANDOM"};
270  log << "RNGservice::takeSnapshot_() of the following engine labels:\n";
271  data_[sid].snapshot_.clear();
272  for (auto const& pr : data_[sid].dict_) {
273  string const& label = pr.first;
274  shared_ptr<CLHEP::HepRandomEngine> const& eptr = pr.second;
275  assert(eptr && "RNGservice::takeSnapshot_()");
276  data_[sid].snapshot_.emplace_back(
277  data_[sid].kind_[label], label, eptr->put());
278  log << " | " << label;
279  }
280  log << " |\n";
281  }
PerScheduleContainer< ScheduleData > data_
void art::RandomNumberGenerator::validate_ ( std::string const &  user_specified_engine_kind,
long  user_specified_seed 
)
privatenoexcept

Definition at line 199 of file RandomNumberGenerator.cc.

202  {
203  // The only time a user-specified seed can be negative is for
204  // indicating to this service that the default seed for the
205  // requested engine kind should be used.
206  if (user_specified_seed == useDefaultSeed)
207  return;
208 
209  if (user_specified_seed < 0) {
210  throw cet::exception("RANGE") << "RNGservice::throw_if_invalid_seed():\n"
211  << "Seed " << user_specified_seed
212  << " is not permitted to be negative.\n";
213  }
214 
215  if (user_specified_seed <= maxCLHEPSeed)
216  return;
217 
218  // For now, only MixMaxRng engines can be constructed with a seed
219  // value greater than maxCLHEPSeed.
220  if (user_specified_engine_kind == "MixMaxRng"s)
221  return;
222 
223  if (user_specified_engine_kind == "G4Engine"s &&
224  defaultEngineKind_ == "MixMaxRng"s)
225  return;
226 
227  throw cet::exception("RANGE")
228  << "RNGservice::throw_if_invalid_seed():\n"
229  << "Seed " << user_specified_seed << " exceeds permitted maximum of "
230  << maxCLHEPSeed << " for engine type " << user_specified_engine_kind
231  << ".\n";
232  }
static long constexpr maxCLHEPSeed
static long constexpr useDefaultSeed
static QCString * s
Definition: config.cpp:1042
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33

Friends And Related Function Documentation

friend class detail::EngineCreator
friend

Definition at line 161 of file RandomNumberGenerator.h.

friend class EventProcessor
friend

Definition at line 160 of file RandomNumberGenerator.h.

friend class RandomNumberSaver
friend

Definition at line 162 of file RandomNumberGenerator.h.

Member Data Documentation

PerScheduleContainer<ScheduleData> art::RandomNumberGenerator::data_
private

Definition at line 321 of file RandomNumberGenerator.h.

bool const art::RandomNumberGenerator::debug_
private

Definition at line 293 of file RandomNumberGenerator.h.

std::string const art::RandomNumberGenerator::defaultEngineKind_
private

Definition at line 281 of file RandomNumberGenerator.h.

bool art::RandomNumberGenerator::engine_creation_is_okay_ {true}
private

Definition at line 297 of file RandomNumberGenerator.h.

long constexpr art::RandomNumberGenerator::maxCLHEPSeed {900000000}
static

Definition at line 168 of file RandomNumberGenerator.h.

std::recursive_mutex art::RandomNumberGenerator::mutex_ {}
mutableprivate

Definition at line 279 of file RandomNumberGenerator.h.

unsigned const art::RandomNumberGenerator::nPrint_
private

Definition at line 294 of file RandomNumberGenerator.h.

std::string const art::RandomNumberGenerator::restoreFromFilename_
private

Definition at line 290 of file RandomNumberGenerator.h.

std::string const art::RandomNumberGenerator::restoreStateLabel_
private

Definition at line 284 of file RandomNumberGenerator.h.

std::string const art::RandomNumberGenerator::saveToFilename_
private

Definition at line 287 of file RandomNumberGenerator.h.

long constexpr art::RandomNumberGenerator::useDefaultSeed {-1}
static

Definition at line 169 of file RandomNumberGenerator.h.


The documentation for this class was generated from the following files: