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" 30 #include "cetlib/container_algorithms.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());
118 RandomNumberGenerator::RandomNumberGenerator(
Parameters const& config,
120 : defaultEngineKind_{config().defaultEngineKind()}
124 ,
debug_{config().debug()}
129 actReg.sPreProcessEvent.watch(
this,
134 CLHEP::HepRandomEngine&
136 std::string
const& module_label,
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";
185 data_[sid].dict_[label] = eptr;
187 data_[sid].kind_[label] = engineKind;
188 mf::LogInfo{
"RANDOM"} <<
"Instantiated " << engineKind <<
" engine \"" 189 << label <<
"\" with " 194 "RNGservice::createEngine() invariant failed");
200 std::string
const& user_specified_engine_kind,
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();
254 cet::for_all_with_index(
data_, print_per_stream);
257 vector<RNGsnapshot>
const&
260 std::lock_guard sentry{
mutex_};
261 return data_[sid].snapshot_;
267 std::lock_guard sentry{
mutex_};
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;
284 std::lock_guard sentry{
mutex_};
292 for (
auto const& snapshot : saved) {
293 string const& label = snapshot.label();
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";
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";
309 shared_ptr<CLHEP::HepRandomEngine> ep{
data_[sid].dict_[label]};
310 assert(ep &&
"RNGservice::restoreSnapshot_()");
312 auto const& est = snapshot.restoreState();
314 log <<
" successfully restored.\n";
317 <<
"RNGservice::restoreSnapshot_():\n" 318 <<
"Failed during restore of state of engine for \"" << label
328 std::lock_guard sentry{
mutex_};
332 HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
340 for (
auto const&
d :
data_) {
341 for (
auto const& [label, eptr] :
d.dict_) {
342 outfile << label <<
'\n';
343 assert(eptr &&
"RNGservice::saveToFile_()");
347 <<
"This module's engine has not been saved;\n" 357 std::lock_guard sentry{
mutex_};
361 HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
366 <<
"RNGservice::restoreFromFile_():\n" 368 <<
"\" to initialize engines\n";
371 for (
string label{}; infile >> 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(
':');
378 auto d =
data_[sid].dict_.find(label);
379 if (
d ==
data_[sid].dict_.end()) {
381 <<
"Attempt to restore an engine with label " << label
382 <<
" not configured in this job.\n";
384 assert((
data_[sid].tracker_.find(label) !=
data_[sid].tracker_.cend()) &&
385 "RNGservice::restoreFromFile_()");
388 auto& eptr =
d->second;
389 assert(eptr &&
"RNGservice::restoreFromFile_()");
390 if (!eptr->get(infile)) {
392 <<
"RNGservice::restoreFromFile_():\n" 393 <<
"Failed during restore of state of engine for label " << label
399 <<
"Engine state file contains two engine states with the same " 404 <<
"Internal error: attempt to restore an engine state " << label
406 <<
"which was originally initialized via an unknown or impossible " 410 "RNGservice::restoreFromFile_() invariant failure");
418 std::lock_guard sentry{
mutex_};
427 auto const sid = sc.
id();
428 std::lock_guard sentry{
mutex_};
438 std::lock_guard sentry{
mutex_};
static long constexpr maxCLHEPSeed
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_
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::string const saveToFilename_
bool invariant_holds_(ScheduleID)
void preProcessEvent(Event const &, ScheduleContext)
void validate_(std::string const &user_specified_engine_kind, long user_specified_seed) noexcept(false)
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
void takeSnapshot_(ScheduleID)
void for_each_schedule(F f) const
static Globals * instance()
cet::coded_exception< error, detail::translate > exception
Event finding and building.
std::string const restoreStateLabel_