9 #include "CLHEP/Random/DRand48Engine.h" 10 #include "CLHEP/Random/DualRand.h" 11 #include "CLHEP/Random/Hurd160Engine.h" 12 #include "CLHEP/Random/Hurd288Engine.h" 13 #include "CLHEP/Random/JamesRandom.h" 14 #include "CLHEP/Random/MTwistEngine.h" 15 #include "CLHEP/Random/MixMaxRng.h" 16 #include "CLHEP/Random/NonRandomEngine.h" 17 #include "CLHEP/Random/Random.h" 18 #include "CLHEP/Random/RanecuEngine.h" 19 #include "CLHEP/Random/Ranlux64Engine.h" 20 #include "CLHEP/Random/RanluxEngine.h" 21 #include "CLHEP/Random/RanshiEngine.h" 22 #include "CLHEP/Random/TripleRand.h" 31 #include "cetlib_except/exception.h" 32 #include "hep_concurrency/assert_only_one_thread.h" 43 using namespace string_literals;
49 long constexpr RandomNumberGenerator::maxCLHEPSeed;
50 long constexpr RandomNumberGenerator::useDefaultSeed;
55 qualify_engine_label(ScheduleID
const sid,
56 string const& module_label,
57 string const& engine_label)
61 label += module_label;
65 label += engine_label;
69 template <
class DesiredEngineType>
70 shared_ptr<CLHEP::HepRandomEngine>
71 manufacture_an_engine(
long const seed)
73 shared_ptr<CLHEP::HepRandomEngine> ret;
74 if (seed == RandomNumberGenerator::useDefaultSeed) {
75 ret.reset(
new DesiredEngineType);
77 ret.reset(
new DesiredEngineType(seed));
82 shared_ptr<CLHEP::HepRandomEngine>
83 engine_factory(
string const& kind_of_engine_to_make,
long const seed)
85 #define MANUFACTURE(ENGINE) \ 86 if (kind_of_engine_to_make == string{#ENGINE}) { \ 87 return manufacture_an_engine<CLHEP::ENGINE>(seed); \ 103 <<
"engine_factory():\n" 104 <<
"Attempt to create engine of unknown kind \"" 105 << kind_of_engine_to_make <<
"\".\n";
111 RandomNumberGenerator::invariant_holds_(
ScheduleID const sid)
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());
129 actReg.sPreProcessEvent.watch(
this,
134 CLHEP::HepRandomEngine&
138 string const& requested_engine_kind,
139 string const& engine_label)
141 std::lock_guard sentry{
mutex_};
144 <<
"RNGservice::createEngine():\n" 145 <<
"Attempt to create engine \"" << engine_label <<
"\" is too late.\n";
147 if (sid.
id() >=
data_.size()) {
149 <<
"RNGservice::createEngine():\n" 150 <<
"Attempt to create engine with out-of-range ScheduleID: " << sid
153 string const& label = qualify_engine_label(sid, module_label, engine_label);
154 if (
data_[sid].tracker_.find(label) !=
data_[sid].tracker_.cend()) {
156 <<
"RNGservice::createEngine():\n" 157 <<
"Engine \"" << label <<
"\" has already been created.\n";
159 string engineKind{requested_engine_kind};
160 if (requested_engine_kind.empty()) {
166 shared_ptr<CLHEP::HepRandomEngine> eptr;
167 if (engineKind ==
"G4Engine"s) {
171 CLHEP::HepRandom::setTheEngine(eptr.get());
172 if (seed != RandomNumberGenerator::useDefaultSeed) {
173 CLHEP::HepRandom::setTheSeed(seed);
175 }
else if (engineKind ==
"NonRandomEngine"s) {
176 eptr = std::make_shared<CLHEP::NonRandomEngine>();
178 eptr = engine_factory(engineKind, seed);
182 <<
"RNGservice::createEngine():\n" 183 <<
"Engine \"" << label <<
"\" could not be created.\n";
188 mf::LogInfo{
"RANDOM"} <<
"Instantiated " << engineKind <<
" engine \"" 189 << label <<
"\" with " 194 "RNGservice::createEngine() invariant failed");
201 long const user_specified_seed) noexcept(
false)
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";
220 if (user_specified_engine_kind ==
"MixMaxRng"s)
223 if (user_specified_engine_kind ==
"G4Engine"s &&
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
237 std::lock_guard sentry{
mutex_};
238 static unsigned ncalls = 0;
242 auto print_per_stream = [](
size_t const i,
auto const&
d) {
244 if (
d.snapshot_.empty()) {
245 log <<
"No snapshot has yet been made.\n";
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();
258 vector<RNGsnapshot>
const&
261 std::lock_guard sentry{
mutex_};
262 return data_[sid].snapshot_;
268 std::lock_guard sentry{
mutex_};
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;
287 std::lock_guard sentry{
mutex_};
295 for (
auto const& snapshot : saved) {
296 string const& label = snapshot.label();
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";
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";
312 shared_ptr<CLHEP::HepRandomEngine> ep{
data_[sid].dict_[
label]};
313 assert(ep &&
"RNGservice::restoreSnapshot_()");
315 auto const& est = snapshot.restoreState();
317 log <<
" successfully restored.\n";
320 <<
"RNGservice::restoreSnapshot_():\n" 321 <<
"Failed during restore of state of engine for \"" << label
331 std::lock_guard sentry{
mutex_};
335 HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
343 for (
auto const&
d :
data_) {
344 for (
auto const& pr :
d.dict_) {
346 auto const& eptr = pr.second;
347 assert(eptr &&
"RNGservice::saveToFile_()");
351 <<
"This module's engine has not been saved;\n" 361 std::lock_guard sentry{
mutex_};
365 HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
370 <<
"RNGservice::restoreFromFile_():\n" 372 <<
"\" to initialize engines\n";
377 assert(
count(label.cbegin(), label.cend(),
':') == 2u);
378 auto const p1 = label.find_first_of(
':');
379 auto const p2 = label.find_last_of(
':');
382 auto d =
data_[sid].dict_.find(label);
383 if (
d ==
data_[sid].dict_.end()) {
385 <<
"Attempt to restore an engine with label " << label
386 <<
" not configured in this job.\n";
388 assert((
data_[sid].tracker_.find(label) !=
data_[sid].tracker_.cend()) &&
389 "RNGservice::restoreFromFile_()");
392 auto& eptr =
d->second;
393 assert(eptr &&
"RNGservice::restoreFromFile_()");
396 <<
"RNGservice::restoreFromFile_():\n" 397 <<
"Failed during restore of state of engine for label " << label
403 <<
"Engine state file contains two engine states with the same " 408 <<
"Internal error: attempt to restore an engine state " << label
410 <<
"which was originally initialized via an unknown or impossible " 414 "RNGservice::restoreFromFile_() invariant failure");
422 std::lock_guard sentry{
mutex_};
431 auto const sid = sc.
id();
432 std::lock_guard sentry{
mutex_};
442 std::lock_guard sentry{
mutex_};
static long constexpr maxCLHEPSeed
void for_all_with_index(FwdCont &, Func)
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={})
std::string const restoreFromFilename_
std::vector< RNGsnapshot > const & accessSnapshot_(ScheduleID) const
PerScheduleContainer< ScheduleData > data_
void restoreSnapshot_(ScheduleID, Event const &)
#define MANUFACTURE(ENGINE)
static long constexpr useDefaultSeed
std::recursive_mutex mutex_
std::string const saveToFilename_
bool invariant_holds_(ScheduleID)
Atom< std::string > restoreStateLabel
void preProcessEvent(Event const &, ScheduleContext)
void validate_(std::string const &user_specified_engine_kind, long user_specified_seed) noexcept(false)
Atom< std::string > restoreFrom
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
constexpr id_type id() const noexcept
std::string const defaultEngineKind_
bool engine_creation_is_okay_
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
Atom< std::string > saveTo
void takeSnapshot_(ScheduleID)
void for_each_schedule(F f) const
static Globals * instance()
std::string to_string(ModuleType const mt)
cet::coded_exception< error, detail::translate > exception
Event finding and building.
Atom< std::string > defaultEngineKind
std::string const restoreStateLabel_