Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:19:18

0001 /*******************************************************************************
0002  * Copyright (c) The JETSCAPE Collaboration, 2018
0003  *
0004  * Modular, task-based framework for simulating all aspects of heavy-ion collisions
0005  *
0006  * For the list of contributors see AUTHORS.
0007  *
0008  * Report issues at https://github.com/JETSCAPE/JETSCAPE/issues
0009  *
0010  * or via email to bugs.jetscape@gmail.com
0011  *
0012  * Distributed under the GNU General Public License 3.0 (GPLv3 or later).
0013  * See COPYING for details.
0014  ******************************************************************************/
0015 
0016 #include "JetScape.h"
0017 #include "JetScapeXML.h"
0018 #include "JetScapeSignalManager.h"
0019 #include "JetEnergyLossManager.h"
0020 #include "FluidDynamics.h"
0021 #include "JetScapeBanner.h"
0022 #include "InitialState.h"
0023 #include "PreequilibriumDynamics.h"
0024 #include "JetEnergyLoss.h"
0025 #include "CausalLiquefier.h"
0026 
0027 #ifdef USE_HEPMC
0028 #include "JetScapeWriterHepMC.h"
0029   #ifdef USE_ROOT
0030   #include "JetScapeWriterRootHepMC.h"
0031   #endif
0032 #endif
0033 
0034 #include <iostream>
0035 #include <string>
0036 #include <vector>
0037 #include <algorithm>
0038 
0039 using namespace std;
0040 
0041 namespace Jetscape {
0042 
0043 /** Default constructor to create the main task of the JetScape framework. It sets the total number of events to 1.
0044    * By default, hydro events are used only once
0045    */
0046 JetScape::JetScape()
0047     : JetScapeModuleBase(), n_events(1), n_events_printout(100), reuse_hydro_(false), n_reuse_hydro_(1),
0048       liquefier(nullptr), fEnableAutomaticTaskListDetermination(true) {
0049   VERBOSE(8);
0050   SetId("primary");
0051 }
0052 
0053 JetScape::~JetScape() {
0054   VERBOSE(8);
0055   //JetScapeSignalManager::Instance()->Clear();
0056   //not needed, use weak_ptr in JetScapeSignalManager class (=not owning)
0057 }
0058 
0059 void JetScape::Show() { ShowJetscapeBanner(); }
0060 
0061 //________________________________________________________________
0062 void JetScape::Init() {
0063   Show();
0064 
0065   JSINFO << BOLDRED << "Initialize JetScape ...";
0066 
0067   // Set the names of the XML files in the JetScapeXML instance
0068   JetScapeXML::Instance()->OpenXMLMainFile(GetXMLMainFileName());
0069   JetScapeXML::Instance()->OpenXMLUserFile(GetXMLUserFileName());
0070   JSINFO << "================================================================";
0071 
0072   // Check whether XML elements in the User file are not included in the Main file
0073   CompareElementsFromXML();
0074 
0075   // Read some general parameters from the XML configuration file
0076   ReadGeneralParametersFromXML();
0077 
0078   // Loop through the XML User file elements to determine the task list, if enabled
0079   if (fEnableAutomaticTaskListDetermination) {
0080     DetermineTaskListFromXML();
0081     DetermineWritersFromXML();
0082     JSINFO
0083         << "================================================================";
0084   }
0085 
0086   // Has to be called explicitly since not really fully recursively (if ever needed)
0087   // So --> JetScape is "Task Manager" of all modules ...
0088   JSINFO << "Found " << GetNumberOfTasks() << " Modules Initialize them ... ";
0089   SetPointers();
0090   JSINFO << "Calling JetScape InitTasks()...";
0091   JetScapeTask::InitTasks();
0092 }
0093 
0094 //________________________________________________________________
0095 void JetScape::recurseToBuild(std::vector<std::string> &elems, tinyxml2::XMLElement *mElement)
0096 {
0097   tinyxml2::XMLElement *nextElement = mElement->FirstChildElement();
0098 
0099   if (nextElement != nullptr)
0100     recurseToBuild(elems, nextElement);
0101 
0102   nextElement = mElement->NextSiblingElement();
0103 
0104   if (nextElement != nullptr)
0105     recurseToBuild(elems, nextElement);
0106 
0107   elems.push_back(mElement->Name());
0108 }
0109 
0110 //________________________________________________________________
0111 void JetScape::recurseToSearch(std::vector<std::string> &elems, tinyxml2::XMLElement *uElement)
0112 {
0113   tinyxml2::XMLElement *nextElement = uElement->FirstChildElement();
0114 
0115   if (nextElement != nullptr)
0116     recurseToSearch(elems, nextElement);
0117 
0118   nextElement = uElement->NextSiblingElement();
0119 
0120   if (nextElement != nullptr)
0121     recurseToSearch(elems, nextElement);
0122 
0123   if (!std::binary_search(elems.begin(), elems.end(), uElement->Name())) {
0124     JSWARN << "User XML tag <" << uElement->Name() << "> is unrecognized. A default entry in the main XML file is required.";
0125     exit(-1);
0126   }
0127 }
0128 
0129 //________________________________________________________________
0130 void JetScape::CompareElementsFromXML() {
0131 
0132   tinyxml2::XMLElement *uElement = JetScapeXML::Instance()->GetXMLRootUser()->FirstChildElement();
0133   tinyxml2::XMLElement *mElement = JetScapeXML::Instance()->GetXMLRootMain()->FirstChildElement();
0134 
0135   std::vector<std::string> elems;
0136 
0137   recurseToBuild(elems, mElement);
0138   sort(elems.begin(), elems.end());
0139   recurseToSearch(elems, uElement);
0140 }
0141 
0142 //________________________________________________________________
0143 void JetScape::ReadGeneralParametersFromXML() {
0144 
0145   // Debug level
0146   std::string log_debug = GetXMLElementText({"debug"});
0147   if ((int)log_debug.find("off") >= 0)
0148     JetScapeLogger::Instance()->SetDebug(false);
0149   VERBOSE(1) << "JetScape Debug = " << log_debug;
0150 
0151   // Remark
0152   std::string log_remark = GetXMLElementText({"remark"});
0153   if ((int)log_remark.find("on") >= 0)
0154     JetScapeLogger::Instance()->SetRemark(true);
0155   VERBOSE(1) << "JetScape Remark = " << log_remark;
0156 
0157   // Verbose level
0158   int m_vlevel = GetXMLElementInt({"vlevel"});
0159   if (m_vlevel > 0) {
0160     JetScapeLogger::Instance()->SetVerboseLevel(m_vlevel);
0161     VERBOSE(1) << "JetScape Verbose Level = " << m_vlevel;
0162   }
0163 
0164   // Flag for automatic task list determination from User XML
0165   std::string enableAutomaticTaskListDetermination =
0166       GetXMLElementText({"enableAutomaticTaskListDetermination"});
0167   if ((int)enableAutomaticTaskListDetermination.find("true") >= 0) {
0168     fEnableAutomaticTaskListDetermination = true;
0169     VERBOSE(1)
0170         << "Enable automatic task list determination from User XML: True.";
0171   } else if ((int)enableAutomaticTaskListDetermination.find("false") >= 0) {
0172     fEnableAutomaticTaskListDetermination = false;
0173     VERBOSE(1)
0174         << "Enable automatic task list determination from User XML: False.";
0175   }
0176 
0177   // nEvents
0178   int nEvents = GetXMLElementInt({"nEvents"});
0179   if (nEvents) {
0180     SetNumberOfEvents(nEvents);
0181     JSINFO << "nEvents = " << nEvents;
0182   }
0183   n_events_printout = GetXMLElementInt({"nEvents_printout"});
0184 
0185   // Set whether to reuse hydro
0186   std::string reuseHydro = GetXMLElementText({"setReuseHydro"});
0187   if ((int)reuseHydro.find("true") >= 0) {
0188     SetReuseHydro(true);
0189     JSINFO << "Reuse Hydro: " << reuseHydro;
0190   }
0191   int nReuseHydro = GetXMLElementInt({"nReuseHydro"});
0192   if (nReuseHydro) {
0193     SetNReuseHydro(nReuseHydro);
0194     JSINFO << "nReuseHydro: " << nReuseHydro;
0195   }
0196 
0197   // Set up helper. Mostly used for random numbers
0198   // Needs the XML reader singleton set up
0199   JetScapeTaskSupport::ReadSeedFromXML();
0200 
0201   JSDEBUG << "JetScape Debug from XML = " << log_debug;
0202   JSDEBUG << "JetScape Remark from XML = " << log_remark;
0203 }
0204 
0205 //________________________________________________________________
0206 void JetScape::DetermineTaskListFromXML() {
0207 
0208   // First, check for Liquefier and create it if so (since it needs to be passed to other modules)
0209   VERBOSE(2) << "Checking if Liquifier should be created...";
0210   tinyxml2::XMLElement *elementXML =
0211       (tinyxml2::XMLElement *)JetScapeXML::Instance()
0212           ->GetXMLRootUser()
0213           ->FirstChildElement();
0214   while (elementXML) {
0215     std::string elementName = elementXML->Name();
0216     if (elementName == "Liquefier") {
0217       liquefier = make_shared<CausalLiquefier>();
0218       JSINFO << "Created liquefier.";
0219     }
0220     elementXML = elementXML->NextSiblingElement();
0221   }
0222 
0223   // Loop through and create all modules
0224   tinyxml2::XMLElement *element =
0225       (tinyxml2::XMLElement *)JetScapeXML::Instance()
0226           ->GetXMLRootUser()
0227           ->FirstChildElement();
0228   while (element) {
0229     std::string elementName = element->Name();
0230     VERBOSE(2) << "Parsing element: " << elementName;
0231 
0232     // Initial state
0233     if (elementName == "IS") {
0234 
0235       tinyxml2::XMLElement *childElement =
0236           (tinyxml2::XMLElement *)element->FirstChildElement();
0237       while (childElement) {
0238         std::string childElementName = childElement->Name();
0239         VERBOSE(2) << "Parsing childElement: " << childElementName;
0240 
0241         //   - Trento
0242         if (childElementName == "Trento") {
0243           auto trento = JetScapeModuleFactory::createInstance("TrentoInitial");
0244           if (trento) {
0245             Add(trento);
0246             JSINFO << "JetScape::DetermineTaskList() -- Initial State: Added "
0247                       "Trento module to task list.";
0248           }
0249         }
0250         //   - Read initial conditions from file
0251         else if (childElementName == "initial_profile_path") {
0252 #ifdef USE_HDF5
0253           auto initial =
0254               JetScapeModuleFactory::createInstance("InitialFromFile");
0255           if (initial) {
0256             Add(initial);
0257             JSINFO << "JetScape::DetermineTaskList() -- Initial state: Added "
0258                       "InitialFromFile to task list.";
0259           }
0260 #else
0261           JSWARN << "InitialFromFile is attempted to be added, but HDF5 is not "
0262                     "installed!";
0263 #endif
0264         } else if (childElementName == "IPGlasma") {
0265           auto ipglasma = JetScapeModuleFactory::createInstance("IPGlasma");
0266           if (ipglasma) {
0267             Add(ipglasma);
0268             JSINFO << "JetScape::DetermineTaskList() -- Initial State: Added "
0269                       "IPGlasma module to task list.";
0270           }
0271         } else if (childElementName == "initial_Ncoll_list") {
0272           auto initial =
0273               JetScapeModuleFactory::createInstance("NcollListFromFile");
0274           if (initial) {
0275             Add(initial);
0276             JSINFO << "JetScape::DetermineTaskList() -- Initial state: Added "
0277                       "NcollListFromFile to task list.";
0278           }
0279         }
0280         //   - Custom module
0281         else if (((int)childElementName.find("CustomModule") >= 0)) {
0282           auto customModule =
0283               JetScapeModuleFactory::createInstance(childElementName);
0284           if (customModule) {
0285             Add(customModule);
0286             JSINFO << "JetScape::DetermineTaskList() -- Initial state: Added "
0287                    << childElementName << " to task list.";
0288           }
0289         }
0290 
0291         childElement = childElement->NextSiblingElement();
0292       }
0293     }
0294 
0295     // Hard process
0296     else if (elementName == "Hard") {
0297 
0298       tinyxml2::XMLElement *childElement =
0299           (tinyxml2::XMLElement *)element->FirstChildElement();
0300       while (childElement) {
0301         std::string childElementName = childElement->Name();
0302         VERBOSE(2) << "Parsing childElement: " << childElementName;
0303 
0304         //   - PGun
0305         if (childElementName == "PGun") {
0306           auto pGun = JetScapeModuleFactory::createInstance(childElementName);
0307           if (pGun) {
0308             Add(pGun);
0309             JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
0310                       "PGun to task list.";
0311           }
0312         }
0313         //   - PythiaGun
0314         else if (childElementName == "PythiaGun") {
0315           auto pythiaGun =
0316               JetScapeModuleFactory::createInstance(childElementName);
0317           if (pythiaGun) {
0318             Add(pythiaGun);
0319             JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
0320                       "PythiaGun to task list.";
0321           }
0322         }
0323         //   - epemGun
0324         else if (childElementName == "epemGun") {
0325           auto EpemGun =
0326               JetScapeModuleFactory::createInstance(childElementName);
0327           if (EpemGun) {
0328             Add(EpemGun);
0329             JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
0330                       "epemGun to task list.";
0331             }
0332           } 
0333         else if (((int)childElementName.find("CustomModule") >= 0)) {
0334           auto customModule =
0335               JetScapeModuleFactory::createInstance(childElementName);
0336           if (customModule) {
0337             Add(customModule);
0338             JSINFO << "JetScape::DetermineTaskList() -- Hard Process: Added "
0339                    << childElementName << " to task list.";
0340           }
0341         }
0342 
0343         childElement = childElement->NextSiblingElement();
0344       }
0345 
0346     }
0347 
0348     // Pre-equilibrium
0349     else if (elementName == "Preequilibrium") {
0350 
0351       tinyxml2::XMLElement *childElement =
0352           (tinyxml2::XMLElement *)element->FirstChildElement();
0353       while (childElement) {
0354         std::string childElementName = childElement->Name();
0355         VERBOSE(2) << "Parsing childElement: " << childElementName;
0356 
0357         //    - NullPreDynamics
0358         if (childElementName == "NullPreDynamics") {
0359           auto predynamics =
0360               JetScapeModuleFactory::createInstance(childElementName);
0361           if (predynamics) {
0362             Add(predynamics);
0363             JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
0364                       "NullPreDynamics to task list.";
0365           }
0366         } else if (childElementName == "Glasma") {
0367           auto predynamics =
0368               JetScapeModuleFactory::createInstance(childElementName);
0369           if (predynamics) {
0370             Add(predynamics);
0371             JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
0372                       "Glasma to task list.";
0373           }
0374         } else if (childElementName == "FreestreamMilne") {
0375         //    - FreestreamMilne
0376 #ifdef USE_FREESTREAM
0377           auto predynamics =
0378               JetScapeModuleFactory::createInstance(childElementName);
0379           if (predynamics) {
0380             Add(predynamics);
0381             JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
0382                       "FreestreamMilne to task list.";
0383           }
0384 #else
0385           JSWARN << "FreestreamMilne is attempted to be added, but freestream "
0386                     "is not installed!";
0387 #endif
0388         } else if (((int)childElementName.find("CustomModule") >= 0)) {
0389         //   - Custom module
0390           auto customModule =
0391               JetScapeModuleFactory::createInstance(childElementName);
0392           if (customModule) {
0393             Add(customModule);
0394             JSINFO << "JetScape::DetermineTaskList() -- PreDynamics: Added "
0395                    << childElementName << " to task list.";
0396           }
0397         }
0398 
0399         childElement = childElement->NextSiblingElement();
0400       }
0401 
0402     }
0403 
0404     // Hydro
0405     else if (elementName == "Hydro") {
0406 
0407       // First, check if liquefier should be added (Note: Can't use GetXMLElementText(), since that only works for unique tags)
0408       VERBOSE(2) << "Checking if liquefer should be added: Hydro";
0409       bool bAddLiquefier = false;
0410       tinyxml2::XMLElement *childElementLiquefier =
0411           (tinyxml2::XMLElement *)element->FirstChildElement();
0412       while (childElementLiquefier) {
0413         std::string childElementName = childElementLiquefier->Name();
0414         VERBOSE(2) << "Parsing childElementLiq: " << childElementName;
0415         if (childElementName == "AddLiquefier") {
0416           std::string strAddLiquefier = childElementLiquefier->GetText();
0417           if ((int)strAddLiquefier.find("true") >= 0) {
0418             bAddLiquefier = true;
0419             VERBOSE(1) << "Add liquefier to Hydro: True.";
0420           } else {
0421             VERBOSE(1) << "Add liquefier to Hydro: False.";
0422           }
0423         }
0424         childElementLiquefier = childElementLiquefier->NextSiblingElement();
0425       }
0426 
0427       // Loop through elements to look for specific hydro module
0428       tinyxml2::XMLElement *childElement =
0429           (tinyxml2::XMLElement *)element->FirstChildElement();
0430       while (childElement) {
0431         std::string childElementName = childElement->Name();
0432         VERBOSE(2) << "Parsing childElement: " << childElementName;
0433 
0434         //   - Brick
0435         if (childElementName == "Brick") {
0436           auto hydro = JetScapeModuleFactory::createInstance(childElementName);
0437           if (hydro) {
0438             Add(hydro);
0439             JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added Brick to "
0440                       "task list.";
0441             SetModuleId(childElement, hydro);
0442             if (bAddLiquefier) {
0443               dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
0444                   liquefier);
0445               JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
0446                         "liquefier to Brick.";
0447             }
0448           }
0449         }
0450         //   - Gubser
0451         else if (childElementName == "Gubser") {
0452           auto hydro = JetScapeModuleFactory::createInstance(childElementName);
0453           if (hydro) {
0454             Add(hydro);
0455             JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added Gubser to "
0456                       "task list.";
0457             SetModuleId(childElement, hydro);
0458             if (bAddLiquefier) {
0459               dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
0460                   liquefier);
0461               JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
0462                         "liquefier to Gubser.";
0463             }
0464           }
0465         }
0466         //   - hydro_from_file
0467         else if (childElementName == "hydro_from_file") {
0468           auto hydro = JetScapeModuleFactory::createInstance("HydroFromFile");
0469           if (hydro) {
0470             Add(hydro);
0471             JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
0472                       "hydro_from_file to task list.";
0473             SetModuleId(childElement, hydro);
0474             if (bAddLiquefier) {
0475               dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
0476                   liquefier);
0477               JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
0478                         "liquefier to hydro_from_file.";
0479             }
0480           }
0481         }
0482         //   - MUSIC
0483         else if (childElementName == "MUSIC") {
0484 #ifdef USE_MUSIC
0485           auto hydro = JetScapeModuleFactory::createInstance("MUSIC");
0486           if (hydro) {
0487             Add(hydro);
0488             JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added MUSIC to "
0489                       "task list.";
0490             SetModuleId(childElement, hydro);
0491             if (bAddLiquefier) {
0492               dynamic_pointer_cast<FluidDynamics>(hydro)->add_a_liquefier(
0493                   liquefier);
0494               JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
0495                         "liquefier to MUSIC.";
0496             }
0497           }
0498 #else
0499           JSWARN << "MUSIC is attempted to be added, but it is not installed!";
0500 #endif
0501         }
0502         //   - CLVisc
0503         else if (childElementName == "CLVisc") {
0504           auto hydro = JetScapeModuleFactory::createInstance("CLVisc");
0505           if (hydro) {
0506             Add(hydro);
0507             JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added CLVisc to "
0508                       "task list.";
0509           } else {
0510             JSWARN
0511                 << "CLVisc is attempted to be added, but it is not installed!";
0512           }
0513         }
0514 
0515         //   - Custom module
0516         else if (((int)childElementName.find("CustomModule") >= 0)) {
0517           auto customModule =
0518               JetScapeModuleFactory::createInstance(childElementName);
0519           if (customModule) {
0520             Add(customModule);
0521             JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
0522                    << childElementName << " to task list.";
0523             SetModuleId(childElement, customModule);
0524             if (bAddLiquefier) {
0525               dynamic_pointer_cast<FluidDynamics>(customModule)
0526                   ->add_a_liquefier(liquefier);
0527               JSINFO << "JetScape::DetermineTaskList() -- Hydro: Added "
0528                         "liquefier to CustomModule.";
0529             }
0530           }
0531         }
0532 
0533         childElement = childElement->NextSiblingElement();
0534       }
0535     }
0536 
0537     // Eloss
0538     else if (elementName == "Eloss") {
0539 
0540       auto jlossmanager = make_shared<JetEnergyLossManager>();
0541       auto jloss = make_shared<JetEnergyLoss>();
0542 
0543       // Check if liquefier should be added, and add it if so
0544       std::string strAddLiquefier =
0545           GetXMLElementText({"Eloss", "AddLiquefier"});
0546       if ((int)strAddLiquefier.find("true") >= 0) {
0547         jloss->add_a_liquefier(liquefier);
0548         JSINFO << "JetScape::DetermineTaskList() -- Added liquefier to Eloss.";
0549       } else {
0550         VERBOSE(1) << "Add liquefier to Eloss: False.";
0551       }
0552 
0553       // Loop through and add Eloss modules
0554       tinyxml2::XMLElement *childElement =
0555           (tinyxml2::XMLElement *)element->FirstChildElement();
0556       while (childElement) {
0557         std::string childElementName = childElement->Name();
0558         VERBOSE(2) << "Parsing childElement: " << childElementName;
0559 
0560         //   - Matter
0561         if (childElementName == "Matter") {
0562           auto matter = JetScapeModuleFactory::createInstance(childElementName);
0563           if (matter) {
0564             jloss->Add(
0565                 matter); // Note: if you use Matter, it MUST come first (to set virtuality)
0566             JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added Matter to "
0567                       "Eloss list.";
0568           }
0569         }
0570         //   - LBT
0571         else if (childElementName == "Lbt") {
0572           auto lbt = JetScapeModuleFactory::createInstance(childElementName);
0573           if (lbt) {
0574             jloss->Add(
0575                 lbt); // go to 3rd party and ./get_lbtTab before adding this module
0576             JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added LBT to "
0577                       "Eloss list.";
0578           }
0579         }
0580         //   - Martini
0581         else if (childElementName == "Martini") {
0582           auto martini =
0583               JetScapeModuleFactory::createInstance(childElementName);
0584           if (martini) {
0585             jloss->Add(martini);
0586             JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added Martini "
0587                       "to Eloss list.";
0588           }
0589         }
0590         //   - AdS/CFT
0591         else if (childElementName == "AdSCFT") {
0592           auto adscft = JetScapeModuleFactory::createInstance(childElementName);
0593           if (adscft) {
0594             jloss->Add(adscft);
0595             JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added AdS/CFT "
0596                       "to Eloss list.";
0597           }
0598         }
0599         //   - Custom module
0600         else if (((int)childElementName.find("CustomModule") >= 0)) {
0601           auto customModule =
0602               JetScapeModuleFactory::createInstance(childElementName);
0603           if (customModule) {
0604             jloss->Add(customModule);
0605             JSINFO << "JetScape::DetermineTaskList() -- Eloss: Added "
0606                    << childElementName << " to Eloss list.";
0607           }
0608         }
0609 
0610         childElement = childElement->NextSiblingElement();
0611       }
0612 
0613       jlossmanager->Add(jloss);
0614       Add(jlossmanager);
0615     }
0616 
0617     // Jet Hadronization
0618     else if (elementName == "JetHadronization") {
0619 
0620       // Create hadronization manager and module
0621       auto hadroMgr = make_shared<HadronizationManager>();
0622       auto hadro = make_shared<Hadronization>();
0623 
0624       // Determine type of hadronization module, and add it
0625       std::string hadronizationName =
0626           element->FirstChildElement("name")->GetText();
0627       if (hadronizationName == "colored") {
0628         auto hadroModule =
0629             JetScapeModuleFactory::createInstance("ColoredHadronization");
0630         if (hadroModule) {
0631           hadro->Add(hadroModule);
0632           JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
0633                     "ColoredHadronization to task list.";
0634         }
0635       } else if (hadronizationName == "colorless") {
0636         auto hadroModule =
0637             JetScapeModuleFactory::createInstance("ColorlessHadronization");
0638         if (hadroModule) {
0639           hadro->Add(hadroModule);
0640           JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
0641                     "ColorlessHadronization to task list.";
0642         }
0643       } else if (hadronizationName == "hybrid") {
0644         auto hadroModule =
0645             JetScapeModuleFactory::createInstance("HybridHadronization");
0646         if (hadroModule) {
0647           hadro->Add(hadroModule);
0648           JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
0649                     "HybridHadronization to task list.";
0650         }
0651       }
0652       //   - Custom module
0653       else if (((int)hadronizationName.find("CustomModule") >= 0)) {
0654         auto customModule =
0655             JetScapeModuleFactory::createInstance(hadronizationName);
0656         if (customModule) {
0657           hadro->Add(customModule);
0658           JSINFO << "JetScape::DetermineTaskList() -- JetHadronization: Added "
0659                  << hadronizationName << " to task list.";
0660         }
0661       }
0662 
0663       hadroMgr->Add(hadro);
0664       Add(hadroMgr);
0665     }
0666 
0667     // Soft Particlization
0668     else if (elementName == "SoftParticlization") {
0669 
0670       tinyxml2::XMLElement *childElement =
0671           (tinyxml2::XMLElement *)element->FirstChildElement();
0672       while (childElement) {
0673         std::string childElementName = childElement->Name();
0674         VERBOSE(2) << "Parsing childElement: " << childElementName;
0675 
0676         //    - iSS
0677         if (childElementName == "iSS") {
0678 #ifdef iSpectraSampler
0679           auto iSSmodule =
0680               JetScapeModuleFactory::createInstance(childElementName);
0681           if (iSSmodule) {
0682             Add(iSSmodule);
0683             JSINFO << "JetScape::DetermineTaskList() -- SoftParticlization: "
0684                       "Added iSS to task list.";
0685           }
0686 #else
0687           JSWARN << "iSS is attempted to be added, but iSS is not installed!";
0688 #endif
0689         }
0690         //   - Custom module
0691         else if (((int)childElementName.find("CustomModule") >= 0)) {
0692           auto customModule =
0693               JetScapeModuleFactory::createInstance(childElementName);
0694           if (customModule) {
0695             Add(customModule);
0696             JSINFO
0697                 << "JetScape::DetermineTaskList() -- SoftParticlization: Added "
0698                 << childElementName << " to task list.";
0699           }
0700         }
0701 
0702         childElement = childElement->NextSiblingElement();
0703       }
0704     }
0705 
0706     // Afterburner
0707     else if (elementName == "Afterburner") {
0708 
0709       tinyxml2::XMLElement *childElement =
0710           (tinyxml2::XMLElement *)element->FirstChildElement();
0711       while (childElement) {
0712         std::string childElementName = childElement->Name();
0713         VERBOSE(2) << "Parsing childElement: " << childElementName;
0714 
0715         //    - SMASH
0716         if (childElementName == "SMASH") {
0717 #ifdef USE_SMASH
0718           auto smashModule =
0719               JetScapeModuleFactory::createInstance(childElementName);
0720           if (smashModule) {
0721             Add(smashModule);
0722             JSINFO << "JetScape::DetermineTaskList() -- Afterburner: Added "
0723                       "SMASH to task list.";
0724           }
0725 #else
0726           JSWARN
0727               << "SMASH is attempted to be added, but SMASH is not installed!";
0728 #endif
0729         }
0730         //   - Custom module
0731         else if (((int)childElementName.find("CustomModule") >= 0)) {
0732           auto customModule =
0733               JetScapeModuleFactory::createInstance(childElementName);
0734           if (customModule) {
0735             Add(customModule);
0736             JSINFO << "JetScape::DetermineTaskList() -- Afterburner: Added "
0737                    << childElementName << " to task list.";
0738           }
0739         }
0740 
0741         childElement = childElement->NextSiblingElement();
0742       }
0743     }
0744 
0745     // Parton printer
0746     else if (elementName == "PartonPrinter") {
0747 
0748       auto partonPrinter = JetScapeModuleFactory::createInstance(elementName);
0749       if (partonPrinter) {
0750         Add(partonPrinter);
0751         JSINFO << "JetScape::DetermineTaskList() -- Added PartonPrinter to "
0752                   "task list.";
0753       }
0754     }
0755     else if (elementName == "HadronPrinter") {
0756       auto hadronPrinter = JetScapeModuleFactory::createInstance(elementName);
0757       if (hadronPrinter) {
0758         Add(hadronPrinter);
0759         JSINFO << "JetScape::DetermineTaskList() -- Added HadronPrinter to "
0760                   "task list.";
0761       }
0762     }
0763 
0764     else {
0765       VERBOSE(2) << "Nothing to do.";
0766     }
0767 
0768     element = element->NextSiblingElement();
0769   }
0770 }
0771 
0772 //________________________________________________________________
0773 void JetScape::SetModuleId(tinyxml2::XMLElement *moduleElement,
0774                            shared_ptr<JetScapeModuleBase> module) {
0775 
0776   tinyxml2::XMLElement *childElement =
0777       (tinyxml2::XMLElement *)moduleElement->FirstChildElement();
0778   while (childElement) {
0779     std::string childElementName = childElement->Name();
0780     if (childElementName == "name") {
0781       std::string name = childElement->GetText();
0782       module->SetId(name);
0783       JSINFO << "Set ID to: " << name;
0784     }
0785     childElement = childElement->NextSiblingElement();
0786   }
0787 }
0788 
0789 //________________________________________________________________
0790 void JetScape::DetermineWritersFromXML() {
0791 
0792   // Get file output name to write to (without file extension, except if custom writer)
0793   std::string outputFilename = GetXMLElementText({"outputFilename"});
0794 
0795   // Copy string in order to set file extensions for each type
0796   std::string outputFilenameAscii = outputFilename;
0797   std::string outputFilenameAsciiGZ = outputFilename;
0798   std::string outputFilenameHepMC = outputFilename;
0799   std::string outputFilenameRootHepMC = outputFilename;
0800   std::string outputFilenameFinalStatePartonsAscii = outputFilename;
0801   std::string outputFilenameFinalStateHadronsAscii = outputFilename;
0802 
0803   // Check if each writer is enabled, and if so add it to the task list
0804   CheckForWriterFromXML("JetScapeWriterAscii",
0805                         outputFilenameAscii.append(".dat"));
0806   CheckForWriterFromXML("JetScapeWriterAsciiGZ",
0807                         outputFilenameAsciiGZ.append(".dat.gz"));
0808   CheckForWriterFromXML("JetScapeWriterHepMC",
0809                         outputFilenameHepMC.append(".hepmc"));
0810   CheckForWriterFromXML("JetScapeWriterRootHepMC",
0811                         outputFilenameRootHepMC.append("_hepmc.root"));
0812   CheckForWriterFromXML("JetScapeWriterFinalStatePartonsAscii",
0813                         outputFilenameFinalStatePartonsAscii.append("_final_state_partons.dat"));
0814   CheckForWriterFromXML("JetScapeWriterFinalStateHadronsAscii",
0815                         outputFilenameFinalStateHadronsAscii.append("_final_state_hadrons.dat"));
0816 
0817   // Check for custom writers
0818   tinyxml2::XMLElement *element =
0819       (tinyxml2::XMLElement *)JetScapeXML::Instance()
0820           ->GetXMLRootUser()
0821           ->FirstChildElement();
0822   while (element) {
0823     std::string elementName = element->Name();
0824     VERBOSE(2) << "Parsing element: " << elementName;
0825 
0826     if (((int)elementName.find("CustomWriter") >= 0)) {
0827       CheckForWriterFromXML(elementName.c_str(), outputFilename);
0828     }
0829     element = element->NextSiblingElement();
0830   }
0831 }
0832 
0833 //________________________________________________________________
0834 void JetScape::CheckForWriterFromXML(const char *writerName,
0835                                      std::string outputFilename) {
0836 
0837   std::string enableWriter = GetXMLElementText({writerName});
0838   VERBOSE(2) << "Parsing writer: " << writerName;
0839   if ((int)enableWriter.find("on") >= 0) {
0840     VERBOSE(2) << "Writer is on.";
0841     auto writer = JetScapeModuleFactory::createInstance(writerName);
0842     
0843     if (writer) {
0844       dynamic_pointer_cast<JetScapeWriter>(writer)->SetOutputFileName(
0845           outputFilename);
0846       Add(writer);
0847       JSINFO << "JetScape::DetermineTaskList() -- " << writerName << " ("
0848              << outputFilename.c_str() << ") added to task list.";
0849     }
0850     // Manually create HepMC writer if it is enabled, since JetScapeModuleFactor::map_type assumes single inheritance
0851     // from JetScapeModuleBase -- but JetScapeWriterHepMC has multiple inheritance
0852     else if (strcmp(writerName, "JetScapeWriterHepMC") == 0) {
0853 #ifdef USE_HEPMC
0854       VERBOSE(2) << "Manually creating JetScapeWriterHepMC (due to multiple "
0855                     "inheritance)";
0856       auto writer = std::make_shared<JetScapeWriterHepMC>(outputFilename);
0857       Add(writer);
0858       JSINFO << "JetScape::DetermineTaskList() -- " << writerName << " ("
0859              << outputFilename.c_str() << ") added to task list.";
0860 #endif
0861     }
0862     else if (strcmp(writerName, "JetScapeWriterRootHepMC") == 0) {
0863 #ifdef USE_HEPMC
0864       #ifdef USE_ROOT
0865       VERBOSE(2) << "Manually creating JetScapeWriterRootHepMC (due to multiple "
0866                     "inheritance)";
0867       auto writer = std::make_shared<JetScapeWriterRootHepMC>(outputFilename);
0868       Add(writer);
0869       JSINFO << "JetScape::DetermineTaskList() -- " << writerName << " ("
0870              << outputFilename.c_str() << ") added to task list.";
0871       #endif
0872 #endif
0873     } else {
0874       VERBOSE(2) << "Writer is NOT created...";
0875     }
0876   } else {
0877     VERBOSE(2) << "Writer is off.";
0878   }
0879 }
0880 
0881 // kind of cluncky, maybe a better way ... ?
0882 // Handle signal/slots in JetScape hence avoid passing pointers to sub tasks ...
0883 void JetScape::SetPointers() {
0884   // to get hydro pointer for signals, use signal?
0885   JSINFO << "Set Hydro,JetEnergylossManager and IS Pointers for "
0886          << "SignalManager to create Signal/Slots";
0887 
0888   bool hydro_pointer_is_set = false;
0889   for (auto it : GetTaskList()) {
0890     if (dynamic_pointer_cast<InitialState>(it)) {
0891       JetScapeSignalManager::Instance()->SetInitialStatePointer(
0892           dynamic_pointer_cast<InitialState>(it));
0893     } else if (dynamic_pointer_cast<PreequilibriumDynamics>(it)) {
0894       JetScapeSignalManager::Instance()->SetPreEquilibriumPointer(
0895           dynamic_pointer_cast<PreequilibriumDynamics>(it));
0896     } else if (dynamic_pointer_cast<FluidDynamics>(it) &&
0897                !hydro_pointer_is_set) {
0898       JetScapeSignalManager::Instance()->SetHydroPointer(
0899           dynamic_pointer_cast<FluidDynamics>(it));
0900       hydro_pointer_is_set = true;
0901     } else if (dynamic_pointer_cast<JetEnergyLossManager>(it)) {
0902       JetScapeSignalManager::Instance()->SetJetEnergyLossManagerPointer(
0903           dynamic_pointer_cast<JetEnergyLossManager>(it));
0904     } else if (dynamic_pointer_cast<HardProcess>(it)) {
0905       JetScapeSignalManager::Instance()->SetHardProcessPointer(
0906           dynamic_pointer_cast<HardProcess>(it));
0907     } else if (dynamic_pointer_cast<JetScapeWriter>(it) && it->GetActive()) {
0908       JetScapeSignalManager::Instance()->SetWriterPointer(
0909           dynamic_pointer_cast<JetScapeWriter>(it));
0910     } else if (dynamic_pointer_cast<PartonPrinter>(it)) {
0911       JetScapeSignalManager::Instance()->SetPartonPrinterPointer(
0912           dynamic_pointer_cast<PartonPrinter>(it));
0913     } else if (dynamic_pointer_cast<SoftParticlization>(it)) {
0914       JetScapeSignalManager::Instance()->SetSoftParticlizationPointer(
0915           dynamic_pointer_cast<SoftParticlization>(it));
0916     } else if (dynamic_pointer_cast<HadronizationManager>(it)) {
0917       JetScapeSignalManager::Instance()->SetHadronizationManagerPointer(
0918                                         dynamic_pointer_cast<HadronizationManager>(it));
0919     } else if (dynamic_pointer_cast<HadronPrinter>(it)) {
0920       JetScapeSignalManager::Instance()->SetHadronPrinterPointer(
0921                                         dynamic_pointer_cast<HadronPrinter>(it));
0922                 }
0923   }
0924 }
0925 
0926 void JetScape::Exec() {
0927   JSINFO << BOLDRED << "Run JetScape ...";
0928   JSINFO << BOLDRED << "Number of Events = " << GetNumberOfEvents();
0929 
0930   // JetScapeTask::ExecuteTasks(); Has to be called explicitly since not really fully recursively (if ever needed)
0931   // --> JetScape is "Task Manager" of all modules ...
0932 
0933   // Simple way of passing the writer module pointer
0934   vector<weak_ptr<JetScapeWriter>> vWriter;
0935 
0936   for (auto it : GetTaskList()) {
0937     if (dynamic_pointer_cast<JetScapeWriter>(it)) {
0938       if (it->GetActive()) {
0939         vWriter.push_back(dynamic_pointer_cast<JetScapeWriter>(it));
0940       }
0941     }
0942   }
0943 
0944   for (int i = 0; i < GetNumberOfEvents(); i++) {
0945     if (i % n_events_printout == 0) {
0946       JSINFO << BOLDRED << "Run Event # = " << i;
0947     }
0948     VERBOSE(1) << BOLDRED << "Run Event # = " << i;
0949     JSDEBUG << "Found " << GetNumberOfTasks() << " Modules Execute them ... ";
0950 
0951     // First run all tasks
0952     JetScapeTask::ExecuteTasks();
0953 
0954     // Then hand around the collection of writers and ask
0955     // modules to write what they like
0956     // Sequence of events:
0957     // -- writer->Exec is called and redirects to WriteEvent, which starts a new event line
0958     // -- any remaining exec's finish
0959     // -- all modules write their headers
0960     // -- Now all header info is known to the writers, so write out the header
0961     // -- all other Write()'s are being called
0962     // the result still confuses me. It's in the best possible order but it shouldn't be.
0963 
0964     // collect module header data
0965     for (auto w : vWriter) {
0966       auto f = w.lock();
0967       if (f) {
0968         JetScapeTask::CollectHeaders(w);
0969       }
0970     }
0971     // official header
0972     for (auto w : vWriter) {
0973       auto f = w.lock();
0974       if (f) {
0975         f->WriteHeaderToFile();
0976       }
0977     }
0978 
0979     // event data
0980     for (auto w : vWriter) {
0981       auto f = w.lock();
0982       if (f) {
0983         JetScapeTask::WriteTasks(w);
0984       }
0985     }
0986 
0987     // Finalize
0988     for (auto w : vWriter) {
0989       auto f = w.lock();
0990       if (f) {
0991         f->WriteEvent();
0992       }
0993     }
0994 
0995     // For reusal, deactivate task after it has finished
0996     // but before it gets cleaned up.
0997     if (reuse_hydro_) {
0998       if (n_reuse_hydro_ <= 0) {
0999         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
1036     JetScapeTask::ClearTasks();
1037 
1038     IncrementCurrentEvent();
1039   }
1040 }
1041 
1042 void JetScape::Finish() {
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