Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JetScapeTaskSupport.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file JetScapeTaskSupport.cc
1 /*******************************************************************************
2  * Copyright (c) The JETSCAPE Collaboration, 2018
3  *
4  * Modular, task-based framework for simulating all aspects of heavy-ion collisions
5  *
6  * For the list of contributors see AUTHORS.
7  *
8  * Report issues at https://github.com/JETSCAPE/JETSCAPE/issues
9  *
10  * or via email to bugs.jetscape@gmail.com
11  *
12  * Distributed under the GNU General Public License 3.0 (GPLv3 or later).
13  * See COPYING for details.
14  ******************************************************************************/
15 
16 #include "JetScapeTaskSupport.h"
17 #include "JetScapeLogger.h"
18 #include <stdlib.h>
19 
20 using namespace std;
21 
22 namespace Jetscape {
23 
24 // static member initialization
25 JetScapeTaskSupport *JetScapeTaskSupport::m_pInstance = nullptr;
26 shared_ptr<std::mt19937> JetScapeTaskSupport::one_for_all_ = nullptr;
27 unsigned int JetScapeTaskSupport::random_seed_ = 0;
28 bool JetScapeTaskSupport::initialized_ = false;
29 bool JetScapeTaskSupport::one_generator_per_task_ = false;
30 
31 // ---------------------------------------------------------------------------
32 JetScapeTaskSupport *JetScapeTaskSupport::Instance() {
33  if (!m_pInstance) {
34  m_pInstance = new JetScapeTaskSupport;
35  VERBOSE(1) << "Created JetScapeTaskSupport Instance";
36  }
37  return m_pInstance;
38 }
39 
40 // ---------------------------------------------------------------------------
41 int JetScapeTaskSupport::RegisterTask() {
42  VERBOSE(1) << "JetScapeTaskSupport::RegisterTask called, answering "
43  << CurrentTaskNumber;
44  CurrentTaskNumber++;
45  return CurrentTaskNumber - 1;
46 }
47 
48 // ---------------------------------------------------------------------------
49 void JetScapeTaskSupport::ReadSeedFromXML() {
50  VERBOSE(1) << "JetScapeTaskSupport::ReadSeedFromXML called. ";
51 
52  // xml limits us to unsigned int :-/ -- but so does 32 bits Mersenne Twist
53  tinyxml2::XMLElement *RandomXmlDescription =
54  JetScapeXML::Instance()->GetElement({"Random"});
55  tinyxml2::XMLElement *xmle = 0;
56  if (RandomXmlDescription) {
57  xmle = RandomXmlDescription->FirstChildElement("seed");
58  if (!xmle)
59  throw std::runtime_error("Cannot parse xml");
60  xmle->QueryUnsignedText(&random_seed_);
61  } else {
62  JSWARN << "No <Random> element found in xml, seeding to 0";
63  }
64 
65  VERBOSE(7) << "Seeding JetScapeTaskSupport to " << random_seed_;
66  if (random_seed_ == 0) {
67  // random seed
68  random_seed_ = std::chrono::system_clock::now().time_since_epoch().count();
69  JSINFO << "JetScapeTaskSupport found seed 0, using one engine for all and "
70  "reseeding to "
71  << random_seed_;
72  one_generator_per_task_ = false;
73  } else {
74  JSINFO << "JetScapeTaskSupport found seed " << random_seed_
75  << ", using individual engines with seeds created from "
76  << random_seed_;
77  one_generator_per_task_ = true;
78  }
79 
80  one_for_all_ = make_shared<std::mt19937>(random_seed_);
81 
82  // VERBOSE(7) << "Setting random seed for mt19937 to " << seed;
83  // generator.seed(seed);
84  // ZeroOneDistribution = uniform_real_distribution<double> { 0.0, 1.0 };
85 
86  initialized_ = true;
87 }
88 
89 // ---------------------------------------------------------------------------
90 shared_ptr<std::mt19937> JetScapeTaskSupport::GetMt19937Generator(int TaskId) {
91  if (!initialized_) {
92  JSWARN << "Trying to use JetScapeTaskSupport::GetMt19937Generator before "
93  "initialization";
94  throw std::runtime_error(
95  "Trying to use JetScapeTaskSupport::GetMt19937Generator before "
96  "initialization");
97  }
98 
99  if (!one_for_all_) {
100  throw std::runtime_error("generator not initialized?");
101  }
102 
103  // In this case, we use our own engine to create a repeatable
104  // sequence of seeds and hand over a properly seeded engine
105  if (one_generator_per_task_) {
106  if (random_seed_ == 0)
107  throw std::runtime_error("This should never happen");
108  // reseed to be on the safe side
109  one_for_all_->seed(random_seed_);
110  // Advance according to TaskId
111  // Note that this method can be lied to.
112  // Could design a safer interface but for now, trust the user
113  one_for_all_->discard(TaskId);
114  // And get the unique seed for this task
115  unsigned int localseed = (*one_for_all_)();
116  JSDEBUG << "Asked by " << TaskId
117  << " for an individual generator, returning one seeded with "
118  << localseed;
119  return make_shared<std::mt19937>(localseed);
120  }
121 
122  // this singleton owns the generator(s) and keeps them until deletion
123  JSDEBUG << "Asked by " << TaskId
124  << " for the static generator, returning one originally seeded with "
125  << random_seed_;
126  return one_for_all_;
127 }
128 
129 // ---------------------------------------------------------------------------
130 
131 } // end namespace Jetscape