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