ATLAS Offline Software
Loading...
Searching...
No Matches
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
24using namespace std;
25
27AtRndmGenSvc::AtRndmGenSvc(const std::string& name,ISvcLocator* svc)
28 : base_class(name,svc),
31{
32 // Set Default values
33 m_default_seed1 = 3591;
34 m_default_seed2 = 2309736;
35 m_PYTHIA_default_seed1 = 93453591;
39}
40
41
44{
45 engineIter i(m_engines.begin()), e(m_engines.end());
46 while (i != e) delete (i++)->second;
47}
48
49
50StatusCode
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
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;
88 uint32_t seed1, seed2;
89 if (interpretSeeds(buffer, stream, seed1, seed2)) {
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;
111 if (interpretSeeds(i, stream, seed1, seed2, dummy, offset)) {
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
149void
150AtRndmGenSvc::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()
174 CLHEP::RandGauss::setFlag(false);
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()
208 CLHEP::RandGauss::setFlag(false);
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
235StatusCode
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
257CLHEP::HepRandomEngine*
258AtRndmGenSvc::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
271void
272AtRndmGenSvc::CreateStream(uint32_t seed1, uint32_t seed2,
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
283void
284AtRndmGenSvc::SetStreamSeeds ( const std::string& streamName )
285{
286 long seed1;
287 long seed2;
288 if (streamName == "PYTHIA")
289 {
292 }
293 else if (streamName == "HERWIG")
294 {
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
313void
314AtRndmGenSvc::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
329void
331{
332 for (engineConstIter i = m_engines.begin(); i != m_engines.end(); ++i)
333 print( (*i).first );
334}
335
336CLHEP::HepRandomEngine*
337AtRndmGenSvc::setOnDefinedSeeds(uint32_t eventNumber, uint32_t runNumber,
338 const std::string& streamName)
339{
341 return oldSetOnDefinedSeeds(eventNumber, runNumber, streamName);
342 //do it properly
343 uint32_t theHash(eventNumber);
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
356CLHEP::HepRandomEngine*
358 const std::string& streamName){
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
377CLHEP::HepRandomEngine*
378AtRndmGenSvc::oldSetOnDefinedSeeds(uint32_t eventNumber, uint32_t runNumber,
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
395CLHEP::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
411bool
412AtRndmGenSvc::setAllOnDefinedSeeds(uint32_t eventNumber, uint32_t runNumber)
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
425bool
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}
#define endmsg
A random number engine manager, based on Ranecu.
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
uint32_t crc_combine(uint32_t seed, uint32_t v)
using crc32 for architecture independence in combining the seeds
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
long m_HERWIG_default_seed1
Gaudi::Property< bool > m_read_from_file
read engine status from file
AtRndmGenSvc(const std::string &name, ISvcLocator *svc)
Standard Constructor.
std::map< std::string, uint32_t > m_reseedingOffsets
optional offsets to combine to run/evt no when reseeding.
virtual bool setAllOnDefinedSeeds(uint32_t theSeed) override
seed all streams we manage, combining theSeed and the stream names
StringArrayProperty m_streams_seeds
Gaudi::Property< bool > m_save_to_file
should current engine status be saved to file ?
long m_HERWIG_default_seed2
Gaudi::Property< std::string > m_file_to_read
name of the file to read the engine status from
engineMap::const_iterator engineConstIter
long m_PYTHIA_default_seed1
virtual void handle(const Incident &) override
IIncidentListener implementation. Handles EndEvent incident.
virtual StatusCode finalize() override
unsigned int number_of_streams(void) const
virtual void print(void) override
engineConstIter begin(void) const
StringArrayProperty m_reseedStreamNames
streams to be reseeded for every event
engineMap::iterator engineIter
engineMap m_engines
void SetStreamSeeds(const std::string &streamName)
Gaudi::Property< std::string > m_file_to_write
name of the file to save the engine status to.
virtual void CreateStream(uint32_t seed1, uint32_t seed2, const std::string &streamName) override
virtual CLHEP::HepRandomEngine * GetEngine(const std::string &streamName) override
virtual CLHEP::HepRandomEngine * setOnDefinedSeeds(uint32_t theSeed, const std::string &streamName) override
virtual StatusCode initialize() override
Gaudi::Property< bool > m_useOldBrokenSeeding
backward compatibility only, broken 32/64 bits
virtual ~AtRndmGenSvc()
Standard Destructor.
engineMap::value_type engineValType
CLHEP::HepRandomEngine * oldSetOnDefinedSeeds(uint32_t theSeed, const std::string &streamName)
broken, temporarily keep for backward compatibility
std::map< std::string, std::vector< long int > > m_engines_copy
Random engine copy (for output to a file)
long m_PYTHIA_default_seed2
engineConstIter end(void) const
Gaudi::Property< bool > m_eventReseed
reseed for every event
STL iterator class.
bool interpretSeeds(const std::string &buffer, std::string &stream, uint32_t &seed1, uint32_t &seed2, short &luxury, uint32_t &offset)
int simpleStringHash(const std::string &str, int maxInt=0xFFFF)
simple hash function derived from Sedgewick Algorithms in C++ 3rd ed
STL namespace.
MsgStream & msg
Definition testRead.cxx:32