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