Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JetScape.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file JetScape.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 "JetScape.h"
17 #include "JetScapeXML.h"
18 #include "JetScapeSignalManager.h"
19 #include "JetEnergyLossManager.h"
20 #include "FluidDynamics.h"
21 #include "JetScapeBanner.h"
22 #include "InitialState.h"
23 #include "PreequilibriumDynamics.h"
24 #include "JetEnergyLoss.h"
25 #include "CausalLiquefier.h"
26 
27 #ifdef USE_HEPMC
28 #include "JetScapeWriterHepMC.h"
29  #ifdef USE_ROOT
30  #include "JetScapeWriterRootHepMC.h"
31  #endif
32 #endif
33 
34 #include <iostream>
35 #include <string>
36 #include <vector>
37 #include <algorithm>
38 
39 using namespace std;
40 
41 namespace Jetscape {
42 
46 JetScape::JetScape()
47  : JetScapeModuleBase(), n_events(1), n_events_printout(100), reuse_hydro_(false), n_reuse_hydro_(1),
48  liquefier(nullptr), fEnableAutomaticTaskListDetermination(true) {
49  VERBOSE(8);
50  SetId("primary");
51 }
52 
54  VERBOSE(8);
55  //JetScapeSignalManager::Instance()->Clear();
56  //not needed, use weak_ptr in JetScapeSignalManager class (=not owning)
57 }
58 
60 
61 //________________________________________________________________
63  Show();
64 
65  JSINFO << BOLDRED << "Initialize JetScape ...";
66 
67  // Set the names of the XML files in the JetScapeXML instance
70  JSINFO << "================================================================";
71 
72  // Check whether XML elements in the User file are not included in the Main file
74 
75  // Read some general parameters from the XML configuration file
77 
78  // Loop through the XML User file elements to determine the task list, if enabled
82  JSINFO
83  << "================================================================";
84  }
85 
86  // Has to be called explicitly since not really fully recursively (if ever needed)
87  // So --> JetScape is "Task Manager" of all modules ...
88  JSINFO << "Found " << GetNumberOfTasks() << " Modules Initialize them ... ";
89  SetPointers();
90  JSINFO << "Calling JetScape InitTasks()...";
92 }
93 
94 //________________________________________________________________
95 void JetScape::recurseToBuild(std::vector<std::string> &elems, tinyxml2::XMLElement *mElement)
96 {
97  tinyxml2::XMLElement *nextElement = mElement->FirstChildElement();
98 
99  if (nextElement != nullptr)
100  recurseToBuild(elems, nextElement);
101 
102  nextElement = mElement->NextSiblingElement();
103 
104  if (nextElement != nullptr)
105  recurseToBuild(elems, nextElement);
106 
107  elems.push_back(mElement->Name());
108 }
109 
110 //________________________________________________________________
111 void JetScape::recurseToSearch(std::vector<std::string> &elems, tinyxml2::XMLElement *uElement)
112 {
113  tinyxml2::XMLElement *nextElement = uElement->FirstChildElement();
114 
115  if (nextElement != nullptr)
116  recurseToSearch(elems, nextElement);
117 
118  nextElement = uElement->NextSiblingElement();
119 
120  if (nextElement != nullptr)
121  recurseToSearch(elems, nextElement);
122 
123  if (!std::binary_search(elems.begin(), elems.end(), uElement->Name())) {
124  JSWARN << "User XML tag <" << uElement->Name() << "> is unrecognized. A default entry in the main XML file is required.";
125  exit(-1);
126  }
127 }
128 
129 //________________________________________________________________
131 
134 
135  std::vector<std::string> elems;
136 
137  recurseToBuild(elems, mElement);
138  sort(elems.begin(), elems.end());
139  recurseToSearch(elems, uElement);
140 }
141 
142 //________________________________________________________________
144 
145  // Debug level
146  std::string log_debug = GetXMLElementText({"debug"});
147  if ((int)log_debug.find("off") >= 0)
149  VERBOSE(1) << "JetScape Debug = " << log_debug;
150 
151  // Remark
152  std::string log_remark = GetXMLElementText({"remark"});
153  if ((int)log_remark.find("on") >= 0)
155  VERBOSE(1) << "JetScape Remark = " << log_remark;
156 
157  // Verbose level
158  int m_vlevel = GetXMLElementInt({"vlevel"});
159  if (m_vlevel > 0) {
161  VERBOSE(1) << "JetScape Verbose Level = " << m_vlevel;
162  }
163 
164  // Flag for automatic task list determination from User XML
165  std::string enableAutomaticTaskListDetermination =
166  GetXMLElementText({"enableAutomaticTaskListDetermination"});
167  if ((int)enableAutomaticTaskListDetermination.find("true") >= 0) {
169  VERBOSE(1)
170  << "Enable automatic task list determination from User XML: True.";
171  } else if ((int)enableAutomaticTaskListDetermination.find("false") >= 0) {
173  VERBOSE(1)
174  << "Enable automatic task list determination from User XML: False.";
175  }
176 
177  // nEvents
178  int nEvents = GetXMLElementInt({"nEvents"});
179  if (nEvents) {
180  SetNumberOfEvents(nEvents);
181  JSINFO << "nEvents = " << nEvents;
182  }
183  n_events_printout = GetXMLElementInt({"nEvents_printout"});
184 
185  // Set whether to reuse hydro
186  std::string reuseHydro = GetXMLElementText({"setReuseHydro"});
187  if ((int)reuseHydro.find("true") >= 0) {
188  SetReuseHydro(true);
189  JSINFO << "Reuse Hydro: " << reuseHydro;
190  }
191  int nReuseHydro = GetXMLElementInt({"nReuseHydro"});
192  if (nReuseHydro) {
193  SetNReuseHydro(nReuseHydro);
194  JSINFO << "nReuseHydro: " << nReuseHydro;
195  }
196 
197  // Set up helper. Mostly used for random numbers
198  // Needs the XML reader singleton set up
200 
201  JSDEBUG << "JetScape Debug from XML = " << log_debug;
202  JSDEBUG << "JetScape Remark from XML = " << log_remark;
203 }
204 
205 //________________________________________________________________
207 
208  // First, check for Liquefier and create it if so (since it needs to be passed to other modules)
209  VERBOSE(2) << "Checking if Liquifier should be created...";
210  tinyxml2::XMLElement *elementXML =
212  ->GetXMLRootUser()
213  ->FirstChildElement();
214  while (elementXML) {
215  std::string elementName = elementXML->Name();
216  if (elementName == "Liquefier") {
217  liquefier = make_shared<CausalLiquefier>();
218  JSINFO << "Created liquefier.";
219  }
220  elementXML = elementXML->NextSiblingElement();
221  }
222 
223  // Loop through and create all modules
226  ->GetXMLRootUser()
227  ->FirstChildElement();
228  while (element) {
229  std::string elementName = element->Name();
230  VERBOSE(2) << "Parsing element: " << elementName;
231 
232  // Initial state
233  if (elementName == "IS") {
234 
235  tinyxml2::XMLElement *childElement =
237  while (childElement) {
238  std::string childElementName = childElement->Name();
239  VERBOSE(2) << "Parsing childElement: " << childElementName;
240 
241  // - Trento
242  if (childElementName == "Trento") {
243  auto trento = JetScapeModuleFactory::createInstance("TrentoInitial");
244  if (trento) {
245  Add(trento);
246  JSINFO << "JetScape::DetermineTaskList() -- Initial State: Added "
247  "Trento module to task list.";
248  }
249  }
250  // - Read initial conditions from file
251  else if (childElementName == "initial_profile_path") {
252 #ifdef USE_HDF5
253  auto initial =
254  JetScapeModuleFactory::createInstance("InitialFromFile");
255  if (initial) {
256  Add(initial);
257  JSINFO << "JetScape::DetermineTaskList() -- Initial state: Added "
258  "InitialFromFile to task list.";
259  }
260 #else
261  JSWARN << "InitialFromFile is attempted to be added, but HDF5 is not "
262  "installed!";
263 #endif
264  } else if (childElementName == "IPGlasma") {
265  auto ipglasma = JetScapeModuleFactory::createInstance("IPGlasma");
266  if (ipglasma) {
267  Add(ipglasma);
268  JSINFO << "JetScape::DetermineTaskList() -- Initial State: Added "
269  "IPGlasma module to task list.";
270  }
271  } else if (childElementName == "initial_Ncoll_list") {
272  auto initial =
273  JetScapeModuleFactory::createInstance("NcollListFromFile");
274  if (initial) {
275  Add(initial);
276  JSINFO << "JetScape::DetermineTaskList() -- Initial state: Added "
277  "NcollListFromFile to task list.";
278  }
279  }
280  // - Custom module
281  else if (((int)childElementName.find("CustomModule") >= 0)) {
282  auto customModule =
283  JetScapeModuleFactory::createInstance(childElementName);
284  if (customModule) {
285  Add(customModule);
286  JSINFO << "JetScape::DetermineTaskList() -- Initial state: Added "
287  << childElementName << " to task list.";
288  }
289  }
290 
291  childElement = childElement->NextSiblingElement();
292  }
293  }
294 
295  // Hard process
296  else if (elementName == "Hard") {
297 
298  tinyxml2::XMLElement *childElement =
300  while (childElement) {
301  std::string childElementName = childElement->Name();
302  VERBOSE(2) << "Parsing childElement: " << childElementName;
303 
304  // - PGun
305  if (childElementName == "PGun") {
306  auto pGun = JetScapeModuleFactory::createInstance(childElementName);
307  if (pGun) {
308  Add(pGun);
309  JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
310  "PGun to task list.";
311  }
312  }
313  // - PythiaGun
314  else if (childElementName == "PythiaGun") {
315  auto pythiaGun =
316  JetScapeModuleFactory::createInstance(childElementName);
317  if (pythiaGun) {
318  Add(pythiaGun);
319  JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
320  "PythiaGun to task list.";
321  }
322  }
323  // - epemGun
324  else if (childElementName == "epemGun") {
325  auto EpemGun =
326  JetScapeModuleFactory::createInstance(childElementName);
327  if (EpemGun) {
328  Add(EpemGun);
329  JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
330  "epemGun to task list.";
331  }
332  }
333  else if (((int)childElementName.find("CustomModule") >= 0)) {
334  auto customModule =
335  JetScapeModuleFactory::createInstance(childElementName);
336  if (customModule) {
337  Add(customModule);
338  JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
339  << childElementName << " to task list.";
340  }
341  }
342 
343  childElement = childElement->NextSiblingElement();
344  }
345 
346  }
347 
348  // Pre-equilibrium
349  else if (elementName == "Preequilibrium") {
350 
351  tinyxml2::XMLElement *childElement =
353  while (childElement) {
354  std::string childElementName = childElement->Name();
355  VERBOSE(2) << "Parsing childElement: " << childElementName;
356 
357  // - NullPreDynamics
358  if (childElementName == "NullPreDynamics") {
359  auto predynamics =
360  JetScapeModuleFactory::createInstance(childElementName);
361  if (predynamics) {
362  Add(predynamics);
363  JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
364  "NullPreDynamics to task list.";
365  }
366  } else if (childElementName == "Glasma") {
367  auto predynamics =
368  JetScapeModuleFactory::createInstance(childElementName);
369  if (predynamics) {
370  Add(predynamics);
371  JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
372  "Glasma to task list.";
373  }
374  } else if (childElementName == "FreestreamMilne") {
375  // - FreestreamMilne
376 #ifdef USE_FREESTREAM
377  auto predynamics =
378  JetScapeModuleFactory::createInstance(childElementName);
379  if (predynamics) {
380  Add(predynamics);
381  JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
382  "FreestreamMilne to task list.";
383  }
384 #else
385  JSWARN << "FreestreamMilne is attempted to be added, but freestream "
386  "is not installed!";
387 #endif
388  } else if (((int)childElementName.find("CustomModule") >= 0)) {
389  // - Custom module
390  auto customModule =
391  JetScapeModuleFactory::createInstance(childElementName);
392  if (customModule) {
393  Add(customModule);
394  JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
395  << childElementName << " to task list.";
396  }
397  }
398 
399  childElement = childElement->NextSiblingElement();
400  }
401 
402  }
403 
404  // Hydro
405  else if (elementName == "Hydro") {
406 
407  // First, check if liquefier should be added (Note: Can't use GetXMLElementText(), since that only works for unique tags)
408  VERBOSE(2) << "Checking if liquefer should be added: Hydro";
409  bool bAddLiquefier = false;
410  tinyxml2::XMLElement *childElementLiquefier =
412  while (childElementLiquefier) {
413  std::string childElementName = childElementLiquefier->Name();
414  VERBOSE(2) << "Parsing childElementLiq: " << childElementName;
415  if (childElementName == "AddLiquefier") {
416  std::string strAddLiquefier = childElementLiquefier->GetText();
417  if ((int)strAddLiquefier.find("true") >= 0) {
418  bAddLiquefier = true;
419  VERBOSE(1) << "Add liquefier to Hydro: True.";
420  } else {
421  VERBOSE(1) << "Add liquefier to Hydro: False.";
422  }
423  }
424  childElementLiquefier = childElementLiquefier->NextSiblingElement();
425  }
426 
427  // Loop through elements to look for specific hydro module
428  tinyxml2::XMLElement *childElement =
430  while (childElement) {
431  std::string childElementName = childElement->Name();
432  VERBOSE(2) << "Parsing childElement: " << childElementName;
433 
434  // - Brick
435  if (childElementName == "Brick") {
436  auto hydro = JetScapeModuleFactory::createInstance(childElementName);
437  if (hydro) {
438  Add(hydro);
439  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added Brick to "
440  "task list.";
441  SetModuleId(childElement, hydro);
442  if (bAddLiquefier) {
443  dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
444  liquefier);
445  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
446  "liquefier to Brick.";
447  }
448  }
449  }
450  // - Gubser
451  else if (childElementName == "Gubser") {
452  auto hydro = JetScapeModuleFactory::createInstance(childElementName);
453  if (hydro) {
454  Add(hydro);
455  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added Gubser to "
456  "task list.";
457  SetModuleId(childElement, hydro);
458  if (bAddLiquefier) {
459  dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
460  liquefier);
461  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
462  "liquefier to Gubser.";
463  }
464  }
465  }
466  // - hydro_from_file
467  else if (childElementName == "hydro_from_file") {
468  auto hydro = JetScapeModuleFactory::createInstance("HydroFromFile");
469  if (hydro) {
470  Add(hydro);
471  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
472  "hydro_from_file to task list.";
473  SetModuleId(childElement, hydro);
474  if (bAddLiquefier) {
475  dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
476  liquefier);
477  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
478  "liquefier to hydro_from_file.";
479  }
480  }
481  }
482  // - MUSIC
483  else if (childElementName == "MUSIC") {
484 #ifdef USE_MUSIC
485  auto hydro = JetScapeModuleFactory::createInstance("MUSIC");
486  if (hydro) {
487  Add(hydro);
488  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added MUSIC to "
489  "task list.";
490  SetModuleId(childElement, hydro);
491  if (bAddLiquefier) {
492  dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
493  liquefier);
494  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
495  "liquefier to MUSIC.";
496  }
497  }
498 #else
499  JSWARN << "MUSIC is attempted to be added, but it is not installed!";
500 #endif
501  }
502  // - CLVisc
503  else if (childElementName == "CLVisc") {
504  auto hydro = JetScapeModuleFactory::createInstance("CLVisc");
505  if (hydro) {
506  Add(hydro);
507  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added CLVisc to "
508  "task list.";
509  } else {
510  JSWARN
511  << "CLVisc is attempted to be added, but it is not installed!";
512  }
513  }
514 
515  // - Custom module
516  else if (((int)childElementName.find("CustomModule") >= 0)) {
517  auto customModule =
518  JetScapeModuleFactory::createInstance(childElementName);
519  if (customModule) {
520  Add(customModule);
521  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
522  << childElementName << " to task list.";
523  SetModuleId(childElement, customModule);
524  if (bAddLiquefier) {
525  dynamic_pointer_cast<FluidDynamics>(customModule)
526  ->add_a_liquefier(liquefier);
527  JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
528  "liquefier to CustomModule.";
529  }
530  }
531  }
532 
533  childElement = childElement->NextSiblingElement();
534  }
535  }
536 
537  // Eloss
538  else if (elementName == "Eloss") {
539 
540  auto jlossmanager = make_shared<JetEnergyLossManager>();
541  auto jloss = make_shared<JetEnergyLoss>();
542 
543  // Check if liquefier should be added, and add it if so
544  std::string strAddLiquefier =
545  GetXMLElementText({"Eloss", "AddLiquefier"});
546  if ((int)strAddLiquefier.find("true") >= 0) {
547  jloss->add_a_liquefier(liquefier);
548  JSINFO << "JetScape::DetermineTaskList() -- Added liquefier to Eloss.";
549  } else {
550  VERBOSE(1) << "Add liquefier to Eloss: False.";
551  }
552 
553  // Loop through and add Eloss modules
554  tinyxml2::XMLElement *childElement =
556  while (childElement) {
557  std::string childElementName = childElement->Name();
558  VERBOSE(2) << "Parsing childElement: " << childElementName;
559 
560  // - Matter
561  if (childElementName == "Matter") {
562  auto matter = JetScapeModuleFactory::createInstance(childElementName);
563  if (matter) {
564  jloss->Add(
565  matter); // Note: if you use Matter, it MUST come first (to set virtuality)
566  JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added Matter to "
567  "Eloss list.";
568  }
569  }
570  // - LBT
571  else if (childElementName == "Lbt") {
572  auto lbt = JetScapeModuleFactory::createInstance(childElementName);
573  if (lbt) {
574  jloss->Add(
575  lbt); // go to 3rd party and ./get_lbtTab before adding this module
576  JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added LBT to "
577  "Eloss list.";
578  }
579  }
580  // - Martini
581  else if (childElementName == "Martini") {
582  auto martini =
583  JetScapeModuleFactory::createInstance(childElementName);
584  if (martini) {
585  jloss->Add(martini);
586  JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added Martini "
587  "to Eloss list.";
588  }
589  }
590  // - AdS/CFT
591  else if (childElementName == "AdSCFT") {
592  auto adscft = JetScapeModuleFactory::createInstance(childElementName);
593  if (adscft) {
594  jloss->Add(adscft);
595  JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added AdS/CFT "
596  "to Eloss list.";
597  }
598  }
599  // - Custom module
600  else if (((int)childElementName.find("CustomModule") >= 0)) {
601  auto customModule =
602  JetScapeModuleFactory::createInstance(childElementName);
603  if (customModule) {
604  jloss->Add(customModule);
605  JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added "
606  << childElementName << " to Eloss list.";
607  }
608  }
609 
610  childElement = childElement->NextSiblingElement();
611  }
612 
613  jlossmanager->Add(jloss);
614  Add(jlossmanager);
615  }
616 
617  // Jet Hadronization
618  else if (elementName == "JetHadronization") {
619 
620  // Create hadronization manager and module
621  auto hadroMgr = make_shared<HadronizationManager>();
622  auto hadro = make_shared<Hadronization>();
623 
624  // Determine type of hadronization module, and add it
625  std::string hadronizationName =
626  element->FirstChildElement("name")->GetText();
627  if (hadronizationName == "colored") {
628  auto hadroModule =
629  JetScapeModuleFactory::createInstance("ColoredHadronization");
630  if (hadroModule) {
631  hadro->Add(hadroModule);
632  JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
633  "ColoredHadronization to task list.";
634  }
635  } else if (hadronizationName == "colorless") {
636  auto hadroModule =
637  JetScapeModuleFactory::createInstance("ColorlessHadronization");
638  if (hadroModule) {
639  hadro->Add(hadroModule);
640  JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
641  "ColorlessHadronization to task list.";
642  }
643  } else if (hadronizationName == "hybrid") {
644  auto hadroModule =
645  JetScapeModuleFactory::createInstance("HybridHadronization");
646  if (hadroModule) {
647  hadro->Add(hadroModule);
648  JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
649  "HybridHadronization to task list.";
650  }
651  }
652  // - Custom module
653  else if (((int)hadronizationName.find("CustomModule") >= 0)) {
654  auto customModule =
655  JetScapeModuleFactory::createInstance(hadronizationName);
656  if (customModule) {
657  hadro->Add(customModule);
658  JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
659  << hadronizationName << " to task list.";
660  }
661  }
662 
663  hadroMgr->Add(hadro);
664  Add(hadroMgr);
665  }
666 
667  // Soft Particlization
668  else if (elementName == "SoftParticlization") {
669 
670  tinyxml2::XMLElement *childElement =
672  while (childElement) {
673  std::string childElementName = childElement->Name();
674  VERBOSE(2) << "Parsing childElement: " << childElementName;
675 
676  // - iSS
677  if (childElementName == "iSS") {
678 #ifdef iSpectraSampler
679  auto iSSmodule =
680  JetScapeModuleFactory::createInstance(childElementName);
681  if (iSSmodule) {
682  Add(iSSmodule);
683  JSINFO << "JetScape::DetermineTaskList() -- SoftParticlization: "
684  "Added iSS to task list.";
685  }
686 #else
687  JSWARN << "iSS is attempted to be added, but iSS is not installed!";
688 #endif
689  }
690  // - Custom module
691  else if (((int)childElementName.find("CustomModule") >= 0)) {
692  auto customModule =
693  JetScapeModuleFactory::createInstance(childElementName);
694  if (customModule) {
695  Add(customModule);
696  JSINFO
697  << "JetScape::DetermineTaskList() -- SoftParticlization: Added "
698  << childElementName << " to task list.";
699  }
700  }
701 
702  childElement = childElement->NextSiblingElement();
703  }
704  }
705 
706  // Afterburner
707  else if (elementName == "Afterburner") {
708 
709  tinyxml2::XMLElement *childElement =
711  while (childElement) {
712  std::string childElementName = childElement->Name();
713  VERBOSE(2) << "Parsing childElement: " << childElementName;
714 
715  // - SMASH
716  if (childElementName == "SMASH") {
717 #ifdef USE_SMASH
718  auto smashModule =
719  JetScapeModuleFactory::createInstance(childElementName);
720  if (smashModule) {
721  Add(smashModule);
722  JSINFO << "JetScape::DetermineTaskList() -- Afterburner: Added "
723  "SMASH to task list.";
724  }
725 #else
726  JSWARN
727  << "SMASH is attempted to be added, but SMASH is not installed!";
728 #endif
729  }
730  // - Custom module
731  else if (((int)childElementName.find("CustomModule") >= 0)) {
732  auto customModule =
733  JetScapeModuleFactory::createInstance(childElementName);
734  if (customModule) {
735  Add(customModule);
736  JSINFO << "JetScape::DetermineTaskList() -- Afterburner: Added "
737  << childElementName << " to task list.";
738  }
739  }
740 
741  childElement = childElement->NextSiblingElement();
742  }
743  }
744 
745  // Parton printer
746  else if (elementName == "PartonPrinter") {
747 
748  auto partonPrinter = JetScapeModuleFactory::createInstance(elementName);
749  if (partonPrinter) {
750  Add(partonPrinter);
751  JSINFO << "JetScape::DetermineTaskList() -- Added PartonPrinter to "
752  "task list.";
753  }
754  }
755  else if (elementName == "HadronPrinter") {
756  auto hadronPrinter = JetScapeModuleFactory::createInstance(elementName);
757  if (hadronPrinter) {
758  Add(hadronPrinter);
759  JSINFO << "JetScape::DetermineTaskList() -- Added HadronPrinter to "
760  "task list.";
761  }
762  }
763 
764  else {
765  VERBOSE(2) << "Nothing to do.";
766  }
767 
768  element = element->NextSiblingElement();
769  }
770 }
771 
772 //________________________________________________________________
774  shared_ptr<JetScapeModuleBase> module) {
775 
776  tinyxml2::XMLElement *childElement =
777  (tinyxml2::XMLElement *)moduleElement->FirstChildElement();
778  while (childElement) {
779  std::string childElementName = childElement->Name();
780  if (childElementName == "name") {
781  std::string name = childElement->GetText();
782  module->SetId(name);
783  JSINFO << "Set ID to: " << name;
784  }
785  childElement = childElement->NextSiblingElement();
786  }
787 }
788 
789 //________________________________________________________________
791 
792  // Get file output name to write to (without file extension, except if custom writer)
793  std::string outputFilename = GetXMLElementText({"outputFilename"});
794 
795  // Copy string in order to set file extensions for each type
796  std::string outputFilenameAscii = outputFilename;
797  std::string outputFilenameAsciiGZ = outputFilename;
798  std::string outputFilenameHepMC = outputFilename;
799  std::string outputFilenameRootHepMC = outputFilename;
800  std::string outputFilenameFinalStatePartonsAscii = outputFilename;
801  std::string outputFilenameFinalStateHadronsAscii = outputFilename;
802 
803  // Check if each writer is enabled, and if so add it to the task list
804  CheckForWriterFromXML("JetScapeWriterAscii",
805  outputFilenameAscii.append(".dat"));
806  CheckForWriterFromXML("JetScapeWriterAsciiGZ",
807  outputFilenameAsciiGZ.append(".dat.gz"));
808  CheckForWriterFromXML("JetScapeWriterHepMC",
809  outputFilenameHepMC.append(".hepmc"));
810  CheckForWriterFromXML("JetScapeWriterRootHepMC",
811  outputFilenameRootHepMC.append("_hepmc.root"));
812  CheckForWriterFromXML("JetScapeWriterFinalStatePartonsAscii",
813  outputFilenameFinalStatePartonsAscii.append("_final_state_partons.dat"));
814  CheckForWriterFromXML("JetScapeWriterFinalStateHadronsAscii",
815  outputFilenameFinalStateHadronsAscii.append("_final_state_hadrons.dat"));
816 
817  // Check for custom writers
820  ->GetXMLRootUser()
821  ->FirstChildElement();
822  while (element) {
823  std::string elementName = element->Name();
824  VERBOSE(2) << "Parsing element: " << elementName;
825 
826  if (((int)elementName.find("CustomWriter") >= 0)) {
827  CheckForWriterFromXML(elementName.c_str(), outputFilename);
828  }
829  element = element->NextSiblingElement();
830  }
831 }
832 
833 //________________________________________________________________
834 void JetScape::CheckForWriterFromXML(const char *writerName,
835  std::string outputFilename) {
836 
837  std::string enableWriter = GetXMLElementText({writerName});
838  VERBOSE(2) << "Parsing writer: " << writerName;
839  if ((int)enableWriter.find("on") >= 0) {
840  VERBOSE(2) << "Writer is on.";
841  auto writer = JetScapeModuleFactory::createInstance(writerName);
842 
843  if (writer) {
844  dynamic_pointer_cast<JetScapeWriter>(writer)->SetOutputFileName(
845  outputFilename);
846  Add(writer);
847  JSINFO << "JetScape::DetermineTaskList() -- " << writerName << " ("
848  << outputFilename.c_str() << ") added to task list.";
849  }
850  // Manually create HepMC writer if it is enabled, since JetScapeModuleFactor::map_type assumes single inheritance
851  // from JetScapeModuleBase -- but JetScapeWriterHepMC has multiple inheritance
852  else if (strcmp(writerName, "JetScapeWriterHepMC") == 0) {
853 #ifdef USE_HEPMC
854  VERBOSE(2) << "Manually creating JetScapeWriterHepMC (due to multiple "
855  "inheritance)";
856  auto writer = std::make_shared<JetScapeWriterHepMC>(outputFilename);
857  Add(writer);
858  JSINFO << "JetScape::DetermineTaskList() -- " << writerName << " ("
859  << outputFilename.c_str() << ") added to task list.";
860 #endif
861  }
862  else if (strcmp(writerName, "JetScapeWriterRootHepMC") == 0) {
863 #ifdef USE_HEPMC
864  #ifdef USE_ROOT
865  VERBOSE(2) << "Manually creating JetScapeWriterRootHepMC (due to multiple "
866  "inheritance)";
867  auto writer = std::make_shared<JetScapeWriterRootHepMC>(outputFilename);
868  Add(writer);
869  JSINFO << "JetScape::DetermineTaskList() -- " << writerName << " ("
870  << outputFilename.c_str() << ") added to task list.";
871  #endif
872 #endif
873  } else {
874  VERBOSE(2) << "Writer is NOT created...";
875  }
876  } else {
877  VERBOSE(2) << "Writer is off.";
878  }
879 }
880 
881 // kind of cluncky, maybe a better way ... ?
882 // Handle signal/slots in JetScape hence avoid passing pointers to sub tasks ...
884  // to get hydro pointer for signals, use signal?
885  JSINFO << "Set Hydro,JetEnergylossManager and IS Pointers for "
886  << "SignalManager to create Signal/Slots";
887 
888  bool hydro_pointer_is_set = false;
889  for (auto it : GetTaskList()) {
890  if (dynamic_pointer_cast<InitialState>(it)) {
892  dynamic_pointer_cast<InitialState>(it));
893  } else if (dynamic_pointer_cast<PreequilibriumDynamics>(it)) {
895  dynamic_pointer_cast<PreequilibriumDynamics>(it));
896  } else if (dynamic_pointer_cast<FluidDynamics>(it) &&
897  !hydro_pointer_is_set) {
899  dynamic_pointer_cast<FluidDynamics>(it));
900  hydro_pointer_is_set = true;
901  } else if (dynamic_pointer_cast<JetEnergyLossManager>(it)) {
903  dynamic_pointer_cast<JetEnergyLossManager>(it));
904  } else if (dynamic_pointer_cast<HardProcess>(it)) {
906  dynamic_pointer_cast<HardProcess>(it));
907  } else if (dynamic_pointer_cast<JetScapeWriter>(it) && it->GetActive()) {
909  dynamic_pointer_cast<JetScapeWriter>(it));
910  } else if (dynamic_pointer_cast<PartonPrinter>(it)) {
912  dynamic_pointer_cast<PartonPrinter>(it));
913  } else if (dynamic_pointer_cast<SoftParticlization>(it)) {
915  dynamic_pointer_cast<SoftParticlization>(it));
916  } else if (dynamic_pointer_cast<HadronizationManager>(it)) {
918  dynamic_pointer_cast<HadronizationManager>(it));
919  } else if (dynamic_pointer_cast<HadronPrinter>(it)) {
921  dynamic_pointer_cast<HadronPrinter>(it));
922  }
923  }
924 }
925 
927  JSINFO << BOLDRED << "Run JetScape ...";
928  JSINFO << BOLDRED << "Number of Events = " << GetNumberOfEvents();
929 
930  // JetScapeTask::ExecuteTasks(); Has to be called explicitly since not really fully recursively (if ever needed)
931  // --> JetScape is "Task Manager" of all modules ...
932 
933  // Simple way of passing the writer module pointer
934  vector<weak_ptr<JetScapeWriter>> vWriter;
935 
936  for (auto it : GetTaskList()) {
937  if (dynamic_pointer_cast<JetScapeWriter>(it)) {
938  if (it->GetActive()) {
939  vWriter.push_back(dynamic_pointer_cast<JetScapeWriter>(it));
940  }
941  }
942  }
943 
944  for (int i = 0; i < GetNumberOfEvents(); i++) {
945  if (i % n_events_printout == 0) {
946  JSINFO << BOLDRED << "Run Event # = " << i;
947  }
948  VERBOSE(1) << BOLDRED << "Run Event # = " << i;
949  JSDEBUG << "Found " << GetNumberOfTasks() << " Modules Execute them ... ";
950 
951  // First run all tasks
953 
954  // Then hand around the collection of writers and ask
955  // modules to write what they like
956  // Sequence of events:
957  // -- writer->Exec is called and redirects to WriteEvent, which starts a new event line
958  // -- any remaining exec's finish
959  // -- all modules write their headers
960  // -- Now all header info is known to the writers, so write out the header
961  // -- all other Write()'s are being called
962  // the result still confuses me. It's in the best possible order but it shouldn't be.
963 
964  // collect module header data
965  for (auto w : vWriter) {
966  auto f = w.lock();
967  if (f) {
969  }
970  }
971  // official header
972  for (auto w : vWriter) {
973  auto f = w.lock();
974  if (f) {
975  f->WriteHeaderToFile();
976  }
977  }
978 
979  // event data
980  for (auto w : vWriter) {
981  auto f = w.lock();
982  if (f) {
984  }
985  }
986 
987  // Finalize
988  for (auto w : vWriter) {
989  auto f = w.lock();
990  if (f) {
991  f->WriteEvent();
992  }
993  }
994 
995  // For reusal, deactivate task after it has finished
996  // but before it gets cleaned up.
997  if (reuse_hydro_) {
998  if (n_reuse_hydro_ <= 0) {
999  JSWARN << " reuse_hydro is set, but n_reuse_hydro = " << n_reuse_hydro_;
1000  throw std::runtime_error("Incompatible reusal settings.");
1001  }
1002  bool hydro_pointer_is_set = false;
1003  for (auto it : GetTaskList()) {
1004  if (!dynamic_pointer_cast<FluidDynamics>(it) &&
1005  !dynamic_pointer_cast<PreequilibriumDynamics>(it) &&
1006  !dynamic_pointer_cast<InitialState>(it)) {
1007  continue;
1008  }
1009 
1010  // only deactivate the first hydro
1011  if (dynamic_pointer_cast<FluidDynamics>(it) && hydro_pointer_is_set) {
1012  continue;
1013  }
1014 
1015  if (i % n_reuse_hydro_ == n_reuse_hydro_ - 1) {
1016  JSDEBUG << " i was " << i
1017  << " i%n_reuse_hydro_ = " << i % n_reuse_hydro_
1018  << " --> ACTIVATING";
1019  it->SetActive(true);
1020  if (dynamic_pointer_cast<FluidDynamics>(it)) {
1021  hydro_pointer_is_set = true;
1022  }
1023  } else {
1024  JSDEBUG << " i was " << i
1025  << " i%n_reuse_hydro_ = " << i % n_reuse_hydro_
1026  << " --> DE-ACTIVATING";
1027  it->SetActive(false);
1028  if (dynamic_pointer_cast<FluidDynamics>(it)) {
1029  hydro_pointer_is_set = true;
1030  }
1031  }
1032  }
1033  }
1034 
1035  // Now clean up, only affects active taskjs
1037 
1039  }
1040 }
1041 
1043  JSINFO << BOLDBLACK << "JetScape finished after " << GetNumberOfEvents()
1044  << " events!";
1045  JSDEBUG << "More infos wrap up/saving to file/closing file ...";
1046 
1047  // same as in Init() and Exec() ...
1048  JetScapeTask::FinishTasks(); //dummy so far ...
1049 }
1050 
1051 } // end namespace Jetscape