Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JetEnergyLoss.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file JetEnergyLoss.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 <iostream>
17 #include <thread>
18 //#include <mutex>
19 //#include <condition_variable>
20 //#include <future>
21 
22 #include "JetEnergyLoss.h"
23 #include "JetScapeLogger.h"
24 #include "JetScapeXML.h"
25 #include <string>
26 #include "tinyxml2.h"
27 #include "JetScapeSignalManager.h"
28 #include "JetScapeWriterStream.h"
29 #include "HardProcess.h"
30 #include "JetScapeModuleMutex.h"
31 #include "LiquefierBase.h"
32 #include "MakeUniqueHelper.h"
33 #include "FluidDynamics.h"
34 #include <GTL/dfs.h>
35 
36 #ifdef USE_HEPMC
37 #include "JetScapeWriterHepMC.h"
38 #endif
39 
40 #define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
41 
42 using namespace std;
43 
44 namespace Jetscape {
45 
46 JetEnergyLoss::JetEnergyLoss() {
47  qhat = -99.99;
48  SetId("JetEnergyLoss");
49  jetSignalConnected = false;
50  edensitySignalConnected = false;
51  GetHydroCellSignalConnected = false;
52  GetHydroTau0SignalConnected = false;
53  SentInPartonsConnected = false;
54 
55  deltaT = 0;
56  maxT = 0;
57 
58  inP = nullptr;
59  pShower = nullptr;
60 
61  VERBOSE(8);
62 }
63 
64 JetEnergyLoss::~JetEnergyLoss() {
65  VERBOSE(8);
66 
67  //pShower->clear();
68  disconnect_all();
69 }
70 
71 JetEnergyLoss::JetEnergyLoss(const JetEnergyLoss &j) {
72  qhat = j.GetQhat();
73  SetActive(j.GetActive());
74  SetId(j.GetId());
75  SetJetSignalConnected(false);
76  SetEdensitySignalConnected(false);
77  SetGetHydroCellSignalConnected(false);
78  SetGetHydroTau0SignalConnected(false);
79  SetSentInPartonsConnected(false);
80 
81  deltaT = j.deltaT;
82  maxT = j.maxT;
83 
84  inP = nullptr;
85  pShower = nullptr;
86 
87  VERBOSE(8) << "To be copied : # Subtasks = " << j.GetTaskList().size();
88  for (auto it : j.GetTaskList()) {
89  // Working via CRTP JetEnergyLossModule Clone function !
91  ->Clone(); //shared ptr with clone !!????
92  Add(st);
93  }
94 }
95 
97  VERBOSESHOWER(8);
98  if (pShower)
99  pShower->clear();
100 
101  this->final_Partons.clear();
102 
103  inP = nullptr;
104 }
105 
108 
109  JSINFO << "Initialize JetEnergyLoss ...";
110 
111  deltaT = GetXMLElementDouble({"Eloss", "deltaT"});
112 
113  maxT = GetXMLElementDouble({"Eloss", "maxT"});
114  JSINFO << "Eloss shower with deltaT = " << deltaT << " and maxT = " << maxT;
115 
116  std::string mutexOnString = GetXMLElementText({"Eloss", "mutex"}, false);
117  if (!mutexOnString.compare("ON"))
118  //Check mutual exclusion of Eloss Modules
119  {
120  if (GetNumberOfTasks() > 1) {
121  for (auto elossModule : GetTaskList()) {
122  shared_ptr<JetScapeModuleMutex> mutex_ptr = elossModule->GetMutex();
123  if (mutex_ptr) {
124  if (!(mutex_ptr->CheckMutex(GetTaskList()))) {
125  JSWARN << "Mutually exclusive Energy-Loss modules attached together!";
126  throw std::runtime_error("Fix it by attaching one of them.");
127  }
128  }
129  }
130  }
131  }
132 
133  if (GetNumberOfTasks() < 1) {
134  JSWARN << " : No valid Energy Loss modules found ...";
135  exit(-1);
136  }
137 
138  inP = nullptr;
139  pShower = nullptr;
140 
141  JSINFO << "Found " << GetNumberOfTasks()
142  << " Eloss Tasks/Modules Initialize them ... ";
143 
144  JetScapeTask::InitTasks();
145 }
146 
147 void JetEnergyLoss::DoShower() {
148  double tStart = 0;
149  double currentTime = 0;
150 
151  VERBOSESHOWER(8) << "Hard Parton from Initial Hard Process ...";
152  VERBOSEPARTON(6, *GetShowerInitiatingParton());
153 
154  // consider pointers for speed up ...
155  vector<Parton> pIn;
156  // DEBUG this guy isn't linked to anything - put in test particle for now
157  pIn.push_back(*GetShowerInitiatingParton());
158 
159  vector<node> vStartVec;
160  // Add here the Hard Shower emitting parton ...
161  vStart = pShower->new_vertex(make_shared<Vertex>());
162  vEnd = pShower->new_vertex(make_shared<Vertex>());
163  // Add original parton later, after it had a chance to acquire virtuality
164  // pShower->new_parton(vStart,vEnd,make_shared<Parton>(*GetShowerInitiatingParton()));
165 
166  // start then the recursive shower ...
167  vStartVec.push_back(vEnd);
168 
169  // cerr << " ---------------------------------------------- " << endl;
170  // cerr << "Start with " << *GetShowerInitiatingParton()
171  // << " -> " << GetShowerInitiatingParton()->t() << endl;
172  bool foundchangedorig = false;
173  int droplet_stat = -11;
174  int miss_stat = -13;
175  int neg_stat = -17;
176  if (!weak_ptr_is_uninitialized(liquefier_ptr)) {
177  droplet_stat = liquefier_ptr.lock()->get_drop_stat();
178  miss_stat = liquefier_ptr.lock()->get_miss_stat();
179  neg_stat = liquefier_ptr.lock()->get_neg_stat();
180  }
181  do {
182  vector<Parton> pOut;
183  vector<Parton> pInTemp;
184 
185  vector<node> vStartVecOut;
186  vector<node> vStartVecTemp;
187 
188  VERBOSESHOWER(7) << "Current time = " << currentTime << " with #Input "
189  << pIn.size();
190  currentTime += deltaT;
191 
192  for (int i = 0; i < pIn.size(); i++) {
193  vector<Parton> pInTempModule;
194  vector<Parton> pOutTemp;
195  // JSINFO << pIn.at(i).edgeid();
196  pInTempModule.push_back(pIn[i]);
197  SentInPartons(deltaT, currentTime, pIn[i].pt(), pInTempModule, pOutTemp);
198 
199  // apply liquefier
200  if (!weak_ptr_is_uninitialized(liquefier_ptr)) {
201  liquefier_ptr.lock()->add_hydro_sources(pInTempModule, pOutTemp);
202  }
203 
204  // stuffs related to vertex
205  if (!foundchangedorig) {
206  // cerr << " End with "<< pInTempModule.at(0) << " -> "
207  // << pInTempModule.at(0).t() << endl;
208  // cerr << " ---------------------------------------------- "
209  // << endl;
210  pShower->new_parton(vStart, vEnd,
211  make_shared<Parton>(pInTempModule.at(0)));
212  foundchangedorig = true;
213  }
214 
215  vStart = vStartVec[i];
216  if (pOutTemp.size() == 0) {
217  // no need to generate a vStart for photons and liquefied
218  // partons
219  if (pInTempModule[0].pstat() != droplet_stat &&
220  pInTempModule[0].pstat() != miss_stat &&
221  pInTempModule[0].pstat() != neg_stat &&
222  !pInTempModule[0].isPhoton(pInTempModule[0].pid())) {
223  vStartVecTemp.push_back(vStart);
224  }
225  } else if (pOutTemp.size() == 1) {
226  // no need to generate a vStart for photons and liquefied
227  // partons
228  if (pOutTemp[0].pstat() != droplet_stat &&
229  pOutTemp[0].pstat() != miss_stat &&
230  pOutTemp[0].pstat() != neg_stat &&
231  !pOutTemp[0].isPhoton(pOutTemp[0].pid())) {
232  vStartVecTemp.push_back(vStart);
233  }
234  } else {
235  for (int k = 0; k < pOutTemp.size(); k++) {
236  int edgeid = 0;
237  if (pOutTemp[k].pstat() == neg_stat) {
238  node vNewRootNode = pShower->new_vertex(
239  make_shared<Vertex>(0, 0, 0, currentTime - deltaT));
240  edgeid = pShower->new_parton(vNewRootNode, vStart,
241  make_shared<Parton>(pOutTemp[k]));
242  } else {
243  vEnd =
244  pShower->new_vertex(make_shared<Vertex>(0, 0, 0, currentTime));
245  edgeid = pShower->new_parton(vStart, vEnd,
246  make_shared<Parton>(pOutTemp[k]));
247  }
248  pOutTemp[k].set_shower(pShower);
249  pOutTemp[k].set_edgeid(edgeid);
250 
251  // no need to generate a vStart for photons and liquefied
252  // partons
253  if (pOutTemp[k].pstat() != droplet_stat &&
254  pOutTemp[k].pstat() != miss_stat &&
255  pOutTemp[k].pstat() != neg_stat &&
256  !pOutTemp[k].isPhoton(pOutTemp[k].pid())) {
257  vStartVecOut.push_back(vEnd);
258  }
259 
260  // --------------------------------------------
261  // Add new roots from ElossModules ...
262  // (maybe add for clarity a new vector in the signal!???)
263  // Otherwise keep track of input size (so far always 1
264  // and check if size > 1 and create additional root nodes to that vertex ...
265  // Simple Test here below:
266  // DEBUG:
267  //cout<<"In JetEnergyloss : "<<pInTempModule.size()<<end;
268  if (pInTempModule.size() > 1) {
269  VERBOSE(7) << pInTempModule.size() - 1
270  << " new root node(s) to be added ...";
271  //cout << pInTempModule.size()-1
272  // << " new root node(s) to be added ..." << endl;
273 
274  for (int l = 1; l < pInTempModule.size(); l++) {
275  node vNewRootNode = pShower->new_vertex(
276  make_shared<Vertex>(0, 0, 0, currentTime - deltaT));
277  pShower->new_parton(vNewRootNode, vEnd,
278  make_shared<Parton>(pInTempModule[l]));
279  }
280  }
281  }
282  }
283 
284  // update parton shower
285  if (pOutTemp.size() == 0) {
286  // this is the free-streaming case for MATTER
287  // do not push back droplets
288  if (!weak_ptr_is_uninitialized(liquefier_ptr)) {
289  if (pInTempModule[0].pstat() == droplet_stat)
290  continue;
291  if (pInTempModule[0].pstat() == miss_stat)
292  continue;
293  if (pInTempModule[0].pstat() == neg_stat)
294  continue;
295  }
296  // do not push back photons
297  if (pInTempModule[0].isPhoton(pInTempModule[0].pid()))
298  continue;
299  pInTemp.push_back(pInTempModule[0]);
300  } else if (pOutTemp.size() == 1) {
301  // this is the free-streaming case for MARTINI or LBT
302  // do not push back droplets
303  if (!weak_ptr_is_uninitialized(liquefier_ptr)) {
304  if (pOutTemp[0].pstat() == droplet_stat)
305  continue;
306  if (pOutTemp[0].pstat() == miss_stat)
307  continue;
308  if (pOutTemp[0].pstat() == neg_stat)
309  continue;
310  }
311  // do not push back photons
312  if (pOutTemp[0].isPhoton(pOutTemp[0].pid()))
313  continue;
314  pInTemp.push_back(pOutTemp[0]);
315  } else {
316  for (int k = 0; k < pOutTemp.size(); k++) {
317  // do not push back droplets
318  if (!weak_ptr_is_uninitialized(liquefier_ptr)) {
319  if (pOutTemp[k].pstat() == droplet_stat)
320  continue;
321  if (pOutTemp[k].pstat() == miss_stat)
322  continue;
323  if (pOutTemp[k].pstat() == neg_stat)
324  continue;
325  }
326  // do not push back missing (from AdSCFT)
327  if (pOutTemp[k].pstat() == miss_stat)
328  continue;
329  // do not push back photons
330  if (pOutTemp[k].isPhoton(pOutTemp[k].pid()))
331  continue;
332 
333  pOut.push_back(pOutTemp[k]);
334  }
335  }
336  }
337 
338  // one time step is finished, now update parton shower to pIn
339  pIn.clear();
340  pIn.insert(pIn.end(), pInTemp.begin(), pInTemp.end());
341  pIn.insert(pIn.end(), pOut.begin(), pOut.end());
342 
343  // update vertex vector
344  vStartVec.clear();
345  vStartVec.insert(vStartVec.end(), vStartVecTemp.begin(),
346  vStartVecTemp.end());
347  vStartVec.insert(vStartVec.end(), vStartVecOut.begin(), vStartVecOut.end());
348  } while (currentTime < maxT); // other criteria (how to include; TBD)
349 
350  pIn.clear();
351  vStartVec.clear();
352 }
353 
354 void JetEnergyLoss::Exec() {
355  VERBOSE(1) << "Run JetEnergyLoss ...";
356  VERBOSE(1) << "Found " << GetNumberOfTasks()
357  << " Eloss Tasks/Modules Execute them ... ";
358  //DEBUGTHREAD<<"Task Id = "<<this_thread::get_id()<<" | Run JetEnergyLoss ...";
359  //DEBUGTHREAD<<"Task Id = "<<this_thread::get_id()<<" | Found "<<GetNumberOfTasks()<<" Eloss Tasks/Modules Execute them ... ";
360 
361  if (GetShowerInitiatingParton()) {
362  pShower = make_shared<PartonShower>();
363 
364  /*
365  //Check Memory ...
366  VERBOSE(8)<<"Use PartonShowerGenerator to do Parton shower stored in PartonShower Graph class";
367  JSDEBUG<<"Use PartonShowerGenerator to do Parton shower stored in PartonShower Graph class";
368 
369  PartonShowerGenerator PSG;
370  PSG.DoShower(*shared_from_this()); //needed otherwise all signal slots have to be recreated for shower module ....
371  // Overall not the nicest logic though .... Just to make changing and expanding the shower code in the future ...
372  // (basically, just now to remove the code out of the jet energy loss class ...) TBD
373  // also not really nice, since now the energy loss part in the parton shower and not really visible in this class ...
374  // Keep both codes so far ...
375  */
376 
377  // Shower handled in this class ...
378  DoShower();
379 
380  pShower->PrintNodes();
381  pShower->PrintEdges();
382 
383  weak_ptr<HardProcess> hproc =
384  JetScapeSignalManager::Instance()->GetHardProcessPointer();
385 
386  for (unsigned int ipart = 0; ipart < pShower->GetNumberOfPartons();
387  ipart++) {
388  // Uncomment to dump the whole parton shower into the parton container
389  // auto hp = hproc.lock();
390  // if ( hp ) hp->AddParton(pShower->GetPartonAt(ipart));
391  }
392 
393  shared_ptr<PartonPrinter> pPrinter =
394  JetScapeSignalManager::Instance()->GetPartonPrinterPointer().lock();
395  if (pPrinter) {
396  pPrinter->GetFinalPartons(pShower);
397  }
398 
399  shared_ptr<JetEnergyLoss> pEloss =
400  JetScapeSignalManager::Instance()->GetEnergyLossPointer().lock();
401  if (pEloss) {
402  pEloss->GetFinalPartonsForEachShower(pShower);
403  }
404  } else {
405  JSWARN << "NO Initial Hard Parton for Parton shower received ...";
406  }
407 
408  //DEBUGTHREAD<<"Task Id = "<<this_thread::get_id()<<" Finished!";
409  //JetScapeTask::ExecuteTasks(); // prevent Further modules to be execute, everything done by JetEnergyLoss ... (also set the no active flag ...!?)
410 }
411 
412 void JetEnergyLoss::WriteTask(weak_ptr<JetScapeWriter> w) {
413  VERBOSE(8);
414  VERBOSE(4) << "In JetEnergyLoss::WriteTask";
415  auto f = w.lock();
416  if (!f)
417  return;
418 
419  f->WriteComment("Energy loss Shower Initating Parton: " + GetId());
420  f->Write(inP);
421 
422  VERBOSE(4) << " writing partons... found " << pShower->GetNumberOfPartons();
423  f->Write(pShower);
424 }
425 
426 void JetEnergyLoss::PrintShowerInitiatingParton() {
427  //JSDEBUG<<inP->pid();
428 }
429 
430 void JetEnergyLoss::GetFinalPartonsForEachShower(
432 
433  this->final_Partons.push_back(shower.get()->GetFinalPartons());
434 }
435 
436 } // end namespace Jetscape