LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
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 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.

References data_, debug_, art::Globals::instance(), nPrint_, postBeginJob(), postEndJob(), preProcessEvent(), restoreFromFilename_, restoreStateLabel_, and saveToFilename_.

120  : defaultEngineKind_{config().defaultEngineKind()}
121  , restoreStateLabel_{config().restoreStateLabel()}
122  , saveToFilename_{config().saveTo()}
123  , restoreFromFilename_{config().restoreFrom()}
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_
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 258 of file RandomNumberGenerator.cc.

References data_, and mutex_.

259  {
260  std::lock_guard sentry{mutex_};
261  return data_[sid].snapshot_;
262  }
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.

References data_, defaultEngineKind_, engine_creation_is_okay_, art::ScheduleID::id(), invariant_holds_(), mutex_, Seed, useDefaultSeed, and validate_().

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
long seed
Definition: chem4.cc:67
void validate_(std::string const &user_specified_engine_kind, long user_specified_seed) noexcept(false)
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.

References seed.

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

Definition at line 111 of file RandomNumberGenerator.cc.

Referenced by createEngine(), restoreFromFile_(), and restoreSnapshot_().

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 416 of file RandomNumberGenerator.cc.

References engine_creation_is_okay_, mutex_, and restoreFromFile_().

Referenced by RandomNumberGenerator().

417  {
418  std::lock_guard sentry{mutex_};
420  engine_creation_is_okay_ = false;
421  }
void art::RandomNumberGenerator::postEndJob ( )
private

Definition at line 434 of file RandomNumberGenerator.cc.

References data_, art::ScheduleIteration::for_each_schedule(), mutex_, saveToFile_(), and takeSnapshot_().

Referenced by RandomNumberGenerator().

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

Definition at line 424 of file RandomNumberGenerator.cc.

References art::ScheduleContext::id(), mutex_, restoreSnapshot_(), and takeSnapshot_().

Referenced by RandomNumberGenerator().

426  {
427  auto const sid = sc.id();
428  std::lock_guard sentry{mutex_};
429  takeSnapshot_(sid);
430  restoreSnapshot_(sid, e);
431  }
void restoreSnapshot_(ScheduleID, Event const &)
Float_t sc
Definition: plot.C:23
Float_t e
Definition: plot.C:35
void art::RandomNumberGenerator::print_ ( ) const
private

Definition at line 235 of file RandomNumberGenerator.cc.

References d, data_, debug_, mutex_, and nPrint_.

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  };
254  cet::for_all_with_index(data_, print_per_stream);
255  }
PerScheduleContainer< ScheduleData > data_
Float_t d
Definition: plot.C:235
void art::RandomNumberGenerator::restoreFromFile_ ( )
private

Definition at line 355 of file RandomNumberGenerator.cc.

References art::errors::Configuration, d, data_, File, invariant_holds_(), art::errors::LogicError, mutex_, restoreFromFilename_, and Seed.

Referenced by postBeginJob().

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

References data_, File, invariant_holds_(), mutex_, Product, and restoreStateLabel_.

Referenced by preProcessEvent().

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

Definition at line 326 of file RandomNumberGenerator.cc.

References d, data_, mutex_, and saveToFilename_.

Referenced by postEndJob().

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

Definition at line 265 of file RandomNumberGenerator.cc.

References data_, and mutex_.

Referenced by postEndJob(), and preProcessEvent().

266  {
267  std::lock_guard sentry{mutex_};
268  mf::LogDebug log{"RANDOM"};
269  log << "RNGservice::takeSnapshot_() of the following engine labels:\n";
270  data_[sid].snapshot_.clear();
271  for (auto const& [label, eptr] : data_[sid].dict_) {
272  assert(eptr && "RNGservice::takeSnapshot_()");
273  data_[sid].snapshot_.emplace_back(
274  data_[sid].kind_[label], label, eptr->put());
275  log << " | " << label;
276  }
277  log << " |";
278  }
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.

References defaultEngineKind_, maxCLHEPSeed, and useDefaultSeed.

Referenced by createEngine().

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
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

bool const art::RandomNumberGenerator::debug_
private

Definition at line 293 of file RandomNumberGenerator.h.

Referenced by print_(), and RandomNumberGenerator().

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

Definition at line 281 of file RandomNumberGenerator.h.

Referenced by createEngine(), and validate_().

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

Definition at line 297 of file RandomNumberGenerator.h.

Referenced by createEngine(), and postBeginJob().

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

Definition at line 168 of file RandomNumberGenerator.h.

Referenced by validate_().

std::recursive_mutex art::RandomNumberGenerator::mutex_ {}
mutableprivate
unsigned const art::RandomNumberGenerator::nPrint_
private

Definition at line 294 of file RandomNumberGenerator.h.

Referenced by print_(), and RandomNumberGenerator().

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

Definition at line 290 of file RandomNumberGenerator.h.

Referenced by RandomNumberGenerator(), and restoreFromFile_().

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

Definition at line 284 of file RandomNumberGenerator.h.

Referenced by RandomNumberGenerator(), and restoreSnapshot_().

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

Definition at line 287 of file RandomNumberGenerator.h.

Referenced by RandomNumberGenerator(), and saveToFile_().

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

Definition at line 169 of file RandomNumberGenerator.h.

Referenced by createEngine(), and validate_().


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