Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ColoredHadronization.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ColoredHadronization.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 "ColoredHadronization.h"
17 #include "JetScapeXML.h"
18 #include "JetScapeLogger.h"
19 #include "tinyxml2.h"
20 
21 using namespace Jetscape;
22 using namespace Pythia8;
23 
24 // Register the module with the base class
26  ColoredHadronization::reg("ColoredHadronization");
27 
28 Pythia8::Pythia ColoredHadronization::pythia("IntentionallyEmpty", false);
29 
31  SetId("MyHadroTest");
32  VERBOSE(8);
33 }
34 
36 
38 
39  std::string s = GetXMLElementText({"JetHadronization", "name"});
40  JSDEBUG << s << " to be initializied ...";
41 
42  double p_read_xml =
43  GetXMLElementDouble({"JetHadronization", "eCMforHadronization"});
44  p_fake = p_read_xml;
45 
46  /*std::string weak_decays =
47  GetXMLElementText({"JetHadronization", "weak_decays"});*/
48 
49  VERBOSE(2) << "Start Hadronizing using the PYTHIA module...";
50 
51  // Show initialization at DEBUG or high verbose level
52  pythia.readString("Init:showProcesses = off");
53  pythia.readString("Init:showChangedSettings = off");
54  pythia.readString("Init:showMultipartonInteractions = off");
55  pythia.readString("Init:showChangedParticleData = off");
56  if (JetScapeLogger::Instance()->GetDebug() ||
57  JetScapeLogger::Instance()->GetVerboseLevel() > 2) {
58  pythia.readString("Init:showProcesses = on");
59  pythia.readString("Init:showChangedSettings = on");
60  pythia.readString("Init:showMultipartonInteractions = on");
61  pythia.readString("Init:showChangedParticleData = on");
62  }
63 
64  // No event record printout.
65  pythia.readString("Next:numberShowInfo = 0");
66  pythia.readString("Next:numberShowProcess = 0");
67  pythia.readString("Next:numberShowEvent = 0");
68  if (JetScapeLogger::Instance()->GetDebug() ||
69  JetScapeLogger::Instance()->GetVerboseLevel() > 2) {
70  pythia.readString("Next:numberShowInfo = 1");
71  pythia.readString("Next:numberShowProcess = 1");
72  pythia.readString("Next:numberShowEvent = 1");
73  }
74 
75  pythia.readString("ProcessLevel:all = off");
76  pythia.readString("PartonLevel:FSR=off");
77 
78  // General settings for hadron decays
79  std::string pythia_decays = GetXMLElementText({"JetHadronization", "pythia_decays"});
80  double tau0Max = 10.0;
81  double tau0Max_xml = GetXMLElementDouble({"JetHadronization", "tau0Max"});
82  if(tau0Max_xml >= 0){tau0Max = tau0Max_xml;}
83  else{JSWARN << "tau0Max should be larger than 0. Set it to 10.";}
84  if(pythia_decays == "on"){
85  JSINFO << "Pythia decays are turned on for tau0Max < " << tau0Max;
86  pythia.readString("HadronLevel:Decay = on");
87  pythia.readString("ParticleDecays:limitTau0 = on");
88  pythia.readString("ParticleDecays:tau0Max = " + std::to_string(tau0Max));
89  } else {
90  JSINFO << "Pythia decays are turned off";
91  pythia.readString("HadronLevel:Decay = off");
92  }
93 
94  // Settings for decays (old flag, will be depracted at some point)
95  // This overwrites the previous settings if the user xml file contains the flag
96  std::string weak_decays =
97  GetXMLElementText({"JetHadronization", "weak_decays"});
98  if (weak_decays == "off") {
99  JSINFO << "Hadron decays are turned off.";
100  JSWARN << "This parameter will be depracted at some point. Use 'pythia_decays' instead.\nOverwriting 'pythia_decays'.";
101  pythia.readString("HadronLevel:Decay = off");
102  } else if(weak_decays == "on") {
103  JSINFO << "Hadron decays inside a range of 10 mm/c are turned on.";
104  JSWARN << "This parameter will be depracted at some point. Use 'pythia_decays' and 'tau0Max' for more control on decays.\nOverwriting 'pythia_decays' and fix 'tau0Max' to 10.";
105  pythia.readString("HadronLevel:Decay = on");
106  pythia.readString("ParticleDecays:limitTau0 = on");
107  pythia.readString("ParticleDecays:tau0Max = 10.0");
108  }
109 
110  std::stringstream lines;
111  lines << GetXMLElementText({"JetHadronization", "LinesToRead"}, false);
112  while (std::getline(lines, s, '\n')) {
113  if (s.find_first_not_of(" \t\v\f\r") == s.npos)
114  continue; // skip empty lines
115  JSINFO << "Also reading in: " << s;
116  pythia.readString(s);
117  }
118 
119  pythia.init();
120 }
121 
122 void ColoredHadronization::WriteTask(weak_ptr<JetScapeWriter> w) {
123  VERBOSE(8);
124  auto f = w.lock();
125  if (!f)
126  return;
127  f->WriteComment("Hadronization Module : " + GetId());
128  f->WriteComment("Hadronization to be implemented accordingly ...");
129 }
130 
132  vector<vector<shared_ptr<Parton>>> &shower,
133  vector<shared_ptr<Hadron>> &hOut, vector<shared_ptr<Parton>> &pOut) {
134 
135  Event &event = pythia.event;
136  event.reset();
137  double pz = p_fake;
138 
139  JSDEBUG << "&&&&&&&&&&&&&&&&&&& the number of showers are: " << shower.size();
140  for (unsigned int ishower = 0; ishower < shower.size(); ++ishower) {
141  JSDEBUG << "&&&&&&&&&&&&&&&&&&& there are " << shower.at(ishower).size()
142  << " partons in the shower number " << ishower;
143  for (unsigned int ipart = 0; ipart < shower.at(ishower).size(); ++ipart) {
144  double onshellE = pow(pow(shower.at(ishower).at(ipart)->px(), 2) +
145  pow(shower.at(ishower).at(ipart)->py(), 2) +
146  pow(shower.at(ishower).at(ipart)->pz(), 2),
147  0.5);
148 
149  if (shower.at(ishower).at(ipart)->pid() == 22) {
150 
151  VERBOSE(1) << BOLDYELLOW
152  << " photon found in colored hadronization with ";
153  VERBOSE(1) << BOLDYELLOW
154  << "px = " << shower.at(ishower).at(ipart)->px();
155  //cin >> blurb;
156  }
157  event.append(shower.at(ishower).at(ipart)->pid(), 23,
158  shower.at(ishower).at(ipart)->color(),
159  shower.at(ishower).at(ipart)->anti_color(),
160  shower.at(ishower).at(ipart)->px(),
161  shower.at(ishower).at(ipart)->py(),
162  shower.at(ishower).at(ipart)->pz(), onshellE);
163  }
164 
165  //first, find unpaired color and anticolor tags.
166  std::vector<int> cols;
167  std::vector<int> acols;
168  for (unsigned int ipart = 0; ipart < shower.at(ishower).size(); ++ipart) {
169  if (shower.at(ishower).at(ipart)->pid() == 22) {
170  continue;
171  }
172  if (shower.at(ishower).at(ipart)->color() != 0) {
173  cols.push_back(shower.at(ishower).at(ipart)->color());
174  }
175  if (shower.at(ishower).at(ipart)->anti_color() != 0) {
176  acols.push_back(shower.at(ishower).at(ipart)->anti_color());
177  }
178  }
179  //the outcomes are: 1-unpaired color tag, 2-unpaired anticolor tag, 3-both an unpaired color & anticolor tag, 4-no unpaired tags
180  //1-add an antiquark, 2-add a quark, 3-add a gluon, 4-add nothing (possibly photon only event)
181  int icol = 0;
182  while (icol < cols.size()) {
183  bool foundpair = false;
184  for (int iacol = 0; iacol < acols.size(); ++iacol) {
185  if (cols[icol] == acols[iacol]) {
186  cols.erase(cols.begin() + icol);
187  acols.erase(acols.begin() + iacol);
188  foundpair = true;
189  continue;
190  }
191  }
192  if (!foundpair) {
193  ++icol;
194  }
195  }
196 
197  int pid = 0;
198  int color = 0;
199  int anti_color = 0;
200  if ((cols.size() > 0) && (acols.size() > 0)) {
201  pid = 21;
202  color = cols[0];
203  anti_color = acols[0];
204  } else if ((cols.size() > 0) && (acols.size() == 0)) {
205  pid = -1;
206  color = cols[0];
207  anti_color = 0;
208  } else if ((cols.size() == 0) && (acols.size() > 0)) {
209  pid = 1;
210  color = 0;
211  anti_color = acols[0];
212  }
213 
214  if (pid != 0) {
215  pz = -1 * pz;
216  event.append(pid, 23, anti_color, color, 0.2, 0.2, pz,
217  sqrt(pz * pz + 0.08));
218  }
219 
220  VERBOSE(2) << "There are " << hOut.size() << " Hadrons and " << pOut.size()
221  << " partons after Hadronization";
222  }
223 
224  //there still may be color tag duplicates - will SegFault if color_reconnections is ever invoked.
225  //this should be fixed *here*, before pythia.next() below, if that's ever a concern.
226  //scan over list of color & anticolor tags - if we find a duplicate, set it to a new value >0, <101 (will fail for more than 100 duplicates)
227  std::vector<std::vector<int>> col_instances;
228  for (unsigned int i = 0; i < event.size(); ++i) {
229  bool newcol = true;
230  bool newacol = true;
231  for (int icols = 0; icols < col_instances.size(); ++icols) {
232  if (event[i].col() == col_instances[icols][0]) {
233  ++col_instances[icols][1];
234  newcol = false;
235  }
236  if (event[i].acol() == col_instances[icols][0]) {
237  ++col_instances[icols][1];
238  newacol = false;
239  }
240  }
241  if (newcol && (event[i].col() != 0)) {
242  std::vector<int> tmpcol;
243  tmpcol.push_back(event[i].col());
244  tmpcol.push_back(1);
245  col_instances.push_back(tmpcol);
246  }
247  if (newacol && (event[i].acol() != 0)) {
248  std::vector<int> tmpcol;
249  tmpcol.push_back(event[i].acol());
250  tmpcol.push_back(1);
251  col_instances.push_back(tmpcol);
252  }
253  }
254  col_instances.erase(
255  std::remove_if(col_instances.begin(), col_instances.end(),
256  [](const std::vector<int> &val) { return val[1] <= 2; }),
257  col_instances.end());
258  int updcol = 1;
259  while (col_instances.size() > 0) {
260  int nupd = 2;
261  for ( int i = event.size() - 1; i >= 0; --i) {
262  if (col_instances[0][0] == event[i].col()) {
263  event[i].col(updcol);
264  --nupd;
265  }
266  if (col_instances[0][0] == event[i].acol()) {
267  event[i].acol(updcol);
268  --nupd;
269  }
270  if (nupd == 0) {
271  break;
272  }
273  }
274  ++updcol;
275  col_instances[0][1] -= 2;
276  col_instances.erase(
277  std::remove_if(col_instances.begin(), col_instances.end(),
278  [](const std::vector<int> &val) { return val[1] <= 2; }),
279  col_instances.end());
280  }
281 
282  pythia.next();
283  // event.list();
284 
285  unsigned int ip = hOut.size();
286  for (unsigned int i = 0; i < event.size(); ++i) {
287  if (!event[i].isFinal())
288  continue;
289  //if ( !event[i].isHadron() ) continue;
290  if (fabs(event[i].eta()) > 20)
291  continue; //To prevent "nan" from propagating, very rare though
292 
293  double x[4] = {0, 0, 0, 0};
294  hOut.push_back(make_shared<Hadron>(ip, event[i].id(), event[i].status(),
295  event[i].pT(), event[i].eta(),
296  event[i].phi(), event[i].e(), x));
297  ++ip;
298  }
299 
300  shower.clear();
301 }