ATLAS Offline Software
AtRndmGenSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "GaudiKernel/ISvcLocator.h"
6 #include "GaudiKernel/IIncidentSvc.h"
7 #include "GaudiKernel/Incident.h"
8 #include "GaudiKernel/DataIncident.h"
9 #include "GaudiKernel/ServiceHandle.h"
10 
11 #include "CLHEP/Random/RanecuEngine.h"
12 #include "CLHEP/Random/RandGauss.h"
13 
14 #include "interpretSeeds.h"
15 #include "AtRndmGenSvc.h"
16 #include "crc_combine.h"
17 
18 #include <cassert>
19 #include <iostream>
20 
21 /*FIXME temporarily needed for old seeding scheme*/
23 
24 using namespace std;
25 
27 AtRndmGenSvc::AtRndmGenSvc(const std::string& name,ISvcLocator* svc)
28  : base_class(name,svc),
29  m_reseedingOffsets(),
30  m_engines(), m_engines_copy()
31 {
32  // Set Default values
33  m_default_seed1 = 3591;
34  m_default_seed2 = 2309736;
35  m_PYTHIA_default_seed1 = 93453591;
36  m_PYTHIA_default_seed2 = 73436;
37  m_HERWIG_default_seed1 = 355391;
38  m_HERWIG_default_seed2 = 97336;
39 }
40 
41 
44 {
45  engineIter i(m_engines.begin()), e(m_engines.end());
46  while (i != e) delete (i++)->second;
47 }
48 
49 
52 {
54  ("Initializing " << name()
55  << "\n INITIALISING RANDOM NUMBER STREAMS. ");
56 
57 
59  ServiceHandle<IIncidentSvc> pIncSvc("IncidentSvc", name());
60 
61  // set up the incident service:
62  ATH_CHECK( pIncSvc.retrieve() );
63 
64  //start listening to "EndEvent"
65  static const int PRIORITY = 100;
66  pIncSvc->addListener(this, "EndEvent", PRIORITY);
67  pIncSvc->addListener(this, "AfterReseedIncident", PRIORITY);
68 
69  //and to BeginEvent if we are reseeding
70  if (m_eventReseed) {
71  ATH_MSG_INFO ("will be reseeded for every event");
72  pIncSvc->addListener(this, "BeginEvent");
73  pIncSvc->addListener(this, "ReseedIncident", PRIORITY);
74  }
75  pIncSvc.release().ignore();
76 
77  if (m_read_from_file)
78  {
79  // Read from a file
80  ifstream infile( m_file_to_read.value().c_str() );
81  if ( !infile ) {
82  ATH_MSG_ERROR (" Unable to open: " << m_file_to_read.value());
83  return StatusCode::FAILURE;
84  } else {
85  std::string buffer;
86  while (std::getline(infile, buffer)) {
87  string stream;
91  (" INITIALISING " << stream << " stream with seeds "
92  << seed1 << " " << seed2
93  << " read from file " << m_file_to_read.value());
94  CreateStream(seed1, seed2, stream);
95  } else {
97  ("bad line\n" << buffer
98  << "\n in input file " << m_file_to_read.value());
99  return StatusCode::FAILURE;
100  }
101  }
102 
103  }
104  }
105 
106  // Create the various streams according to user's request
107  for (const auto& i : m_streams_seeds.value()) {
108  string stream;
109  uint32_t seed1, seed2, offset(0);
110  short dummy;
113  ("Seeds property: stream " << stream
114  << " seeds " << seed1 << ' ' << seed2
115  << ", reseeding offset " << offset);
116  } else {
117  ATH_MSG_ERROR ("bad Seeds property\n" << i);
118  return StatusCode::FAILURE;
119  }
120 
121  // Check if stream already generated (e.g. from reading a file)
122  bool not_found = true;
123  if ( number_of_streams() != 0 ) {
125  do {
126  if ((*sf).first == stream) not_found = false;
127  ++sf;
128  } while (sf != end() && not_found);
129  }
130 
131  if (not_found) {
133  (" INITIALISING " << stream << " stream with seeds "
134  << seed1 << " " << seed2);
135  CreateStream(seed1, seed2, stream);
136  if (m_eventReseed) {
137  m_reseedingOffsets.insert(std::make_pair(stream, offset));
138  // apply the offset we just inserted
139  ATH_MSG_DEBUG("Applying reseeding offset " << offset <<
140  " to stream " << stream);
141  this->setOnDefinedSeeds(seed1, seed2, stream);
142  }
143  }
144 
145  }
146  return StatusCode::SUCCESS;
147 }
148 
149 void
150 AtRndmGenSvc::handle(const Incident &inc) {
151 
152  if ( inc.type() == "EndEvent" ||
153  inc.type() == "AfterReseedIncident" )
154  {
155  ATH_MSG_DEBUG (" Handle EndEvent ");
156  m_engines_copy.clear();
157  for (engineConstIter i = begin(); i != end(); ++i)
158  {
159  CLHEP::HepRandomEngine* engine = GetEngine((*i).first);
160  const long* s = engine->getSeeds();
161  std::vector<long int> tseeds;
162  tseeds.push_back(s[0]);
163  tseeds.push_back(s[1]);
164  m_engines_copy.insert(
165  std::map<std::string, std::vector<long int> >::value_type( (*i).first,
166  tseeds ) );
167  }
168  print();
169  } else if (inc.type() == "BeginEvent") {
170  ATH_MSG_DEBUG (" Handle BeginEvent ");
171  EventContext context = inc.context();
172  const EventIDBase& ei = context.eventID();
173  //clear static RandGauss cache (generates two numbers per call to shoot()
175  //loop over generator streams, combining the stream name to the hash
176  vector<string>::const_iterator i(m_reseedStreamNames.begin());
177  vector<string>::const_iterator e(m_reseedStreamNames.end());
178  //by default (when no streams are specified in streamNames, seed all
179  //streams
180  if (i == e) {
181  if (!(this->setAllOnDefinedSeeds(ei.event_number(),
182  ei.run_number())))
183  throw GaudiException("can not reseed all streams ", name(), StatusCode::FAILURE);
184  } else {
185  while (i != e) {
186  const string& strName(*i++);
187  if (0 == this->setOnDefinedSeeds(ei.event_number(),
188  ei.run_number(),
189  strName)) {
190  throw GaudiException(string("can not reseed stream ") + strName,
191  name(), StatusCode::FAILURE);
192  } else {
193  msg() << MSG::VERBOSE << "Reseeded stream " << strName
194  << " for random service " << endmsg;
195  }
196  }
197  }
198  }
199  else if (inc.type() == "ReseedIncident") {
200  typedef ContextIncident<std::pair<unsigned,unsigned> > Ctxt;
201  const Ctxt* incident = dynamic_cast<const Ctxt*>(&inc);
202  if (!incident) {
203  throw GaudiException(string("can not cast to ContextIncident "),
204  name(), StatusCode::FAILURE);
205  }
206  const std::pair<unsigned,unsigned>& data = incident->tag();
207  //clear static RandGauss cache (generates two numbers per call to shoot()
209  //loop over generator streams, combining the stream name to the hash
210  vector<string>::const_iterator i(m_reseedStreamNames.begin());
211  vector<string>::const_iterator e(m_reseedStreamNames.end());
212  //by default (when no streams are specified in streamNames, seed all
213  //streams
214  if (i == e) {
215  if (!(this->setAllOnDefinedSeeds(data.first,
216  data.second)))
217  throw GaudiException("can not reseed all streams ", name(), StatusCode::FAILURE);
218  } else {
219  while (i != e) {
220  const string& strName(*i++);
221  if (0 == this->setOnDefinedSeeds(data.first,
222  data.second,
223  strName)) {
224  throw GaudiException(string("can not reseed stream ") + strName,
225  name(), StatusCode::FAILURE);
226  } else {
227  msg() << MSG::VERBOSE << "Reseeded stream " << strName
228  << " for random service " << endmsg;
229  }
230  }
231  }
232  }
233 }
234 
235 StatusCode
237 {
238  ATH_MSG_INFO (" FINALISING ");
239 
240  if (m_save_to_file) {
241  // Write the status of the Service into a file
242  std::ofstream outfile( m_file_to_write.value().c_str() );
243  if ( !outfile ) {
244  ATH_MSG_ERROR ("error: unable to open: " << m_file_to_write.value());
245  } else {
246  for (std::map<std::string, std::vector<long int> >::const_iterator i = m_engines_copy.begin();
247  i != m_engines_copy.end();
248  ++i) {
249  outfile << (*i).first << " " << (*i).second[0] << " " << (*i).second[1] << "\n";
250  }
251  ATH_MSG_DEBUG (" wrote seeds to " << m_file_to_write.value() );
252  }
253  }
254  return StatusCode::SUCCESS;
255 }
256 
257 CLHEP::HepRandomEngine*
258 AtRndmGenSvc::GetEngine ( const std::string& streamName )
259 {
260  engineConstIter citer = m_engines.find(streamName);
261  if ( citer == m_engines.end() )
262  {
263  m_engines.insert( engineValType( streamName, new CLHEP::RanecuEngine() ) );
264  SetStreamSeeds ( streamName );
265  }
266 
267  engineIter iter = m_engines.find(streamName);
268  return (CLHEP::HepRandomEngine*)(*iter).second;
269 }
270 
271 void
273  const std::string& streamName )
274 {
275  engineConstIter citer = m_engines.find(streamName);
276  if (citer == m_engines.end())
277  m_engines.insert(engineValType(streamName, new CLHEP::RanecuEngine()));
278  engineIter iter = m_engines.find(streamName);
279  long seeds[3] = { (long)seed1, (long) seed2, 0 };
280  ((*iter).second)->setSeeds( seeds, -1 );
281 }
282 
283 void
285 {
286  long seed1;
287  long seed2;
288  if (streamName == "PYTHIA")
289  {
290  seed1 = m_PYTHIA_default_seed1;
291  seed2 = m_PYTHIA_default_seed2;
292  }
293  else if (streamName == "HERWIG")
294  {
295  seed1 = m_HERWIG_default_seed1;
296  seed2 = m_HERWIG_default_seed2;
297  }
298  else
299  {
300  seed1 = m_default_seed1;
301  seed2 = m_default_seed2;
302  }
304  (" INITIALISING " << streamName << " stream with DEFAULT seeds "
305  << seed1 << " " << seed2);
306 
307  long seeds[3] = { seed1, seed2, 0 };
308  const long* s = seeds;
309  engineIter iter = m_engines.find(streamName);
310  ((*iter).second)->setSeeds( s, -1 );
311 }
312 
313 void
314 AtRndmGenSvc::print ( const std::string& streamName )
315 {
316  engineConstIter citer = m_engines.find(streamName);
317  if ( citer == m_engines.end() )
318  {
319  ATH_MSG_WARNING (" Stream = " << streamName << " NOT FOUND");
320  }
321  else
322  {
323  const long* s = ((*citer).second)->getSeeds();
324  ATH_MSG_INFO (" Stream = " << streamName << ", Seed1 = "
325  << s[0] << ", Seed2 = " << s[1]);
326  }
327 }
328 
329 void
330 AtRndmGenSvc::print ( void )
331 {
332  for (engineConstIter i = m_engines.begin(); i != m_engines.end(); ++i)
333  print( (*i).first );
334 }
335 
336 CLHEP::HepRandomEngine*
338  const std::string& streamName)
339 {
340  if (m_useOldBrokenSeeding)
341  return oldSetOnDefinedSeeds(eventNumber, runNumber, streamName);
342  //do it properly
343  uint32_t theHash(eventNumber);
344  map<string, uint32_t>::const_iterator citer(m_reseedingOffsets.find(streamName));
345  bool hasOffset(citer != m_reseedingOffsets.end() && 0 != citer->second);
346  if (hasOffset) theHash=crc_combine(theHash, citer->second);
347 
348  theHash=crc_combine(theHash, runNumber);
349  ATH_MSG_VERBOSE( "Reseeding stream " << streamName
350  << " with eventNumber " << eventNumber
351  << " runNumber " << runNumber);
352  if (hasOffset) ATH_MSG_VERBOSE("Applied offset " << citer->second);
353  return this->setOnDefinedSeeds(theHash, streamName);
354 }
355 
356 CLHEP::HepRandomEngine*
358  const std::string& streamName){
359  if (m_useOldBrokenSeeding)
360  return oldSetOnDefinedSeeds(theSeed, streamName);
361  //do it properly
362  engineConstIter citer = m_engines.find(streamName);
364  if ( citer == m_engines.end() )
365  m_engines.insert(engineValType(streamName,
366  new CLHEP::RanecuEngine() ) );
367  engineIter iter = m_engines.find(streamName);
368  theSeed=crc_combine(theSeed, streamName);
369  ATH_MSG_DEBUG("Reseeding stream " << streamName << " with " << theSeed);
370  //Ranecu takes a long as seed and makes a test on the sign of the seed
371  //so let's make sure that our seed is presented to Ranecu as a 32 bit
372  //signed int
373  ((*iter).second)->setSeed( (int32_t)theSeed, 0);
374  return (CLHEP::HepRandomEngine*)(*iter).second;
375 }
376 
377 CLHEP::HepRandomEngine*
379  const std::string& streamName)
380 {
381  engineConstIter citer = m_engines.find(streamName);
382  if ( citer == m_engines.end() )
383  m_engines.insert( engineValType(streamName, new CLHEP::RanecuEngine() ) );
384  engineIter iter = m_engines.find(streamName);
385  int hashedStream(SG::simpleStringHash(streamName));
386  long seeds[3] = { (long)(1000*runNumber + hashedStream),
387  (long)eventNumber, 0 };
388  assert( seeds[0] > 0 );
389  assert( seeds[1] > 0 );
390  const long* s = seeds;
391  ((*iter).second)->setSeeds( s, -1 );
392  return (CLHEP::HepRandomEngine*)(*iter).second;
393 }
394 
395 CLHEP::HepRandomEngine*
397  const std::string& streamName){
398  engineConstIter citer = m_engines.find(streamName);
399  if ( citer == m_engines.end() )
400  m_engines.insert( engineValType(streamName, new CLHEP::RanecuEngine() ) );
401  engineIter iter = m_engines.find(streamName);
402  int hashedStream(SG::simpleStringHash(streamName));
403  long seeds[3] = { (long)(hashedStream % (theSeed+13)), (long)theSeed, 0 };
404  assert( seeds[0] > 0 );
405  assert( seeds[1] > 0 );
406  const long* s = seeds;
407  ((*iter).second)->setSeeds( s, -1 );
408  return (CLHEP::HepRandomEngine*)(*iter).second;
409 }
410 
411 bool
413 {
414  bool allOK(true);
415  engineIter i(m_engines.begin()), e(m_engines.end());
416  while (i!=e &&
417  (allOK=(0 != this->setOnDefinedSeeds(eventNumber,
418  runNumber,
419  (*i++).first)))) {
420  /*empty*/
421  }
422  return allOK;
423 }
424 
425 bool
427  bool allOK(true);
428  engineIter i(m_engines.begin()), e(m_engines.end());
429  while (i!=e &&
430  (allOK=(0 != this->setOnDefinedSeeds(theSeed, (*i++).first)))) {
431  /* empty */
432  }
433  return allOK;
434 }
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
run.infile
string infile
Definition: run.py:13
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
AtRndmGenSvc::finalize
virtual StatusCode finalize() override
Definition: AtRndmGenSvc.cxx:236
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
AtRndmGenSvc::GetEngine
virtual CLHEP::HepRandomEngine * GetEngine(const std::string &streamName) override
Definition: AtRndmGenSvc.cxx:258
hash_functions.h
AtRndmGenSvc::AtRndmGenSvc
AtRndmGenSvc(const std::string &name, ISvcLocator *svc)
Standard Constructor.
Definition: AtRndmGenSvc.cxx:27
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
AtRndmGenSvc::m_default_seed2
long m_default_seed2
Definition: AtRndmGenSvc.h:145
crc_combine.h
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
AtRndmGenSvc::m_HERWIG_default_seed1
long m_HERWIG_default_seed1
Definition: AtRndmGenSvc.h:148
genPbPbJobOpt.seed2
seed2
Definition: genPbPbJobOpt.py:57
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
AtRndmGenSvc::setOnDefinedSeeds
virtual CLHEP::HepRandomEngine * setOnDefinedSeeds(uint32_t theSeed, const std::string &streamName) override
AtRndmGenSvc.h
A random number engine manager, based on Ranecu. Its usage is deprecated, at least when high quality ...
AtRndmGenSvc::SetStreamSeeds
void SetStreamSeeds(const std::string &streamName)
Definition: AtRndmGenSvc.cxx:284
crc_combine
uint32_t crc_combine(uint32_t seed, uint32_t v)
using crc32 for architecture independence in combining the seeds
Definition: AthenaKernel/src/crc_combine.h:11
AtRndmGenSvc::~AtRndmGenSvc
virtual ~AtRndmGenSvc()
Standard Destructor.
Definition: AtRndmGenSvc.cxx:43
AtRndmGenSvc::m_PYTHIA_default_seed1
long m_PYTHIA_default_seed1
Definition: AtRndmGenSvc.h:146
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:11
AtRndmGenSvc::m_HERWIG_default_seed2
long m_HERWIG_default_seed2
Definition: AtRndmGenSvc.h:149
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
AtRndmGenSvc::setAllOnDefinedSeeds
virtual bool setAllOnDefinedSeeds(uint32_t theSeed) override
seed all streams we manage, combining theSeed and the stream names
lumiFormat.i
int i
Definition: lumiFormat.py:85
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AtRndmGenSvc::engineIter
engineMap::iterator engineIter
Definition: AtRndmGenSvc.h:68
CalibDbCompareRT.dummy
dummy
Definition: CalibDbCompareRT.py:59
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
interpretSeeds
bool interpretSeeds(const std::string &buffer, std::string &stream, uint32_t &seed1, uint32_t &seed2, short &luxury, uint32_t &offset)
Definition: interpretSeeds.cxx:28
xAOD::eventNumber
eventNumber
Definition: EventInfo_v1.cxx:124
interpretSeeds.h
Handler::svc
AthROOTErrorHandlerSvc * svc
Definition: AthROOTErrorHandlerSvc.cxx:10
HLT::setFlag
void setFlag(TrigPassFlags *flags, const T *obj, const CONTAINER *container, const std::vector< bool > &flag)
Set the flag at index position.
Definition: TrigPassFlags.h:121
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
WriteHiveWithMetaData.streamName
string streamName
Definition: WriteHiveWithMetaData.py:22
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
AtRndmGenSvc::oldSetOnDefinedSeeds
CLHEP::HepRandomEngine * oldSetOnDefinedSeeds(uint32_t theSeed, const std::string &streamName)
broken, temporarily keep for backward compatibility
Definition: AtRndmGenSvc.cxx:396
DeMoAtlasDataLoss.runNumber
string runNumber
Definition: DeMoAtlasDataLoss.py:64
AtRndmGenSvc::CreateStream
virtual void CreateStream(uint32_t seed1, uint32_t seed2, const std::string &streamName) override
Definition: AtRndmGenSvc.cxx:272
AtRndmGenSvc::print
virtual void print(void) override
mapkey::sf
@ sf
Definition: TElectronEfficiencyCorrectionTool.cxx:38
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AtRndmGenSvc::m_default_seed1
long m_default_seed1
Definition: AtRndmGenSvc.h:144
DeMoScan.first
bool first
Definition: DeMoScan.py:534
genPbPbJobOpt.seed1
seed1
Definition: genPbPbJobOpt.py:56
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
SG::simpleStringHash
int simpleStringHash(const std::string &str, int maxInt=0xFFFF)
simple hash function derived from Sedgewick Algorithms in C++ 3rd ed
Definition: hash_functions.h:16
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
AtRndmGenSvc::handle
virtual void handle(const Incident &) override
IIncidentListener implementation. Handles EndEvent incident.
Definition: AtRndmGenSvc.cxx:150
AtRndmGenSvc::engineConstIter
engineMap::const_iterator engineConstIter
Definition: AtRndmGenSvc.h:69
AtRndmGenSvc::m_PYTHIA_default_seed2
long m_PYTHIA_default_seed2
Definition: AtRndmGenSvc.h:147
value_type
Definition: EDM_MasterSearch.h:11
AtRndmGenSvc::engineValType
engineMap::value_type engineValType
Definition: AtRndmGenSvc.h:70
PrepareReferenceFile.outfile
outfile
Definition: PrepareReferenceFile.py:42
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
AtRndmGenSvc::initialize
virtual StatusCode initialize() override
Definition: AtRndmGenSvc.cxx:51
ServiceHandle< IIncidentSvc >