00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "IOMC/RandomEngine/src/RandomNumberGeneratorService.h"
00014
00015 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00016 #include "FWCore/Framework/interface/Event.h"
00017 #include "FWCore/Framework/interface/LuminosityBlock.h"
00018 #include "FWCore/MessageLogger/interface/JobReport.h"
00019 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00020 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00021 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00022 #include "FWCore/ParameterSet/interface/ParameterWildcard.h"
00023 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
00024 #include "FWCore/ServiceRegistry/interface/Service.h"
00025 #include "FWCore/Utilities/interface/EDMException.h"
00026 #include "IOMC/RandomEngine/src/TRandomAdaptor.h"
00027 #include "SimDataFormats/RandomEngine/interface/RandomEngineState.h"
00028 #include "SimDataFormats/RandomEngine/interface/RandomEngineStates.h"
00029
00030 #include "CLHEP/Random/engineIDulong.h"
00031 #include "CLHEP/Random/JamesRandom.h"
00032 #include "CLHEP/Random/RanecuEngine.h"
00033
00034 #include <iostream>
00035 #include <limits>
00036 #include <sstream>
00037 #include <unistd.h>
00038
00039 namespace edm {
00040 namespace service {
00041
00042 uint32_t RandomNumberGeneratorService::maxSeedRanecu = 2147483647U;
00043 uint32_t RandomNumberGeneratorService::maxSeedHepJames = 900000000U;
00044 uint32_t RandomNumberGeneratorService::maxSeedTRandom3 = 4294967295U;
00045
00046 RandomNumberGeneratorService::RandomNumberGeneratorService(ParameterSet const& pset,
00047 ActivityRegistry& activityRegistry):
00048 restoreStateLabel_(pset.getUntrackedParameter<std::string>("restoreStateLabel")),
00049 saveFileName_(pset.getUntrackedParameter<std::string>("saveFileName")),
00050 saveFileNameRecorded_(false),
00051 restoreFileName_(pset.getUntrackedParameter<std::string>("restoreFileName")),
00052 enableChecking_(pset.getUntrackedParameter<bool>("enableChecking")),
00053 firstLumi_(true),
00054 childIndex_(0U),
00055 eventSeedOffset_(pset.getUntrackedParameter<unsigned>("eventSeedOffset")),
00056 failedToFindStatesInLumi_(false) {
00057
00058 if(!restoreFileName_.empty() && !restoreStateLabel_.empty()) {
00059 throw Exception(errors::Configuration)
00060 << "In the configuration for the RandomNumberGeneratorService both\n"
00061 << "restoreFileName and restoreStateLabel were set to nonempty values\n"
00062 << "which is illegal. It is impossible to restore the random engine\n"
00063 << "states two different ways in the same process.\n";
00064 }
00065
00066
00067
00068 if(!saveFileName_.empty() && (saveFileName_.find("/") != std::string::npos)) {
00069 throw Exception(errors::Configuration)
00070 << "The saveFileName parameter must be a simple file name with no path\n"
00071 << "specification. In the configuration, it was given the value \""
00072 << saveFileName_ << "\"\n";
00073 }
00074
00075
00076
00077
00078 if(pset.exists("moduleSeeds")) {
00079 oldStyleConfig(pset);
00080 } else {
00081
00082 uint32_t initialSeed;
00083 VUint32 initialSeedSet;
00084 std::string engineName;
00085
00086 VString pSets = pset.getParameterNamesForType<ParameterSet>();
00087 for(VString::const_iterator it = pSets.begin(), itEnd = pSets.end(); it != itEnd; ++it) {
00088
00089 ParameterSet const& modulePSet = pset.getParameterSet(*it);
00090 engineName = modulePSet.getUntrackedParameter<std::string>("engineName", std::string("HepJamesRandom"));
00091
00092 bool initialSeedExists = modulePSet.exists("initialSeed");
00093 bool initialSeedSetExists = modulePSet.exists("initialSeedSet");
00094
00095 if(initialSeedExists && initialSeedSetExists) {
00096 throw Exception(errors::Configuration)
00097 << "For the module with the label \"" << *it << "\",\n"
00098 << "both the parameters \"initialSeed\" and \"initialSeedSet\"\n"
00099 << "have been set in the configuration. You must set one or\n"
00100 << "the other. It is illegal to set both.\n";
00101 } else if(!initialSeedExists && !initialSeedSetExists) {
00102 throw Exception(errors::Configuration)
00103 << "For the module with the label \"" << *it << "\",\n"
00104 << "neither the parameter \"initialSeed\" nor \"initialSeedSet\"\n"
00105 << "has been set in the configuration. You must set one or\n"
00106 << "the other.\n";
00107 } else if(initialSeedExists) {
00108 initialSeed = modulePSet.getUntrackedParameter<uint32_t>("initialSeed");
00109 initialSeedSet.clear();
00110 initialSeedSet.push_back(initialSeed);
00111 } else if(initialSeedSetExists) {
00112 initialSeedSet = modulePSet.getUntrackedParameter<VUint32>("initialSeedSet");
00113 }
00114 seedMap_[*it] = initialSeedSet;
00115 engineNameMap_[*it] = engineName;
00116
00117
00118
00119 if(engineName == std::string("RanecuEngine")) {
00120 if(initialSeedSet.size() != 2U) {
00121 throw Exception(errors::Configuration)
00122 << "Random engines of type \"RanecuEngine\" require 2 seeds\n"
00123 << "be specified with the parameter named \"initialSeedSet\".\n"
00124 << "Either \"initialSeedSet\" was not in the configuration\n"
00125 << "or its size was not 2 for the module with label \"" << *it << "\".\n" ;
00126 }
00127 boost::shared_ptr<CLHEP::HepRandomEngine> engine(new CLHEP::RanecuEngine());
00128 engineMap_[*it] = engine;
00129
00130 if(initialSeedSet[0] > maxSeedRanecu ||
00131 initialSeedSet[1] > maxSeedRanecu) {
00132 throw Exception(errors::Configuration)
00133 << "The RanecuEngine seeds should be in the range 0 to 2147483647.\n"
00134 << "The seeds passed to the RandomNumberGenerationService from the\n"
00135 "configuration file were " << initialSeedSet[0] << " and " << initialSeedSet[1]
00136 << "\nThis was for the module with label \"" << *it << "\".\n";
00137 }
00138 long int seedL[2];
00139 seedL[0] = static_cast<long int>(initialSeedSet[0]);
00140 seedL[1] = static_cast<long int>(initialSeedSet[1]);
00141 engine->setSeeds(seedL, 0);
00142 }
00143
00144 else {
00145 if(initialSeedSet.size() != 1U) {
00146 throw Exception(errors::Configuration)
00147 << "Random engines of type \"HepJamesRandom\" and \"TRandom3\n"
00148 << "require exactly 1 seed be specified in the configuration.\n"
00149 << "There were " << initialSeedSet.size() << " seeds set for the\n"
00150 << "module with label \"" << *it << "\".\n" ;
00151 }
00152 long int seedL = static_cast<long int>(initialSeedSet[0]);
00153
00154 if(engineName == "HepJamesRandom") {
00155 if(initialSeedSet[0] > maxSeedHepJames) {
00156 throw Exception(errors::Configuration)
00157 << "The CLHEP::HepJamesRandom engine seed should be in the range 0 to 900000000.\n"
00158 << "The seed passed to the RandomNumberGenerationService from the\n"
00159 "configuration file was " << initialSeedSet[0] << ". This was for \n"
00160 << "the module with label " << *it << ".\n";
00161 }
00162 boost::shared_ptr<CLHEP::HepRandomEngine> engine(new CLHEP::HepJamesRandom(seedL));
00163 engineMap_[*it] = engine;
00164 } else if(engineName == "TRandom3") {
00165
00166
00167
00168
00169
00170
00171
00172
00173 uint32_t seedu32 = static_cast<uint32_t>(seedL);
00174 assert(initialSeedSet[0] == seedu32);
00175
00176 boost::shared_ptr<CLHEP::HepRandomEngine> engine(new TRandomAdaptor(seedL));
00177 engineMap_[*it] = engine;
00178 } else {
00179 throw Exception(errors::Configuration)
00180 << "The random engine name, \"" << engineName
00181 << "\", does not correspond to a supported engine.\n"
00182 << "This engine was configured for the module with label \"" << *it << "\"";
00183 }
00184 }
00185 }
00186 }
00187
00188 activityRegistry.watchPostBeginLumi(this, &RandomNumberGeneratorService::postBeginLumi);
00189
00190 activityRegistry.watchPreModuleConstruction(this, &RandomNumberGeneratorService::preModuleConstruction);
00191 activityRegistry.watchPostModuleConstruction(this, &RandomNumberGeneratorService::postModuleConstruction);
00192
00193 activityRegistry.watchPreModuleBeginJob(this, &RandomNumberGeneratorService::preModuleBeginJob);
00194 activityRegistry.watchPostModuleBeginJob(this, &RandomNumberGeneratorService::postModuleBeginJob);
00195
00196 activityRegistry.watchPreModuleBeginRun(this, &RandomNumberGeneratorService::preModuleBeginRun);
00197 activityRegistry.watchPostModuleBeginRun(this, &RandomNumberGeneratorService::postModuleBeginRun);
00198
00199 activityRegistry.watchPreModuleBeginLumi(this, &RandomNumberGeneratorService::preModuleBeginLumi);
00200 activityRegistry.watchPostModuleBeginLumi(this, &RandomNumberGeneratorService::postModuleBeginLumi);
00201
00202 activityRegistry.watchPreModule(this, &RandomNumberGeneratorService::preModule);
00203 activityRegistry.watchPostModule(this, &RandomNumberGeneratorService::postModule);
00204
00205 activityRegistry.watchPreModuleEndLumi(this, &RandomNumberGeneratorService::preModuleEndLumi);
00206 activityRegistry.watchPostModuleEndLumi(this, &RandomNumberGeneratorService::postModuleEndLumi);
00207
00208 activityRegistry.watchPreModuleEndRun(this, &RandomNumberGeneratorService::preModuleEndRun);
00209 activityRegistry.watchPostModuleEndRun(this, &RandomNumberGeneratorService::postModuleEndRun);
00210
00211 activityRegistry.watchPreModuleEndJob(this, &RandomNumberGeneratorService::preModuleEndJob);
00212 activityRegistry.watchPostModuleEndJob(this, &RandomNumberGeneratorService::postModuleEndJob);
00213
00214 activityRegistry.watchPostForkReacquireResources(this, &RandomNumberGeneratorService::postForkReacquireResources);
00215
00216
00217 engineStack_.push_back(engineMap_.end());
00218 currentEngine_ = engineMap_.end();
00219
00220 labelStack_.push_back(std::string());
00221 currentLabel_ = std::string();
00222 }
00223
00224 RandomNumberGeneratorService::~RandomNumberGeneratorService() {
00225 }
00226
00227 CLHEP::HepRandomEngine&
00228 RandomNumberGeneratorService::getEngine() const {
00229
00230 if(currentEngine_ == engineMap_.end()) {
00231 if(currentLabel_ != std::string()) {
00232 throw Exception(errors::Configuration)
00233 << "The module with label \""
00234 << currentLabel_
00235 << "\" requested a random number engine from the \n"
00236 "RandomNumberGeneratorService, but that module was not configured\n"
00237 "for random numbers. An engine is created only if a seed(s) is provided\n"
00238 "in the configuration file. Please add the following PSet to the\n"
00239 "configuration file for the RandomNumberGeneratorService:\n\n"
00240 " " << currentLabel_ << " = cms.PSet(\n"
00241 " initialSeed = cms.untracked.uint32(your_seed),\n"
00242 " engineName = cms.untracked.string('TRandom3')\n"
00243 " )\n"
00244 "where you replace \"your_seed\" with a number and add a comma if necessary\n"
00245 "The \"engineName\" parameter is optional. If absent the default is \"HepJamesRandom\".\n";
00246 } else {
00247 throw Exception(errors::Unknown)
00248 << "Requested a random number engine from the RandomNumberGeneratorService\n"
00249 "when no module was active. This is not supposed to be possible.\n"
00250 "Please inform the edm developers about this. It would be helpful to\n"
00251 "know the stack. If a source was requesting a random engine this could\n"
00252 "happen. Sources are not supposed to be doing that anymore.\n";
00253 }
00254 }
00255 return *(currentEngine_->second);
00256 }
00257
00258 uint32_t
00259 RandomNumberGeneratorService::mySeed() const {
00260
00261 std::map<std::string, VUint32>::const_iterator iter;
00262 iter = seedMap_.find(currentLabel_);
00263
00264 if(iter == seedMap_.end()) {
00265 if(currentLabel_ != std::string()) {
00266 throw Exception(errors::Configuration)
00267 << "The module with label \""
00268 << currentLabel_
00269 << "\" requested a random number seed from the \n"
00270 "RandomNumberGeneratorService, but that module was not configured\n"
00271 "for random numbers. An engine is created only if a seed(s) is provided\n"
00272 "in the configuration file. Please add the following PSet to the\n"
00273 "configuration file for the RandomNumberGeneratorService:\n\n"
00274 " " << currentLabel_ << " = cms.PSet(\n"
00275 " initialSeed = cms.untracked.uint32(your_seed),\n"
00276 " engineName = cms.untracked.string('TRandom3')\n"
00277 " )\n"
00278 "where you replace \"your_seed\" with a number and add a comma if necessary\n"
00279 "The \"engineName\" parameter is optional. If absent the default is \"HepJamesRandom\".\n";
00280 } else {
00281 throw Exception(errors::Unknown)
00282 << "Requested a random number seed from the RandomNumberGeneratorService\n"
00283 "when no module was active. This is not supposed to be possible.\n"
00284 "Please inform the edm developers about this. It would be helpful to\n"
00285 "know the stack. If a source was requesting a random engine this could\n"
00286 "happen. Sources are not supposed to be doing that anymore.\n";
00287 }
00288 }
00289 return iter->second[0];
00290 }
00291
00292 void
00293 RandomNumberGeneratorService::fillDescriptions(ConfigurationDescriptions& descriptions) {
00294 ParameterSetDescription desc;
00295
00296 std::string emptyString;
00297 desc.addUntracked<std::string>("restoreStateLabel", emptyString);
00298 desc.addUntracked<std::string>("saveFileName", emptyString);
00299 desc.addUntracked<std::string>("restoreFileName", emptyString);
00300 desc.addUntracked<bool>("enableChecking", false);
00301 desc.addUntracked<unsigned>("eventSeedOffset", 0U);
00302
00303 ParameterSetDescription val;
00304
00305
00306
00307
00308 val.addWildcardUntracked<uint32_t>("*")->setComment("In the new interface, this wildcard will "
00309 "match either nothing or one parameter named initialSeed. Either initialSeed will exist or "
00310 "initialSeedSet will exist but not both. In the old deprecated interface, this will match "
00311 "parameters with the names being the module labels and the values being the seeds");
00312 val.addOptionalUntracked<std::vector<uint32_t> >("initialSeedSet")->setComment("New interface only");
00313 val.addOptionalUntracked<std::string>("engineName",std::string("HepJamesRandom"))->setComment("New interface only");
00314
00315 ParameterWildcard<ParameterSetDescription> wnode("*", RequireZeroOrMore, true, val);
00316 wnode.setComment("In the new interface, the name of each ParameterSet will be the associated module label. "
00317 "In the old deprecated interface there will be one ParameterSet named moduleSeeds");
00318 desc.addNode(wnode);
00319
00320
00321
00322
00323 desc.addOptionalUntracked<uint32_t>("sourceSeed")->
00324 setComment("This parameter is deprecated, has no effect and will likely be completely removed someday");
00325
00326 descriptions.add("RandomNumberGeneratorService", desc);
00327 }
00328
00329 void
00330 RandomNumberGeneratorService::postForkReacquireResources(unsigned childIndex, unsigned ) {
00331 childIndex_ = childIndex;
00332
00333 if(!saveFileName_.empty()) {
00334 std::ostringstream suffix;
00335 suffix << "_" << childIndex;
00336 saveFileName_ += suffix.str();
00337 }
00338 }
00339
00340
00341
00342
00343
00344 void
00345 RandomNumberGeneratorService::preBeginLumi(LuminosityBlock const& lumi) {
00346
00347 if(firstLumi_) {
00348
00349 snapShot(lumiCache_);
00350
00351 if(!restoreFileName_.empty()) {
00352
00353 readLumiStatesFromTextFile(restoreFileName_);
00354 }
00355 } else {
00356 snapShot(eventCache_);
00357 }
00358
00359
00360 if(!restoreStateLabel_.empty()) {
00361 readFromLuminosityBlock(lumi);
00362 }
00363
00364 if(!firstLumi_ || !restoreFileName_.empty() || !restoreStateLabel_.empty()) {
00365
00366 restoreFromCache(lumiCache_);
00367 }
00368 }
00369
00370
00371
00372
00373
00374 void
00375 RandomNumberGeneratorService::postBeginLumi(LuminosityBlock const&, EventSetup const&) {
00376
00377 if(firstLumi_) {
00378
00379 startNewSequencesForEvents();
00380 if(!restoreFileName_.empty()) {
00381 snapShot(eventCache_);
00382
00383 readEventStatesFromTextFile(restoreFileName_);
00384 }
00385 }
00386 if(!firstLumi_ || !restoreFileName_.empty()) {
00387
00388 restoreFromCache(eventCache_);
00389 }
00390 firstLumi_ = false;
00391 }
00392
00393 void
00394 RandomNumberGeneratorService::postEventRead(Event const& event) {
00395
00396 if(!restoreStateLabel_.empty()) {
00397 snapShot(eventCache_);
00398 readFromEvent(event);
00399
00400
00401 restoreFromCache(eventCache_);
00402 } else {
00403
00404 snapShot(eventCache_);
00405 }
00406
00407 if(!saveFileName_.empty()) {
00408 saveStatesToFile(saveFileName_);
00409 if(!saveFileNameRecorded_) {
00410 std::string fullName = constructSaveFileName();
00411 Service<JobReport> reportSvc;
00412 reportSvc->reportRandomStateFile(fullName);
00413 saveFileNameRecorded_ = true;
00414 }
00415 }
00416 }
00417
00418
00419
00420
00421
00422 void
00423 RandomNumberGeneratorService::preModuleConstruction(ModuleDescription const& description) {
00424 push(description.moduleLabel());
00425 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00426 engineStateStack_.push_back(currentEngine_->second->put());
00427 }
00428 }
00429
00430 void
00431 RandomNumberGeneratorService::postModuleConstruction(ModuleDescription const& description) {
00432 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00433 if(engineStateStack_.back() != currentEngine_->second->put()) {
00434 throw Exception(errors::LogicError)
00435 << "It is illegal to generate random numbers during module construction because \n"
00436 "that makes it very difficult to reproduce the processing of individual\n"
00437 "events. Random numbers were generated during module construction for the module with\n"
00438 "class name \"" << description.moduleName() << "\"\n"
00439 "and module label \"" << description.moduleLabel() << "\"\n";
00440 }
00441 engineStateStack_.pop_back();
00442 }
00443 pop();
00444 }
00445
00446 void
00447 RandomNumberGeneratorService::preModuleBeginJob(ModuleDescription const& description) {
00448 push(description.moduleLabel());
00449 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00450 engineStateStack_.push_back(currentEngine_->second->put());
00451 }
00452 }
00453
00454 void
00455 RandomNumberGeneratorService::postModuleBeginJob(ModuleDescription const& description) {
00456 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00457 if(engineStateStack_.back() != currentEngine_->second->put()) {
00458 throw Exception(errors::LogicError)
00459 << "It is illegal to generate random numbers during beginJob because \n"
00460 "that makes it very difficult to reproduce the processing of individual\n"
00461 "events. Random numbers were generated during beginJob for the module with\n"
00462 "class name \"" << description.moduleName() << "\"\n"
00463 "and module label \"" << description.moduleLabel() << "\"\n";
00464 }
00465 engineStateStack_.pop_back();
00466 }
00467 pop();
00468 }
00469
00470 void
00471 RandomNumberGeneratorService::preModuleBeginRun(ModuleDescription const& description) {
00472 push(description.moduleLabel());
00473 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00474 engineStateStack_.push_back(currentEngine_->second->put());
00475 }
00476 }
00477
00478 void
00479 RandomNumberGeneratorService::postModuleBeginRun(ModuleDescription const& description) {
00480 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00481 if(engineStateStack_.back() != currentEngine_->second->put()) {
00482 throw Exception(errors::LogicError)
00483 << "It is illegal to generate random numbers during beginRun because \n"
00484 "that makes it very difficult to reproduce the processing of individual\n"
00485 "events. Random numbers were generated during beginRun for the module with\n"
00486 "class name \"" << description.moduleName() << "\"\n"
00487 "and module label \"" << description.moduleLabel() << "\"\n";
00488 }
00489 engineStateStack_.pop_back();
00490 }
00491 pop();
00492 }
00493
00494 void
00495 RandomNumberGeneratorService::preModuleBeginLumi(ModuleDescription const& description) {
00496 push(description.moduleLabel());
00497 }
00498
00499 void
00500 RandomNumberGeneratorService::postModuleBeginLumi(ModuleDescription const&) {
00501 pop();
00502 }
00503
00504 void
00505 RandomNumberGeneratorService::preModule(ModuleDescription const& description) {
00506 push(description.moduleLabel());
00507 }
00508
00509 void
00510 RandomNumberGeneratorService::postModule(ModuleDescription const&) {
00511 pop();
00512 }
00513
00514 void
00515 RandomNumberGeneratorService::preModuleEndLumi(ModuleDescription const& description) {
00516 push(description.moduleLabel());
00517 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00518 engineStateStack_.push_back(currentEngine_->second->put());
00519 }
00520 }
00521
00522 void
00523 RandomNumberGeneratorService::postModuleEndLumi(ModuleDescription const& description) {
00524 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00525 if(engineStateStack_.back() != currentEngine_->second->put()) {
00526 throw Exception(errors::LogicError)
00527 << "It is illegal to generate random numbers during endLumi because \n"
00528 "that makes it very difficult to reproduce the processing of individual\n"
00529 "events. Random numbers were generated during endLumi for the module with\n"
00530 "class name \"" << description.moduleName() << "\"\n"
00531 "and module label \"" << description.moduleLabel() << "\"\n";
00532 }
00533 engineStateStack_.pop_back();
00534 }
00535 pop();
00536 }
00537
00538 void
00539 RandomNumberGeneratorService::preModuleEndRun(ModuleDescription const& description) {
00540 push(description.moduleLabel());
00541 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00542 engineStateStack_.push_back(currentEngine_->second->put());
00543 }
00544 }
00545
00546 void
00547 RandomNumberGeneratorService::postModuleEndRun(ModuleDescription const& description) {
00548 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00549 if(engineStateStack_.back() != currentEngine_->second->put()) {
00550 throw Exception(errors::LogicError)
00551 << "It is illegal to generate random numbers during endRun because \n"
00552 "that makes it very difficult to reproduce the processing of individual\n"
00553 "events. Random numbers were generated during endRun for the module with\n"
00554 "class name \"" << description.moduleName() << "\"\n"
00555 "and module label \"" << description.moduleLabel() << "\"\n";
00556 }
00557 engineStateStack_.pop_back();
00558 }
00559 pop();
00560 }
00561
00562 void
00563 RandomNumberGeneratorService::preModuleEndJob(ModuleDescription const& description) {
00564 push(description.moduleLabel());
00565 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00566 engineStateStack_.push_back(currentEngine_->second->put());
00567 }
00568 }
00569
00570 void
00571 RandomNumberGeneratorService::postModuleEndJob(ModuleDescription const& description) {
00572 if(enableChecking_ && currentEngine_ != engineMap_.end()) {
00573 if(engineStateStack_.back() != currentEngine_->second->put()) {
00574 throw Exception(errors::LogicError)
00575 << "It is illegal to generate random numbers during endJob because \n"
00576 "that makes it very difficult to reproduce the processing of individual\n"
00577 "events. Random numbers were generated during endJob for the module with\n"
00578 "class name \"" << description.moduleName() << "\"\n"
00579 "and module label \"" << description.moduleLabel() << "\"\n";
00580 }
00581 engineStateStack_.pop_back();
00582 }
00583 pop();
00584 }
00585
00586 std::vector<RandomEngineState> const&
00587 RandomNumberGeneratorService::getLumiCache() const {
00588 return lumiCache_;
00589 }
00590
00591 std::vector<RandomEngineState> const&
00592 RandomNumberGeneratorService::getEventCache() const {
00593 return eventCache_;
00594 }
00595
00596 void
00597 RandomNumberGeneratorService::print() {
00598 std::cout << "\n\nRandomNumberGeneratorService dump\n\n";
00599
00600 std::cout << " Contents of seedMap\n";
00601 for(std::map<std::string, std::vector<uint32_t> >::const_iterator iter = seedMap_.begin();
00602 iter != seedMap_.end();
00603 ++iter) {
00604 std::cout << " " << iter->first;
00605 std::vector<uint32_t> seeds = iter->second;
00606 for(std::vector<uint32_t>::const_iterator vIter = seeds.begin();
00607 vIter != seeds.end();
00608 ++vIter) {
00609 std::cout << " " << *vIter;
00610 }
00611 std::cout << "\n";
00612 }
00613 std::cout << "\n Contents of engineNameMap\n";
00614 for(std::map<std::string, std::string>::const_iterator iter = engineNameMap_.begin();
00615 iter != engineNameMap_.end();
00616 ++iter) {
00617 std::cout << " " << iter->first << " " << iter->second << "\n";
00618 }
00619 std::cout << "\n Contents of engineMap\n";
00620 for(EngineMap::const_iterator iter = engineMap_.begin();
00621 iter != engineMap_.end();
00622 ++iter) {
00623 std::cout << " " << iter->first
00624 << " " << iter->second->name() << " ";
00625 if(iter->second->name() == std::string("HepJamesRandom")) {
00626 std::cout << iter->second->getSeed();
00627 } else {
00628 std::cout << "Engine does not know original seed";
00629 }
00630 std::cout << "\n";
00631 }
00632 std::cout << "\n";
00633 std::cout << " currentLabel_ = " << currentLabel_ << "\n";
00634 std::cout << " labelStack_ size = " << labelStack_.size() << "\n";
00635 int i = 0;
00636 for(VString::const_iterator iter = labelStack_.begin();
00637 iter != labelStack_.end();
00638 ++iter, ++i) {
00639 std::cout << " " << i << " " << *iter << "\n";
00640 }
00641 if(currentEngine_ == engineMap_.end()) {
00642 std::cout << " currentEngine points to end\n";
00643 } else {
00644 std::cout << " currentEngine_ = " << currentEngine_->first
00645 << " " << currentEngine_->second->name()
00646 << " " << currentEngine_->second->getSeed() << "\n";
00647 }
00648
00649 std::cout << " engineStack_ size = " << engineStack_.size() << "\n";
00650 i = 0;
00651 for(std::vector<EngineMap::const_iterator>::const_iterator iter = engineStack_.begin();
00652 iter != engineStack_.end();
00653 ++iter, ++i) {
00654 if(*iter == engineMap_.end()) {
00655 std::cout << " " << i << " Points to end of engine map\n";
00656 } else {
00657 std::cout << " " << i << " " << (*iter)->first
00658 << " " << (*iter)->second->name() << " " << (*iter)->second->getSeed() << "\n";
00659 }
00660 }
00661
00662 std::cout << " restoreStateLabel_ = " << restoreStateLabel_ << "\n";
00663 std::cout << " saveFileName_ = " << saveFileName_ << "\n";
00664 std::cout << " restoreFileName_ = " << restoreFileName_ << "\n";
00665 }
00666
00667 void
00668 RandomNumberGeneratorService::push(std::string const& iLabel) {
00669 currentEngine_ = engineMap_.find(iLabel);
00670 engineStack_.push_back(currentEngine_);
00671
00672 labelStack_.push_back(iLabel);
00673 currentLabel_ = iLabel;
00674 }
00675
00676 void
00677 RandomNumberGeneratorService::pop() {
00678 engineStack_.pop_back();
00679
00680 currentEngine_ = engineStack_.back();
00681 labelStack_.pop_back();
00682 currentLabel_ = labelStack_.back();
00683 }
00684
00685 void
00686 RandomNumberGeneratorService::readFromLuminosityBlock(LuminosityBlock const& lumi) {
00687
00688 Handle<RandomEngineStates> states;
00689
00690 lumi.getByLabel(restoreStateLabel_, "beginLumi", states);
00691
00692 if(!states.isValid()) {
00693 failedToFindStatesInLumi_ = true;
00694 return;
00695 }
00696 failedToFindStatesInLumi_ = false;
00697 states->getRandomEngineStates(lumiCache_);
00698 }
00699
00700 void
00701 RandomNumberGeneratorService::readFromEvent(Event const& event) {
00702
00703 Handle<RandomEngineStates> states;
00704
00705 event.getByLabel(restoreStateLabel_, states);
00706
00707 if(!states.isValid()) {
00708 if(failedToFindStatesInLumi_ && backwardCompatibilityRead(event)) {
00709 return;
00710 } else {
00711 throw Exception(errors::ProductNotFound)
00712 << "The RandomNumberGeneratorService is trying to restore\n"
00713 << "the state of the random engines by reading a product from\n"
00714 << "the Event with label \"" << restoreStateLabel_ << "\". It\n"
00715 << "fails to find one. The label used in the request for the product\n"
00716 << "is set in the configuration. It is probably set to the wrong value\n"
00717 << "in the configuration file. It must match the module label\n"
00718 << "of the RandomEngineStateProducer that created the product in\n"
00719 << "a previous process\n";
00720 }
00721 }
00722 if(failedToFindStatesInLumi_) {
00723 throw Exception(errors::ProductNotFound)
00724 << "The RandomNumberGeneratorService is trying to restore\n"
00725 << "the state of the random engines by reading a product from\n"
00726 << "the Event and LuminosityBlock with label \"" << restoreStateLabel_ << "\".\n"
00727 << "It found the product in the Event but not the one in the LuminosityBlock.\n"
00728 << "Either the product in the LuminosityBlock was dropped or\n"
00729 << "there is a bug somewhere\n";
00730 }
00731 states->getRandomEngineStates(eventCache_);
00732 }
00733
00734 bool
00735 RandomNumberGeneratorService::backwardCompatibilityRead(Event const& event) {
00736
00737 Handle<std::vector<RandomEngineState> > states;
00738
00739 event.getByLabel(restoreStateLabel_, states);
00740 if(!states.isValid()) {
00741 return false;
00742 }
00743 for(std::vector<RandomEngineState>::const_iterator state = states->begin(),
00744 iEnd = states->end();
00745 state != iEnd; ++state) {
00746
00747 std::vector<RandomEngineState>::iterator cachedState =
00748 std::lower_bound(eventCache_.begin(), eventCache_.end(), *state);
00749
00750
00751 if(cachedState != eventCache_.end() && cachedState->getLabel() == state->getLabel()) {
00752 if(cachedState->getSeed().size() != state->getSeed().size() ||
00753 cachedState->getState().size() != state->getState().size()) {
00754 throw Exception(errors::Configuration)
00755 << "In function RandomNumberGeneratorService::backwardCompatibilityRead.\n"
00756 << "When attempting to replay processing with the RandomNumberGeneratorService,\n"
00757 << "the engine type for each module must be the same in the replay configuration\n"
00758 << "and the original configuration. If this is not the problem, then the data\n"
00759 << "is somehow corrupted or there is a bug because the vector in the data containing\n"
00760 << "the seeds or engine state is the incorrect size for the type of random engine.\n";
00761 }
00762 cachedState->setSeed(state->getSeed());
00763 cachedState->setState(state->getState());
00764 }
00765 }
00766 return true;
00767 }
00768
00769 void
00770 RandomNumberGeneratorService::snapShot(std::vector<RandomEngineState>& cache) {
00771 cache.resize(engineMap_.size());
00772 std::vector<RandomEngineState>::iterator state = cache.begin();
00773
00774 for(EngineMap::const_iterator iter = engineMap_.begin();
00775 iter != engineMap_.end();
00776 ++iter, ++state) {
00777
00778 state->setLabel(iter->first);
00779 state->setSeed(seedMap_[iter->first]);
00780
00781 std::vector<unsigned long> stateL = iter->second->put();
00782 state->clearStateVector();
00783 state->reserveStateVector(stateL.size());
00784 for(std::vector<unsigned long>::const_iterator vIter = stateL.begin();
00785 vIter != stateL.end();
00786 ++vIter) {
00787 state->push_back_stateVector(static_cast<uint32_t>(*vIter));
00788 }
00789 }
00790 }
00791
00792 void
00793 RandomNumberGeneratorService::restoreFromCache(std::vector<RandomEngineState> const& cache) {
00794 for(std::vector<RandomEngineState>::const_iterator iter = cache.begin(),
00795 iEnd = cache.end();
00796 iter != iEnd; ++iter) {
00797
00798 std::string const& engineLabel = iter->getLabel();
00799
00800 std::vector<uint32_t> const& engineState = iter->getState();
00801 std::vector<unsigned long> engineStateL;
00802 for(std::vector<uint32_t>::const_iterator iVal = engineState.begin(),
00803 theEnd = engineState.end();
00804 iVal != theEnd; ++iVal) {
00805 engineStateL.push_back(static_cast<unsigned long>(*iVal));
00806 }
00807
00808 std::vector<uint32_t> const& engineSeeds = iter->getSeed();
00809 std::vector<long> engineSeedsL;
00810 for(std::vector<uint32_t>::const_iterator iVal = engineSeeds.begin(),
00811 theEnd = engineSeeds.end();
00812 iVal != theEnd;
00813 ++iVal) {
00814 long seedL = static_cast<long>(*iVal);
00815 engineSeedsL.push_back(seedL);
00816
00817
00818
00819
00820
00821
00822
00823
00824 uint32_t seedu32 = static_cast<uint32_t>(seedL);
00825 assert(*iVal == seedu32);
00826 }
00827
00828 EngineMap::iterator engine = engineMap_.find(engineLabel);
00829
00830 if(engine != engineMap_.end()) {
00831
00832 seedMap_[engineLabel] = engineSeeds;
00833
00834
00835
00836 if(engineStateL[0] == CLHEP::engineIDulong<CLHEP::HepJamesRandom>()) {
00837
00838 checkEngineType(engine->second->name(), std::string("HepJamesRandom"), engineLabel);
00839
00840
00841 engine->second->setSeed(engineSeedsL[0], 0);
00842 engine->second->get(engineStateL);
00843 } else if(engineStateL[0] == CLHEP::engineIDulong<CLHEP::RanecuEngine>()) {
00844
00845 checkEngineType(engine->second->name(), std::string("RanecuEngine"), engineLabel);
00846
00847
00848 engine->second->get(engineStateL);
00849 } else if(engineStateL[0] == CLHEP::engineIDulong<TRandomAdaptor>()) {
00850
00851 checkEngineType(engine->second->name(), std::string("TRandom3"), engineLabel);
00852
00853
00854 engine->second->setSeed(engineSeedsL[0], 0);
00855 engine->second->get(engineStateL);
00856 } else {
00857
00858
00859 throw Exception(errors::Unknown)
00860 << "The RandomNumberGeneratorService is trying to restore the state\n"
00861 "of the random engines. The state in the event indicates an engine\n"
00862 "of an unknown type. This should not be possible unless you are\n"
00863 "running with an old code release on a new file that was created\n"
00864 "with a newer release which had new engine types added. In this case\n"
00865 "the only solution is to use a newer release. In any other case, notify\n"
00866 "the EDM developers because this should not be possible\n";
00867 }
00868 }
00869 }
00870 }
00871
00872 void
00873 RandomNumberGeneratorService::checkEngineType(std::string const& typeFromConfig,
00874 std::string const& typeFromEvent,
00875 std::string const& engineLabel) {
00876 if(typeFromConfig != typeFromEvent) {
00877 throw Exception(errors::Configuration)
00878 << "The RandomNumberGeneratorService is trying to restore\n"
00879 << "the state of the random engine for the module \""
00880 << engineLabel << "\". An\n"
00881 << "error was detected because the type of the engine in the\n"
00882 << "input file and the configuration file do not match.\n"
00883 << "In the configuration file the type is \"" << typeFromConfig
00884 << "\".\nIn the input file the type is \"" << typeFromEvent << "\". If\n"
00885 << "you are not generating any random numbers in this module, then\n"
00886 << "remove the line in the configuration file that gives it\n"
00887 << "a seed and the error will go away. Otherwise, you must give\n"
00888 << "this module the same engine type in the configuration file or\n"
00889 << "stop trying to restore the random engine state.\n";
00890 }
00891 }
00892
00893 void
00894 RandomNumberGeneratorService::saveStatesToFile(std::string const& fileName) {
00895 if(!outFile_.is_open()) {
00896 outFile_.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
00897 }
00898 if(!outFile_) {
00899 throw Exception(errors::Configuration)
00900 << "Unable to open the file \""
00901 << fileName << "\" to save the state of the random engines.\n";
00902 }
00903 outFile_.seekp(0, std::ios_base::beg);
00904 outFile_ << "<RandomEngineStates>\n";
00905
00906 outFile_ << "<Event>\n";
00907 writeStates(eventCache_, outFile_);
00908 outFile_ << "</Event>\n" ;
00909
00910 outFile_ << "<Lumi>\n";
00911 writeStates(lumiCache_, outFile_);
00912 outFile_ << "</Lumi>\n" ;
00913
00914 outFile_ << "</RandomEngineStates>\n" ;
00915 outFile_.flush();
00916 }
00917
00918 void
00919 RandomNumberGeneratorService::writeStates(std::vector<RandomEngineState> const& v,
00920 std::ofstream& outFile) {
00921 for(std::vector<RandomEngineState>::const_iterator iter = v.begin(),
00922 iEnd = v.end();
00923 iter != iEnd; ++iter) {
00924
00925 std::vector<uint32_t> const& seedVector = iter->getSeed();
00926 std::vector<uint32_t>::size_type seedVectorLength = seedVector.size();
00927
00928 std::vector<uint32_t> const& stateVector = iter->getState();
00929 std::vector<uint32_t>::size_type stateVectorLength = stateVector.size();
00930
00931 outFile << "<ModuleLabel>\n" << iter->getLabel() << "\n</ModuleLabel>\n";
00932
00933 outFile << "<SeedLength>\n" << seedVectorLength << "\n</SeedLength>\n" ;
00934 outFile << "<InitialSeeds>\n";
00935 writeVector(seedVector, outFile);
00936 outFile << "</InitialSeeds>\n";
00937 outFile << "<FullStateLength>\n" << stateVectorLength << "\n</FullStateLength>\n";
00938 outFile << "<FullState>\n";
00939 writeVector(stateVector, outFile);
00940 outFile << "</FullState>\n";
00941 }
00942 }
00943
00944 void
00945 RandomNumberGeneratorService::writeVector(VUint32 const& v,
00946 std::ofstream& outFile) {
00947 if(v.empty()) return;
00948 size_t numItems = v.size();
00949 for(size_t i = 0; i < numItems; ++i) {
00950 if(i != 0 && i % 10 == 0) outFile << "\n";
00951 outFile << std::setw(13) << v[i];
00952 }
00953 outFile << "\n";
00954 }
00955
00956 std::string RandomNumberGeneratorService::constructSaveFileName() {
00957 char directory[1500];
00958 std::string fullName(getcwd(directory, sizeof(directory)) ? directory : "/PathIsTooBig");
00959 fullName += "/" + saveFileName_;
00960 return fullName;
00961 }
00962
00963 void
00964 RandomNumberGeneratorService::readEventStatesFromTextFile(std::string const& fileName) {
00965 std::string whichStates("<Event>");
00966 readStatesFromFile(fileName, eventCache_, whichStates);
00967 }
00968
00969 void
00970 RandomNumberGeneratorService::readLumiStatesFromTextFile(std::string const& fileName) {
00971 std::string whichStates("<Lumi>");
00972 readStatesFromFile(fileName, lumiCache_, whichStates);
00973 }
00974
00975
00976 void
00977 RandomNumberGeneratorService::readStatesFromFile(std::string const& fileName,
00978 std::vector<RandomEngineState>& cache,
00979 std::string const& whichStates) {
00980 std::ifstream inFile;
00981 inFile.open(fileName.c_str(), std::ifstream::in);
00982 if(!inFile) {
00983 throw Exception(errors::Configuration)
00984 << "Unable to open the file \""
00985 << fileName << "\" to restore the random engine states.\n";
00986 }
00987
00988 std::string text;
00989 inFile >> text;
00990 if(!inFile.good() || text != std::string("<RandomEngineStates>")) {
00991 throw Exception(errors::Configuration)
00992 << "Attempting to read file with random number engine states.\n"
00993 << "File \"" << restoreFileName_
00994 << "\" is ill-structured or otherwise corrupted.\n"
00995 << "Cannot read the file header word.\n";
00996 }
00997 bool saveToCache = false;
00998 while(readEngineState(inFile, cache, whichStates, saveToCache)) {}
00999 }
01000
01001 bool RandomNumberGeneratorService::readEngineState(std::istream& is,
01002 std::vector<RandomEngineState>& cache,
01003 std::string const& whichStates,
01004 bool& saveToCache) {
01005 std::string leading;
01006 std::string trailing;
01007 std::string moduleLabel;
01008 std::vector<uint32_t>::size_type seedVectorSize;
01009 std::vector<uint32_t> seedVector;
01010 std::vector<uint32_t>::size_type stateVectorSize;
01011 std::vector<uint32_t> stateVector;
01012
01013
01014
01015
01016
01017 is >> leading;
01018 if(!is.good()) {
01019 throw Exception(errors::Configuration)
01020 << "File \"" << restoreFileName_
01021 << "\" is ill-structured or otherwise corrupted.\n"
01022 << "Cannot read next field and did not hit the end yet.\n";
01023 }
01024
01025
01026 if(leading == std::string("</RandomEngineStates>")) return false;
01027
01028
01029 if(leading == std::string("</Event>") ||
01030 leading == std::string("</Lumi>")) {
01031 saveToCache = false;
01032 return true;
01033 }
01034
01035
01036 if(leading == std::string("<Event>") ||
01037 leading == std::string("<Lumi>")) {
01038 saveToCache = (leading == whichStates);
01039 return true;
01040 }
01041
01042
01043
01044 is >> moduleLabel >> trailing;
01045 if(!is.good() ||
01046 leading != std::string("<ModuleLabel>") ||
01047 trailing != std::string("</ModuleLabel>")) {
01048 throw Exception(errors::Configuration)
01049 << "File \"" << restoreFileName_
01050 << "\" is ill-structured or otherwise corrupted.\n"
01051 << "Cannot read a module label when restoring random engine states.\n";
01052 }
01053
01054 is >> leading >> seedVectorSize >> trailing;
01055 if(!is.good() ||
01056 leading != std::string("<SeedLength>") ||
01057 trailing != std::string("</SeedLength>")) {
01058 throw Exception(errors::Configuration)
01059 << "File \"" << restoreFileName_
01060 << "\" is ill-structured or otherwise corrupted.\n"
01061 << "Cannot read seed vector length when restoring random engine states.\n";
01062 }
01063
01064 is >> leading;
01065 if(!is.good() ||
01066 leading != std::string("<InitialSeeds>")) {
01067 throw Exception(errors::Configuration)
01068 << "File \"" << restoreFileName_
01069 << "\" is ill-structured or otherwise corrupted.\n"
01070 << "Cannot read beginning of InitialSeeds when restoring random engine states.\n";
01071 }
01072
01073 readVector(is, seedVectorSize, seedVector);
01074
01075 is >> trailing;
01076 if(!is.good() ||
01077 trailing != std::string("</InitialSeeds>")) {
01078 throw Exception(errors::Configuration)
01079 << "File \"" << restoreFileName_
01080 << "\" is ill-structured or otherwise corrupted.\n"
01081 << "Cannot read end of InitialSeeds when restoring random engine states.\n";
01082 }
01083
01084 is >> leading >> stateVectorSize >> trailing;
01085 if(!is.good() ||
01086 leading != std::string("<FullStateLength>") ||
01087 trailing != std::string("</FullStateLength>")) {
01088 throw Exception(errors::Configuration)
01089 << "File \"" << restoreFileName_
01090 << "\" is ill-structured or otherwise corrupted.\n"
01091 << "Cannot read state vector length when restoring random engine states.\n";
01092 }
01093
01094 is >> leading;
01095 if(!is.good() ||
01096 leading != std::string("<FullState>")) {
01097 throw Exception(errors::Configuration)
01098 << "File \"" << restoreFileName_
01099 << "\" is ill-structured or otherwise corrupted.\n"
01100 << "Cannot read beginning of FullState when restoring random engine states.\n";
01101 }
01102
01103 readVector(is, stateVectorSize, stateVector);
01104
01105 is >> trailing;
01106 if(!is.good() ||
01107 trailing != std::string("</FullState>")) {
01108 throw Exception(errors::Configuration)
01109 << "File \"" << restoreFileName_
01110 << "\" is ill-structured or otherwise corrupted.\n"
01111 << "Cannot read end of FullState when restoring random engine states.\n";
01112 }
01113
01114 if(saveToCache) {
01115 RandomEngineState randomEngineState;
01116 randomEngineState.setLabel(moduleLabel);
01117 std::vector<RandomEngineState>::iterator state =
01118 std::lower_bound(cache.begin(), cache.end(), randomEngineState);
01119
01120 if(state != cache.end() && moduleLabel == state->getLabel()) {
01121 if(seedVector.size() != state->getSeed().size() ||
01122 stateVector.size() != state->getState().size()) {
01123 throw Exception(errors::Configuration)
01124 << "File \"" << restoreFileName_
01125 << "\" is ill-structured or otherwise corrupted.\n"
01126 << "Vectors containing engine state are the incorrect size for the type of random engine.\n";
01127 }
01128 state->setSeed(seedVector);
01129 state->setState(stateVector);
01130 }
01131 }
01132 return true;
01133 }
01134
01135 void
01136 RandomNumberGeneratorService::readVector(std::istream& is, unsigned numItems, std::vector<uint32_t>& v) {
01137 v.clear();
01138 v.reserve(numItems);
01139 uint32_t data;
01140 for(unsigned i = 0; i < numItems; ++i) {
01141 is >> data;
01142 if(!is.good()) {
01143 throw Exception(errors::Configuration)
01144 << "File \"" << restoreFileName_
01145 << "\" is ill-structured or otherwise corrupted.\n"
01146 << "Cannot read vector when restoring random engine states.\n";
01147 }
01148 v.push_back(data);
01149 }
01150 }
01151
01152 void
01153 RandomNumberGeneratorService::startNewSequencesForEvents() {
01154
01155 if(childIndex_ == 0U && eventSeedOffset_ == 0U) return;
01156
01157 for(EngineMap::const_iterator iter = engineMap_.begin();
01158 iter != engineMap_.end();
01159 ++iter) {
01160
01161 uint32_t offset1 = childIndex_;
01162 uint32_t offset2 = eventSeedOffset_;
01163
01164 std::string const& moduleLabel = iter->first;
01165 std::string const& engineName = engineNameMap_[moduleLabel];
01166 VUint32& seeds = seedMap_[moduleLabel];
01167
01168 if(engineName == std::string("RanecuEngine")) {
01169 assert(seeds.size() == 2U);
01170
01171 uint32_t mod = maxSeedRanecu + 1U;
01172 offset1 = offset1 % mod;
01173 offset2 = offset2 % mod;
01174 seeds[0] = (seeds[0] + offset1) % mod;
01175 seeds[0] = (seeds[0] + offset2) % mod;
01176 long int seedL[2];
01177 seedL[0] = static_cast<long int>(seeds[0]);
01178 seedL[1] = static_cast<long int>(seeds[1]);
01179 iter->second->setSeeds(seedL,0);
01180 } else {
01181 assert(seeds.size() == 1U);
01182
01183 if(engineName == "HepJamesRandom") {
01184
01185 uint32_t mod = maxSeedHepJames + 1U;
01186 offset1 = offset1 % mod;
01187 offset2 = offset2 % mod;
01188 seeds[0] = (seeds[0] + offset1) % mod;
01189 seeds[0] = (seeds[0] + offset2) % mod;
01190
01191 long int seedL = static_cast<long int>(seeds[0]);
01192 iter->second->setSeed(seedL, 0);
01193 } else {
01194 assert(engineName == "TRandom3");
01195
01196
01197
01198 uint32_t max32 = maxSeedTRandom3;
01199 if((max32 - seeds[0]) >= offset1) {
01200 seeds[0] = seeds[0] + offset1;
01201 } else {
01202 seeds[0] = offset1 - (max32 - seeds[0]) - 1U;
01203 }
01204 if((max32 - seeds[0]) >= offset2) {
01205 seeds[0] = seeds[0] + offset2;
01206 } else {
01207 seeds[0] = offset2 - (max32 - seeds[0]) - 1U;
01208 }
01209 long seedL = static_cast<long>(seeds[0]);
01210
01211
01212
01213
01214
01215
01216
01217
01218 uint32_t seedu32 = static_cast<uint32_t>(seedL);
01219 assert(seeds[0] == seedu32);
01220
01221 iter->second->setSeed(seedL, 0);
01222 }
01223 }
01224 }
01225 }
01226
01227 void
01228 RandomNumberGeneratorService::oldStyleConfig(ParameterSet const& pset) {
01229 VString pSets = pset.getParameterNamesForType<ParameterSet>();
01230 for(VString::const_iterator it = pSets.begin(), itEnd = pSets.end(); it != itEnd; ++it) {
01231 if(*it != std::string("moduleSeeds")) {
01232 throw Exception(errors::Configuration)
01233 << "RandomNumberGeneratorService supports two configuration interfaces.\n"
01234 << "One is old and deprecated, but still supported for backward compatibility\n"
01235 << "reasons. It is illegal to mix parameters using both the old and new service\n"
01236 << "interface in the same configuration. It is assumed the old interface is being\n"
01237 << "used if the parameter set named \"moduleSeeds\" exists. In that case it is\n"
01238 << "illegal to have any other nested ParameterSets. This exception was thrown\n"
01239 << "because that happened.\n";
01240 }
01241 }
01242
01243 ParameterSet const& moduleSeeds = pset.getParameterSet("moduleSeeds");
01244
01245 std::vector<uint32_t> seeds;
01246
01247 VString names = moduleSeeds.getParameterNames();
01248 for(VString::const_iterator itName = names.begin(), itNameEnd = names.end();
01249 itName != itNameEnd; ++itName) {
01250
01251 uint32_t seed = moduleSeeds.getUntrackedParameter<uint32_t>(*itName);
01252
01253 seeds.clear();
01254 seeds.push_back(seed);
01255 seedMap_[*itName] = seeds;
01256 engineNameMap_[*itName] = std::string("HepJamesRandom");
01257
01258 if(seed > maxSeedHepJames) {
01259 throw Exception(errors::Configuration)
01260 << "The CLHEP::HepJamesRandom engine seed should be in the range 0 to 900000000.\n"
01261 << "The seed passed to the RandomNumberGenerationService from the\n"
01262 "configuration file was " << seed << ". This was for the module\n"
01263 << "with label \"" << *itName << "\".";
01264 }
01265 long seedL = static_cast<long>(seed);
01266 engineMap_[*itName] = boost::shared_ptr<CLHEP::HepRandomEngine>(new CLHEP::HepJamesRandom(seedL));
01267 }
01268 }
01269 }
01270 }