Newer
Older
Markus Frank
committed
//==========================================================================
// AIDA Detector description implementation for LCD
Markus Frank
committed
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
Markus Frank
committed
// All rights reserved.
Markus Frank
committed
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
Markus Frank
committed
// Author : M.Frank
//
//==========================================================================
// Framework include files
#include "DD4hep/Printout.h"
#include "DD4hep/InstanceCount.h"
#include "DDG4/Geant4Random.h"
#include "CLHEP/Random/EngineFactory.h"
#include "CLHEP/Random/Random.h"
Markus Frank
committed
// ROOT include files
#include "TRandom1.h"
// C/C++ include files
#include <cmath>
using namespace std;
using namespace DD4hep::Simulation;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
namespace CLHEP {
unsigned long crc32ul(const std::string& s);
}
namespace {
/// Helper class to redirect calls to gRandon to Geant4Random
class RNDM : public TRandom {
/// Reference to the generator object
Geant4Random* m_generator;
/// Reference to HepRandomEngine
CLHEP::HepRandomEngine* m_engine;
public:
/// Initializing constructor
RNDM(Geant4Random* r) : TRandom(), m_generator(r) {
m_engine = m_generator->engine();
}
/// Default destructor
virtual ~RNDM() { }
/// Set new seed
virtual void SetSeed(UInt_t seed=0) {
fSeed = seed;
m_generator->setSeed((long)seed);
}
/// Single shot random number creation
virtual Double_t Rndm(Int_t) {
return m_engine->flat();
}
/// Return an array of n random numbers uniformly distributed in ]0,1].
virtual void RndmArray(Int_t size, Float_t *array) {
for (Int_t i=0;i<size;i++) array[i] = m_engine->flat();
}
/// Return an array of n random numbers uniformly distributed in ]0,1].
virtual void RndmArray(Int_t size, Double_t *array) {
m_engine->flatArray(size,array);
}
};
static Geant4Random* s_instance = 0;
}
/// Default constructor
Geant4Random::Geant4Random(Geant4Context* ctxt, const std::string& nam)
: Geant4Action(ctxt,nam), m_engine(0), m_rootRandom(0), m_rootOLD(0),
m_inited(false)
{
declareProperty("File", m_file="");
declareProperty("Type", m_engineType="");
declareProperty("Seed", m_seed = 123456789);
declareProperty("Luxury", m_luxury = 1);
declareProperty("Replace_gRandom", m_replace = true);
// Default: static Geant4 random engine.
m_engine = CLHEP::HepRandom::getTheEngine();
InstanceCount::increment(this);
}
/// Default destructor
Geant4Random::~Geant4Random() {
if ( s_instance == this ) s_instance = 0;
if ( !m_engineType.empty() ) deletePtr(m_engine);
if ( m_rootRandom == gRandom ) gRandom = m_rootOLD;
deletePtr(m_rootRandom);
InstanceCount::decrement(this);
}
/// Access the main Geant4 random generator instance. Must be created before used!
Geant4Random* Geant4Random::instance(bool throw_exception) {
if ( !s_instance && throw_exception ) {
throw runtime_error("No global random number generator defined!");
}
return s_instance;
/// Make this random generator instance the one used by Geant4
Geant4Random* Geant4Random::setMainInstance(Geant4Random* ptr) {
if ( s_instance != ptr ) {
if ( !ptr ) {
throw runtime_error("Attempt to declare invalid Geant4Random instance.");
}
if ( !ptr->m_inited ) {
throw runtime_error("Attempt to declare uninitialized Geant4Random instance.");
}
Geant4Random* old = s_instance;
if ( ptr->m_engine != CLHEP::HepRandom::getTheEngine() ) {
CLHEP::HepRandom::setTheEngine(ptr->m_engine);
}
if ( ptr->m_replace ) {
ptr->m_rootOLD = gRandom;
gRandom = ptr->m_rootRandom;
}
s_instance = ptr;
return old;
}
return 0;
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "CLHEP/Random/DualRand.h"
#include "CLHEP/Random/JamesRandom.h"
#include "CLHEP/Random/MTwistEngine.h"
#include "CLHEP/Random/RanecuEngine.h"
#include "CLHEP/Random/Ranlux64Engine.h"
#include "CLHEP/Random/RanluxEngine.h"
#include "CLHEP/Random/RanshiEngine.h"
#include "CLHEP/Random/NonRandomEngine.h"
/// Initialize the instance.
void Geant4Random::initialize() {
if ( !m_file.empty() ) {
ifstream in(m_file);
m_engine = CLHEP::EngineFactory::newEngine(in);
if ( !m_engine ) {
except("Failed to create CLHEP random engine from file:%s.",m_file.c_str());
}
m_seed = m_engine->getSeed();
}
else if ( !m_engineType.empty() ) {
/// Create new engine if a type is specified
if ( m_engineType == CLHEP::HepJamesRandom::engineName() )
m_engine = new CLHEP::HepJamesRandom();
else if ( m_engineType == CLHEP::RanecuEngine::engineName() )
m_engine = new CLHEP::RanecuEngine();
else if ( m_engineType == CLHEP::Ranlux64Engine::engineName() )
m_engine = new CLHEP::Ranlux64Engine();
else if ( m_engineType == CLHEP::MTwistEngine::engineName() )
m_engine = new CLHEP::MTwistEngine();
else if ( m_engineType == CLHEP::DualRand::engineName() )
m_engine = new CLHEP::DualRand();
else if ( m_engineType == CLHEP::RanluxEngine::engineName() )
m_engine = new CLHEP::RanluxEngine();
else if ( m_engineType == CLHEP::RanshiEngine::engineName() )
m_engine = new CLHEP::RanshiEngine();
else if ( m_engineType == CLHEP::NonRandomEngine::engineName() )
m_engine = new CLHEP::NonRandomEngine();
if ( !m_engine ) {
except("Failed to create CLHEP random engine of type: %s.",m_engineType.c_str());
}
}
m_engine->setSeed(m_seed,m_luxury);
m_rootRandom = new RNDM(this);
m_inited = true;
if ( 0 == s_instance ) {
setMainInstance(this);
}
/// Should initialise the status of the algorithm according to seed.
void Geant4Random::setSeed(long seed) {
if ( !m_inited ) initialize();
m_engine->setSeed(m_seed=seed,0);
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/// Should initialise the status of the algorithm
/** Initialization according to the zero terminated
* array of seeds. It is allowed to ignore one or
* many seeds in this array.
*/
void Geant4Random::setSeeds(const long* seeds, int size) {
if ( !m_inited ) initialize();
m_seed = seeds[0];
m_engine->setSeeds(seeds, size);
}
/// Should save on a file specific to the instantiated engine in use the current status.
void Geant4Random::saveStatus( const char filename[] ) const {
if ( !m_inited ) {
except("Failed to save RandomGenerator status. [Not-inited]");
}
m_engine->saveStatus(filename);
}
/// Should read from a file and restore the last saved engine configuration.
void Geant4Random::restoreStatus( const char filename[] ) {
if ( !m_inited ) initialize();
m_engine->restoreStatus(filename);
}
/// Should dump the current engine status on the screen.
void Geant4Random::showStatus() const {
if ( !m_inited ) {
error("Failed to show RandomGenerator status. [Not-inited]");
return;
}
printP2("Random engine status of object of type Geant4Random @ 0x%p",this);
if ( !m_file.empty() )
printP2(" Created from file: %s",m_file.c_str());
else if ( !m_engineType.empty() )
printP2(" Special instance created of type:%s",m_engineType.c_str());
else
printP2(" Reused HepRandom instance @ 0x%p",m_engine);
if ( m_engine != CLHEP::HepRandom::getTheEngine() )
printP2(" Instance is identical to Geant4's HepRandom instance.");
printP2(" Instance is %sidentical to ROOT's gRandom instance.",
gRandom == m_rootRandom ? "" : "NOT ");
if ( gRandom != m_rootRandom ) {
printP2(" Local TRandom: 0x%p gRandom: 0x%p",m_rootRandom,gRandom);
}
m_engine->showStatus();
}
/// Create flat distributed random numbers in the interval ]0,1]
double Geant4Random::rndm(int i) {
return gRandom->Rndm(i);
}
/// Create a float array of flat distributed random numbers in the interval ]0,1]
void Geant4Random::rndmArray(int n, float *array) {
gRandom->RndmArray(n,array);
}
/// Create a double array of flat distributed random numbers in the interval ]0,1]
void Geant4Random::rndmArray(int n, double *array) {
gRandom->RndmArray(n,array);
}
/// Create uniformly disributed random numbers in the interval ]0,x1]
double Geant4Random::uniform(double x1) {
return gRandom->Uniform(x1);
}
/// Create uniformly disributed random numbers in the interval ]x1,x2]
double Geant4Random::uniform(double x1, double x2) {
return gRandom->Uniform(x1,x2);
}
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/// Create exponentially distributed random numbers
double Geant4Random::exp(double tau) {
if ( !m_inited ) initialize();
return gRandom->Exp(tau);
}
/// Generates random vectors, uniformly distributed over a circle of given radius.
double Geant4Random::gauss(double mean, double sigma) {
if ( !m_inited ) initialize();
return gRandom->Gaus(mean,sigma);
}
/// Create landau distributed random numbers
double Geant4Random::landau(double mean, double sigma) {
if ( !m_inited ) initialize();
return gRandom->Landau(mean,sigma);
}
/// Create tuple of randum number around a circle with radius r
void Geant4Random::circle(double &x, double &y, double r) {
if ( !m_inited ) initialize();
gRandom->Circle(x,y,r);
}
/// Create tuple of randum number on a sphere with radius r
void Geant4Random::sphere(double &x, double &y, double &z, double r) {
if ( !m_inited ) initialize();
gRandom->Sphere(x,y,z,r);
}