Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HybridHadronization.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HybridHadronization.cc
1 /*******************************************************************************
2  * Copyright (c) The JETSCAPE Collaboration, 2019
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 "HybridHadronization.h"
17 #include "ThermPtnSampler.h"
18 #include "JetScapeXML.h"
19 #include "JetScapeLogger.h"
20 #include "tinyxml2.h"
21 #include "JetScapeConstants.h"
22 
23 #include "FluidDynamics.h"
24 #include "FluidCellInfo.h"
25 #include "SurfaceCellInfo.h"
26 #include "FluidEvolutionHistory.h"
27 #include "JetScapeSignalManager.h"
28 
29 #include <sstream>
30 #include <iostream>
31 #include <fstream>
32 #include <sstream>
33 #include <random>
34 #include <algorithm>
35 #include <limits>
36 //#include <cmath>
37 
38 using namespace Jetscape;
39 using namespace Pythia8;
40 
41 // Register the module with the base class
43 
44 // Initialize static helper here
45 Pythia8::Pythia HybridHadronization::pythia ("IntentionallyEmpty",false);
46 
47 //RNG - Mersenne Twist - 64 bit
48 //std::mt19937_64 eng(std::random_device{}());
49 //std::mt19937_64 eng(1);
50 //returns a random number between 0 and 1, based on above engine
52  std::uniform_real_distribution<double> uniran(0.0,1.0);
53  return uniran(eng);
54 }
55 
57  SetId("HybridHadronization");
58  VERBOSE(8);
59 }
60 
62  VERBOSE(8);
63 }
64 
65 //meson width function
66 double HybridHadronization::SigM2_calc(double R2chg, double qm1, double qm2, double qq1, double qq2){
67  return R2chg*(2./3.)*(qm1+qm2)*(qm1+qm2)/(std::abs(qq1)*qm2*qm2 + std::abs(qq2)*qm1*qm1) * (std::abs(qq1) + std::abs(qq2));
68 }
69 
70 //baryon width function
71 double HybridHadronization::SigBR2_calc(double R2chg, double qm1, double qm2, double qm3, double qq1, double qq2, double qq3){
72  return R2chg*(2./3.)*(qm1+qm2+qm3)/(std::abs(qq1)*qm2*(qm2+qm3)/(qm1+qm2)+std::abs(qq2)*qm1*(qm1+qm3)/(qm1+qm2)+std::abs(qq3)*(qm1*qm2)/qm3) * (std::abs(qq1) + std::abs(qq2) + std::abs(qq3));
73 }
74 
75 double HybridHadronization::SigBL2_calc(double SigBR2, double qm1, double qm2, double qm3){
76  return SigBR2*((qm1*qm2)/(qm1+qm2))/(qm3*(qm1+qm2)/(qm1+qm2+qm3));
77 }
78 
80 
81  tinyxml2::XMLElement *hadronization = GetXMLElement({"JetHadronization"});
82 
83  if ( !hadronization ) {
84  JSWARN << "Couldn't find tag Jet Hadronization";
85  throw std::runtime_error ("Couldn't find tag Jet Hadronization");
86  }
87  if (hadronization) {
88  string s = hadronization->FirstChildElement( "name" )->GetText();
89  //std::string s = GetXMLElementText({"JetHadronization", "name"});
90  JSDEBUG << s << " to be initialized ...";
91  JSINFO<<"Initialize Hybrid Hadronization ...";
92 
93  JSDEBUG<<"Initialize HybridHadronization";
94  VERBOSE(8);
95 
96  maxM_level = 1; //maximum energy level considered for meson recombination; maximum: 4
97  maxB_level = 1; //maximum energy level considered for baryon recombination; no maximum but no physical baryons beyond 0
98  goldstonereco = false; // don't allow recombination of Goldstone bosons
99  gmax = 1.25; //maximum allowed mass of the gluon (for q-qbar split), in GeV
100  xmq = 0.33; //light quark mass, in GeV
101  xms = 0.5; //strange quark mass, in GeV
102  xmc = 1.5; //charm quark mass in GeV
103  xmb = 4.8; //bottom quark mass in GeV
104  hbarc = 0.197327; // GeV*fm - maybe just set this as a constant in common?
105  dist2cut = 25.; //maximum distance [fm] squared for recombination (involving thermal partons) - in lab frame
106  sh_recofactor = 1.; //suppression/enhancement factor for shower-shower recombination
107  th_recofactor = 1.; //suppression/enhancement factor for shower-thermal recombination
108  attempts_max = 15; //maximum number of failed attempts to hadronize a single event before we give up.
109  p_fake = 0.; //momentum used for fake parton, if needed
110  rand_seed = 0; //seed for RNGs used - 0 means use a randomly determined random seed (from system time or std::random_device{}())
111  had_prop = 0.; //propagation of hadrons after formation by this time in lab frame
112  part_prop = 0.; //minimum propagation time of partons after last split
113  reco_hadrons_pythia = 0; //flag to put recombination hadrons into pythia for decays (position would be lost)
114 
115  //xml read in to alter settings...
116  double xml_doublein = -1.; int xml_intin = -1; unsigned int xml_uintin = std::numeric_limits<unsigned int>::max();
117 
118  xml_doublein = GetXMLElementDouble({"JetHadronization", "eCMforHadronization"});
119  if(xml_doublein >= 0.){p_fake = xml_doublein / 6.;} xml_doublein = -1.; // for colliders set fake momentum to valence quark energy
120 
121  xml_doublein = GetXMLElementDouble({"JetHadronization", "thermreco_distmax"});
122  if(xml_doublein >= 0.){dist2cut = xml_doublein*xml_doublein;} xml_doublein = -1.;
123 
124  xml_doublein = GetXMLElementDouble({"JetHadronization", "shower_recofactor"});
125  if(xml_doublein >= 0.){sh_recofactor = xml_doublein;} xml_doublein = -1.;
126 
127  xml_doublein = GetXMLElementDouble({"JetHadronization", "thermal_recofactor"});
128  if(xml_doublein >= 0.){th_recofactor = xml_doublein;} xml_doublein = -1.;
129 
130  xml_intin = GetXMLElementInt({"JetHadronization", "reco_Mlevelmax"});
131  if(xml_intin >= 0){maxM_level = xml_intin;} xml_intin = -1;
132 
133  xml_intin = GetXMLElementInt({"JetHadronization", "reco_Blevelmax"});
134  if(xml_intin >= -1){maxB_level = xml_intin;} xml_intin = -1;
135 
136  xml_intin = GetXMLElementInt({"JetHadronization", "reco_goldstone"});
137  if(xml_intin >= 0){goldstonereco = xml_intin;} xml_intin = -1;
138 
139  torder_reco = false;
140  xml_intin = GetXMLElementInt({"JetHadronization", "recobias_t"});
141  if(xml_intin == 1){torder_reco = true;} xml_intin = -1;
142 
143  xml_doublein = GetXMLElementDouble({"JetHadronization", "hydro_Tc"});
144  if(xml_doublein >= 0){hydro_Tc = xml_doublein;} xml_doublein = -1;
145 
146  xml_doublein = GetXMLElementDouble({"JetHadronization", "had_postprop"});
147  if(xml_doublein >= 0){had_prop = xml_doublein;} xml_doublein = -1;
148 
149  xml_doublein = GetXMLElementDouble({"JetHadronization", "part_prop"});
150  if(xml_doublein >= 0){part_prop = xml_doublein;} xml_doublein = -1;
151 
152  xml_intin = GetXMLElementInt({"JetHadronization", "reco_hadrons_in_pythia"});
153  if(xml_intin == 0 || xml_intin == 1){reco_hadrons_pythia = xml_intin;} xml_intin = -1;
154 
155  xml_intin = GetXMLElementInt({"Afterburner", "include_fragmentation_hadrons"});
156  if(xml_intin == 1){afterburner_frag_hadrons = true;} xml_intin = -1;
157 
158  if(maxM_level > 4) {
159  maxM_level=4;
160  JSWARN << "Requested maximum energy level for mesons too large. Set it to 4.";
161  }
162  // No, really, the maximum is four
163 
164  // random seed
165  // xml limits us to unsigned int :-/ -- but so does 32 bits Mersenne Twist
166  tinyxml2::XMLElement *RandomXmlDescription = GetXMLElement({"Random"});
167  if ( RandomXmlDescription ){
168  tinyxml2::XMLElement *xmle; xmle = RandomXmlDescription->FirstChildElement( "seed" );
169  xmle->QueryUnsignedText(&xml_uintin);
170  if(xml_uintin < std::numeric_limits<unsigned int>::max()){rand_seed = xml_uintin;} xml_uintin = std::numeric_limits<unsigned int>::max();
171  }else{
172  JSWARN << "No <Random> element found in xml, seeding to 0";
173  }
174  VERBOSE(7) <<"Seeding PYTHIA(hadronization) to "<< rand_seed;
175 
176  //not sure if we can seed with a negative integer...
177  if(rand_seed != 0){eng.seed(rand_seed);}
178  //else{eng.seed(std::random_device{}());}
179  else{ //seeding the mt19937_64 object 'eng' PROPERLY!
180  std::random_device rd;
181  std::array<int,std::mt19937_64::state_size> seedarray; std::generate_n(seedarray.data(), seedarray.size(), std::ref(rd));
182  std::seed_seq seeds(std::begin(seedarray), std::end(seedarray)); eng.seed(seeds);
183  }
184 
185 
186  //Since PYTHIA has no spacetime information, we shouldn't use recombination as it is necessary to calculate recombination probabilities
187  //later, this will instead update to set a flag to attempt to artificially generate this information
188  //for now, we just print a warning - but still try to run recombination. It will just be unphysically enhanced, esp. for certain configurations
189  //tinyxml2::XMLElement *XmlPythiaGun=JetScapeXML::Instance()->GetXMLRoot()->FirstChildElement("Hard" )->FirstChildElement("PythiaGun");
190  /* tinyxml2::XMLElement *XmlPythiaGun = GetXMLElement({"Hard", "PythiaGun"});
191  bool PYgun_FSRon = false;
192  if ( XmlPythiaGun ){
193  tinyxml2::XMLElement *xmle; xmle = XmlPythiaGun->FirstChildElement( "FSR_on" );
194  xmle->QueryIntText(&xml_intin);
195  if(xml_intin == 1){PYgun_FSRon = true;} xml_intin = -1;
196  }
197  if(PYgun_FSRon && (sh_recofactor > 0.0000000001)){JSWARN << "Recombination with a PYTHIA FSR shower is not fully implemented.";}
198  */
199  xml_intin = GetXMLElementInt({"Hard", "PythiaGun", "FSR_on"});
200  if(xml_intin && (sh_recofactor > 0.0000000001)){JSWARN << "Recombination with a PYTHIA FSR shower is not fully implemented.";}
201  xml_intin = -1;
202 
203  //quark masses/charges used to get widths from charged radii (use Pythia masses)
204  double Qm_ud = xmq; double Qm_s = xms; double Qm_c = xmc; double Qm_b = xmb;
205  double chg_u = 2./3.; double chg_d = -1./3.;
206 
207  //rms charge radii
208  //mesons
209  double R2chg_Pi = 0.42 ;
210  double R2chg_Phi = 0.21 ;
211  double R2chg_K = 0.34 ;
212  double R2chg_Jpi = 0.04 ;
213  double R2chg_Ds = 0.09 ;
214  double R2chg_D = 0.165;
215  double R2chg_Ups = 0.032; //????? setting to a linear extrapolation from Jpsi -> Bc -> Ups
216  double R2chg_Bc = 0.036;
217  double R2chg_B = 0.273;
218  //baryons
219  double R2chg_Nuc = 0.69 ;
220  double R2chg_Omg = 0.355;
221  double R2chg_Xi = 0.52 ;
222  double R2chg_Sig = 0.61 ;
223  double R2chg_Occc = 0.179; //?????
224  double R2chg_Occ = 0.043; //?
225  double R2chg_Xicc = 0.049; //?
226  double R2chg_Oc = 0.1 ; //?????
227  double R2chg_Xic = 0.24 ; //?
228  double R2chg_Sigc = 0.27 ; //?
229  double R2chg_Obbb = 0.001; //?????
230  double R2chg_Obbc = 0.001; //?????
231  double R2chg_Obb = 0.001; //?????
232  double R2chg_Xibb = 0.001; //?????
233  double R2chg_Obcc = 0.001; //?????
234  double R2chg_Obc = 0.001; //?????
235  double R2chg_Xibc = 0.001; //?????
236  double R2chg_Ob = 0.6 ; //?????
237  double R2chg_Xib = 0.63 ; //?????
238  double R2chg_Sigb = 0.66 ; //?????
239 
240  //meson width calculations (r2) - recalc if r2chg is changed on command line...
241  SigPi2 = SigM2_calc(R2chg_Pi, Qm_ud, Qm_ud, chg_d, chg_u);
242  SigPhi2 = SigM2_calc(R2chg_Phi, Qm_s, Qm_s, chg_d, -chg_d); //normalizing
243  SigK2 = SigM2_calc(R2chg_K, Qm_s, Qm_ud, chg_d, chg_u);
244  SigJpi2 = SigM2_calc(R2chg_Jpi, Qm_c, Qm_c, chg_u, -chg_u); //normalizing
245  SigDs2 = SigM2_calc(R2chg_Ds, Qm_c, Qm_s, chg_u, chg_d);
246  SigD2 = SigM2_calc(R2chg_D, Qm_c, Qm_ud, chg_u, chg_d);
247  SigUps2 = SigM2_calc(R2chg_Ups, Qm_b, Qm_b, chg_d, -chg_d); //normalizing
248  SigBc2 = SigM2_calc(R2chg_Bc, Qm_b, Qm_c, chg_d, chg_u);
249  SigB2 = SigM2_calc(R2chg_B, Qm_b, Qm_ud, chg_d, chg_u); // (treating B_s as B)
250 
251  //baryon width calculations (r2) - recalc if r2chg is changed on command line...
252  //light/strange baryons
253  SigNucR2 = SigBR2_calc(R2chg_Nuc, Qm_ud, Qm_ud, Qm_ud, chg_d, chg_u, chg_u);
254  SigNucL2 = SigBL2_calc(SigNucR2, Qm_ud, Qm_ud, Qm_ud);
255  SigOmgR2 = SigBR2_calc(R2chg_Omg, Qm_s, Qm_s, Qm_s, chg_d, chg_d, chg_d);
256  SigOmgL2 = SigBL2_calc(SigOmgR2, Qm_s, Qm_s, Qm_s );
257  SigXiR2 = SigBR2_calc(R2chg_Xi, Qm_s, Qm_s, Qm_ud, chg_d, chg_d, chg_d);
258  SigXiL2 = SigBL2_calc(SigXiR2, Qm_s, Qm_s, Qm_ud);
259  SigSigR2 = SigBR2_calc(R2chg_Sig, Qm_s, Qm_ud, Qm_ud, chg_d, chg_u, chg_u);
260  SigSigL2 = SigBL2_calc(SigSigR2, Qm_s, Qm_ud, Qm_ud);
261 
262  //charm baryons
263  SigOcccR2 = SigBR2_calc(R2chg_Occc, Qm_c, Qm_c, Qm_c, chg_d, chg_d, chg_d); // ! maybe need to normalize? (just setting all to -1/3 for now)
264  SigOcccL2 = SigBL2_calc(SigOcccR2, Qm_c, Qm_c, Qm_c );
265  SigOccR2 = SigBR2_calc(R2chg_Occ, Qm_c, Qm_c, Qm_s, chg_u, chg_u, chg_d);
266  SigOccL2 = SigBL2_calc(SigOccR2, Qm_c, Qm_c, Qm_s );
267  SigXiccR2 = SigBR2_calc(R2chg_Xicc, Qm_c, Qm_c, Qm_ud, chg_u, chg_u, chg_d);
268  SigXiccL2 = SigBL2_calc(SigXiccR2, Qm_c, Qm_c, Qm_ud);
269  SigOcR2 = SigBR2_calc(R2chg_Oc, Qm_c, Qm_s, Qm_s, chg_d, chg_d, chg_d); // ! setting all quark charges to -1/3
270  SigOcL2 = SigBL2_calc(SigOcR2, Qm_c, Qm_s, Qm_s );
271  SigXicR2 = SigBR2_calc(R2chg_Xic, Qm_c, Qm_s, Qm_ud, chg_u, chg_d, chg_u);
272  SigXicL2 = SigBL2_calc(SigXicR2, Qm_c, Qm_s, Qm_ud);
273  SigSigcR2 = SigBR2_calc(R2chg_Sigc, Qm_c, Qm_ud, Qm_ud, chg_u, chg_d, chg_u);
274  SigSigcL2 = SigBL2_calc(SigSigcR2, Qm_c, Qm_ud, Qm_ud);
275 
276  //bottom baryons
277  SigObbbR2 = SigBR2_calc(R2chg_Obbb, Qm_b, Qm_b, Qm_b, chg_d, chg_d, chg_d);
278  SigObbbL2 = SigBL2_calc(SigObbbR2, Qm_b, Qm_b, Qm_b );
279  SigObbcR2 = SigBR2_calc(R2chg_Obbc, Qm_b, Qm_b, Qm_c, chg_d, chg_d, chg_d); // ! setting all quark charges to -1/3
280  SigObbcL2 = SigBL2_calc(SigObbcR2, Qm_b, Qm_b, Qm_c );
281  SigObbR2 = SigBR2_calc(R2chg_Obb, Qm_b, Qm_b, Qm_s, chg_d, chg_d, chg_d);
282  SigObbL2 = SigBL2_calc(SigObbR2, Qm_b, Qm_b, Qm_s );
283  SigXibbR2 = SigBR2_calc(R2chg_Xibb, Qm_b, Qm_b, Qm_ud, chg_d, chg_d, chg_d);
284  SigXibbL2 = SigBL2_calc(SigXibbR2, Qm_b, Qm_b, Qm_ud);
285  SigObccR2 = SigBR2_calc(R2chg_Obcc, Qm_b, Qm_c, Qm_c, chg_d, chg_u, chg_u);
286  SigObccL2 = SigBL2_calc(SigObccR2, Qm_b, Qm_c, Qm_c );
287  SigObcR2 = SigBR2_calc(R2chg_Obc, Qm_b, Qm_c, Qm_s, chg_d, chg_d, chg_d); // ! flipping c quark charge (all to -1/3)
288  SigObcL2 = SigBL2_calc(SigObcR2, Qm_b, Qm_c, Qm_s );
289  SigXibcR2 = SigBR2_calc(R2chg_Xibc, Qm_b, Qm_c, Qm_ud, chg_d, chg_u, chg_u);
290  SigXibcL2 = SigBL2_calc(SigXibcR2, Qm_b, Qm_c, Qm_ud);
291  SigObR2 = SigBR2_calc(R2chg_Ob, Qm_b, Qm_s, Qm_s, chg_d, chg_d, chg_d);
292  SigObL2 = SigBL2_calc(SigObR2, Qm_b, Qm_s, Qm_s );
293  SigXibR2 = SigBR2_calc(R2chg_Xib, Qm_b, Qm_s, Qm_ud, chg_d, chg_d, chg_d);
294  SigXibL2 = SigBL2_calc(SigXibR2, Qm_b, Qm_s, Qm_ud);
295  SigSigbR2 = SigBR2_calc(R2chg_Sigb, Qm_b, Qm_ud, Qm_ud, chg_d, chg_u, chg_u);
296  SigSigbL2 = SigBL2_calc(SigSigbR2, Qm_b, Qm_ud, Qm_ud);
297 
298  // No event record printout.
299  pythia.readString("Next:numberShowInfo = 0");
300  pythia.readString("Next:numberShowProcess = 0");
301  pythia.readString("Next:numberShowEvent = 0");
302  pythia.readString("Init:showProcesses = off");
303  pythia.readString("Init:showChangedSettings = off");
304  pythia.readString("Init:showMultipartonInteractions = off");
305  pythia.readString("Init:showChangedParticleData = off");
306 
307  // Standard settings
308  pythia.readString("ProcessLevel:all = off");
309  //pythia.readString("PartonLevel:FSR=off"); //is this necessary?
310 
311  // General settings for hadron decays
312  pythia_decays = GetXMLElementText({"JetHadronization", "pythia_decays"});
313  double tau0Max = 10.0;
314  double tau0Max_xml = GetXMLElementDouble({"JetHadronization", "tau0Max"});
315  if(tau0Max_xml >= 0){tau0Max = tau0Max_xml;}
316  else{JSWARN << "tau0Max should be larger than 0. Set it to 10.";}
317  if(pythia_decays == "on"){
318  JSINFO << "Pythia decays are turned on for tau0Max < " << tau0Max;
319  pythia.readString("HadronLevel:Decay = on");
320  pythia.readString("ParticleDecays:limitTau0 = on");
321  pythia.readString("ParticleDecays:tau0Max = " + std::to_string(tau0Max));
322  } else {
323  JSINFO << "Pythia decays are turned off";
324  pythia.readString("HadronLevel:Decay = off");
325  }
326 
327  // Settings for decays (old flag, will be depracted at some point)
328  // This overwrites the previous settings if the user xml file contains the flag
329  std::string weak_decays =
330  GetXMLElementText({"JetHadronization", "weak_decays"});
331  if (weak_decays == "off") {
332  JSINFO << "Hadron decays are turned off.";
333  JSWARN << "This parameter will be depracted at some point. Use 'pythia_decays' instead.\nOverwriting 'pythia_decays'.";
334  pythia.readString("HadronLevel:Decay = off");
335  } else if(weak_decays == "on") {
336  JSINFO << "Hadron decays inside a range of 10 mm/c are turned on.";
337  JSWARN << "This parameter will be depracted at some point. Use 'pythia_decays' and 'tau0Max' for more control on decays.\nOverwriting 'pythia_decays' and fix 'tau0Max' to 10.";
338  pythia.readString("HadronLevel:Decay = on");
339  pythia.readString("ParticleDecays:limitTau0 = on");
340  pythia.readString("ParticleDecays:tau0Max = 10.0");
341  }
342 
343  //setting seed, or using random seed
344  pythia.readString("Random:setSeed = on");
345  pythia.readString("Random:seed = " + std::to_string(rand_seed));
346 
347  //additional settings
348  //turning off pythia checks for runtime decrease (can be turned back on if necessary, but it shouldn't make much of a difference)
349  pythia.readString("Check:event = off"); // is probably a bad idea, but shouldn't really be necessary... will use a bit of runtime on event checks...
350  pythia.readString("Check:history = off"); // might be a good idea to set 'off' as it saves runtime - provided we know that we've set up mother/daughter relations correctly...
351 
352  //making the pythia event checks a little less stringent (PYTHIA documentation already states that LHC events will occasionally violate default constraint, without concern)
353  //pythia.readString("Check:epTolWarn = 1e-4"); // setting E/P conservation violation constraint somewhat weaker, just for ease
354  //pythia.readString("Check:epTolErr = 1e-2"); // setting E/P conservation violation constraint somewhat weaker, just for ease
355  //pythia.readString("Check:mTolWarn = 1e-2"); // setting EP/M conservation violation constraint somewhat weaker, just for ease
356  //pythia.readString("Check:mTolErr = 1e-1"); // setting EP/M conservation violation constraint somewhat weaker, just for ease
357 
358  //allowing for partonic space-time information to be used by PYTHIA
359  //pythia.readString("PartonVertex:setVertex = on"); //this might allow PYTHIA to keep track of partonic space-time information (default was for 'rope hadronization')
360 
361  //setting hadron color tags so that spacetime information can be reconstructed
362  pythia.readString("StringFragmentation:TraceColours = on");
363 
364  //using QCD based color reconnection (original PYTHIA MPI based CR can't be used at hadron level)
365  pythia.readString("ColourReconnection:reconnect = off"); //allowing color reconnections (should have been default on, but doing it here for clarity)
366  /*pythia.readString("ColourReconnection:mode = 1"); //sets the color reconnection scheme to 'new' QCD based scheme (TODO: make sure this is better than (2)gluon move)
367  pythia.readString("ColourReconnection:forceHadronLevelCR = on"); //allowing color reconnections for these constructed strings!
368  //a few params for the QCD based color reconnection scheme are set below.
369  pythia.readString("MultipartonInteractions:pT0Ref = 2.15"); //not sure if this is needed for this setup, but is part of the recommended 'default'
370  pythia.readString("ColourReconnection:allowDoubleJunRem = off"); //default on - allows directly connected double junction systems to split into two strings
371  pythia.readString("ColourReconnection:junctionCorrection = 1.15");
372  pythia.readString("ColourReconnection:timeDilationMode = 3"); //allow reconnection if single pair of dipoles are in causal contact (maybe try 5 as well?)
373  pythia.readString("ColourReconnection:timeDilationPar = 0.18"); //parameter used in causal interaction between strings (mode set above)(maybe try 0.073?)
374  */
375 
376  std::stringstream lines;
377  lines << GetXMLElementText({"JetHadronization", "LinesToRead"}, false);
378  while (std::getline(lines, s, '\n')) {
379  if (s.find_first_not_of(" \t\v\f\r") == s.npos)
380  continue; // skip empty lines
381  JSINFO << "Also reading in: " << s;
382  pythia.readString(s);
383  }
384 
385  // optional input of another pythia particle data xml file (higher excited states,...)
386  xml_intin = GetXMLElementInt({"JetHadronization", "additional_pythia_particles"});
387  if(xml_intin == 0 || xml_intin == 1){additional_pythia_particles = xml_intin;} xml_intin = -1;
388 
389  if(additional_pythia_particles == 1) {
390  std::string additional_pythia_particle_file =
391  GetXMLElementText({"JetHadronization", "additional_pythia_particles_path"});
392  pythia.particleData.readXML(additional_pythia_particle_file,false);
393  }
394 
395  // And initialize
396  pythia.init();
397 
398  //reading in info for thermal partons
399  inbrick = false; brickL = -1.;
400  inhydro = false; nreusehydro = 1;
401 
402  xml_intin = GetXMLElementInt({"Eloss", "Matter", "brick_med"});
403  if(xml_intin == 1){inbrick = true;} xml_intin = -1;
404  xml_doublein = GetXMLElementDouble({"Eloss", "Matter", "brick_length"});
405  if(inbrick && (xml_doublein >= 0.)){brickL = xml_doublein;} xml_doublein = -1.;
406  xml_intin = GetXMLElementInt({"nReuseHydro"});
407  if(xml_intin > 0){nreusehydro = xml_intin;} xml_intin = -1;
408  xml_doublein = GetXMLElementDouble({"Eloss", "deltaT"});
409  if(xml_doublein >= 0.){delta_t = xml_doublein;} xml_doublein = -1.;
410 
411  // Check if hydro is used in user xml file
413  while (elementXML) {
414  std::string elementName = elementXML->Name();
415  if (elementName == "Hydro") {
416  inhydro = true;
417  }
418  elementXML = elementXML->NextSiblingElement();
419  } // at this point the hydro could still be a brick -> check this in the following part
420 
421  if(inhydro){
423  while (element) {
424  std::string elementName = element->Name();
425  if (elementName == "Hydro") {
426  inhydro = true;
427  tinyxml2::XMLElement *childElement = (tinyxml2::XMLElement *)element->FirstChildElement();
428  while (childElement) {
429  std::string childElementName = childElement->Name();
430  if (childElementName == "Brick") {
431  inbrick = true;
432  inhydro = false;
433  }
434  childElement = childElement->NextSiblingElement();
435  }
436  }
437  element = element->NextSiblingElement();
438  }
439  }
440 
441  // this is only important if a boost invariant 2+1d hydro is used
442  xml_doublein = GetXMLElementDouble({"JetHadronization", "eta_max_boost_inv"});
443  if(inhydro && (xml_doublein >= 0.)){eta_max_boost_inv = xml_doublein;} xml_doublein = -1.;
444  }
445 }
446 
447 void HybridHadronization::WriteTask(weak_ptr<JetScapeWriter> w){
448  VERBOSE(8);
449  auto f = w.lock();
450  if ( !f ) return;
451  f->WriteComment("Hadronization Module : "+GetId());
452 }
453 
454 //TODO: Junction Strings, Thermal Partons
456  number_p_fake = 0; //reset counter for the number of fake partons
457  double energy_hadrons = 0.; //needed for the kinetic scaling of the negative hadrons
458 
459  //JSINFO<<"Start Hybrid Hadronization using both Recombination and PYTHIA Lund string model.";
460  pythia.event.reset(); HH_shower.clear();
461  parton_collection neg_ptns;
462 
463  //pointer to get hydro temperature info
464  std::unique_ptr<FluidCellInfo> check_fluid_info_ptr;
465 
466  bool boost_invariant = true;
467  bool Cartesian_hydro = false; // not properly initialized by all hydro modules at the moment, don't use it
468  if(inhydro){
469  std::shared_ptr<FluidDynamics> hydro_ptr = JetScapeSignalManager::Instance()->GetHydroPointer().lock();
470  const EvolutionHistory& bulk_info = hydro_ptr->get_bulk_info();
471 
472  boost_invariant = bulk_info.is_boost_invariant();
473  Cartesian_hydro = bulk_info.is_Cartesian();
474  Cartesian_hydro = false;
475  }
476 
477  //negative brickL, then we will not run a brick sampler
478  if(brickL < 0.){brickL = 0.; inbrick = false;}
479 
480  //The framework uses unsigned int for partons, while HHpartons have int anti-/color tags.
481  //Changing the HH partons to unsigned int is not that easy as some workflow, e.g. in recomb(),
482  //needs them to be integer in some structures. Let's have a workaround and set the
483  //tags of partons which are too large for an int value to a new unused value.
484  convert_color_tags_to_int_type(shower);
485 
486  double total_shower_energy = 0.; // used to scale the negative hadrons
487  double total_shower_energy_neg = 0.; // used to scale the negative hadrons
488  //sort positive partons into HH_shower and negative partons from LBT to neg_ptns
489  for(unsigned int ishower=0; ishower < shower.size(); ++ishower){
490  for(unsigned int ipart=0; ipart < shower.at(ishower).size(); ++ipart){
491  HHparton sh_parton;
492  sh_parton.is_shower(true); sh_parton.id(shower.at(ishower).at(ipart)->pid()); sh_parton.orig(0); //sh_parton.string_id(str)
493  sh_parton.px(shower.at(ishower).at(ipart)->px()); sh_parton.py(shower.at(ishower).at(ipart)->py());
494  sh_parton.pz(shower.at(ishower).at(ipart)->pz()); sh_parton.e(shower.at(ishower).at(ipart)->e());
495  sh_parton.x( shower.at(ishower).at(ipart)->x_in().x() ); sh_parton.y( shower.at(ishower).at(ipart)->x_in().y() );
496  sh_parton.z( shower.at(ishower).at(ipart)->x_in().z() ); sh_parton.x_t(shower.at(ishower).at(ipart)->x_in().t() );
497  sh_parton.mass( sh_parton.e()*sh_parton.e() - sh_parton.px()*sh_parton.px() - sh_parton.py()*sh_parton.py() - sh_parton.pz()*sh_parton.pz() );
498  sh_parton.mass( (sh_parton.mass() >= 0.) ? sqrt(sh_parton.mass()) : sqrt(-sh_parton.mass()) );
499  sh_parton.col( shower.at(ishower).at(ipart)->color() ); sh_parton.acol( shower.at(ishower).at(ipart)->anti_color() );
500 
501  if(shower.at(ishower).at(ipart)->pstat()>-1){
502  HH_shower.add(sh_parton);
503  total_shower_energy += HH_shower[HH_shower.num()-1].e();
504  }else{
505  neg_ptns.add(sh_parton);
506  total_shower_energy_neg += neg_ptns[neg_ptns.num()-1].e();
507  }
508  }
509  JSDEBUG<<"Shower#"<<ishower+1 << ". Number of partons to hadronize: " << HH_shower.num();
510  JSDEBUG<<"Shower#"<<ishower+1 << ". Number of (neg) partons to hadronize: " << neg_ptns.num();
511  }
512 
513  //sample thermal partons, brick or hydro hypersurface
514  //checking to see if we need to sample thermal partons, if either in brick or hydro
515  bool runsampler = (((inhydro || inbrick) && HH_thermal.num()==0) || (GetCurrentEvent()%nreusehydro==0)) ? true : false;
516 
517  if(runsampler && inbrick){
518  HH_thermal.clear(); //emptying the thermal partons if we're resampling
519  ThermalPartonSampler brick(rand_seed); //creating a thermal brick
520  brick.brick_length_width(brickL,brickL);
521  brick.brick_flow(0., 0., 0.);
522  brick.brick_Tc(hydro_Tc);
523  brick.samplebrick();
524 
525  JSINFO << "A " << brickL << " fm brick was sampled, generating " << brick.nTot() << " partons (" << brick.th_nL() << " light, " << brick.th_nS() << " strange).";
526 
527  for(int ith=0; ith<brick.nTot(); ++ith){
528  HHparton thparton;
529  thparton.is_thermal(true); thparton.id(brick.th_pid(ith)); thparton.orig(1); //sh_parton.string_id(str)
530  thparton.col(0); thparton.acol(0);
531  thparton.px(brick.th_px(ith)); thparton.py(brick.th_py(ith)); thparton.pz(brick.th_pz(ith)); thparton.e( brick.th_e(ith));
532  thparton.x( brick.th_x(ith) ); thparton.y( brick.th_y(ith) ); thparton.z( brick.th_z(ith) ); thparton.x_t(brick.th_t(ith));
533  thparton.mass( thparton.e()*thparton.e() - thparton.px()*thparton.px() - thparton.py()*thparton.py() - thparton.pz()*thparton.pz() );
534  thparton.mass( (thparton.mass() >= 0.) ? sqrt(thparton.mass()) : sqrt(-thparton.mass()) );
535  thparton.pos_str(1);
536  HH_thermal.add(thparton); //adding this parton to thermal collection
537  }
538  //read in thermal partons, THEN do sibling setup...
539  for(int i=0;i<HH_thermal.num();++i){
540  HH_thermal[i].sibling(i); HH_thermal[i].string_id(-i);
541  HH_thermal[i].is_used(true); HH_thermal[i].sibling( findthermalsibling(i, HH_thermal) ); HH_thermal[i].is_used(false);
542  }
543  } else if(runsampler && inhydro){
544  HH_thermal.clear(); //emptying the thermal partons if we're resampling
545  std::vector<SurfaceCellInfo> surface_cells;
546  GetHydroHyperSurface(hydro_Tc, surface_cells);
547  /*std::cout << "\n\n Surface Cells\n";
548  for(int icel=0; icel<surface_cells.size(); ++icel){
549  if(icel % int(surface_cells.size()/100) != 0){continue;}
550  std::cout << surface_cells[icel].tau << ":" << surface_cells[icel].eta << ":" << surface_cells[icel].x << ":" << surface_cells[icel].y << ", ";
551  std::cout << surface_cells[icel].vx << ":" << surface_cells[icel].vy << ":" << surface_cells[icel].vz << ", ";
552  std::cout << surface_cells[icel].qgp_fraction << ":" << surface_cells[icel].temperature << ":" << surface_cells[icel].pressure << "\n";
553  }
554  std::cout << "\n\n";*/
555 
556  //not happy about having to do this, this way, but it is what it is.
557  std::vector<std::vector<double>> surface;
558  for(int icel=0; icel<surface_cells.size(); ++icel){
559  std::vector<double> cell;
560  cell.push_back(surface_cells[icel].tau); cell.push_back(surface_cells[icel].x); cell.push_back(surface_cells[icel].y); cell.push_back(surface_cells[icel].eta);
561  cell.push_back(surface_cells[icel].d3sigma_mu[0]); cell.push_back(surface_cells[icel].d3sigma_mu[1]);
562  cell.push_back(surface_cells[icel].d3sigma_mu[2]); cell.push_back(surface_cells[icel].d3sigma_mu[3]);
563  cell.push_back(surface_cells[icel].temperature);
564  cell.push_back(surface_cells[icel].vx); cell.push_back(surface_cells[icel].vy); cell.push_back(surface_cells[icel].vz);
565  surface.push_back(cell);
566  }
567 
568  ThermalPartonSampler part_samp(rand_seed); //initializing sampler with random seed
569  part_samp.set_hypersurface(surface);
570  if(boost_invariant){
571  part_samp.sample_2p1d(eta_max_boost_inv);
572  }else{
573  part_samp.sample_3p1d(Cartesian_hydro);
574  }
575 
576  JSINFO << "Hydro was sampled, generating " << part_samp.nTot() << " partons (" << part_samp.th_nL() << " light, " << part_samp.th_nS() << " strange).";
577 
578  for(int ith=0; ith<part_samp.nTot(); ++ith){
579  HHparton thparton;
580  thparton.is_thermal(true); thparton.id(part_samp.th_pid(ith)); thparton.orig(1); //sh_parton.string_id(str)
581  thparton.px(part_samp.th_px(ith)); thparton.py(part_samp.th_py(ith)); thparton.pz(part_samp.th_pz(ith)); thparton.e( part_samp.th_e(ith));
582  thparton.x( part_samp.th_x(ith) ); thparton.y( part_samp.th_y(ith) ); thparton.z( part_samp.th_z(ith) ); thparton.x_t(part_samp.th_t(ith));
583  thparton.mass( thparton.e()*thparton.e() - thparton.px()*thparton.px() - thparton.py()*thparton.py() - thparton.pz()*thparton.pz() );
584  thparton.mass( (thparton.mass() >= 0.) ? sqrt(thparton.mass()) : sqrt(-thparton.mass()) );
585  thparton.pos_str(1);
586  HH_thermal.add(thparton); //adding this parton to thermal collection
587  }
588  //read in thermal partons, THEN do sibling setup...
589  for(int i=0;i<HH_thermal.num();++i){
590  HH_thermal[i].sibling(i); HH_thermal[i].string_id(-i);
591  HH_thermal[i].is_used(true); HH_thermal[i].sibling( findthermalsibling(i, HH_thermal) ); HH_thermal[i].is_used(false);
592  }
593  }
594 
595  if(!inbrick && !inhydro){ //propagate positive and negative partons for time part_prop in vacuum
596  for(int i_sh=0; i_sh<HH_shower.num(); ++i_sh){
597  double max_t_dif = part_prop;
598  double vel[3]; vel[0]=HH_shower[i_sh].px()/HH_shower[i_sh].e(); vel[1]=HH_shower[i_sh].py()/HH_shower[i_sh].e(); vel[2]=HH_shower[i_sh].pz()/HH_shower[i_sh].e();
599  HH_shower[i_sh].x(HH_shower[i_sh].x() + vel[0]*max_t_dif); HH_shower[i_sh].y(HH_shower[i_sh].y() + vel[1]*max_t_dif); HH_shower[i_sh].z(HH_shower[i_sh].z() + vel[2]*max_t_dif);
600  HH_shower[i_sh].x_t(HH_shower[i_sh].x_t() + max_t_dif);
601  }
602  for(int i_sh=0; i_sh<neg_ptns.num(); ++i_sh){
603  double max_t_dif = part_prop;
604  double vel[3]; vel[0]=neg_ptns[i_sh].px()/neg_ptns[i_sh].e(); vel[1]=neg_ptns[i_sh].py()/neg_ptns[i_sh].e(); vel[2]=neg_ptns[i_sh].pz()/neg_ptns[i_sh].e();
605  neg_ptns[i_sh].x(neg_ptns[i_sh].x() + vel[0]*max_t_dif); neg_ptns[i_sh].y(neg_ptns[i_sh].y() + vel[1]*max_t_dif); neg_ptns[i_sh].z(neg_ptns[i_sh].z() + vel[2]*max_t_dif);
606  neg_ptns[i_sh].x_t(neg_ptns[i_sh].x_t() + max_t_dif);
607  }
608  }
609 
610  //checking to see if partons are inside medium, and if so then propagate all partons to hypersurface!
611  //also can propagate by part_prop time
612  for(int i_sh=0; i_sh<HH_shower.num(); ++i_sh){
613  double vel[3]; vel[0]=HH_shower[i_sh].px()/HH_shower[i_sh].e(); vel[1]=HH_shower[i_sh].py()/HH_shower[i_sh].e(); vel[2]=HH_shower[i_sh].pz()/HH_shower[i_sh].e();
614  double t_dif = 0.;
615  if(inbrick && HH_shower[i_sh].x_t() < brickL){
616  t_dif = brickL - HH_shower[i_sh].x_t();
617  }else if(inhydro){
618  int i=0;
619  double temp=999999.;
620  while(temp > hydro_Tc){
621  double tnow = HH_shower[i_sh].x_t() + delta_t*double(i);
622  double xnow = HH_shower[i_sh].x() + vel[0]*delta_t*double(i);
623  double ynow = HH_shower[i_sh].y() + vel[1]*delta_t*double(i);
624  double znow = HH_shower[i_sh].z() + vel[2]*delta_t*double(i);
625  GetHydroCellSignal(tnow, xnow, ynow, znow, check_fluid_info_ptr);
626  temp = check_fluid_info_ptr->temperature;
627  if(temp <= hydro_Tc){
628  t_dif = delta_t*double(i);
629  }
630  ++i;
631  }
632  }
633  double max_t_dif = std::max(t_dif,part_prop);
634  HH_shower[i_sh].x(HH_shower[i_sh].x() + vel[0]*max_t_dif); HH_shower[i_sh].y(HH_shower[i_sh].y() + vel[1]*max_t_dif); HH_shower[i_sh].z(HH_shower[i_sh].z() + vel[2]*max_t_dif);
635  HH_shower[i_sh].x_t(HH_shower[i_sh].x_t() + max_t_dif);
636  //JSINFO<<"Parton propagated to: " << HH_shower[i_sh].x() << ", " << HH_shower[i_sh].y() << ", " << HH_shower[i_sh].z() << ", " << HH_shower[i_sh].x_t();
637  }
638  //do the same for the negative partons
639  for(int i_sh=0; i_sh<neg_ptns.num(); ++i_sh){
640  double vel[3]; vel[0]=neg_ptns[i_sh].px()/neg_ptns[i_sh].e(); vel[1]=neg_ptns[i_sh].py()/neg_ptns[i_sh].e(); vel[2]=neg_ptns[i_sh].pz()/neg_ptns[i_sh].e();
641  double t_dif = 0.;
642  if(inbrick && neg_ptns[i_sh].x_t() < brickL){
643  t_dif = brickL - neg_ptns[i_sh].x_t();
644  }else if(inhydro){
645  int i=0;
646  double temp=999999.;
647  while(temp > hydro_Tc){
648  double tnow = neg_ptns[i_sh].x_t() + delta_t*double(i);
649  double xnow = neg_ptns[i_sh].x() + vel[0]*delta_t*double(i);
650  double ynow = neg_ptns[i_sh].y() + vel[1]*delta_t*double(i);
651  double znow = neg_ptns[i_sh].z() + vel[2]*delta_t*double(i);
652  GetHydroCellSignal(tnow, xnow, ynow, znow, check_fluid_info_ptr);
653  temp = check_fluid_info_ptr->temperature;
654  if(temp <= hydro_Tc){
655  t_dif = delta_t*double(i);
656  }
657  ++i;
658  }
659  }
660  double max_t_dif = std::max(t_dif,part_prop);
661  neg_ptns[i_sh].x(neg_ptns[i_sh].x() + vel[0]*max_t_dif); neg_ptns[i_sh].y(neg_ptns[i_sh].y() + vel[1]*max_t_dif); neg_ptns[i_sh].z(neg_ptns[i_sh].z() + vel[2]*max_t_dif);
662  neg_ptns[i_sh].x_t(neg_ptns[i_sh].x_t() + max_t_dif);
663  //JSINFO<<"Parton propagated to: " << neg_ptns[i_sh].x() << ", " << neg_ptns[i_sh].y() << ", " << neg_ptns[i_sh].z() << ", " << neg_ptns[i_sh].x_t();
664  }
665 
666  /*for(int i=0; i<HH_thermal.num(); i++){
667  std::cout << HH_thermal[i].id() << "," << HH_thermal[i].x_t() << "," << HH_thermal[i].x()
668  << "," << HH_thermal[i].y() << "," << HH_thermal[i].z() << "," << HH_thermal[i].e()
669  << "," << HH_thermal[i].px() << "," << HH_thermal[i].py() << "," << HH_thermal[i].pz()
670  << "," << HH_thermal[i].mass() << std::endl;
671  }*/
672 
673  //separately running over positive and negative partons
674  for(int pos_ptn = 1; pos_ptn>=0; --pos_ptn){
675  double tmp_threco = th_recofactor; //need to keep track of th_recofactor (strength) to disable it for negative partons
676  double tmp_maxB_level = maxB_level; //need to keep track of maxB_level to disable baryon recombination for negative partons
677  int tmp_reco_hadrons_pythia = reco_hadrons_pythia;
678  if(pos_ptn == 0){//handling negative partons by wiping shower partons & hadrons, then rerunning with negative partons
679  pythia.event.reset(); HH_shower.clear(); HH_shower = neg_ptns; //hadrons, remnants, pyremn cleared below
680 
681  // if the fragmentation hadrons are given to the afterburner module
682  // let the negative partons decay here, as they are not propagated in the
683  // afterburner
684  if(afterburner_frag_hadrons){
685  reco_hadrons_pythia = 1;
686  pythia.readString("HadronLevel:Decay = on");
687  pythia.init();
688  }
689 
690  //add holes left by used thermal partons to HH_shower
691  for(int i=0; i<HH_thermal.num(); ++i){
692  if(HH_thermal[i].is_used()) {
693  HH_thermal[i].is_used(false);
694  HH_shower.add(HH_thermal[i]);
695  }
696  }
697 
698  //add Extrapartons from recomb() of hadrons to HH_shower of negative partons
699  for(int i=0; i<HH_recomb_extrapartons.num(); ++i){
700  HH_shower.add(HH_recomb_extrapartons[i]);
701  }
702 
703  if(HH_shower.num() != 0){
704  th_recofactor = 0.;//killing thermal + negative parton recombination.
705  maxB_level = -1;//disable baryon recombination for negative partons
706  } //do this only if there are negative partons, otherwise the baryon recombination would be switched off after the first event without negative partons
707  }
708  if(HH_shower.num() == 0){
709  continue;
710  } //attempting to handle events/configurations with 0 partons will result in a crash
711 
712  int attempt_num = 0; bool run_successfully = false;
713  while((attempt_num < attempts_max) && (!run_successfully)){
714  HH_showerptns = HH_shower;
715  //clearing hadrons and remnants collections
716  HH_hadrons.clear(); HH_remnants.clear(); HH_pyremn.clear(); HH_pythia_hadrons.clear(); HH_recomb_extrapartons.clear();
717 
718  //since we 'might' need to reset the thermal partons (if present!)... because we alter the thermal parton collection in the string repair routine
719  for(int i=0; i<HH_thermal.num(); ++i){
720  HH_thermal[i].is_used(false); HH_thermal[i].is_decayedglu(false); HH_thermal[i].is_remnant(false); HH_thermal[i].used_reco(false); HH_thermal[i].used_str(false); HH_thermal[i].is_thermal(true);
721  HH_thermal[i].orig(1); HH_thermal[i].par(-1); HH_thermal[i].status(0); HH_thermal[i].col(0); HH_thermal[i].acol(0); HH_thermal[i].is_fakeparton(false);
722  HH_thermal[i].PY_par1(-1); HH_thermal[i].PY_par2(-1); HH_thermal[i].PY_dau1(-1); HH_thermal[i].PY_dau2(-1); HH_thermal[i].PY_stat(23);
723  HH_thermal[i].string_id(-i); HH_thermal[i].is_strendpt(false); HH_thermal[i].pos_str(1); HH_thermal[i].endpt_id(0);
724 
725  if(pos_ptn == 0) {
726  HH_thermal[i].is_used(true); //set all the thermal partons to is used for negative partons, such that they are not used in the findthermalsibling routine
727  }
728  }
729 
730  //checking the shower for any color singlet particles to just dump into PYTHIA
731  //also handling colored non-partonic particles
732  int i_show=0;
733  while(i_show<HH_showerptns.num()){
734  if(HH_showerptns[i_show].id() == 21){++i_show; continue;} //is gluon
735  else if(std::abs(HH_showerptns[i_show].id()) <= 6){++i_show; continue;} //is quark
736  else if((std::abs(HH_showerptns[i_show].id()) >= 1103) && (std::abs(HH_showerptns[i_show].id()) <= 5503) && ((HH_showerptns[i_show].id()/10)%10 == 0)){++i_show; continue;} //is diquark
737  else if(pythia.particleData.colType(HH_showerptns[i_show].id()) == 2){//this is a non-gluon color octet...
738  HH_showerptns[i_show].PY_origid(HH_showerptns[i_show].id()); HH_showerptns[i_show].id(21); ++i_show; continue;
739  }//this is a non-(simple)quark color triplet... (pid 42(scalar leptoquark), 4000001(1-6, excited quarks), and SUSY particles)
740  else if(std::abs(pythia.particleData.colType(HH_showerptns[i_show].id())) == 1){
741  HH_showerptns[i_show].PY_origid( HH_showerptns[i_show].id() );
742  HH_showerptns[i_show].id( 1*(2*std::signbit(-pythia.particleData.colType(HH_showerptns[i_show].id()))-1) ); ++i_show; continue;
743  } //and the two above should catch 'colored technihadrons' too!
744  else if(HH_showerptns[i_show].id() == 90){HH_showerptns.remove(i_show); continue;} //PYTHIA specific pid for the 'system' as a whole, shouldn't actually be here. Dumping it.
745  //is none of the above (a colorless object of some sort (a hadron, photon, lepton...))
746  HHhadron had; had.id( HH_showerptns[i_show].id() ); had.orig( HH_showerptns[i_show].orig() ); had.mass( HH_showerptns[i_show].mass() );
747  had.pos(HH_showerptns[i_show].pos()); had.P(HH_showerptns[i_show].P());
748  HH_hadrons.add(had); HH_showerptns.remove(i_show);
749  }
750 
751  //setting up the strings appropriately for showers - assumes that color tags are set.
752  //if there are colored particles without set color tags, it will dump those partons in particular into a single string
753  int num_strings = 0;
754  stringform();
755  num_strings = HH_showerptns[HH_showerptns.num()-1].string_id();
756 
757  // last attempt in hadronization is done without recombination
758  double sh_recofactor_store = sh_recofactor;
759  if(attempt_num == attempts_max -1) {
760  sh_recofactor = 0.;
761  if(pos_ptn == 1) {
762  JSWARN << "Hadronization failed, try without recombination one more time";
763  } else {
764  JSWARN << "Hadronization of negative partons failed, try without recombination one more time";
765  }
766  }
767 
768  //running recombination
769  recomb();
770  sh_recofactor = sh_recofactor_store;
771 
772  //function to prepare strings for input into PYTHIA8
773  //will need a final reindexing for py_remn (all PY_par#, PY_dau# will need to be += 1) AFTER this function (either here, or in invoke_py)
774  //when recursive 'workaround' for large strings is properly handled/removed, then can put this reindexing inside the function
775  if(HH_remnants.num()){
776  bool cut = (attempt_num > -1) ? true : false;
777  stringprep(HH_remnants, HH_pyremn, cut);
778  }
779 
780  //temporary workaround to force all formed hadrons to be final state - so pythia won't overwrite spacetime info
781  for(int i=0; i<HH_hadrons.num(); ++i){
782  HH_hadrons[i].is_final(true);
783  }
784 
785  //if negative fakepartons, we set the momenta and energy to zero before giving them to pythia
786  if (pos_ptn == 0) {
787  for(int ipart = 0; ipart < HH_pyremn.num(); ipart++) {
788  if(HH_pyremn[ipart].is_fakeparton()) {
789  if(HH_pyremn[ipart].id() == 21 && HH_pyremn[ipart].mass() > (2.*pythia.particleData.m0(211) + 0.01)) {
790  HH_pyremn[ipart].mass(2.*pythia.particleData.m0(211) + 0.01);
791  }
792  HH_pyremn[ipart].e(HH_pyremn[ipart].mass());
793  HH_pyremn[ipart].px(0.);
794  HH_pyremn[ipart].py(0.);
795  HH_pyremn[ipart].pz(0.);
796  }
797  }
798  }
799 
800  //running remaining partons through PYTHIA8 string fragmentation
801  run_successfully = invoke_py();
802 
803  //for a successful run, go though final hadrons here and set parton parents up
804  //bring the hadrons to their corresponding pythia mass shell
805  if(run_successfully){
806 
807  //remove all hadrons from HH_hadrons if reco hadrons are put into pythia
808  //in this case they are already contained in HH_pythia_hadrons
809  if(reco_hadrons_pythia) {
810  HH_hadrons.clear();
811  }
812 
813  //add all fragmentation hadrons from pythia to HH_hadrons, now that pythia hadronization was successfull
814  for(int iHad = 0; iHad < HH_pythia_hadrons.num(); iHad++) {
815  HH_hadrons.add(HH_pythia_hadrons[iHad]);
816  }
817 
818  bring_hadrons_to_mass_shell(HH_hadrons);
819 
820  //hadron propagation (neglect the photons)
821  for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){
822  if(std::abs(had_prop) > 0.0001 && HH_hadrons[iHad].id() != 22){ //assumes that hadron will be propagated by more than 0.0001 fm/c in lab frame - can even propagate backwards, if that's something wanted...
823  double vel[3]; vel[0]=HH_hadrons[iHad].px()/HH_hadrons[iHad].e(); vel[1]=HH_hadrons[iHad].py()/HH_hadrons[iHad].e(); vel[2]=HH_hadrons[iHad].pz()/HH_hadrons[iHad].e();
824  double t_prop = had_prop/sqrt(1. - vel[0]*vel[0] - vel[1]*vel[1] - vel[2]*vel[2]);
825  HH_hadrons[iHad].x(HH_hadrons[iHad].x() + vel[0]*t_prop); HH_hadrons[iHad].y(HH_hadrons[iHad].y() + vel[1]*t_prop); HH_hadrons[iHad].z(HH_hadrons[iHad].z() + vel[2]*t_prop);
826  HH_hadrons[iHad].x_t(HH_hadrons[iHad].x_t() + had_prop);
827  //JSINFO<<"Hadron propagated to: " << HH_hadrons[iHad].x() << ", " << HH_hadrons[iHad].y() << ", " << HH_hadrons[iHad].z() << ", " << HH_hadrons[iHad].x_t();
828  }
829  }
830 
831  double energy_check = 0.;
832  for(int iHad = 0; iHad < HH_hadrons.num(); iHad++){
833  energy_check += HH_hadrons[iHad].e();
834  }
835  if(pos_ptn == 1 && (energy_check < 0.99*total_shower_energy)){
836  run_successfully = false;
837  }
838  }
839  ++attempt_num;
840  }
841 
842  if(!run_successfully){
843  HH_hadrons.clear();
844  if(pos_ptn == 1) {
845  JSWARN << "This event could not be hadronized.";
846  } else {
847  JSWARN << "The negative partons of this event could not be hadronized.";
848  }
849  }
850 
851  // scale the negative hadron energies/momenta such that the energy is
852  // conserved when subtracting negative hadrons from the positive ones
853  if(pos_ptn == 0){
854  if(HH_hadrons.num() > 0){
855  scale_kinematics_negative_hadrons(HH_hadrons, total_shower_energy-total_shower_energy_neg, energy_hadrons);
856  }
857  }
858 
859  for(unsigned int iHad=0; iHad<HH_hadrons.num(); ++iHad){
860  if(HH_hadrons[iHad].is_final()){
861  //setting status flag => xy -> x=1 reco, x=2 frag; y=1 sh-sh, y=2 sh-th; neg sign means negative hadron
862  //all colorless particles get fragmentation status labels
863  int stat = (HH_hadrons[iHad].is_recohad()) ? 810 : 820;
864  stat += (HH_hadrons[iHad].is_shth()) ? 2 : 1;
865  stat *= (pos_ptn == 0) ? -1 : 1 ;
866  int lab = (pos_ptn == 0) ? -1 : 1 ;
867  int idH = HH_hadrons[iHad].id(); double mH = HH_hadrons[iHad].mass();
868  FourVector p(HH_hadrons[iHad].P()); FourVector x(HH_hadrons[iHad].pos());
869  hOut.push_back(std::make_shared<Hadron> (Hadron (lab,idH,stat,p,x,mH)));
870 
871  if(pos_ptn == 1){ // used for scaling of negative hadrons
872  energy_hadrons += HH_hadrons[iHad].e();
873  }
874  }
875  }
876  th_recofactor = tmp_threco;
877  maxB_level = tmp_maxB_level;
878  reco_hadrons_pythia = tmp_reco_hadrons_pythia;
879  if(pythia_decays == "off"){pythia.readString("HadronLevel:Decay = off"); pythia.init();}
880  }
881 }
882 
883 // scale the negative hadron energies/momenta such that the energy is
884 // conserved when subtracting negative hadrons from the positive ones
885 void HybridHadronization::scale_kinematics_negative_hadrons(hadron_collection& HH_hadrons, double shower_energy, double positive_hadrons_energy){
886  double negative_hadrons_energy_initial = 0;
887  for(int i = 0; i < HH_hadrons.num(); i++){
888  negative_hadrons_energy_initial += HH_hadrons[i].e();
889  }
890 
891  double e_scaling_factor = (positive_hadrons_energy - shower_energy) / negative_hadrons_energy_initial;
892  if(e_scaling_factor < 0.){
893  JSDEBUG << "e_scaling_factor negative, hadron energy below parton energy: " << positive_hadrons_energy - shower_energy << "GeV";
894  return;
895  }
896 
897  for(int i = 0; i < HH_hadrons.num(); i++){
898  double new_energy = HH_hadrons[i].e() * e_scaling_factor;
899  if(new_energy > HH_hadrons[i].mass()){
900  HH_hadrons[i].e(new_energy);
901  double new_abs_momentum = std::sqrt(new_energy*new_energy - HH_hadrons[i].mass()*HH_hadrons[i].mass());
902  double p_scaling_factor = new_abs_momentum / std::sqrt(HH_hadrons[i].px()*HH_hadrons[i].px()+HH_hadrons[i].py()*HH_hadrons[i].py()+HH_hadrons[i].pz()*HH_hadrons[i].pz());
903  HH_hadrons[i].px(HH_hadrons[i].px() * p_scaling_factor);
904  HH_hadrons[i].py(HH_hadrons[i].py() * p_scaling_factor);
905  HH_hadrons[i].pz(HH_hadrons[i].pz() * p_scaling_factor);
906  }else{
907  HH_hadrons[i].e(HH_hadrons[i].mass());
908  HH_hadrons[i].px(0.0);
909  HH_hadrons[i].py(0.0);
910  HH_hadrons[i].pz(0.0);
911  }
912  }
913 }
914 
916  //check which partons have anti-/color tags larger than the int limit
917  std::vector<unsigned int> used_tags;
918  //reduce the upper limit -> the maxtag could fail otherwise, if it becomes larger than maximum int
919  int max_allowed_tag = std::numeric_limits<int>::max() - 1e6;
920  for(unsigned int ishower = 0; ishower < shower.size(); ishower++) {
921  for(unsigned int ipart = 0; ipart < shower.at(ishower).size(); ipart++) {
922  used_tags.push_back(shower.at(ishower).at(ipart)->color());
923  used_tags.push_back(shower.at(ishower).at(ipart)->anti_color());
924  }
925  }
926  //remove consecutive duplicates in the sorted vector
927  std::sort(used_tags.begin(), used_tags.end());
928  used_tags.resize(std::distance(used_tags.begin(), std::unique(used_tags.begin(), used_tags.end())));
929 
930  //count the number of needed tags
931  std::vector<unsigned int> needed_tags_values;
932  int number_needed_tags = 0;
933  for (unsigned int tag : used_tags) {
934  if (tag > max_allowed_tag) {
935  needed_tags_values.push_back(tag);
936  number_needed_tags++;
937  }
938  }
939 
940  //find the first free tag that is not yet used
941  int lower_limit_tag = 100;
942  std::vector<int> new_tags;
943  while (new_tags.size() < number_needed_tags) {
944  if (std::find(used_tags.begin(), used_tags.end(), lower_limit_tag) == used_tags.end()) {
945  new_tags.push_back(lower_limit_tag);
946  }
947  lower_limit_tag++;
948  }
949 
950  //exchange the tags which are too large by the new ones
951  for(int tag = 0; tag < number_needed_tags; tag++) {
952  for(unsigned int ishower = 0; ishower < shower.size(); ishower++) {
953  for(unsigned int ipart = 0; ipart < shower.at(ishower).size(); ipart++) {
954  unsigned int current_tag = needed_tags_values.at(tag);
955  if (shower.at(ishower).at(ipart)->color() == current_tag) {
956  shower.at(ishower).at(ipart)->set_color(new_tags.at(tag));
957  }
958  if (shower.at(ishower).at(ipart)->anti_color() == current_tag) {
959  shower.at(ishower).at(ipart)->set_anti_color(new_tags.at(tag));
960  }
961  }
962  }
963  }
964 }
965 
966 //was used in the pygen code to create ordered strings (and assigned string ids) from color tags
967 //currently has junction functionality commented out until I know how to incorporate it within JETSCAPE
968 //junction functionality WILL be needed in the event that any given string configurations contain them!
970 
971  int nstr=1;
972 
973  for(int i=0; i<HH_showerptns.num(); ++i){
974  if(HH_showerptns[i].string_id() != 0){continue;}
975 
976  std::vector<int> colors;
977  if(HH_showerptns[i].col() > 0){colors.push_back(HH_showerptns[i].col()) ;}
978  if(HH_showerptns[i].acol() > 0){colors.push_back(HH_showerptns[i].acol());}
979  HH_showerptns[i].string_id(nstr); ++nstr;
980  bool newcolor = true;
981  while(newcolor){
982  newcolor = false;
983  //checking all final particles not in a string for new color id matches...
984  int j=0; while(j<HH_showerptns.num()){
985  if(HH_showerptns[j].string_id() != 0){++j; continue;}
986  for(int k=0;k<colors.size();++k){
987  if( colors[k]==HH_showerptns[j].col() && (HH_showerptns[j].acol()>0)){
988  colors.push_back(HH_showerptns[j].acol()); newcolor=true; HH_showerptns[j].string_id(HH_showerptns[i].string_id()); j=-1; break;
989  }
990  else if(colors[k]==HH_showerptns[j].acol() && (HH_showerptns[j].col() >0)){
991  colors.push_back(HH_showerptns[j].col()) ; newcolor=true; HH_showerptns[j].string_id(HH_showerptns[i].string_id()); j=-1; break;
992  }
993  else if(colors[k]==HH_showerptns[j].col() || colors[k]==HH_showerptns[j].acol()){HH_showerptns[j].string_id(HH_showerptns[i].string_id()); break;}
994  }
995  ++j;
996  }
997  /* //this code WILL be needed in the event that any input string configurations contain junctions!
998  //checking all the junctions in the event to see if there are any new color id matches...
999  for(int iJun=0;iJun<pythia.event.sizeJunction();++iJun){
1000  bool thisjuncolors = false;
1001  for(int j=0;j<3;++j){for(int k=0;k<colors.size();++k){if(colors[k]==pythia.event.colJunction(iJun, j)){thisjuncolors=true;}}}
1002  if(!thisjuncolors){continue;}
1003  for(int j=0;j<3;++j){
1004  bool addcolor = true;
1005  for(int k=0;k<colors.size();++k){if(colors[k]==pythia.event.colJunction(iJun,j)){addcolor = false; break;}}
1006  if(addcolor){colors.push_back(pythia.event.colJunction(iJun,j)); newcolor=true;}
1007  }
1008  }
1009  */
1010  }
1011  }
1012 
1013  //now, finding all partons in string 'i'(out of nstr-1 total strings) and reordering them
1014  //for "string" i=0 final partons - these are noncolored particles that should just be written out as-is (shouldn't actually be present...)
1015  for(int i=1;i<nstr;++i){
1016 
1017  std::vector<bool> is_used; std::vector<int> ptns_new;
1018  std::vector<int> ptns_strnow;
1019  for(int j=0; j<HH_showerptns.num(); ++j){if(HH_showerptns[j].string_id()==i){ptns_strnow.push_back(j); is_used.push_back(false);}}
1020  //std::vector<int> usedJuns; for(int j=0; j<NumJunctions; ++j){usedJuns.push_back(false);} int numJunsused = 0;
1021 
1022  //find 'a' quark in the event, if there are none, just grab a gluon.
1023  std::vector<int> stack;
1024  bool readcolor=true; int firstcol = 0;
1025  for(int j=0;j<ptns_strnow.size();++j){
1026  if(!(HH_showerptns[ptns_strnow[j]].id() == 21)){
1027  if((HH_showerptns[ptns_strnow[j]].id() > 0 && HH_showerptns[ptns_strnow[j]].id() <= 6) || (HH_showerptns[ptns_strnow[j]].id() < -6)){
1028  stack.push_back(ptns_strnow[j]); is_used[j]=true; firstcol=HH_showerptns[stack[0]].acol(); break;
1029  }
1030  else{stack.push_back(ptns_strnow[j]); is_used[j]=true; firstcol=HH_showerptns[stack[0]].col(); readcolor=false; break;}
1031  }
1032  //gluon loop catch
1033  else if(j==ptns_strnow.size()-1){stack.push_back(ptns_strnow[0]); is_used[0]=true; firstcol=HH_showerptns[stack[0]].acol();}
1034  }
1035  ptns_new.push_back(stack[0]);
1036 
1037  while(stack.size()>0){
1038 
1039  //catching the end of either a string/junction leg or we've circled back on a gluon loop.
1040  if( readcolor && (HH_showerptns[stack.back()].col() == firstcol)){stack.pop_back(); continue;}
1041  else if(!readcolor && (HH_showerptns[stack.back()].acol() == firstcol)){stack.pop_back(); continue;}
1042 
1043  //keeping track if we've added (a) new parton(s) to the stack
1044  bool found=false;
1045 
1046  for(int j=0;j<ptns_strnow.size();++j){
1047  if( readcolor && !is_used[j] && (HH_showerptns[stack.back()].col() == HH_showerptns[ptns_strnow[j]].acol())){
1048  stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1049  found=true; break;
1050  }
1051  else if(!readcolor && !is_used[j] && (HH_showerptns[stack.back()].acol() == HH_showerptns[ptns_strnow[j]].col() )){
1052  stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1053  found=true; break;
1054  }
1055  }
1056 
1057  //this code WILL be needed in the event that any input string configurations contain junctions!
1058  /*if(!found && ((pythia.event.sizeJunction() - numJunsused) > 0)){
1059  int iJun(0), iCol(0);
1060  if(readcolor){
1061  for(int iJ=0;iJ<pythia.event.sizeJunction();++iJ){
1062  if(usedJuns[iJ]){continue;}
1063  for(int iC=0;iC<3;++iC){if(pythia.event.colJunction(iJ,iC)==HH_showerptns[stack.back()].col() ){iJun=iJ;iCol=iC;found=true;break;}}if(found){break;}
1064  }
1065  }
1066  else{
1067  for(int iJ=0;iJ<pythia.event.sizeJunction();++iJ){
1068  if(usedJuns[iJ]){continue;}
1069  for(int iC=0;iC<3;++iC){if(pythia.event.colJunction(iJ,iC)==HH_showerptns[stack.back()].acol()){iJun=iJ;iCol=iC;found=true;break;}}if(found){break;}
1070  }
1071  }
1072 
1073  //find the next two partons here to add to the stack
1074  if(found){
1075  usedJuns[iJun] = true; ++numJunsused;
1076  readcolor = !readcolor;
1077 
1078  int cols[2]={0,0};
1079  int offset=0; for(int j=0;j<3;++j){if(j==iCol){offset=1;continue;} cols[j-offset]=pythia.event.colJunction(iJun,j);}
1080  if(cols[0]>cols[1]){int temp=cols[0]; cols[0]=cols[1]; cols[1]=temp;}
1081 
1082  if(readcolor){
1083  for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[0]==HH_showerptns[ptns_strnow[j]].acol())){
1084  stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1085  break;
1086  }}
1087  for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[1]==HH_showerptns[ptns_strnow[j]].acol())){
1088  stack.push_back(ptns_strnow[j]); is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1089  break;
1090  }}
1091  }
1092  else{
1093  for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[0]==HH_showerptns[ptns_strnow[j]].col())){
1094  stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1095  break;
1096  }}
1097  for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[1]==HH_showerptns[ptns_strnow[j]].col())){
1098  stack.push_back(ptns_strnow[j]); is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1099  break;
1100  }}
1101  }
1102  }
1103  }*/
1104  if(!found){stack.pop_back();}
1105  }
1106 
1107  //ordering this string
1108  int endpt = 0;
1109  for(int j=0;j<ptns_new.size();++j){
1110  HH_showerptns[ptns_new[j]].pos_str(j);
1111  HH_showerptns[ptns_new[j]].endpt_id( (HH_showerptns[ptns_new[j]].id() == 21) ? 0 : ++endpt );
1112  HH_showerptns[ptns_new[j]].is_strendpt( (HH_showerptns[ptns_new[j]].id() == 21) ? false : true );
1113  }
1114  }
1115 
1116  //handling any remaining colored objects that have not had color tags set
1117  //these are all just thrown into a single string, which may be 'cut' up later on in the string_prep function
1118  //these will not be 'ordered' within the string nicely...
1119  int numendpoint = 0; int num_str0 = -1;
1120  for(int i=0;i<HH_showerptns.num();++i){
1121  if(HH_showerptns[i].string_id() != 0){continue;}
1122  int iendpoint = 0;
1123  bool is_endpoint = false;
1124  if(HH_showerptns[i].id() != 21){iendpoint = ++numendpoint; is_endpoint = true;}
1125  HH_showerptns[i].string_id(0);
1126  HH_showerptns[i].pos_str(++num_str0);
1127  HH_showerptns[i].endpt_id(iendpoint);
1128  HH_showerptns[i].is_strendpt(is_endpoint);
1129  }
1130 
1131  //reordering HH_showerptns - based on string, and position in the string
1132  //isn't strictly necessary to do this here, as the critical pos_str and endpt_id variables have been set, but is 'nice'
1133  //std::stable_sort(&HH_showerptns[0], (&HH_showerptns[HH_showerptns.num()-1])+1, strid_compare);
1134  std::stable_sort(&HH_showerptns[0], (&HH_showerptns[HH_showerptns.num()-1])+1, [](const HHparton& parton1, const HHparton& parton2){return (parton1.string_id() < parton2.string_id());});
1135  //now that the list is sorted based on string id, going to sort the partons in each string based on the position of the partons in the string
1136  for(int i=0; i<HH_showerptns.num(); ++i){
1137  int start, prev_pos, cur_pos, lastfix;
1138  lastfix = 0; if(i == HH_showerptns.num()-1){lastfix = 1;}
1139  cur_pos = HH_showerptns[i].string_id();
1140  if(i==0){prev_pos = HH_showerptns[0].string_id(); start = 0;}
1141  if(cur_pos != prev_pos || i == HH_showerptns.num()-1){
1142  std::stable_sort(&HH_showerptns[start],&HH_showerptns[i]+lastfix, [](const HHparton& parton1, const HHparton& parton2){return (parton1.pos_str() < parton2.pos_str());});
1143  start = i; prev_pos = HH_showerptns[i].pos_str();
1144  }
1145  }
1146 }
1147 
1149 
1150  //parton list for treating thermal siblings for string repair
1151  parton_collection Extraparton;
1152 
1153  //declaring a few needed values (based on values in init)
1154  double hbarc2 = hbarc*hbarc;
1155 
1156  //should create a new parton collection here, one with only shower quarks (inc. from gluon splitting)
1157  //to consider for recombination - then afterwards can reform gluons and output remnants
1158  parton_collection showerquarks;
1159 
1160  //clearing remnants, in case it hasn't been done before
1161  HH_remnants.clear();
1162 
1163  //constructing a list of all the strings in the event
1164  std::vector<int> list_strs;
1165  //adding the first string to the list
1166  list_strs.push_back(HH_showerptns[0].string_id());
1167  //looping over all the partons in the event, and writing each 'unique' string to the list
1168  for(int i=0;i<HH_showerptns.num();++i){
1169  bool str_match = false;
1170  for(int j=0;j<list_strs.size();++j){
1171  if(HH_showerptns[i].string_id() == list_strs[j]){str_match = true;}
1172  }
1173  if(!str_match){list_strs.push_back(HH_showerptns[i].string_id());}
1174  }
1175 
1176  //*********************************************************************************************************************
1177  // Splitting gluons into q-qbar pairs for recombination
1178  //*********************************************************************************************************************
1179 
1180  //std::cout <<"Below is Color information of all particles in the String (Col, Acol)"<<endl;
1181  std::vector<int*> ColInfo3;
1182  for(int i=0; i<HH_showerptns.num(); i++) {
1183  int colinfo3[2] = {HH_showerptns[i].col() , HH_showerptns[i].acol()};
1184  ColInfo3.push_back(colinfo3);
1185  //std::cout <<" ( "<<HH_showerptns[i].string_id()<<" , "<<ColInfo3.at(i)[0]<<" "<<ColInfo3.at(i)[1]<<" ) ";
1186  }
1187  //std::cout <<endl;
1188 
1189  //while running PythiaBrickTest, error{same col tags and acol tag for the different particles, somehow the cause would be in MATTER in determining the color tag} detected,
1190  //So, If there are problems from the initial structure, correct it based on the color flow.
1191  int temptag = 1;
1192  for(int i = 0; i < HH_showerptns.num(); i++){
1193  for(int j = i+1; j < HH_showerptns.num(); j++){
1194  if(HH_showerptns[i].col() != 0 && HH_showerptns[i].col() == HH_showerptns[j].col()){ //same col tag for different particles detected.
1195  for(int k = 0; k < HH_showerptns.num(); k++){
1196  if(HH_showerptns[i].col() == HH_showerptns[k].acol()){
1197  vector<int> Info;// location of i, location of k, temp color tag will be saved in this vector.
1198  Info.push_back(i);
1199  Info.push_back(k);
1200  Info.push_back(temptag);
1201 
1202  HH_showerptns[i].col(temptag);
1203  HH_showerptns[k].acol(temptag); //apply the change for the col, acol pair to preserve the color flow with least impact to the final result.
1204  temptag++;
1205  Info.clear();
1206  }
1207  }
1208  }
1209  }
1210  }
1211 
1212  for(int i = 0; i < HH_showerptns.num(); i++){
1213  for(int j = i+1; j < HH_showerptns.num(); j++){
1214  if(HH_showerptns[i].acol() != 0 && HH_showerptns[i].acol() == HH_showerptns[j].acol()){ //same acol tag for different particles detected.
1215  for(int k = 0; k < HH_showerptns.num(); k++){
1216  if(HH_showerptns[i].acol() == HH_showerptns[k].col()){
1217  vector<int> Info;// location of i, location of k, temp color tag will be saved in this vector.
1218  Info.push_back(i);
1219  Info.push_back(k);
1220  Info.push_back(temptag);
1221 
1222  HH_showerptns[i].acol(temptag);
1223  HH_showerptns[k].col(temptag); //apply the change for the col, acol pair to preserve the color flow with least impact to the final result.
1224  temptag++;
1225  Info.clear();
1226  }
1227  }
1228  }
1229  }
1230  }
1231 
1232  //std::cout <<endl;
1233  //std::cout <<"Below is Color information of all particles in the Revised String (Col, Acol)"<<endl;
1234  std::vector<int*> ColInfo2;
1235  for(int i=0; i<HH_showerptns.num(); i++) {
1236  int colinfo2[2] = {HH_showerptns[i].col() , HH_showerptns[i].acol()};
1237  ColInfo2.push_back(colinfo2);
1238  //std::cout <<" ( "<<HH_showerptns[i].string_id()<<" , "<<ColInfo2.at(i)[0]<<" "<<ColInfo2.at(i)[1]<<" ) ";
1239  }
1240  //std::cout <<endl;
1241 
1242  set_initial_parton_masses(HH_showerptns);
1243 
1244  //starting with shower partons
1245  for(int i_pt=0; i_pt<HH_showerptns.num(); ++i_pt){
1246  //if parton is a quark, stick it into showerquarks - and set it's parent id to the quark in the original shower
1247  if((std::abs(HH_showerptns[i_pt].id()) <= 5 ) && (HH_showerptns[i_pt].PY_origid() == 0)){
1248  showerquarks.add(HH_showerptns.partons[i_pt]);
1249  showerquarks[showerquarks.num()-1].par(i_pt);
1250  }
1251  //else parton is a gluon, decay into q-qbar and stick those into the collection; set parent id appropriately for both
1252  else if((HH_showerptns[i_pt].id() == 21) && (HH_showerptns[i_pt].PY_origid() == 0)){
1253  //setting is_decayedglu; not going to set used until one of it's quarks has been used
1254  //will set the status to -99 here, this will be changed to -1 after first quark, and to 1 after second
1255  HH_showerptns[i_pt].is_decayedglu(true); HH_showerptns[i_pt].status(-99);
1256 
1257  //choosing a gluon mass - if implemented in the future, can (should) read this from the gluon entry itself (or set if necessary)
1258  //maybe discard gluon if it is under some threshold of mass (eg < pion?)
1259  //temporarily saving previously set mass here - here's a good place to check if this is even necessary?
1260  double temp_glumass = HH_showerptns[i_pt].mass();
1261  if(HH_showerptns[i_pt].mass()<2.*xmq+0.001){HH_showerptns[i_pt].mass(2.*xmq+0.001);}
1262 
1263  //gluon decay function reads in the gluon (and the overwritten random mass), and writes the output q-qbar pair to qpair
1264  parton_collection qpair;
1265  gluon_decay(HH_showerptns[i_pt], qpair);
1266 
1267  //swapping back original gluon mass
1268  HH_showerptns[i_pt].mass(temp_glumass);
1269 
1270  //setting the parents of the q-qbar pair to the original gluon (and other vars appropriately here)
1271  qpair[0].par(i_pt); qpair[1].par(i_pt);
1272  qpair[0].is_shower(true); qpair[1].is_shower(true);
1273  qpair[0].orig( HH_showerptns[i_pt].orig() ); qpair[1].orig( HH_showerptns[i_pt].orig() );
1274  qpair[0].string_id ( HH_showerptns[i_pt].string_id()); qpair[1].string_id ( HH_showerptns[i_pt].string_id());
1275  qpair[0].pos_str ( HH_showerptns[i_pt].pos_str()); qpair[1].pos_str ( HH_showerptns[i_pt].pos_str());
1276 
1277  //adding these partons to the collection
1278  showerquarks.add(qpair);
1279 
1280  //setting up the sibling relations in showerquarks
1281  showerquarks[showerquarks.num()-1].sibling( showerquarks.num()-2 );
1282  showerquarks[showerquarks.num()-2].sibling( showerquarks.num()-1 );
1283  }
1284  //else it's not a quark(u,d,s,c,b) or gluon and we're skipping it.
1285  else{
1286  //JSINFO << "\n\nThere is a parton that is not a quark(u,d,s,c,b) or gluon in the input shower. Skipping parton in recombination.\n\n";
1287  }
1288  }
1289  //*********************************************************************************************************************
1290  // Finished splitting gluons
1291  //*********************************************************************************************************************
1292 
1293  //*********************************************************************************************************************
1294  // Beginning of Recombination routine
1295  //*********************************************************************************************************************
1296 
1297  //randomly permute an integer array with 'n' entries from 1 to n (actually from 0 to n-1)
1298  //the array will be used to access the i'th element of the showerquarks collection
1299  //done as showerquarks[perm0_sharray[i]]
1300  //since we have separate shower and thermal arrays, we will force the first quark to always be from the shower
1301  //
1302  //construct perm1 array of size showerquarks.num() and perm2 array of size showerquarks.num() + HH_thermal.num()
1303  //to access an element from either shower or thermal partons
1304  //there will be showerquarks.num() positive entries and HH_thermal.num() negative entries (going to exclude 0 in these, just -1 i's)
1305  //thus, perm2 = { 3, -42, -33,...} will access i=2 from showerquarks, then 41 from thermal, then 32 from thermal...
1306  //
1307  //lastly, need to bypass scenarios where the quark has been used, or we're trying to use the same quark twice
1308  //to determine if we're trying to use the same quark twice, check if perm[i]=perm[j]
1309  //if used=true OR p[i]=p[j]?, then skip this attempt (continue works well for these cases?)
1310 
1311  //constructing permutation arrays; shower quarks are > 0, thermal are < 0
1312  //perm2 will always access element [std::abs(perm2[i]) - 1]
1313  int perm1[showerquarks.num()], perm2[showerquarks.num()+HH_thermal.num()];
1314 
1315  //option to either bias recombination, earlier particles attempt to recombine first
1316  if(torder_reco){
1317  //placeholders to sort by time
1318  std::vector<std::pair<double,int>> tosort1, tosort2;
1319  for (int i=0;i<showerquarks.num();++i){
1320  tosort1.push_back(std::make_pair(showerquarks[i].x_t(),i));
1321  tosort2.push_back(std::make_pair(showerquarks[i].x_t(),i+1));
1322  }
1323  for (int i=0;i<HH_thermal.num();++i){
1324  tosort2.push_back({HH_thermal[i].x_t(),-i-1});
1325  }
1326 
1327  //sorting
1328  std::stable_sort(std::begin(tosort1), std::end(tosort1));
1329  std::stable_sort(std::begin(tosort2), std::end(tosort2));
1330 
1331  //saving order into permutation arrays
1332  for(int i=0;i<tosort1.size();++i){
1333  perm1[i]=tosort1[i].second;
1334  }
1335  for(int i=0;i<tosort2.size();++i){
1336  perm2[i]=tosort2[i].second;
1337  }
1338  }else{
1339  //prepping permutation arrays to be shuffled
1340  for(int i=0;i<showerquarks.num();++i){
1341  perm1[i]=i;
1342  }
1343  for(int i=0;i<HH_thermal.num();++i){
1344  perm2[i]=(i-HH_thermal.num());
1345  }
1346  for(int i=HH_thermal.num();i<showerquarks.num()+HH_thermal.num();++i){
1347  perm2[i]=(i-HH_thermal.num()+1);
1348  }
1349 
1350  //permuting these arrays using Fisher-Yates algorithm
1351  //-- To shuffle an array a of n elements (indices 0..n-1):
1352  //for i from 0 to n−2 do
1353  // j ← random integer such that i ≤ j < n
1354  // exchange a[i] and a[j]
1355  for(int i=0;i<showerquarks.num()-1;++i){
1356  int ranelement = i+floor((showerquarks.num()-i)*ran());
1357  int temp = perm1[i];
1358  perm1[i] = perm1[ranelement];
1359  perm1[ranelement] = temp;
1360  }
1361  for(int i=0;i<showerquarks.num()+HH_thermal.num()-1;++i){
1362  int ranelement = i+floor((showerquarks.num()+HH_thermal.num()-i)*ran());
1363  int temp = perm2[i];
1364  perm2[i] = perm2[ranelement];
1365  perm2[ranelement] = temp;
1366  }
1367  }
1368 
1369  //std::cout <<"Below is Color information of all particles in the String (Col, Acol)"<<endl;
1370  std::vector<int*> ColInfo;
1371  for(int i=0; i<HH_showerptns.num(); i++) {
1372  int colinfo[2] = {HH_showerptns[i].col() , HH_showerptns[i].acol()};
1373  ColInfo.push_back(colinfo);
1374  //std::cout <<" ( "<<HH_showerptns[i].string_id()<<" , "<<ColInfo.at(i)[0]<<" "<<ColInfo.at(i)[1]<<" ) ";
1375  }
1376  //std::cout <<endl;
1377 
1378  // make all color tags to be indices for the matrix (so the indice represent the color tag, don't need to classify anti or not)
1379  std::vector<vector<int>> IndiceForCol1; // this vector will form vector of vectors(location in the string, anti or not, color tag)
1380  std::vector<int> IndiceForCol2; // this vector is one component of vector above
1381  std::vector<int> IndiceForColFin; // this vector is final vector that'll be used for process
1382 
1383  for(int iIndice=0; iIndice < HH_showerptns.num(); iIndice++) {
1384  IndiceForCol2.push_back(iIndice);
1385  IndiceForCol2.push_back(1);
1386  IndiceForCol2.push_back(HH_showerptns[iIndice].col());
1387  IndiceForCol1.push_back(IndiceForCol2);
1388  IndiceForCol2.clear();
1389 
1390  IndiceForCol2.push_back(iIndice);
1391  IndiceForCol2.push_back(-1);
1392  IndiceForCol2.push_back(HH_showerptns[iIndice].acol());
1393  IndiceForCol1.push_back(IndiceForCol2);
1394  IndiceForCol2.clear();
1395  } // As a result, two vectors with 3 component keep being added to bigger vector, now exclude same tag and zero
1396  //dignostic measure
1397  //std::cout <<endl<<" Below is list of all color tags " <<endl;
1398  //std::cout <<" ( ";
1399  //for (int icheck=0; icheck < IndiceForCol1.size(); icheck++) {
1400  //std::cout << IndiceForCol1.at(icheck).at(2) << " , ";
1401  //}
1402  //std::cout <<" ) " <<endl;
1403 
1404  vector<int> tempcol;
1405  // now put all the values in ColInfo into IndiceForColFin
1406  for(int icol = 0; icol < IndiceForCol1.size(); icol++){
1407  tempcol.push_back(IndiceForCol1.at(icol).at(2));
1408  }
1409  if(tempcol.at(0) != 0){
1410  IndiceForColFin.push_back(tempcol.at(0));
1411  }
1412  if(tempcol.at(1) != 0){
1413  IndiceForColFin.push_back(tempcol.at(1));
1414  }
1415 
1416  for(int iclear1 = 0; iclear1 < tempcol.size(); iclear1++){
1417  bool foundsame = false;
1418  for(int iclear2 = 0; iclear2 < IndiceForColFin.size(); iclear2++){
1419  if(tempcol.at(iclear1) == IndiceForColFin.at(iclear2) || tempcol.at(iclear1) == 0){
1420  foundsame = true;
1421  }
1422  }
1423  if(!foundsame){
1424  IndiceForColFin.push_back(tempcol.at(iclear1));
1425  }
1426  foundsame = false;
1427  }
1428 
1429  //last checking whether there is zero in the color tag list
1430  for(int i = 0; i < IndiceForColFin.size(); i++){
1431  if(IndiceForColFin[i] == 0){
1432  std::vector<int>::iterator i1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), 0 );
1433  int distance = std::distance(IndiceForColFin.begin() , i1);
1434  //std::cout <<endl<<" zero is located at "<<distance<<endl;
1435  IndiceForColFin.erase(i1);
1436  }
1437  }
1438 
1439  //dignostic syntax
1440  /*std::cout <<endl<<" Below is list of valid color tags " <<endl;
1441  std::cout <<" ( ";
1442  for (int icheck=0; icheck < IndiceForColFin.size(); icheck++) {
1443  std::cout << IndiceForColFin.at(icheck) << " , ";
1444  }
1445  std::cout <<" ) " <<endl;*/
1446 
1447  //when we includes the partons from LBT, color tags from them are both zero in col and acol tags,
1448  //Therefore, based on the maximum color tag from the parton with col , acol tags, reassign the color tags for LBT partons. As a result, one fake string should be formed based on these color Tags
1449  //First, check the maximum color tags in the vector of valid color tags
1450  int limit;
1451  int maxtag;
1452  maxtag = *max_element(IndiceForColFin.begin() , IndiceForColFin.end()); //this will be so important in dealing thermal partons, beacause they get color tag incremented from this max tag
1453  limit = maxtag; // save initial maxtag for the future usage{It should be used for color reconnection matrix}
1454  //std::cout <<endl<<" max tag is "<<maxtag<<endl;
1455 
1456  // before determine the matrix, need to link color tag with the matrix indices( by color tag and trace back to the particle, then determine the probability) It's done above(IndiceForCol1)
1457  // to define the probability, parameters for distance should exist. possibly, that could be the par() or string number the last
1458  std::vector<vector<double>> MesonrecoMatrix1; // vector of double (prob) , ,,,// in a big scheme, these two vector form a Matrix
1459  std::vector<double> MesonrecoMatrix2; // this is 1d vector of (probabilty)
1460 
1461  //first, Form Meson recombination Matrix
1462  for(int irow=0; irow < IndiceForColFin.size(); irow++){
1463  for(int icol=0; icol < IndiceForColFin.size(); icol++){
1464  double Mesonfactor;
1465  int distance; // distance between the color tags in string(not c++ function)
1466  int tag1 = IndiceForColFin.at(irow);
1467  int tag2 = IndiceForColFin.at(icol);
1468  std::vector<int>::iterator it1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
1469  std::vector<int>::iterator it2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag2);// set up for finding the location of co tag in vector that will be used to find distance
1470  int pos1 = std::distance(IndiceForColFin.begin(), it1); //location of col tag of irow
1471  int pos2 = std::distance(IndiceForColFin.begin(), it2); //location of col tag of icol
1472  //std::cout <<endl<<"position of "<<IndiceForColFin.at(irow)<<" is " << pos1 <<endl;
1473  //std::cout <<endl<<"position of "<<IndiceForColFin.at(icol)<<" is " << pos2 <<endl;
1474 
1475  distance = abs(pos1 - pos2);
1476  //std::cout <<endl<<" At ( "<<irow<<","<<icol<<" ) , distance is "<<distance<<endl;
1477  if(distance == 0) {
1478  Mesonfactor = 1;
1479  //std::cout <<endl<<"Temp Meson Factor is "<<Mesonfactor<<endl;
1480  MesonrecoMatrix2.push_back(Mesonfactor);
1481  };
1482  if(distance > 0) {
1483  Mesonfactor = 0.111;
1484  //std::cout <<endl<<"Temp Meson Factor is "<<Mesonfactor<<endl;
1485  MesonrecoMatrix2.push_back(Mesonfactor);
1486  };
1487  }
1488  MesonrecoMatrix1.push_back(MesonrecoMatrix2);
1489  MesonrecoMatrix2.clear();
1490  }
1491 
1492  // now correct the component in MesonMatrix1 by searching through HH_showerptns{checking gluon}
1493  for(int icheck1 = 0; icheck1 < HH_showerptns.num(); icheck1++ ){
1494  if(HH_showerptns[icheck1].col() != 0 && HH_showerptns[icheck1].acol() != 0 ){//finding gluon means that finding partons that can't form color singlet, but octet
1495  int tag1 = HH_showerptns[icheck1].col();
1496  int tag2 = HH_showerptns[icheck1].acol();
1497  std::vector<int>::iterator it1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
1498  std::vector<int>::iterator it2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag2);// set up for finding the location of co tag in vector that will be used to find distance
1499  int pos1 = std::distance(IndiceForColFin.begin(), it1); //location of col tag of irow
1500  int pos2 = std::distance(IndiceForColFin.begin(), it2); //location of col tag of icol
1501  MesonrecoMatrix1.at(pos1).at(pos2) = 0;
1502  MesonrecoMatrix1.at(pos2).at(pos1) = 0;
1503  }
1504  }
1505  /*
1506  //dignostic measure
1507  std::cout <<endl<<"Meson reco Matrix is same as below"<<endl;
1508  for(int irow=0; irow < IndiceForColFin.size(); irow++){
1509  for(int icol=0; icol < IndiceForColFin.size(); icol++){
1510  std::cout <<" "<<MesonrecoMatrix1.at(irow).at(icol)<<" ";
1511  }
1512  std::cout <<endl<<endl;
1513  }
1514  */
1515  //MesonrecoMatrix is Formed so far, Now make that of Baryon!!
1516 
1517  std::vector<vector<vector<double>>> BaryonrecoMatrix1; // vector of double (prob) , ,,,// in a big scheme, these three items form a Matrix of vector
1518  std::vector<vector<double>> BaryonrecoMatrix2; // this is vector of 2d vector below (probabilty, required color charge for color neutrality), ( , ) , ( , ) ...
1519  std::vector<double> BaryonrecoMatrix3; // this is 2d vector of (probabilty, required color charge for color neutrality)
1520 
1521  for(int irow=0; irow < IndiceForColFin.size(); irow++){
1522  for(int icol=0; icol < IndiceForColFin.size(); icol++){
1523  double Baryonfactor;
1524  BaryonrecoMatrix3.push_back(1./27.);//1/27: probability to get singlet state
1525  BaryonrecoMatrix3.push_back(0.); // now the probability factor and color(not specified yet, it'll be done with baryon formation) for neutrality are saved.
1526 
1527  BaryonrecoMatrix2.push_back(BaryonrecoMatrix3);
1528  BaryonrecoMatrix3.clear();
1529  }
1530  BaryonrecoMatrix1.push_back(BaryonrecoMatrix2);
1531  BaryonrecoMatrix2.clear();
1532  }
1533  /*
1534  //dignostic measure
1535  std::cout <<endl<<"Baryon reco Matrix is same as below"<<endl;
1536  for(int irow=0; irow < IndiceForColFin.size(); irow++){
1537  for(int icol=0; icol < IndiceForColFin.size(); icol++){
1538  std::cout <<" ( "<<BaryonrecoMatrix1.at(irow).at(icol).at(1)<<" ) ";
1539  }
1540  std::cout <<endl<<endl;
1541  }
1542  //std::cout <<endl<<endl;
1543  */
1544 
1545  //looping over all the quarks that we have...
1546  //'q1' loops over all quarks in the shower
1547  //'q2' loops over all quarks in the event
1548  //'q3' loops over all quarks in the event, starting from 'q2' and ending at the last quark
1549  //when 'q2' is at the last quark, we will not consider quark 'q3' - can only make a meson at that point...
1550 
1551  parton_collection considering;
1552  int element[3];
1553 
1554  for(int q1=0;q1<showerquarks.num();++q1){
1555  //accessing first considered quark
1556  //set q1 variables here
1557 
1558  if(sh_recofactor < 0.0000000001){continue;} //turning off recombination in a computationally friendly way...
1559 
1560  //resetting madehadron flag, now that we're going to be considering a new hadron
1561  bool madehadron = false;
1562 
1563  //taking the id from the permutation array, and turning it into quark array element
1564  element[0] = perm1[q1];
1565 
1566  //skipping if current quark has been used or isn't a u,d,s,c,b quark or antiquark
1567  if(showerquarks[element[0]].status() != 0 || showerquarks[element[0]].is_used()){continue;}
1568  else if(std::abs(showerquarks[element[0]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1569 
1570  //assigning quark values to considering - and setting the status to -991
1571  //if at the end of the check, we make a hadron, we will set all -99* entries to 1, else we'll set back to 0
1572 
1573  considering.add(showerquarks[element[0]]);
1574  showerquarks[element[0]].status(-991);
1575 
1576  for(int q2=0;q2<showerquarks.num()+HH_thermal.num();++q2){
1577  //set q2 variables here - if we can form a meson, then skip q3 loop
1578  //also skip q3 loop if q2 is at last quark
1579 
1580  double recofactor2 = 1./9.;
1581 
1582  //accessing the second considered quark
1583  //this will skip over non-quark entries in HH_thermal
1584  if(perm2[q2]>0){/*is shower quark*/ element[1] = perm2[q2] - 1;}
1585  else{/*is thermal quark*/ element[1] = perm2[q2] + 1;}
1586 
1587  //checking to see if quark is in shower or thermal
1588  //only need to check if quark is the same as the previous quark IFF it is in the shower
1589  //only need to check if quark is from the same gluon if it is from a gluon decay in the shower...
1590  //want to check if we've messed up and are accessing a gluon if it is in original shower/thermal
1591  //need to check if used for all cases...
1592  if(perm2[q2]>0){
1593  //skipping if current quark has been used
1594  if(showerquarks[element[1]].status() != 0 || showerquarks[element[1]].is_used()){continue;}
1595  //skipping if current quark is the same as q1
1596  else if(element[0]==element[1]){continue;}
1597  //skipping if the current quark is from the same gluon as q1
1598  else if((showerquarks[element[0]].par() != -1) && (showerquarks[element[0]].par() == showerquarks[element[1]].par())){continue;}
1599  //skipping if the current quark is not in the same string as q1 (both are shower partons)
1600  //else if(showerquarks[element[1]].string_id() != showerquarks[element[0]].string_id()){continue;}
1601  //skipping if current quark is not a u,d,s,c,b quark
1602  else if(std::abs(showerquarks[element[1]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1603 
1604  considering.add(showerquarks[element[1]]);
1605  showerquarks[element[1]].status(-992);
1606  }
1607  else if(perm2[q2]<0){
1608  //skipping if current quark has been used
1609  if(HH_thermal[-element[1]].status() != 0 || HH_thermal[-element[1]].is_used()){continue;}
1610  //skipping if current quark is not a u,d,s,c,b quark
1611  else if(std::abs(HH_thermal[-element[1]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1612  //turning off recombination for thermal partons in a computationally friendly way...
1613  else if(th_recofactor < 0.001){continue;}
1614 
1615  //checking distance cut ONLY if this is a thermal parton - skip if dist2 > dist2cut
1616  FourVector pos_ptn1 = considering[0].pos(); FourVector pos_ptn2 = HH_thermal[-element[1]].pos();
1617  double dt = pos_ptn1.t() - pos_ptn2.t();
1618  if(dt > 0.){
1619  double dt_E = dt/HH_thermal[-element[1]].e(); // P/E * dT = dist = P*(dT/E)
1620  pos_ptn2.Set(pos_ptn2.x()+HH_thermal[-element[1]].px()*dt_E,pos_ptn2.y()+HH_thermal[-element[1]].py()*dt_E,pos_ptn2.z()+HH_thermal[-element[1]].pz()*dt_E,0.);
1621  }
1622  else{
1623  double dt_E = -dt/considering[0].e();
1624  pos_ptn1.Set(pos_ptn1.x()+considering[0].px()*dt_E,pos_ptn1.y()+considering[0].py()*dt_E,pos_ptn1.z()+considering[0].pz()*dt_E, 0.);
1625  }
1626  if(dif2(pos_ptn1,pos_ptn2) > dist2cut){continue;}
1627 
1628  considering.add(HH_thermal[-element[1]]);
1629  HH_thermal[-element[1]].status(-992);
1630  }
1631  else{JSWARN << "SOMETHING WENT HORRIBLY WRONG - DO NOT KNOW WHERE CURRENT QUARK CAME FROM?!";}
1632 
1633  //now that we have two 'acceptable' quarks to check hadron formation against,
1634  //there is no reason to bother checking if we can make a baryon if we have a q-qbar at this point...
1635  //will skip third loop in this case - otherwise we will check if we can make a baryon...
1636  if((considering[0].id()*considering[1].id() > 0) && (q2 < showerquarks.num()+HH_thermal.num()-1) && (maxB_level > -1)){
1637  for(int q3=q2+1;q3<showerquarks.num()+HH_thermal.num();++q3){
1638 
1639  double recofactor3 = 2./27.;
1640 
1641  //removing all but the first two entries in the considering collection...
1642  //this should have been done before, but have this here just in case - remove if this doesn't ever trigger
1643  while(considering.num() > 2){considering.partons.pop_back();}
1644 
1645  //accessing the third considered quark
1646  //this will skip over non-quark entries in HH_thermal
1647  if(perm2[q3]>0){/*is shower quark*/ element[2] = perm2[q3] - 1;}
1648  else{/*is thermal quark*/ element[2] = perm2[q3] + 1;}
1649 
1650  //now that we have q3, we need to check if it is valid:
1651  //q3 needs to be checked if used (all cases)
1652  //q3 needs to be checked if it is a erroneously accessed parton (not u,d,s,c,b quark)
1653  //q3 needs to be checked against q1 to see if it is the same, or from the same gluon
1654  //q3 does not need to be checked against q2 to see if it is the same
1655  //q3 does need to be checked to see if it is from the same gluon as q2
1656  //q3 needs to be checked to make sure that it can form a baryon with q1 and q2 (checking against either is ok)
1657  //check: used, sameq1, sameg_q1, sameg_q2, isglu
1658  if(perm2[q3]>0){
1659  //skipping if the current quark cannot make a baryon with other two quarks
1660  if(showerquarks[element[2]].id()*considering[0].id() < 0){continue;}
1661  //skipping if current quark has been used
1662  if(showerquarks[element[2]].status() != 0 || showerquarks[element[2]].is_used()){continue;}
1663  //skipping if current quark is the same as q1
1664  else if(element[0]==element[2] || element[1] == element[2]){continue;}
1665  //skipping if the current quark is from the same gluon as q1
1666  else if((showerquarks[element[0]].par() != -1) && (showerquarks[element[0]].par() == showerquarks[element[2]].par())){continue;}
1667  //skipping if the current quark is from the same gluon as q2
1668  else if((perm2[q2] > 0) && (showerquarks[element[1]].par() != -1) && (showerquarks[element[1]].par() == showerquarks[element[2]].par())){continue;}
1669  //skipping if the current quark is not in the same string as q1
1670  //(q2 MUST be in the same string as q1 if it's in the shower, and doesn't need to be checked if thermal)
1671  //else if(showerquarks[element[2]].string_id() != showerquarks[element[0]].string_id()){continue;}
1672  //skipping if current quark is not a u,d,s,c,b quark
1673  else if(std::abs(showerquarks[element[2]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1674 
1675  considering.add(showerquarks[element[2]]);
1676  showerquarks[element[2]].status(-993);
1677 
1678  //TODO: Here we need to establish the probability about baryon formation. first, need to find 3sets of col tag pair are included junction info at the same time. if all 3 does, prob is 1/27, if 1 does, find other component's tag with element[2](3rd one)'s in Meson Matrix!
1679  //second, scan all junction lists
1680  //before that, we need to evaluate temporary junction, because some junctions could be eliminated, So need to make tempjunction list. then we need to proocedure to erase the factor in the vectors!
1681  //Now evaluating the Tempjunctions element first, before this, declare bool variables for the next proocedure
1682  bool element1 = false;
1683  bool element2 = false;
1684  bool element3 = false;
1685  int juncnum1 = 999999999;
1686  int juncnum2 = 999999999;
1687  int juncnum3 = 999999999;
1688 
1689  int standard = IndiceForColFin.size(); // to apply the "if" statement, set the condition for later syntax
1690  int tagformatrix = 999999999; // if all three tags are in same junction, we need to set large number not to confuse, this will be filtered by later syntax
1691  int loc1 = standard; //location in the MesonrecoMatrix
1692  std::vector<int>::iterator I1;
1693  std::vector<int>::iterator I2;
1694  int loc2 = standard;
1695 
1696  if(considering[0].id()*considering[1].id()*considering[2].id() > 0){
1697  // baryon case, and this will check whether two particles are in same junction and the other is not.
1698  // and evaluate(by mesonrecomatrix) the other particle's color tag with the the color tag of 3rd particle collected to be baryon.
1699  for(int ijunc=0; ijunc < Tempjunctions.size(); ijunc++){
1700  if((considering[0].col() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1701  (considering[0].col() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1702  (considering[0].col() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1703  element1 = true;
1704  juncnum1 = ijunc;
1705  }
1706  if((considering[1].col() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1707  (considering[1].col() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1708  (considering[1].col() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1709  element2 = true;
1710  juncnum2 = ijunc;
1711  }
1712  if((considering[2].col() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1713  (considering[2].col() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1714  (considering[2].col() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1715  element3 = true;
1716  juncnum3 = ijunc;
1717  }
1718  }
1719  if((juncnum1 == juncnum2) && (juncnum1 != juncnum3) && juncnum1 != 999999999 && considering[2].col() != 0){
1720  tagformatrix = Tempjunctions.at(juncnum1).at(3).at(1);
1721  I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[2].col());
1722  loc2 = std::distance(IndiceForColFin.begin(), I2);
1723  //std::cout <<endl<<"chosen color tag1 is "<<HH_showerptns[showerquarks[element[2]].par()].col();
1724  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc2<<endl;
1725  };
1726  if((juncnum2 == juncnum3) && (juncnum2 != juncnum1) && juncnum2 != 999999999 && considering[0].col() != 0){
1727  tagformatrix = Tempjunctions.at(juncnum2).at(1).at(1);
1728  I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[0].col());
1729  loc2 = std::distance(IndiceForColFin.begin(), I2);
1730  //std::cout <<endl<<"chosen color tag2 is "<<HH_showerptns[showerquarks[element[0]].par()].col();
1731  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc2<<endl;
1732  };
1733  if((juncnum1 == juncnum3) && (juncnum1 != juncnum2) && juncnum3 != 999999999 && considering[1].col() != 0){
1734  tagformatrix = Tempjunctions.at(juncnum3).at(2).at(1);
1735  I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[1].col());
1736  loc2 = std::distance(IndiceForColFin.begin(), I2);
1737  //std::cout <<endl<<"chosen color tag3 is "<<HH_showerptns[showerquarks[element[1]].par()].col();
1738  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc2<<endl;
1739  };
1740 
1741  I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tagformatrix);
1742  loc1 = std::distance(IndiceForColFin.begin(), I1);
1743  //std::cout <<endl<<"chosen orginal color tag is "<<tagformatrix;
1744  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc1<<endl;// now we find the locations of the color tags.
1745 
1746  //std::cout <<endl<<"loc2 is given as "<<loc2<<endl;
1747  // now, search the mesonrecomatrix
1748  if (tagformatrix < 999999999 && loc1 < standard && loc2 < standard) { // Not all the tags are in same junction so loc1,2 has always same or smaller value than the size of INdiceForColFin vector
1749  if(MesonrecoMatrix1.at(loc1).at(loc2) == 1) {
1750  recofactor3 = 1; // one specific tag, which is located in different location from other two strings from a junction, is neighbored with the tag in the not used tag in junction
1751  }else{
1752  recofactor3 = 1./9.;
1753  } // general case
1754  }else{recofactor3 = 1./27.;} // general case
1755 
1756  if((juncnum1 == juncnum2) && (juncnum2 == juncnum3) && (tagformatrix != 999999999)){
1757  recofactor3 = 1.;
1758  }
1759  }
1760  else if(considering[0].id()*considering[1].id()*considering[2].id() < 0){
1761 
1762  for(int ijunc=0; ijunc < Tempjunctions.size(); ijunc++){
1763  if((considering[0].acol() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1764  (considering[0].acol() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1765  (considering[0].acol() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1766  element1 = true;
1767  juncnum1 = ijunc;
1768  }
1769  if((considering[1].acol() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1770  (considering[1].acol() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1771  (considering[1].acol() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1772  element2 = true;
1773  juncnum2 = ijunc;
1774  }
1775  if((considering[2].acol() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1776  (considering[2].acol() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1777  (considering[2].acol() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1778  element3 = true;
1779  juncnum3 = ijunc;
1780  }
1781  }
1782  if((juncnum1 == juncnum2) && (juncnum1 != juncnum3) && juncnum1 != 999999999){
1783  tagformatrix = Tempjunctions.at(juncnum1).at(3).at(1);
1784  I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[2].acol());
1785  loc2 = std::distance(IndiceForColFin.begin(), I2);
1786  //std::cout <<endl<<"chosen color tag1 is "<<HH_showerptns[showerquarks[element[2]].par()].col();
1787  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc2<<endl;
1788  };
1789  if((juncnum2 == juncnum3) && (juncnum2 != juncnum1) && juncnum2 != 999999999){
1790  tagformatrix = Tempjunctions.at(juncnum2).at(1).at(1);
1791  I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[0].acol());
1792  loc2 = std::distance(IndiceForColFin.begin(), I2);
1793  //std::cout <<endl<<"chosen color tag2 is "<<HH_showerptns[showerquarks[element[0]].par()].col();
1794  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc2<<endl;
1795  };
1796  if((juncnum1 == juncnum3) && (juncnum1 != juncnum2) && juncnum3 != 999999999){
1797  tagformatrix = Tempjunctions.at(juncnum3).at(2).at(1);
1798  I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[1].acol());
1799  loc2 = std::distance(IndiceForColFin.begin(), I2);
1800  //std::cout <<endl<<"chosen color tag3 is "<<HH_showerptns[showerquarks[element[1]].par()].col();
1801  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc2<<endl;
1802  };
1803 
1804  I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tagformatrix);
1805  loc1 = std::distance(IndiceForColFin.begin(), I1);
1806  //std::cout <<endl<<"chosen orginal color tag is "<<tagformatrix;
1807  //std::cout <<endl<<"and corresponding indice in the matrix is "<<loc1<<endl;// now we find the locations of the color tags.
1808 
1809  //std::cout <<endl<<"loc2 is given as "<<loc2<<endl;
1810  // now, search the mesonrecomatrix
1811  if (tagformatrix < 999999999 && loc1 < standard && loc2 < standard) { // Not all the tags are in same junction so loc1,2 has always same or smaller value than the size of INdiceForColFin vector
1812  if(MesonrecoMatrix1.at(loc1).at(loc2) == 1) {
1813  recofactor3 = 1; // one specific tag, which is located in different location from other two strings from a junction, is neighbored with the tag in the not used tag in junction
1814  }else{
1815  recofactor3 = 1./9.;
1816  } // general case
1817  }
1818  else{recofactor3 = 1./27.;} // general case
1819 
1820  if((juncnum1 == juncnum2) && (juncnum2 == juncnum3) && (tagformatrix != 999999999)){
1821  recofactor3 = 1.;
1822  }
1823  }
1824  //recofactor3 = sh_recofactor*recofactor2;
1825  }else if(perm2[q3]<0){
1826  //skipping if the current quark cannot make a baryon with other two quarks
1827  if(HH_thermal[-element[2]].id()*considering[0].id() < 0){continue;}
1828  //skipping if current quark has been used
1829  if(HH_thermal[-element[2]].status() != 0 || HH_thermal[-element[2]].is_used()){continue;}
1830  //skipping if the current quark is from the same gluon as q2
1831  else if((perm2[q2] < 0) && (HH_thermal[-element[1]].par() != -1) && (HH_thermal[-element[1]].par() == HH_thermal[-element[2]].par())){continue;}
1832  //skipping if current quark is not a u,d,s,c,b quark
1833  else if(std::abs(HH_thermal[-element[2]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1834  //turning off recombination for thermal partons in a computationally friendly way...
1835  else if(th_recofactor < 0.001){continue;}
1836 
1837  //checking distance cut ONLY if this is a thermal parton - skip if dist2 > dist2cut
1838  FourVector pos_ptn1 = considering[0].pos(); FourVector pos_ptn2 = considering[1].pos(); FourVector pos_ptn3 = HH_thermal[-element[2]].pos();
1839  if((pos_ptn1.t() > pos_ptn2.t()) && (pos_ptn1.t() > pos_ptn3.t())){
1840  double dt_E2 = (pos_ptn1.t() - pos_ptn2.t())/considering[1].e(); double dt_E3 = (pos_ptn1.t() - pos_ptn3.t())/HH_thermal[-element[2]].e();
1841  pos_ptn2.Set(pos_ptn2.x()+considering[1].px()*dt_E2,pos_ptn2.y()+considering[1].py()*dt_E2,pos_ptn2.z()+considering[1].pz()*dt_E2,0.);
1842  pos_ptn3.Set(pos_ptn3.x()+HH_thermal[-element[2]].px()*dt_E3,pos_ptn3.y()+HH_thermal[-element[2]].py()*dt_E3,pos_ptn3.z()+HH_thermal[-element[2]].pz()*dt_E3,0.);
1843  }
1844  else if((pos_ptn2.t() > pos_ptn1.t()) && (pos_ptn2.t() > pos_ptn3.t())){
1845  double dt_E1 = (pos_ptn2.t() - pos_ptn1.t())/considering[0].e(); double dt_E3 = (pos_ptn2.t() - pos_ptn3.t())/HH_thermal[-element[2]].e();
1846  pos_ptn1.Set(pos_ptn1.x()+considering[0].px()*dt_E1,pos_ptn1.y()+considering[0].py()*dt_E1,pos_ptn1.z()+considering[0].pz()*dt_E1,0.);
1847  pos_ptn3.Set(pos_ptn3.x()+HH_thermal[-element[2]].px()*dt_E3,pos_ptn3.y()+HH_thermal[-element[2]].py()*dt_E3,pos_ptn3.z()+HH_thermal[-element[2]].pz()*dt_E3,0.);
1848  }
1849  else{
1850  double dt_E1 = (pos_ptn3.t() - pos_ptn1.t())/considering[0].e(); double dt_E2 = (pos_ptn3.t() - pos_ptn2.t())/considering[1].e();
1851  pos_ptn1.Set(pos_ptn1.x()+considering[0].px()*dt_E1,pos_ptn1.y()+considering[0].py()*dt_E1,pos_ptn1.z()+considering[0].pz()*dt_E1,0.);
1852  pos_ptn2.Set(pos_ptn2.x()+considering[1].px()*dt_E2,pos_ptn2.y()+considering[1].py()*dt_E2,pos_ptn2.z()+considering[1].pz()*dt_E2,0.);
1853  }
1854  if((dif2(pos_ptn3,pos_ptn1) > dist2cut) || (dif2(pos_ptn3,pos_ptn2) > dist2cut) || (dif2(pos_ptn1,pos_ptn2) > dist2cut)){continue;}
1855 
1856  considering.add(HH_thermal[-element[2]]);
1857  HH_thermal[-element[2]].status(-993);
1858  }else{JSWARN << "SOMETHING WENT HORRIBLY WRONG - DO NOT KNOW WHERE CURRENT QUARK CAME FROM?!";}
1859 
1860  //now that we *could* form a baryon, now we check if we actually do form one
1861  //baryon momentum
1862  FourVector Pbaryon;
1863  Pbaryon.Set(considering[0].px()+considering[1].px()+considering[2].px(),considering[0].py()+considering[1].py()+considering[2].py(),considering[0].pz()+considering[1].pz()+considering[2].pz(),0.);
1864 
1865  //baryon(CM) velocity
1866  FourVector betaB; //really p[i]/e below
1867  betaB.Set(Pbaryon.x()/(considering[0].e()+considering[1].e()+considering[2].e()),Pbaryon.y()/(considering[0].e()+considering[1].e()+considering[2].e()),Pbaryon.z()/(considering[0].e()+considering[1].e()+considering[2].e()),0.);
1868  betaB.Set(betaB.x(),betaB.y(),betaB.z(),1./(sqrt(1. - (betaB.x()*betaB.x() + betaB.y()*betaB.y() + betaB.z()*betaB.z()))));
1869 
1870  //boosting into CM frame
1871  FourVector pos_BCM[3], p_BCM[3];
1872  pos_BCM[0] = considering[0].boost_pos(betaB); pos_BCM[1] = considering[1].boost_pos(betaB); pos_BCM[2] = considering[2].boost_pos(betaB);
1873  p_BCM[0] = considering[0].boost_P(betaB); p_BCM[1] = considering[1].boost_P(betaB); p_BCM[2] = considering[2].boost_P(betaB);
1874 
1875  //velocities in CM frame
1876  FourVector v_BCM[3];
1877  v_BCM[0].Set(p_BCM[0].x()/p_BCM[0].t(),p_BCM[0].y()/p_BCM[0].t(),p_BCM[0].z()/p_BCM[0].t(),0.); //these are really p[i]/e
1878  v_BCM[1].Set(p_BCM[1].x()/p_BCM[1].t(),p_BCM[1].y()/p_BCM[1].t(),p_BCM[1].z()/p_BCM[1].t(),0.);
1879  v_BCM[2].Set(p_BCM[2].x()/p_BCM[2].t(),p_BCM[2].y()/p_BCM[2].t(),p_BCM[2].z()/p_BCM[2].t(),0.);
1880 
1881  //propagating quarks until time of youngest quark
1882  double curtime = std::max(std::max(pos_BCM[0].t(), pos_BCM[1].t()), pos_BCM[2].t());
1883  FourVector cur_pos[3];
1884  cur_pos[0].Set(pos_BCM[0].x()+v_BCM[0].x()*(curtime-pos_BCM[0].t()),pos_BCM[0].y()+v_BCM[0].y()*(curtime-pos_BCM[0].t()),pos_BCM[0].z()+v_BCM[0].z()*(curtime-pos_BCM[0].t()),curtime);
1885  cur_pos[1].Set(pos_BCM[1].x()+v_BCM[1].x()*(curtime-pos_BCM[1].t()),pos_BCM[1].y()+v_BCM[1].y()*(curtime-pos_BCM[1].t()),pos_BCM[1].z()+v_BCM[1].z()*(curtime-pos_BCM[1].t()),curtime);
1886  cur_pos[2].Set(pos_BCM[2].x()+v_BCM[2].x()*(curtime-pos_BCM[2].t()),pos_BCM[2].y()+v_BCM[2].y()*(curtime-pos_BCM[2].t()),pos_BCM[2].z()+v_BCM[2].z()*(curtime-pos_BCM[2].t()),curtime);
1887 
1888  //finding position of CM at curtime
1889  FourVector pos_CM;
1890  pos_CM.Set(
1891  (cur_pos[0].x()*considering[0].mass()+cur_pos[1].x()*considering[1].mass()+cur_pos[2].x()*considering[2].mass())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1892  (cur_pos[0].y()*considering[0].mass()+cur_pos[1].y()*considering[1].mass()+cur_pos[2].y()*considering[2].mass())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1893  (cur_pos[0].z()*considering[0].mass()+cur_pos[1].z()*considering[1].mass()+cur_pos[2].z()*considering[2].mass())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1894  curtime
1895  );
1896 
1897  //finding position of baryon in lab frame
1898  betaB.Set(-betaB.x(),-betaB.y(),-betaB.z(),betaB.t());
1899  FourVector pos_lab = HHboost(betaB, pos_CM);
1900 
1901  //finding relative momenta of partons in CM frame
1902  FourVector k_rel_square[2];
1903  k_rel_square[0].Set(
1904  (considering[1].mass()*p_BCM[0].x()-considering[0].mass()*p_BCM[1].x())/(considering[0].mass()+considering[1].mass()),
1905  (considering[1].mass()*p_BCM[0].y()-considering[0].mass()*p_BCM[1].y())/(considering[0].mass()+considering[1].mass()),
1906  (considering[1].mass()*p_BCM[0].z()-considering[0].mass()*p_BCM[1].z())/(considering[0].mass()+considering[1].mass()),
1907  0.);
1908  k_rel_square[1].Set(
1909  (considering[2].mass()*(p_BCM[0].x()+p_BCM[1].x())-(considering[0].mass()+considering[1].mass())*p_BCM[2].x())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1910  (considering[2].mass()*(p_BCM[0].y()+p_BCM[1].y())-(considering[0].mass()+considering[1].mass())*p_BCM[2].y())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1911  (considering[2].mass()*(p_BCM[0].z()+p_BCM[1].z())-(considering[0].mass()+considering[1].mass())*p_BCM[2].z())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1912  0.);
1913 
1914  //finding relative positions of partons in CM frame
1915  FourVector pos_rel_square[2];
1916  pos_rel_square[0].Set((cur_pos[0].x()-cur_pos[1].x()),(cur_pos[0].y()-cur_pos[1].y()),(cur_pos[0].z()-cur_pos[1].z()),0.);
1917  pos_rel_square[1].Set(
1918  ((cur_pos[0].x()*considering[0].mass()+cur_pos[1].x()*considering[1].mass())/(considering[0].mass()+considering[1].mass())-cur_pos[2].x()),
1919  ((cur_pos[0].y()*considering[0].mass()+cur_pos[1].y()*considering[1].mass())/(considering[0].mass()+considering[1].mass())-cur_pos[2].y()),
1920  ((cur_pos[0].z()*considering[0].mass()+cur_pos[1].z()*considering[1].mass())/(considering[0].mass()+considering[1].mass())-cur_pos[2].z()),
1921  0.);
1922 
1923 
1924  double SigRB2 = SigNucR2; double SigLB2 = SigNucL2;
1925  int sortid[3] = {std::abs(considering[0].id()),std::abs(considering[1].id()),std::abs(considering[2].id())};
1926  std::stable_sort(std::begin(sortid), std::end(sortid), std::greater<int>());
1927 
1928  //for particles we don't want to form, setting recofactor3 to 0
1929  if( sortid[0] == 3){
1930  if( sortid[1] == 3){
1931  if( sortid[2] == 3){SigRB2 = SigOmgR2; SigLB2 = SigOmgL2;}
1932  else{ SigRB2 = SigXiR2; SigLB2 = SigXiL2;}
1933  }
1934  else{ SigRB2 = SigSigR2; SigLB2 = SigSigL2;}
1935  }
1936  else if(sortid[0] == 4){
1937  if( sortid[1] == 4){
1938  if( sortid[2] == 4){SigRB2 = SigOcccR2; SigLB2 = SigOcccL2;}
1939  else if(sortid[2] == 3){SigRB2 = SigOccR2; SigLB2 = SigOccL2;}
1940  else{ SigRB2 = SigXiccR2; SigLB2 = SigXiccL2;}
1941  }
1942  else if(sortid[1] == 3){
1943  if( sortid[2] == 3){SigRB2 = SigOcR2; SigLB2 = SigOcL2;}
1944  else{ SigRB2 = SigXicR2; SigLB2 = SigXicL2;}
1945  }
1946  else{ SigRB2 = SigSigcR2; SigLB2 = SigSigcL2;}
1947  }
1948  else if(sortid[0] == 5){
1949  if( sortid[1] == 5){
1950  if( sortid[2] == 5){SigRB2 = SigObbbR2; SigLB2 = SigObbbL2; recofactor3=0.;}
1951  else if(sortid[2] == 4){SigRB2 = SigObbcR2; SigLB2 = SigObbcL2; recofactor3=0.;}
1952  else if(sortid[2] == 3){SigRB2 = SigObbR2; SigLB2 = SigObbL2; recofactor3=0.;}
1953  else{ SigRB2 = SigXibbR2; SigLB2 = SigXibbL2; recofactor3=0.;}
1954  }
1955  else if(sortid[1] == 4){
1956  if( sortid[2] == 4){SigRB2 = SigObccR2; SigLB2 = SigObccL2; recofactor3=0.;}
1957  else if(sortid[2] == 3){SigRB2 = SigObcR2; SigLB2 = SigObcL2; recofactor3=0.;}
1958  else{ SigRB2 = SigXibcR2; SigLB2 = SigXibcL2; recofactor3=0.;}
1959  }
1960  else if(sortid[1] == 3){
1961  if( sortid[2] == 3){SigRB2 = SigObR2; SigLB2 = SigObL2;}
1962  else{ SigRB2 = SigXibR2; SigLB2 = SigXibL2;}
1963  }
1964  else{ SigRB2 = SigSigbR2; SigLB2 = SigSigbL2;}
1965  }
1966 
1967  //precalc's for Wigner Wavefunction
1968  //0:x, 1:y, 2:z ::: urho:(rel. between partons 1,2), ulamb:(rel. between partons (1,2),3)
1969  double urho[3], ulamb[3];
1970  urho[0] = 0.5*(pos_rel_square[0].x()*pos_rel_square[0].x()/SigRB2 + k_rel_square[0].x()*k_rel_square[0].x()*SigRB2/hbarc2);
1971  urho[1] = 0.5*(pos_rel_square[0].y()*pos_rel_square[0].y()/SigRB2 + k_rel_square[0].y()*k_rel_square[0].y()*SigRB2/hbarc2);
1972  urho[2] = 0.5*(pos_rel_square[0].z()*pos_rel_square[0].z()/SigRB2 + k_rel_square[0].z()*k_rel_square[0].z()*SigRB2/hbarc2);
1973  ulamb[0] = 0.5*(pos_rel_square[1].x()*pos_rel_square[1].x()/SigLB2 + k_rel_square[1].x()*k_rel_square[1].x()*SigLB2/hbarc2);
1974  ulamb[1] = 0.5*(pos_rel_square[1].y()*pos_rel_square[1].y()/SigLB2 + k_rel_square[1].y()*k_rel_square[1].y()*SigLB2/hbarc2);
1975  ulamb[2] = 0.5*(pos_rel_square[1].z()*pos_rel_square[1].z()/SigLB2 + k_rel_square[1].z()*k_rel_square[1].z()*SigLB2/hbarc2);
1976 
1977  //1D GS Wig. wavefunction
1978  double wig0[2][3];
1979  wig0[0][0] = std::exp(-urho[0]); wig0[0][1] = std::exp(-urho[1]); wig0[0][2] = std::exp(-urho[2]);
1980  wig0[1][0] = std::exp(-ulamb[0]); wig0[1][1] = std::exp(-ulamb[1]); wig0[1][2] = std::exp(-ulamb[2]);
1981  //3D GS Wig. wavefunction
1982  double WigB[2];
1983  WigB[0] = wig0[0][0]*wig0[0][1]*wig0[0][2]*wig0[1][0]*wig0[1][1]*wig0[1][2];
1984 
1985  //summing up 3D Wig. wavefunctions over nlev excited states
1986  WigB[1] = 0.; //sumWigB;
1987 
1988  double wigE[2][3];
1989  for(int i=0;i<2;++i){for(int j=0;j<2;++j){wigE[i][j]=0.;}}
1990 
1991  wigE[0][0] = wig0[0][0];
1992  for(int iRx=0; iRx<=maxB_level; ++iRx){
1993  wigE[0][1] = wig0[0][1];
1994  for(int iRy=0; iRy<=maxB_level-iRx; ++iRy){
1995  wigE[0][2] = wig0[0][2];
1996  for(int iRz=0; iRz<=maxB_level-iRx-iRy; ++iRz){
1997  wigE[1][0] = wig0[1][0];
1998  for(int iLx=0; iLx<=maxB_level-iRx-iRy-iRz; ++iLx){
1999  wigE[1][1] = wig0[1][1];
2000  for(int iLy=0; iLy<=maxB_level-iRx-iRy-iRz-iLx; ++iLy){
2001  wigE[1][2] = wig0[1][2];
2002  for(int iLz=0; iLz<=maxB_level-iRx-iRy-iRz-iLx-iLy; ++iLz){
2003  WigB[1] += wigE[0][0]*wigE[0][1]*wigE[0][2]*wigE[1][0]*wigE[1][1]*wigE[1][2];
2004  wigE[1][2] *= ulamb[2]/((double(iLz))+1.);
2005  }
2006  wigE[1][1] *= ulamb[1]/((double(iLy))+1.);
2007  }
2008  wigE[1][0] *= ulamb[0]/((double(iLx))+1.);
2009  }
2010  wigE[0][2] *= urho[2]/((double(iRz))+1.);
2011  }
2012  wigE[0][1] *= urho[1]/((double(iRy))+1.);
2013  }
2014  wigE[0][0] *= urho[0]/((double(iRx))+1.);
2015  }
2016 
2017  if(maxB_level == -1) {
2018  WigB[0] = 0.;
2019  WigB[1] = 0.;
2020  }
2021 
2022  //Checking if baryon is formed (either ground or excited state)
2023  double rndbaryon = ran();
2024  double mult = (considering[1].is_thermal() || considering[2].is_thermal()) ? th_recofactor : sh_recofactor;
2025  if(WigB[1]*recofactor3*mult >= rndbaryon){
2026  int junction_with_thermal_parton = 0;
2027 
2028  /*std::cout << "Baryons" << std::endl;
2029  std::cout << considering[0].id() << "," << considering[0].col() << "," << considering[0].acol() << std::endl;
2030  std::cout << considering[1].id() << "," << considering[1].col() << "," << considering[1].acol() << std::endl;
2031  std::cout << considering[2].id() << "," << considering[2].col() << "," << considering[2].acol() << std::endl;*/
2032  if(considering[0].id() * considering[1].id() * considering[2].id() > 0){
2033  // baryon is to be formed, so temporary anti junction is defined
2034  if(considering[0].col() > 0 && considering[1].col() > 0 && considering[2].col() > 0) {
2035  IdColInfo1.push_back(-1); // antijunction tag(-1)
2036  IdColInfo1.push_back(junction_with_thermal_parton);
2037  IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2038  IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2039  IdColInfo3.push_back(-1);
2040  IdColInfo3.push_back(considering[1].col());
2041  IdColInfo4.push_back(-1);
2042  IdColInfo4.push_back(considering[2].col());
2043 
2044  JunctionInfo.push_back(IdColInfo1);
2045  JunctionInfo.push_back(IdColInfo2);
2046  JunctionInfo.push_back(IdColInfo3);
2047  JunctionInfo.push_back(IdColInfo4);
2048 
2049  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2050 
2051  IdColInfo1.clear();
2052  IdColInfo2.clear();
2053  IdColInfo3.clear();
2054  IdColInfo4.clear();
2055  JunctionInfo.clear();
2056 
2057  //Since Baryon is formed, color tag for neutrality should be added, casting int into double is needed!!(ex (double) intvalue
2058  int coltag1 = considering[0].col();
2059  int coltag2 = considering[1].col();
2060  int coltag3 = considering[2].col();
2061  if(coltag1 > 0 && coltag2 > 0 && coltag3 > 0 && coltag1 <= limit && coltag2 <= limit && coltag3 <= limit ){
2062  double tag1 = (double)coltag1; // they are casted to be inserted into the matrix(since it's vector of double
2063  double tag2 = (double)coltag2;
2064  double tag3 = (double)coltag3;
2065  std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
2066  std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
2067  std::vector<int>::iterator I3 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag3);
2068  int loc1 = std::distance(IndiceForColFin.begin(), I1);
2069  int loc2 = std::distance(IndiceForColFin.begin(), I2);
2070  int loc3 = std::distance(IndiceForColFin.begin(), I3); //set up for find matrix indices corresponding to the color tags (we just found the corresponding indice in BaryonrecoMatrix1 with col tags )
2071 
2072  BaryonrecoMatrix1.at(loc1).at(loc2).at(1) = tag3;
2073  BaryonrecoMatrix1.at(loc2).at(loc1).at(1) = tag3;
2074  BaryonrecoMatrix1.at(loc2).at(loc3).at(1) = tag1;
2075  BaryonrecoMatrix1.at(loc3).at(loc2).at(1) = tag1;
2076  BaryonrecoMatrix1.at(loc1).at(loc3).at(1) = tag2;
2077  BaryonrecoMatrix1.at(loc3).at(loc1).at(1) = tag2; // now the color tag info for color neutrality is saved in Matrix, also we need to consider the impact from this to Meson Formation
2078 
2079  //MesonrecoMatrix1 is modified by below
2080  MesonrecoMatrix1.at(loc1).at(loc2) = 0;
2081  MesonrecoMatrix1.at(loc2).at(loc1) = 0;
2082  MesonrecoMatrix1.at(loc2).at(loc3) = 0;
2083  MesonrecoMatrix1.at(loc3).at(loc2) = 0;
2084  MesonrecoMatrix1.at(loc1).at(loc3) = 0;
2085  MesonrecoMatrix1.at(loc3).at(loc1) = 0; // since three color tags of baryon are different from each other, so that these tags can't form meson with each other.
2086  }
2087  /*
2088  //dignostic measure
2089  std::cout <<endl<<"Meson reco Matrix revised by Baryon formation is same as below"<<endl;
2090  for(int irow=0; irow < IndiceForColFin.size(); irow++){
2091  for(int icol=0; icol < IndiceForColFin.size(); icol++){
2092  std::cout <<" "<<MesonrecoMatrix1.at(irow).at(icol)<<" ";
2093  }
2094  std::cout <<endl<<endl;
2095  }
2096  //dignostic measure
2097  std::cout <<endl<<"Revised Baryon reco Matrix is same as below"<<endl;
2098  for(int irow=0; irow < IndiceForColFin.size(); irow++){
2099  for(int icol=0; icol < IndiceForColFin.size(); icol++){
2100  std::cout <<" ( "<<BaryonrecoMatrix1.at(irow).at(icol).at(1)<<" ) ";
2101  }
2102  std::cout <<endl<<endl;
2103  }
2104  */
2105  }
2106  if(considering[0].col() > 0 && considering[1].col() == 0 && considering[2].col() > 0){ // MAT + Therm/LBT + MAT case
2107  IdColInfo1.push_back(-1); // antijunction tag(-1)
2108 
2109  maxtag++;
2110  int loc = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2111  if(loc == 999999999){
2112  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2113  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2114  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2115  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2116  fakep.e(fakep.mass());
2117  fakep.is_fakeparton(true);
2118  Extraparton.add(fakep);
2119  junction_with_thermal_parton = 1;
2120  //somewhere, we need to make for loop to toss all partons to remnants list.
2121  }
2122  else if (loc > 0){showerquarks[loc - 1].acol(maxtag); }
2123  else if(loc < 0){HH_thermal[-loc - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2124 
2125  IdColInfo1.push_back(junction_with_thermal_parton);
2126 
2127  //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2128  IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2129  IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2130  IdColInfo3.push_back(-1);
2131  IdColInfo3.push_back(maxtag);
2132  IdColInfo4.push_back(-1);
2133  IdColInfo4.push_back(considering[2].col());
2134 
2135  JunctionInfo.push_back(IdColInfo1);
2136  JunctionInfo.push_back(IdColInfo2);
2137  JunctionInfo.push_back(IdColInfo3);
2138  JunctionInfo.push_back(IdColInfo4);
2139 
2140  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2141 
2142  IdColInfo1.clear();
2143  IdColInfo2.clear();
2144  IdColInfo3.clear();
2145  IdColInfo4.clear();
2146  JunctionInfo.clear();
2147  }
2148  if(considering[0].col() == 0 && considering[1].col() > 0 && considering[2].col() > 0){ // LBT + MAT + MAT case
2149  IdColInfo1.push_back(-1); // antijunction tag(-1)
2150 
2151  maxtag++;
2152  int loc = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2153  if(loc == 999999999){
2154  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2155  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2156  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2157  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2158  fakep.e(fakep.mass());
2159  fakep.is_fakeparton(true);
2160  Extraparton.add(fakep);
2161  junction_with_thermal_parton = 1;
2162  //somewhere, we need to make for loop to toss all partons to remnants list.
2163  }
2164  else if (loc > 0){showerquarks[loc - 1].acol(maxtag); }
2165  else if(loc < 0){HH_thermal[-loc - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2166 
2167  IdColInfo1.push_back(junction_with_thermal_parton);
2168 
2169  IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2170  IdColInfo2.push_back(maxtag);// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2171  IdColInfo3.push_back(-1);
2172  IdColInfo3.push_back(considering[1].col());
2173  IdColInfo4.push_back(-1);
2174  IdColInfo4.push_back(considering[2].col());
2175 
2176  JunctionInfo.push_back(IdColInfo1);
2177  JunctionInfo.push_back(IdColInfo2);
2178  JunctionInfo.push_back(IdColInfo3);
2179  JunctionInfo.push_back(IdColInfo4);
2180 
2181  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2182 
2183  IdColInfo1.clear();
2184  IdColInfo2.clear();
2185  IdColInfo3.clear();
2186  IdColInfo4.clear();
2187  JunctionInfo.clear();
2188  }
2189  if(considering[0].col() > 0 && considering[1].col() > 0 && considering[2].col() == 0){ // MAT + MAT + Therm/LBT case
2190  IdColInfo1.push_back(-1); // antijunction tag(-1)
2191 
2192  maxtag++;
2193  int loc = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2194  if(loc == 999999999){
2195  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2196  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2197  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2198  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2199  fakep.e(fakep.mass());
2200  fakep.is_fakeparton(true);
2201  Extraparton.add(fakep);
2202  junction_with_thermal_parton = 1;
2203  //somewhere, we need to make for loop to toss all partons to remnants list.
2204  }
2205  else if (loc > 0){showerquarks[loc - 1].acol(maxtag); }
2206  else if(loc < 0){HH_thermal[-loc - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2207 
2208  IdColInfo1.push_back(junction_with_thermal_parton);
2209 
2210  IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2211  IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2212  IdColInfo3.push_back(-1);
2213  IdColInfo3.push_back(considering[1].col());
2214  IdColInfo4.push_back(-1);
2215  IdColInfo4.push_back(maxtag);
2216 
2217  JunctionInfo.push_back(IdColInfo1);
2218  JunctionInfo.push_back(IdColInfo2);
2219  JunctionInfo.push_back(IdColInfo3);
2220  JunctionInfo.push_back(IdColInfo4);
2221 
2222  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2223 
2224  IdColInfo1.clear();
2225  IdColInfo2.clear();
2226  IdColInfo3.clear();
2227  IdColInfo4.clear();
2228  JunctionInfo.clear();
2229  } // so far, we are finished with the list with one zero component.
2230  if(considering[0].col() > 0 && considering[1].col() == 0 && considering[2].col() == 0){ // MAT + Therm/LBT + Therm/LBT case
2231  IdColInfo1.push_back(-1); // antijunction tag(-1)
2232  IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2233  IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2234 
2235  maxtag++;
2236  int loc1 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2237  if(loc1 == 999999999){
2238  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2239  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2240  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2241  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2242  fakep.e(fakep.mass());
2243  fakep.is_fakeparton(true);
2244  Extraparton.add(fakep);
2245  junction_with_thermal_parton = 1;
2246  //somewhere, we need to make for loop to toss all partons to remnants list.
2247  }
2248  else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2249  else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2250  IdColInfo3.push_back(-1);
2251  IdColInfo3.push_back(maxtag);
2252 
2253  maxtag++;
2254  int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2255  if(loc2 == 999999999){
2256  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2257  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2258  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2259  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2260  fakep.e(fakep.mass());
2261  fakep.is_fakeparton(true);
2262  Extraparton.add(fakep);
2263  junction_with_thermal_parton = 1;
2264  //somewhere, we need to make for loop to toss all partons to remnants list.
2265  }
2266  else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2267  else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2268 
2269  IdColInfo1.push_back(junction_with_thermal_parton);
2270 
2271  IdColInfo4.push_back(-1);
2272  IdColInfo4.push_back(maxtag);
2273  //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2274 
2275  JunctionInfo.push_back(IdColInfo1);
2276  JunctionInfo.push_back(IdColInfo2);
2277  JunctionInfo.push_back(IdColInfo3);
2278  JunctionInfo.push_back(IdColInfo4);
2279 
2280  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2281 
2282  IdColInfo1.clear();
2283  IdColInfo2.clear();
2284  IdColInfo3.clear();
2285  IdColInfo4.clear();
2286  JunctionInfo.clear();
2287  }
2288  if(considering[0].col() == 0 && considering[1].col() == 0 && considering[2].col() > 0){ // Therm/LBT + Therm/LBT + MAT case
2289  IdColInfo1.push_back(-1); // antijunction tag(-1)
2290 
2291  maxtag++;
2292  int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2293  if(loc1 == 999999999){
2294  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2295  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2296  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2297  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2298  fakep.e(fakep.mass());
2299  fakep.is_fakeparton(true);
2300  Extraparton.add(fakep);
2301  junction_with_thermal_parton = 1;
2302  //somewhere, we need to make for loop to toss all partons to remnants list.
2303  }
2304  else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2305  else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2306  IdColInfo3.push_back(-1);
2307  IdColInfo3.push_back(maxtag);
2308 
2309  maxtag++;
2310  int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2311  if(loc2 == 999999999){
2312  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2313  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2314  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2315  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2316  fakep.e(fakep.mass());
2317  fakep.is_fakeparton(true);
2318  Extraparton.add(fakep);
2319  junction_with_thermal_parton = 1;
2320  //somewhere, we need to make for loop to toss all partons to remnants list.
2321  }
2322  else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2323  else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2324 
2325  IdColInfo1.push_back(junction_with_thermal_parton);
2326 
2327  IdColInfo4.push_back(-1);
2328  IdColInfo4.push_back(maxtag);
2329  //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2330 
2331  IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2332  IdColInfo2.push_back(considering[2].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2333 
2334  JunctionInfo.push_back(IdColInfo1);
2335  JunctionInfo.push_back(IdColInfo2);
2336  JunctionInfo.push_back(IdColInfo3);
2337  JunctionInfo.push_back(IdColInfo4);
2338 
2339  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2340 
2341  IdColInfo1.clear();
2342  IdColInfo2.clear();
2343  IdColInfo3.clear();
2344  IdColInfo4.clear();
2345  JunctionInfo.clear();
2346  }
2347  if(considering[0].col() == 0 && considering[1].col() > 0 && considering[2].col() == 0){ // Therm/LBT + Therm/LBT + MAT case
2348  IdColInfo1.push_back(-1); // antijunction tag(-1)
2349 
2350  maxtag++;
2351  int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2352  if(loc1 == 999999999){
2353  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2354  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2355  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2356  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2357  fakep.e(fakep.mass());
2358  fakep.is_fakeparton(true);
2359  Extraparton.add(fakep);
2360  junction_with_thermal_parton = 1;
2361  //somewhere, we need to make for loop to toss all partons to remnants list.
2362  }
2363  else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2364  else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2365  IdColInfo2.push_back(-1);
2366  IdColInfo2.push_back(maxtag);
2367 
2368  IdColInfo3.push_back(-1); // means anticolor tag(negative color charge)
2369  IdColInfo3.push_back(considering[1].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2370 
2371  maxtag++;
2372  int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2373  if(loc2 == 999999999){
2374  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2375  HHparton fakep = considering[2]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2376  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2377  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2378  fakep.e(fakep.mass());
2379  fakep.is_fakeparton(true);
2380  Extraparton.add(fakep);
2381  junction_with_thermal_parton = 1;
2382  //somewhere, we need to make for loop to toss all partons to remnants list.
2383  }
2384  else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2385  else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2386 
2387  IdColInfo1.push_back(junction_with_thermal_parton);
2388 
2389  IdColInfo4.push_back(-1);
2390  IdColInfo4.push_back(maxtag);
2391 
2392  JunctionInfo.push_back(IdColInfo1);
2393  JunctionInfo.push_back(IdColInfo2);
2394  JunctionInfo.push_back(IdColInfo3);
2395  JunctionInfo.push_back(IdColInfo4);
2396 
2397  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2398 
2399  IdColInfo1.clear();
2400  IdColInfo2.clear();
2401  IdColInfo3.clear();
2402  IdColInfo4.clear();
2403  JunctionInfo.clear();
2404  } // so far, we are finished with the list with two zeros
2405  if(considering[0].col() == 0 && considering[1].col() == 0 && considering[2].col() == 0){ // Therm/LBT + Therm/LBT + Therm/LBT
2406  IdColInfo1.push_back(-1); // antijunction tag(-1)
2407 
2408  maxtag++;
2409  int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2410  if(loc1 == 999999999){
2411  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2412  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2413  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2414  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2415  fakep.e(fakep.mass());
2416  fakep.is_fakeparton(true);
2417  Extraparton.add(fakep);
2418  junction_with_thermal_parton = 1;
2419  //somewhere, we need to make for loop to toss all partons to remnants list.
2420  }
2421  else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2422  else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2423  IdColInfo2.push_back(-1);
2424  IdColInfo2.push_back(maxtag);
2425 
2426  maxtag++;
2427  int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2428  if(loc2 == 999999999){
2429  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2430  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2431  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2432  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2433  fakep.e(fakep.mass());
2434  fakep.is_fakeparton(true);
2435  Extraparton.add(fakep);
2436  junction_with_thermal_parton = 1;
2437  //somewhere, we need to make for loop to toss all partons to remnants list.
2438  }
2439  else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2440  else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2441  IdColInfo3.push_back(-1);
2442  IdColInfo3.push_back(maxtag);
2443 
2444  maxtag++;
2445  int loc3 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2446  if(loc3 == 999999999){
2447  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2448  HHparton fakep = considering[2]; fakep.id(-fakep.id()); fakep.acol(maxtag);
2449  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2450  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2451  fakep.e(fakep.mass());
2452  fakep.is_fakeparton(true);
2453  Extraparton.add(fakep);
2454  junction_with_thermal_parton = 1;
2455  //somewhere, we need to make for loop to toss all partons to remnants list.
2456  }
2457  else if (loc3 > 0){showerquarks[loc3 - 1].acol(maxtag); }
2458  else if(loc3 < 0){HH_thermal[-loc3 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2459 
2460  IdColInfo1.push_back(junction_with_thermal_parton);
2461 
2462  IdColInfo4.push_back(-1);
2463  IdColInfo4.push_back(maxtag);
2464 
2465  //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2466  JunctionInfo.push_back(IdColInfo1);
2467  JunctionInfo.push_back(IdColInfo2);
2468  JunctionInfo.push_back(IdColInfo3);
2469  JunctionInfo.push_back(IdColInfo4);
2470  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2471  IdColInfo1.clear();
2472  IdColInfo2.clear();
2473  IdColInfo3.clear();
2474  IdColInfo4.clear();
2475  JunctionInfo.clear();
2476  } // so far, we are finished with the list with three zeros
2477  }
2478  else if(considering[0].id() * considering[1].id() * considering[2].id() < 0){ //anti baryon would be made so temporary junction is defined
2479  //std::cout <<endl<<"Anti Baryon is made from "<<" ( "<<considering[0].acol()<<" , "<<considering[1].acol()<<" , "<<considering[2].acol()<<" ) "<<endl;
2480  //std::cout <<endl<<"Anti Baryon is made from "<<" ( "<<HH_showerptns[showerquarks[element[0]].par()].acol()<<" , "<<HH_showerptns[showerquarks[element[1]].par()].acol()<<" , "<<HH_showerptns[showerquarks[element[2]].par()].acol()<<" ) "<<endl;
2481 
2482  if(considering[0].acol() > 0 && considering[1].acol() > 0 && considering[2].acol() > 0){
2483  IdColInfo1.push_back(1); // junction tag(1)
2484  IdColInfo1.push_back(junction_with_thermal_parton); // zero(just room for the other usage) : {1, 0} at 1st
2485  IdColInfo2.push_back(1); // means color tag(positive color charge) : { 1, color tag } at 2nd, 3rd, 4th in the vector
2486  IdColInfo2.push_back(considering[0].acol());
2487  IdColInfo3.push_back(1);
2488  IdColInfo3.push_back(considering[1].acol());
2489  IdColInfo4.push_back(1);
2490  IdColInfo4.push_back(considering[2].acol());
2491 
2492  JunctionInfo.push_back(IdColInfo1);
2493  JunctionInfo.push_back(IdColInfo2);
2494  JunctionInfo.push_back(IdColInfo3);
2495  JunctionInfo.push_back(IdColInfo4);
2496 
2497  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2498 
2499  IdColInfo1.clear();
2500  IdColInfo2.clear();
2501  IdColInfo3.clear();
2502  IdColInfo4.clear();
2503  JunctionInfo.clear();
2504 
2505  //Since Baryon is formed, color tag for neutrality should be added, casting int into double is needed!!(ex (double) intvalue
2506  int coltag1 = considering[0].acol();
2507  int coltag2 = considering[1].acol();
2508  int coltag3 = considering[2].acol();
2509  if(coltag1 > 0 && coltag2 > 0 && coltag3 > 0 && coltag1 <= limit && coltag2 <= limit && coltag3 <= limit ){
2510  double tag1 = (double)coltag1; // they are casted to be inserted into the matrix(since it's vector of double
2511  double tag2 = (double)coltag2;
2512  double tag3 = (double)coltag3;
2513  std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
2514  std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
2515  std::vector<int>::iterator I3 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag3);
2516  int loc1 = std::distance(IndiceForColFin.begin(), I1);
2517  int loc2 = std::distance(IndiceForColFin.begin(), I2);
2518  int loc3 = std::distance(IndiceForColFin.begin(), I3); //set up for find matrix indices corresponding to the color tags (we just found the corresponding indice in BaryonrecoMatrix1 with col tags )
2519 
2520  BaryonrecoMatrix1.at(loc1).at(loc2).at(1) = tag3;
2521  BaryonrecoMatrix1.at(loc2).at(loc1).at(1) = tag3;
2522  BaryonrecoMatrix1.at(loc2).at(loc3).at(1) = tag1;
2523  BaryonrecoMatrix1.at(loc3).at(loc2).at(1) = tag1;
2524  BaryonrecoMatrix1.at(loc1).at(loc3).at(1) = tag2;
2525  BaryonrecoMatrix1.at(loc3).at(loc1).at(1) = tag2; // now the color tag info for color neutrality is saved in Matrix, also we need to consider the impact from this to Meson Formation
2526 
2527  //MesonrecoMatrix1 is modified by below
2528  MesonrecoMatrix1.at(loc1).at(loc2) = 0;
2529  MesonrecoMatrix1.at(loc2).at(loc1) = 0;
2530  MesonrecoMatrix1.at(loc2).at(loc3) = 0;
2531  MesonrecoMatrix1.at(loc3).at(loc2) = 0;
2532  MesonrecoMatrix1.at(loc1).at(loc3) = 0;
2533  MesonrecoMatrix1.at(loc3).at(loc1) = 0; // since three color tags of baryon are different from each other, so that these tags can't form meson with each other.
2534  }
2535  }
2536  if(considering[0].acol() > 0 && considering[1].acol() == 0 && considering[2].acol() > 0){ // MAT + Therm/LBT + MAT case
2537  IdColInfo1.push_back(1); // junction tag(1)
2538 
2539  maxtag++;
2540  int loc = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2541  if(loc == 999999999){
2542  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2543  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.col(maxtag);
2544  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2545  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2546  fakep.e(fakep.mass());
2547  fakep.is_fakeparton(true);
2548  Extraparton.add(fakep);
2549  junction_with_thermal_parton = 1;
2550  //somewhere, we need to make for loop to toss all partons to remnants list.
2551  }
2552  else if (loc > 0){showerquarks[loc - 1].col(maxtag); }
2553  else if(loc < 0){HH_thermal[-loc - 1].col(maxtag); junction_with_thermal_parton = 1;}
2554 
2555  IdColInfo1.push_back(junction_with_thermal_parton);
2556 
2557  IdColInfo2.push_back(1); // color tag
2558  IdColInfo2.push_back(considering[0].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2559  IdColInfo3.push_back(1);
2560  IdColInfo3.push_back(maxtag);
2561  IdColInfo4.push_back(1);
2562  IdColInfo4.push_back(considering[2].acol());
2563 
2564  JunctionInfo.push_back(IdColInfo1);
2565  JunctionInfo.push_back(IdColInfo2);
2566  JunctionInfo.push_back(IdColInfo3);
2567  JunctionInfo.push_back(IdColInfo4);
2568 
2569  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2570 
2571  IdColInfo1.clear();
2572  IdColInfo2.clear();
2573  IdColInfo3.clear();
2574  IdColInfo4.clear();
2575  JunctionInfo.clear();
2576  }
2577  if(considering[0].acol() == 0 && considering[1].acol() > 0 && considering[2].acol() > 0){ // LBT + MAT + MAT case
2578  IdColInfo1.push_back(1); // junction tag(1)
2579 
2580  maxtag++;
2581  int loc = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2582  if(loc == 999999999){
2583  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2584  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.col(maxtag);
2585  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2586  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2587  fakep.e(fakep.mass());
2588  fakep.is_fakeparton(true);
2589  Extraparton.add(fakep);
2590  junction_with_thermal_parton = 1;
2591  //somewhere, we need to make for loop to toss all partons to remnants list.
2592  }
2593  else if (loc > 0){showerquarks[loc - 1].col(maxtag); }
2594  else if(loc < 0){HH_thermal[-loc - 1].col(maxtag); junction_with_thermal_parton = 1;}
2595 
2596  IdColInfo1.push_back(junction_with_thermal_parton);
2597 
2598  IdColInfo2.push_back(1); // means color tag
2599  IdColInfo2.push_back(maxtag);// {1, color tag} will be at 2nd, 3rd, 4th
2600  IdColInfo3.push_back(1);
2601  IdColInfo3.push_back(considering[1].acol());
2602  IdColInfo4.push_back(1);
2603  IdColInfo4.push_back(considering[2].acol());
2604 
2605  JunctionInfo.push_back(IdColInfo1);
2606  JunctionInfo.push_back(IdColInfo2);
2607  JunctionInfo.push_back(IdColInfo3);
2608  JunctionInfo.push_back(IdColInfo4);
2609 
2610  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2611 
2612  IdColInfo1.clear();
2613  IdColInfo2.clear();
2614  IdColInfo3.clear();
2615  IdColInfo4.clear();
2616  JunctionInfo.clear();
2617  }
2618  if(considering[0].acol() > 0 && considering[1].acol() > 0 && considering[2].acol() == 0){ // MAT + MAT + Therm/LBT case
2619  IdColInfo1.push_back(1); // junction tag(1)
2620 
2621  maxtag++;
2622  int loc = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2623  if(loc == 999999999){
2624  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2625  HHparton fakep = considering[2]; fakep.id(-fakep.id()); fakep.col(maxtag);
2626  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2627  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2628  fakep.e(fakep.mass());
2629  fakep.is_fakeparton(true);
2630  Extraparton.add(fakep);
2631  junction_with_thermal_parton = 1;
2632  //somewhere, we need to make for loop to toss all partons to remnants list.
2633  }
2634  else if (loc > 0){showerquarks[loc - 1].col(maxtag); }
2635  else if(loc < 0){HH_thermal[-loc - 1].col(maxtag); junction_with_thermal_parton = 1;}
2636 
2637  IdColInfo1.push_back(junction_with_thermal_parton);
2638 
2639  IdColInfo2.push_back(1); // means color tag
2640  IdColInfo2.push_back(considering[0].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2641  IdColInfo3.push_back(1);
2642  IdColInfo3.push_back(considering[1].acol());
2643  IdColInfo4.push_back(1);
2644  IdColInfo4.push_back(maxtag);
2645 
2646  JunctionInfo.push_back(IdColInfo1);
2647  JunctionInfo.push_back(IdColInfo2);
2648  JunctionInfo.push_back(IdColInfo3);
2649  JunctionInfo.push_back(IdColInfo4);
2650 
2651  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2652 
2653  IdColInfo1.clear();
2654  IdColInfo2.clear();
2655  IdColInfo3.clear();
2656  IdColInfo4.clear();
2657  JunctionInfo.clear();
2658  } // so far, we are finished with the list with one zero component.
2659  if(considering[0].acol() > 0 && considering[1].acol() == 0 && considering[2].acol() == 0){ // MAT + Therm/LBT + Therm/LBT case
2660  IdColInfo1.push_back(1); // junction tag(1)
2661  IdColInfo2.push_back(1); // means color tag
2662  IdColInfo2.push_back(considering[0].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2663 
2664  maxtag++;
2665  int loc1 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2666  if(loc1 == 999999999){
2667  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2668  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.col(maxtag);
2669  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2670  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2671  fakep.e(fakep.mass());
2672  fakep.is_fakeparton(true);
2673  Extraparton.add(fakep);
2674  junction_with_thermal_parton = 1;
2675  //somewhere, we need to make for loop to toss all partons to remnants list.
2676  }
2677  else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2678  else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2679  IdColInfo3.push_back(1);
2680  IdColInfo3.push_back(maxtag);
2681 
2682  maxtag++;
2683  int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2684  if(loc2 == 999999999){
2685  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2686  HHparton fakep = considering[2]; fakep.id(-fakep.id()); fakep.col(maxtag);
2687  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2688  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2689  fakep.e(fakep.mass());
2690  fakep.is_fakeparton(true);
2691  Extraparton.add(fakep);
2692  junction_with_thermal_parton = 1;
2693  //somewhere, we need to make for loop to toss all partons to remnants list.
2694  }
2695  else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2696  else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2697 
2698  IdColInfo1.push_back(junction_with_thermal_parton);
2699 
2700  IdColInfo4.push_back(1);
2701  IdColInfo4.push_back(maxtag);
2702  //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2703 
2704  JunctionInfo.push_back(IdColInfo1);
2705  JunctionInfo.push_back(IdColInfo2);
2706  JunctionInfo.push_back(IdColInfo3);
2707  JunctionInfo.push_back(IdColInfo4);
2708 
2709  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2710 
2711  IdColInfo1.clear();
2712  IdColInfo2.clear();
2713  IdColInfo3.clear();
2714  IdColInfo4.clear();
2715  JunctionInfo.clear();
2716  }
2717  if(considering[0].acol() == 0 && considering[1].acol() == 0 && considering[2].acol() > 0){ // Therm/LBT + Therm/LBT + MAT case
2718  IdColInfo1.push_back(1); // junction tag(1)
2719 
2720  maxtag++;
2721  int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2722  if(loc1 == 999999999){
2723  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2724  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.col(maxtag);
2725  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2726  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2727  fakep.e(fakep.mass());
2728  fakep.is_fakeparton(true);
2729  Extraparton.add(fakep);
2730  junction_with_thermal_parton = 1;
2731  //somewhere, we need to make for loop to toss all partons to remnants list.
2732  }
2733  else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2734  else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2735  IdColInfo2.push_back(1);
2736  IdColInfo2.push_back(maxtag);
2737 
2738  maxtag++;
2739  int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2740  if(loc2 == 999999999){
2741  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2742  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.col(maxtag);
2743  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2744  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2745  fakep.e(fakep.mass());
2746  fakep.is_fakeparton(true);
2747  Extraparton.add(fakep);
2748  junction_with_thermal_parton = 1;
2749  //somewhere, we need to make for loop to toss all partons to remnants list.
2750  }
2751  else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2752  else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2753 
2754  IdColInfo1.push_back(junction_with_thermal_parton);
2755 
2756  IdColInfo3.push_back(1);
2757  IdColInfo3.push_back(maxtag);
2758 
2759  IdColInfo4.push_back(1); // means color tag
2760  IdColInfo4.push_back(considering[2].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2761 
2762  JunctionInfo.push_back(IdColInfo1);
2763  JunctionInfo.push_back(IdColInfo2);
2764  JunctionInfo.push_back(IdColInfo3);
2765  JunctionInfo.push_back(IdColInfo4);
2766 
2767  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2768 
2769  IdColInfo1.clear();
2770  IdColInfo2.clear();
2771  IdColInfo3.clear();
2772  IdColInfo4.clear();
2773  JunctionInfo.clear();
2774  }
2775  if(considering[0].acol() == 0 && considering[1].acol() > 0 && considering[2].acol() == 0){ // Therm/LBT + Therm/LBT + MAT case
2776  IdColInfo1.push_back(1); // junction tag(1)
2777 
2778  maxtag++;
2779  int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2780  if(loc1 == 999999999){
2781  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2782  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.col(maxtag);
2783  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2784  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2785  fakep.e(fakep.mass());
2786  fakep.is_fakeparton(true);
2787  Extraparton.add(fakep);
2788  junction_with_thermal_parton = 1;
2789  //somewhere, we need to make for loop to toss all partons to remnants list.
2790  }
2791  else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2792  else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2793  IdColInfo2.push_back(1);
2794  IdColInfo2.push_back(maxtag);
2795 
2796  IdColInfo3.push_back(1); // means color tag
2797  IdColInfo3.push_back(considering[1].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2798 
2799  maxtag++;
2800  int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2801  if(loc2 == 999999999){
2802  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2803  HHparton fakep = considering[2]; fakep.id(-fakep.id()); fakep.col(maxtag);
2804  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2805  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2806  fakep.e(fakep.mass());
2807  fakep.is_fakeparton(true);
2808  Extraparton.add(fakep);
2809  junction_with_thermal_parton = 1;
2810  //somewhere, we need to make for loop to toss all partons to remnants list.
2811  }
2812  else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2813  else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2814 
2815  IdColInfo1.push_back(junction_with_thermal_parton);
2816 
2817  IdColInfo4.push_back(1);
2818  IdColInfo4.push_back(maxtag);
2819 
2820  JunctionInfo.push_back(IdColInfo1);
2821  JunctionInfo.push_back(IdColInfo2);
2822  JunctionInfo.push_back(IdColInfo3);
2823  JunctionInfo.push_back(IdColInfo4);
2824 
2825  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2826 
2827  IdColInfo1.clear();
2828  IdColInfo2.clear();
2829  IdColInfo3.clear();
2830  IdColInfo4.clear();
2831  JunctionInfo.clear();
2832  } // so far, we are finished with the list with two zeros
2833  if(considering[0].acol() == 0 && considering[1].acol() == 0 && considering[2].acol() == 0){ // Therm/LBT + Therm/LBT + Therm/LBT
2834  IdColInfo1.push_back(1); // junction tag(1)
2835 
2836  maxtag++;
2837  int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2838  if(loc1 == 999999999){
2839  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2840  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.col(maxtag);
2841  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2842  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2843  fakep.e(fakep.mass());
2844  fakep.is_fakeparton(true);
2845  Extraparton.add(fakep);
2846  junction_with_thermal_parton = 1;
2847  //somewhere, we need to make for loop to toss all partons to remnants list.
2848  }
2849  else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2850  else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2851  IdColInfo2.push_back(1);
2852  IdColInfo2.push_back(maxtag);
2853 
2854  maxtag++;
2855  int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2856  if(loc2 == 999999999){
2857  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2858  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.col(maxtag);
2859  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2860  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2861  fakep.e(fakep.mass());
2862  fakep.is_fakeparton(true);
2863  Extraparton.add(fakep);
2864  junction_with_thermal_parton = 1;
2865  //somewhere, we need to make for loop to toss all partons to remnants list.
2866  }
2867  else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2868  else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2869  IdColInfo3.push_back(1);
2870  IdColInfo3.push_back(maxtag);
2871 
2872  maxtag++;
2873  int loc3 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2874  if(loc3 == 999999999){
2875  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2876  HHparton fakep = considering[2]; fakep.id(-fakep.id()); fakep.col(maxtag);
2877  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2878  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2879  fakep.e(fakep.mass());
2880  fakep.is_fakeparton(true);
2881  Extraparton.add(fakep);
2882  junction_with_thermal_parton = 1;
2883  //somewhere, we need to make for loop to toss all partons to remnants list.
2884  }
2885  else if (loc3 > 0){showerquarks[loc3 - 1].col(maxtag); }
2886  else if(loc3 < 0){HH_thermal[-loc3 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2887 
2888  IdColInfo1.push_back(junction_with_thermal_parton);
2889 
2890  IdColInfo4.push_back(1);
2891  IdColInfo4.push_back(maxtag);
2892 
2893  JunctionInfo.push_back(IdColInfo1);
2894  JunctionInfo.push_back(IdColInfo2);
2895  JunctionInfo.push_back(IdColInfo3);
2896  JunctionInfo.push_back(IdColInfo4);
2897  Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2898  IdColInfo1.clear();
2899  IdColInfo2.clear();
2900  IdColInfo3.clear();
2901  IdColInfo4.clear();
2902  JunctionInfo.clear();
2903  } // so far, we are finished with the list with three zeros
2904  //dignostic measure
2905  /*
2906  std::cout <<endl<<"Meson reco Matrix revised by Baryon formation is same as below"<<endl;
2907  for(int irow=0; irow < IndiceForColFin.size(); irow++){
2908  for(int icol=0; icol < IndiceForColFin.size(); icol++){
2909  std::cout <<" "<<MesonrecoMatrix1.at(irow).at(icol)<<" ";
2910  }
2911  std::cout <<endl<<endl;
2912  }
2913  */
2914  }
2915 
2916  //now we're forming the hadron
2917  HHhadron formedhadron;
2918  //setting the hadron values: is a recombined hadron, mass, and parents
2919  formedhadron.is_recohad(true); formedhadron.mass( p_BCM[0].t() + p_BCM[1].t() + p_BCM[2].t() );
2920  formedhadron.add_par(showerquarks[element[0]].par());
2921  if(perm2[q2]>0){formedhadron.add_par(showerquarks[element[1]].par());}else{formedhadron.add_par(element[1]);}
2922  if(perm2[q3]>0){formedhadron.add_par(showerquarks[element[2]].par());}else{formedhadron.add_par(element[2]);}
2923 
2924  //now setting if baryon is in excited state
2925  if(WigB[0]*recofactor3*mult < rndbaryon){formedhadron.is_excited(true);}
2926 
2927  //setting if there are any thermal partons used to make the hadron (with the '0' thermal parent as -99999 so that it doesn't conflict with '0' shower parton)
2928  if( perm2[q2]>0 && perm2[q3]>0){/*is sh-sh-sh*/ formedhadron.is_shsh(true);}
2929  else if(perm2[q2]>0 && perm2[q3]<0){/*is sh-sh-th*/ formedhadron.is_shth(true); if(element[2] == 0){formedhadron.parents[2] = -99999;}}
2930  else if(perm2[q2]<0 && perm2[q3]>0){/*is sh-th-sh*/ formedhadron.is_shth(true); if(element[1] == 0){formedhadron.parents[1] = -99999;}}
2931  else if(perm2[q2]<0 && perm2[q3]<0){/*is sh-th-th*/ formedhadron.is_shth(true); if(element[1] == 0){formedhadron.parents[1] = -99999;}
2932  if(element[2] == 0){formedhadron.parents[2] = -99999;}
2933  }
2934 
2935  //setting hadron position and momentum vectors
2936  Pbaryon.Set(Pbaryon.x(),Pbaryon.y(),Pbaryon.z(),sqrt(Pbaryon.x()*Pbaryon.x() + Pbaryon.y()*Pbaryon.y() + Pbaryon.z()*Pbaryon.z() + formedhadron.mass()*formedhadron.mass()));
2937  formedhadron.pos(pos_lab); formedhadron.P(Pbaryon);
2938 
2939  //setting hadron color tags (for tracing colors of the constituent partons) [**]
2940  //will need to update to reflect color tags given to random (thermal/lbt) partons
2941  formedhadron.add_col((considering[0].col()>0)?considering[0].col():considering[0].acol());
2942  formedhadron.add_col((considering[1].col()>0)?considering[1].col():considering[1].acol());
2943  formedhadron.add_col((considering[2].col()>0)?considering[2].col():considering[2].acol());
2944 
2945  //need to choose *what* hadron we've formed... base this on the parton id's, mass, & if excited
2946  //might want to do this differently? void f'n(partoncollection, formedhadron)?
2947  set_baryon_id(considering, formedhadron);
2948 
2949  //need to add the hadron to the collection
2950  HH_hadrons.add(formedhadron);
2951 
2952  //now that we've formed the hadron, need to set ALL (3) the 'considering' flags to used
2953  showerquarks[element[0]].status(1); showerquarks[element[0]].is_used(true);
2954  if(perm2[q2]>0){showerquarks[element[1]].status(1); showerquarks[element[1]].is_used(true);}
2955  else{ HH_thermal[-element[1]].status(1); HH_thermal[-element[1]].is_used(true);}
2956  if(perm2[q3]>0){showerquarks[element[2]].status(1); showerquarks[element[2]].is_used(true);}
2957  else{ HH_thermal[-element[2]].status(1); HH_thermal[-element[2]].is_used(true);}
2958 
2959  madehadron = true; considering.clear();
2960  break;
2961  }
2962  else{
2963  //since we've not formed a baryon on this try, need to revert the third quark 'considering' used flag
2964  if(perm2[q3]>0){showerquarks[element[2]].status(0);}
2965  else{ HH_thermal[-element[2]].status(0);}
2966 
2967  //and remove the third entry in considering
2968  considering.partons.pop_back();
2969  }
2970  }
2971  }else if(considering[0].id()*considering[1].id() < 0){
2972  //Key point is determing recofactor2
2973  if(considering[0].id() > 0 && considering[1].id() < 0){
2974  int tag0 = considering[0].col();
2975  int tag1 = considering[1].acol();
2976  if(tag0 > 0 && tag1 > 0 && tag0 <= limit && tag1 <= limit ){
2977  std::vector<int>::iterator L1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag0);
2978  std::vector<int>::iterator L2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
2979  int indexMatrix1 = std::distance(IndiceForColFin.begin(), L1);
2980  int indexMatrix2 = std::distance(IndiceForColFin.begin(), L2);
2981 
2982  recofactor2 = (MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2));
2983  //std::cout <<endl<<" the recofactor for meson is "<<(MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2))<<endl;
2984  }
2985  else{recofactor2 = 1./9.;}
2986  }
2987  else if(considering[1].id() > 0 && considering[0].id() < 0){
2988  int tag0 = considering[1].col();
2989  int tag1 = considering[0].acol();
2990  if(tag0 > 0 && tag1 > 0 && tag0 <= limit && tag1 <= limit){
2991  std::vector<int>::iterator L1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag0);
2992  std::vector<int>::iterator L2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
2993  int indexMatrix1 = std::distance(IndiceForColFin.begin(), L1);
2994  int indexMatrix2 = std::distance(IndiceForColFin.begin(), L2);
2995 
2996  recofactor2 = (MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2));
2997  }
2998  else{recofactor2 = 1./9.;}
2999  //std::cout <<endl<<" the recofactor for meson is "<<(MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2))<<endl;
3000  }
3001  //now that we *could* form a meson, now we check if we actually do form one
3002  //meson momentum
3003  FourVector Pmeson;
3004  Pmeson.Set(considering[0].px()+considering[1].px(),considering[0].py()+considering[1].py(),considering[0].pz()+considering[1].pz(),0.);
3005 
3006  //meson(CM) velocity
3007  FourVector betaM;
3008  betaM.Set(Pmeson.x()/(considering[0].e()+considering[1].e()),Pmeson.y()/(considering[0].e()+considering[1].e()),Pmeson.z()/(considering[0].e()+considering[1].e()),0.);
3009  betaM.Set(betaM.x(),betaM.y(),betaM.z(),1./(sqrt(1.-(betaM.x()*betaM.x() + betaM.y()*betaM.y() + betaM.z()*betaM.z()))));
3010 
3011  //boosting into CM frame
3012  FourVector pos_MCM[2], p_MCM[2];
3013  pos_MCM[0] = considering[0].boost_pos(betaM); pos_MCM[1] = considering[1].boost_pos(betaM);
3014  p_MCM[0] = considering[0].boost_P(betaM); p_MCM[1] = considering[1].boost_P(betaM);
3015 
3016  //velocities in CM frame
3017  FourVector v_MCM[2];
3018  v_MCM[0].Set(p_MCM[0].x()/p_MCM[0].t(),p_MCM[0].y()/p_MCM[0].t(),p_MCM[0].z()/p_MCM[0].t(),0.);
3019  v_MCM[1].Set(p_MCM[1].x()/p_MCM[1].t(),p_MCM[1].y()/p_MCM[1].t(),p_MCM[1].z()/p_MCM[1].t(),0.);
3020 
3021  //propagating quarks until time of youngest quark
3022  //is just max(pos_MCM[0].t(), pos_MCM[1].t());
3023  double curtime = (pos_MCM[0].t() > pos_MCM[1].t()) ? pos_MCM[0].t() : pos_MCM[1].t();
3024  FourVector cur_pos[2];
3025  cur_pos[0].Set(pos_MCM[0].x()+v_MCM[0].x()*(curtime-pos_MCM[0].t()),pos_MCM[0].y()+v_MCM[0].y()*(curtime-pos_MCM[0].t()),pos_MCM[0].z()+v_MCM[0].z()*(curtime-pos_MCM[0].t()),curtime);
3026  cur_pos[1].Set(pos_MCM[1].x()+v_MCM[1].x()*(curtime-pos_MCM[1].t()),pos_MCM[1].y()+v_MCM[1].y()*(curtime-pos_MCM[1].t()),pos_MCM[1].z()+v_MCM[1].z()*(curtime-pos_MCM[1].t()),curtime);
3027 
3028  //finding position of CM at curtime
3029  FourVector pos_CM;
3030  pos_CM.Set(
3031  (cur_pos[0].x()*considering[0].mass()+cur_pos[1].x()*considering[1].mass())/(considering[0].mass()+considering[1].mass()),
3032  (cur_pos[0].y()*considering[0].mass()+cur_pos[1].y()*considering[1].mass())/(considering[0].mass()+considering[1].mass()),
3033  (cur_pos[0].z()*considering[0].mass()+cur_pos[1].z()*considering[1].mass())/(considering[0].mass()+considering[1].mass()),
3034  curtime);
3035 
3036  //finding position of meson in lab frame
3037  betaM.Set(-betaM.x(),-betaM.y(),-betaM.z(),betaM.t());
3038  FourVector pos_lab = HHboost(betaM, pos_CM);
3039 
3040  //finding the squares of the relative momenta of partons in CM frame
3041  FourVector k_rel_square;
3042  double sum_mass_square = (considering[0].mass()+considering[1].mass())*(considering[0].mass()+considering[1].mass());
3043  k_rel_square.Set(std::pow(considering[1].mass()*p_MCM[0].x()-considering[0].mass()*p_MCM[1].x(),2.)/sum_mass_square,std::pow(considering[1].mass()*p_MCM[0].y()-considering[0].mass()*p_MCM[1].y(),2.)/sum_mass_square,std::pow(considering[1].mass()*p_MCM[0].z()-considering[0].mass()*p_MCM[1].z(),2.)/sum_mass_square,0.);
3044  k_rel_square.Set(k_rel_square.x(),k_rel_square.y(),k_rel_square.z(),k_rel_square.x()+k_rel_square.y()+k_rel_square.z());
3045 
3046  //finding the squares of relative positions of partons in CM frame
3047  FourVector pos_rel_square;
3048  pos_rel_square.Set((cur_pos[0].x()-cur_pos[1].x())*(cur_pos[0].x()-cur_pos[1].x()),(cur_pos[0].y()-cur_pos[1].y())*(cur_pos[0].y()-cur_pos[1].y()),(cur_pos[0].z()-cur_pos[1].z())*(cur_pos[0].z()-cur_pos[1].z()),0.);
3049  pos_rel_square.Set(pos_rel_square.x(),pos_rel_square.y(),pos_rel_square.z(),pos_rel_square.x()+pos_rel_square.y()+pos_rel_square.z());
3050 
3051  //setting appropriate sigma...
3052  double SigM2 = SigPi2;
3053  int sortid[2] = {0,0};
3054  if(std::abs(considering[0].id()) >= std::abs(considering[1].id())){sortid[0] = std::abs(considering[0].id()); sortid[1] = std::abs(considering[1].id());}
3055  else{sortid[0] = std::abs(considering[1].id()); sortid[1] = std::abs(considering[0].id());}
3056 
3057  if( sortid[0] == 3){
3058  if( sortid[1] == 3){SigM2 = SigPhi2;}
3059  else{ SigM2 = SigK2;}
3060  }
3061  else if(sortid[0] == 4){
3062  if( sortid[1] == 4){SigM2 = SigJpi2;}
3063  else if(sortid[1] == 3){SigM2 = SigDs2;}
3064  else{ SigM2 = SigD2;}
3065  }
3066  else if(sortid[0] == 5){
3067  if( sortid[1] == 5){SigM2 = SigUps2;}
3068  else if(sortid[1] == 4){SigM2 = SigBc2;}
3069  else if(sortid[1] == 3){SigM2 = SigB2;}
3070  else{ SigM2 = SigB2;}
3071  }
3072 
3073  double u[4];
3074  // This is the squared distance in phase space weighted with the widths
3075  u[1] = 0.5*(pos_rel_square.x()/SigM2 + k_rel_square.x()*SigM2/hbarc2);
3076  u[2] = 0.5*(pos_rel_square.y()/SigM2 + k_rel_square.y()*SigM2/hbarc2);
3077  u[3] = 0.5*(pos_rel_square.z()/SigM2 + k_rel_square.z()*SigM2/hbarc2);
3078  u[0] = u[1] + u[2] + u[3];
3079 
3080  // Ground state wave function
3081  double WigM = std::exp(-u[0]);
3082 
3083  // Computing s ~ L^2 for the system
3084  double rdotr = pos_rel_square.t();
3085  double pdotp = k_rel_square.t();
3086  double pdotr = std::sqrt(pos_rel_square.x())*std::sqrt(k_rel_square.x()) + std::sqrt(pos_rel_square.y())*std::sqrt(k_rel_square.y()) + std::sqrt(pos_rel_square.z())*std::sqrt(k_rel_square.z());
3087 
3088  double s = 1/hbarc2*(pdotp*rdotr - pdotr*pdotr);
3089 
3090  // Random number for recombination dice roll
3091  double rndmeson = ran();
3092 
3093  // Initialize quantum numbers and recombination probability
3094  int angular_qnum = -1; // l
3095  int radial_qnum = -1; // k
3096  double mult1 = considering[1].is_thermal() ? th_recofactor : sh_recofactor;
3097  double total_prob = WigM*recofactor2*mult1;
3098 
3099  if(total_prob >= rndmeson)
3100  {
3101  angular_qnum = 0;
3102  radial_qnum = 0;
3103  }
3104  else
3105  {
3106  total_prob += WigM*u[0];
3107  if(total_prob >= rndmeson && maxM_level>0)
3108  {
3109  angular_qnum = 1;
3110  radial_qnum = 0;
3111  }
3112  else
3113  {
3114  total_prob += (1./2.)*WigM*((2./3.)*std::pow(u[0],2) + (1./3.)*s);
3115  if(total_prob >= rndmeson && maxM_level>1)
3116  {
3117  angular_qnum = 2;
3118  radial_qnum = 0;
3119  }
3120  else
3121  {
3122  total_prob += (1./2.)*WigM*((1./3.)*std::pow(u[0],2) - (1./3.)*s);
3123  if(total_prob >= rndmeson && maxM_level>1 )
3124  {
3125  angular_qnum = 0;
3126  radial_qnum = 1;
3127  }
3128  else
3129  {
3130  total_prob += (1./6.)*WigM*((2./5.)*std::pow(u[0],3) + (3./5.)*u[0]*s);
3131  if(total_prob >= rndmeson && maxM_level>2)
3132  {
3133  angular_qnum = 1;
3134  radial_qnum = 1;
3135  }
3136  else
3137  {
3138  total_prob += (1./6.)*WigM*((3./5.)*std::pow(u[0],3) - (3./5.)*u[0]*s);
3139  if(total_prob >= rndmeson && maxM_level>2)
3140  {
3141  angular_qnum = 3;
3142  radial_qnum = 0;
3143  }
3144  else
3145  {
3146  total_prob += (1./120.)*WigM*std::pow((std::pow(u[0],2)-s),2);
3147  if(total_prob >= rndmeson && maxM_level>3)
3148  {
3149  angular_qnum = 0;
3150  radial_qnum = 2;
3151  }
3152  else
3153  {
3154  total_prob += (1./24.)*WigM*((4./7.)*std::pow(u[0],4)-(2./7.)*std::pow(u[0],2)*s-(2./7.)*std::pow(s,2));
3155  if(total_prob >= rndmeson && maxM_level>3)
3156  {
3157  angular_qnum = 2;
3158  radial_qnum = 1;
3159  }
3160  else
3161  {
3162  total_prob += (1./24.)*WigM*((8./35.)*std::pow(u[0],4)+(24./35.)*std::pow(u[0],2)*s+(3./35.)*std::pow(s,2));
3163  if(total_prob >= rndmeson && maxM_level>3)
3164  {
3165  angular_qnum = 4;
3166  radial_qnum = 0;
3167  }
3168  }
3169  }
3170  }
3171  }
3172  }
3173  }
3174  }
3175  }
3176 
3177  //Habemus Recombinationem!
3178  if(angular_qnum >= 0) {
3179  /*std::cout << "Mesons" << std::endl;
3180  std::cout << considering[0].id() << "," << considering[0].col() << "," << considering[0].acol() << std::endl;
3181  std::cout << considering[1].id() << "," << considering[1].col() << "," << considering[1].acol() << std::endl;*/
3182  if(considering[0].id() > 0 && considering[1].id() < 0){//case of first parton is q and second is q-bar
3183  //std::cout <<endl<<"chosen partons are "<< int(considering[0].id()) << " and " << int(considering[1].id()) << endl <<endl;
3184  //std::cout <<endl<<"and their color tag is "<< int(considering[0].col()) << " and " << int(considering[1].acol()) << endl <<endl;
3185  //std::cout <<"color correction implemented as Follows: "<< considering[0].col() <<" = " << considering[1].acol()<<endl;
3186 
3187  // Overwrite non-dominant colortags in tempjunctions with dominant ones
3188  // q-qbar case
3189  if(considering[0].col() != 0 && considering[1].acol() != 0){
3190  for(int ijunc=0; ijunc<Tempjunctions.size(); ijunc++){
3191  if(Tempjunctions.at(ijunc).at(1).at(1) == considering[1].acol()){
3192  Tempjunctions.at(ijunc).at(1).pop_back();
3193  Tempjunctions.at(ijunc).at(1).push_back(considering[0].col());
3194  }
3195  if(Tempjunctions.at(ijunc).at(2).at(1) == considering[1].acol()){
3196  Tempjunctions.at(ijunc).at(2).pop_back();
3197  Tempjunctions.at(ijunc).at(2).push_back(considering[0].col());
3198  }
3199  if(Tempjunctions.at(ijunc).at(3).at(1) == considering[1].acol()){
3200  Tempjunctions.at(ijunc).at(3).pop_back();
3201  Tempjunctions.at(ijunc).at(3).push_back(considering[0].col());
3202  }
3203  }
3204  }
3205 
3206  //before changing the tags, revise the MesonrecoMatrix elements!
3207  int coltag1 = considering[0].col();
3208  int coltag2 = considering[1].acol();
3209  if(coltag1 > 0 && coltag2 > 0 && coltag1 <= limit && coltag2 <= limit){
3210  std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
3211  std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
3212  int loc1 = std::distance(IndiceForColFin.begin(), I1);
3213  int loc2 = std::distance(IndiceForColFin.begin(), I2); //set up for find matrix indices corresponding to the color tags
3214 
3215 
3216  MesonrecoMatrix1.at(loc1).at(loc2) = 1;
3217  MesonrecoMatrix1.at(loc2).at(loc1) = 1; //Matrix revised
3218 
3219  for(int iM=0;iM<MesonrecoMatrix1[0].size();++iM){
3220  if(MesonrecoMatrix1[loc1][iM]==1){MesonrecoMatrix1[loc2][iM]=1;}
3221  if(MesonrecoMatrix1[loc2][iM]==1){MesonrecoMatrix1[loc1][iM]=1;}
3222  if(MesonrecoMatrix1[iM][loc1]==1){MesonrecoMatrix1[iM][loc2]=1;}
3223  if(MesonrecoMatrix1[iM][loc2]==1){MesonrecoMatrix1[iM][loc1]=1;}
3224  if(MesonrecoMatrix1[loc1][iM]==0){MesonrecoMatrix1[loc2][iM]=0;}
3225  if(MesonrecoMatrix1[loc2][iM]==0){MesonrecoMatrix1[loc1][iM]=0;}
3226  if(MesonrecoMatrix1[iM][loc1]==0){MesonrecoMatrix1[iM][loc2]=0;}
3227  if(MesonrecoMatrix1[iM][loc2]==0){MesonrecoMatrix1[iM][loc1]=0;}
3228  }
3229  /*
3230  std::cout <<endl<<"Revised Matrix is same as below"<<endl;
3231  for(int irow=0; irow < IndiceForColFin.size(); irow++){
3232  for(int icol=0; icol < IndiceForColFin.size(); icol++){
3233  std::cout <<" "<<MesonrecoMatrix1.at(irow).at(icol)<<" ";
3234  }
3235  std::cout <<endl<<endl;
3236  }
3237  */
3238  }
3239 
3240  //possible case MAT+LBT, MAT+THERM,
3241  //treatment 1 : based on distance.
3242  if(considering[0].col() > 0 && considering[1].acol() > 0){ //MAT/lbt or therm with color tags + MAT/lbt or therm with color tags
3243  if(perm2[q2] > 0){
3244  HH_showerptns[showerquarks[element[1]].par()].acol(considering[0].col());//now color tags from both partons are same
3245  //also need to set the remaining color tag in showerquarks (if present)
3246  for(int ishq=0;ishq<showerquarks.num();++ishq){
3247  if(!showerquarks[ishq].is_used() && showerquarks[ishq].col()==considering[1].acol()){
3248  showerquarks[ishq].col(considering[0].col());/*break;*/
3249  }
3250  }
3251  for(int ishq=0;ishq<HH_showerptns.num();++ishq){
3252  if(HH_showerptns[ishq].col()==considering[1].acol()){
3253  HH_showerptns[ishq].col(considering[0].col());/*break;*/
3254  }
3255  }
3256  }else{
3257  HH_thermal[-element[1]].acol(considering[0].col());
3258  }
3259  }else if(considering[0].col() > 0){ // MAT + LBT/THERM
3260  int loc = findcloserepl(considering[1] , perm2[q2], true, true, showerquarks, HH_thermal); // functon to find
3261  if(loc == 999999999){
3262  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3263  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.col(considering[0].col());
3264  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3265  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3266  fakep.e(fakep.mass());
3267  fakep.is_fakeparton(true);
3268  Extraparton.add(fakep);
3269  //somewhere, we need to make for loop to toss all partons to remnants list.
3270  }else if(loc < 0){
3271  HH_thermal[-loc-1].col(considering[0].col());
3272  }else{
3273  showerquarks[loc-1].col(considering[0].col());
3274  }
3275  }else if(considering[1].acol() > 0){ //LBT + MAT
3276  int loc = findcloserepl(considering[0] , perm1[q1]+1, true, true, showerquarks, HH_thermal);
3277  if(loc == 999999999){
3278  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3279  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.acol(considering[1].acol());
3280  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3281  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3282  fakep.e(fakep.mass());
3283  fakep.is_fakeparton(true);
3284  Extraparton.add(fakep);
3285  //somewhere, we need to make for loop to toss all partons to remnants list.
3286  }else if(loc < 0){
3287  HH_thermal[-loc-1].acol(considering[1].acol());
3288  }else{
3289  showerquarks[loc-1].acol(considering[1].acol());
3290  }
3291  }
3292  }else if(considering[0].id() < 0 && considering[1].id() > 0){//case of first parton is q-bar and second is q
3293  //std::cout <<endl<<"chosen partons are "<< int(considering[0].id()) << " and " << int(considering[1].id()) << endl <<endl;
3294  //std::cout <<endl<<"and their color tag is "<< int(considering[0].acol()) << " and " << int(considering[1].col()) << endl <<endl;
3295  //std::cout <<"color correction implemented as Follows: "<< considering[0].acol()<<" = "<<considering[1].col()<<endl;
3296 
3297  // Overwrite non-dominant colortags in tempjunctions with dominant ones
3298  // qbar-q case
3299  if(considering[0].acol() != 0 && considering[1].col() != 0){
3300  for(int ijunc=0; ijunc<Tempjunctions.size(); ijunc++){
3301  if(Tempjunctions.at(ijunc).at(1).at(1) == considering[1].col()){
3302  Tempjunctions.at(ijunc).at(1).pop_back();
3303  Tempjunctions.at(ijunc).at(1).push_back(considering[0].acol());
3304  }
3305  if(Tempjunctions.at(ijunc).at(2).at(1) == considering[1].col()){
3306  Tempjunctions.at(ijunc).at(2).pop_back();
3307  Tempjunctions.at(ijunc).at(2).push_back(considering[0].acol());
3308  }
3309  if(Tempjunctions.at(ijunc).at(3).at(1) == considering[1].col()){
3310  Tempjunctions.at(ijunc).at(3).pop_back();
3311  Tempjunctions.at(ijunc).at(3).push_back(considering[0].acol());
3312  }
3313  }
3314  }
3315 
3316  //before changing the tags, revise the MesonrecoMatrix elements!
3317  int coltag1 = considering[0].acol();
3318  int coltag2 = considering[1].col();
3319  if(coltag1 > 0 && coltag2 > 0 && coltag1 <= limit && coltag2 <= limit){
3320  std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
3321  std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
3322  int loc1 = std::distance(IndiceForColFin.begin(), I1);
3323  int loc2 = std::distance(IndiceForColFin.begin(), I2); //set up for find matrix indices corresponding to the color tags
3324 
3325  MesonrecoMatrix1.at(loc1).at(loc2) = 1;
3326  MesonrecoMatrix1.at(loc2).at(loc1) = 1; //Matrix revised
3327 
3328  for(int iM=0;iM<MesonrecoMatrix1[0].size();++iM){
3329  if(MesonrecoMatrix1[loc1][iM]==1){MesonrecoMatrix1[loc2][iM]=1;}
3330  if(MesonrecoMatrix1[loc2][iM]==1){MesonrecoMatrix1[loc1][iM]=1;}
3331  if(MesonrecoMatrix1[iM][loc1]==1){MesonrecoMatrix1[iM][loc2]=1;}
3332  if(MesonrecoMatrix1[iM][loc2]==1){MesonrecoMatrix1[iM][loc1]=1;}
3333  if(MesonrecoMatrix1[loc1][iM]==0){MesonrecoMatrix1[loc2][iM]=0;}
3334  if(MesonrecoMatrix1[loc2][iM]==0){MesonrecoMatrix1[loc1][iM]=0;}
3335  if(MesonrecoMatrix1[iM][loc1]==0){MesonrecoMatrix1[iM][loc2]=0;}
3336  if(MesonrecoMatrix1[iM][loc2]==0){MesonrecoMatrix1[iM][loc1]=0;}
3337  }
3338  }
3339  /*
3340  std::cout <<endl<<"Revised Matrix is same as below"<<endl;
3341  for(int irow=0; irow < IndiceForColFin.size(); irow++){
3342  for(int icol=0; icol < IndiceForColFin.size(); icol++){
3343  std::cout <<" "<<MesonrecoMatrix1.at(irow).at(icol)<<" ";
3344  }
3345  std::cout <<endl<<endl;
3346  }*/
3347  if(considering[0].acol() > 0 && considering[1].col() > 0){ //MAT + MAT
3348  if(perm2[q2] > 0){
3349  HH_showerptns[showerquarks[element[1]].par()].col(considering[0].acol());//now color tags from both partons are same
3350  //also need to set the remaining color tag in showerquarks (if present)
3351  for(int ishq=0;ishq<showerquarks.num();++ishq){
3352  if(!showerquarks[ishq].is_used() && showerquarks[ishq].acol()==considering[1].col()){
3353  showerquarks[ishq].acol(considering[0].acol());/*break;*/
3354  }
3355  }
3356  for(int ishq=0;ishq<HH_showerptns.num();++ishq){
3357  if(HH_showerptns[ishq].acol()==considering[1].col()){
3358  HH_showerptns[ishq].acol(considering[0].acol());/*break;*/
3359  }
3360  }
3361  }else{
3362  HH_thermal[-element[1]].col(considering[0].acol());
3363  }
3364  }else if(considering[0].acol() > 0){ // MAT + LBT/THERM
3365  int loc = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal );
3366  if(loc == 999999999){
3367  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3368  HHparton fakep = considering[1]; fakep.id(-fakep.id()); fakep.acol(considering[0].acol());
3369  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3370  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3371  fakep.e(fakep.mass());
3372  fakep.is_fakeparton(true);
3373  Extraparton.add(fakep);
3374  //somewhere, we need to make for loop to toss all partons to remnants list.
3375  }else if (loc > 0){
3376  showerquarks[loc-1].acol(considering[0].acol());
3377  }else if(loc < 0){
3378  HH_thermal[-loc-1].acol(considering[0].acol());
3379  }
3380  }
3381  else if(considering[1].col() > 0){ //LBT + MAT
3382  int loc = findcloserepl(considering[0], perm1[q1]+1, true, true, showerquarks, HH_thermal );
3383  if(loc == 999999999){
3384  //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3385  HHparton fakep = considering[0]; fakep.id(-fakep.id()); fakep.col(considering[1].col());
3386  fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3387  fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3388  fakep.e(fakep.mass());
3389  fakep.is_fakeparton(true);
3390  Extraparton.add(fakep);
3391  //somewhere, we need to make for loop to toss all partons to remnants list.
3392  }else if (loc > 0){
3393  showerquarks[loc-1].col(considering[1].col());
3394  }else if(loc < 0){
3395  HH_thermal[-loc-1].col(considering[1].col());
3396  }
3397  }
3398  //now color tags from both partons are same
3399  }
3400 
3401  //now we're forming the hadron
3402  HHhadron formedhadron;
3403  //setting the hadron values: is a recombined hadron, mass, and parents - setting the par3 flag to 999999 to denote the lack of a 3rd parent parton
3404  formedhadron.is_recohad(true); formedhadron.mass( p_MCM[0].t() + p_MCM[1].t() );
3405  //formedhadron.par1 = element[0]; formedhadron.par2 = element[1]; formedhadron.par3 = 999999;
3406  formedhadron.add_par(showerquarks[element[0]].par());
3407  if(perm2[q2]>0){formedhadron.add_par(showerquarks[element[1]].par());}else{formedhadron.add_par(element[1]);}
3408 
3409  //now setting if meson is in excited state
3410  if(angular_qnum + radial_qnum > 0){formedhadron.is_excited(true);}
3411 
3412  //setting if there are any thermal partons used to make the hadron: (setting the '0' thermal parent to -99999 so that it doesn't conflict with '0' shower parton)
3413  if( perm2[q2]>0){/*is sh-sh*/ formedhadron.is_shsh(true);}
3414  else if(perm2[q2]<0){/*is sh-th*/ formedhadron.is_shth(true); if(element[1] == 0){formedhadron.parents[1] = -99999;}}
3415 
3416  //setting hadron position and momentum vectors
3417  Pmeson.Set(Pmeson.x(),Pmeson.y(),Pmeson.z(),sqrt(Pmeson.x()*Pmeson.x() + Pmeson.y()*Pmeson.y() + Pmeson.z()*Pmeson.z() + formedhadron.mass()*formedhadron.mass()));
3418  formedhadron.pos(pos_lab); formedhadron.P(Pmeson);
3419 
3420  //setting hadron color tags (for tracing colors of the constituent partons)
3421  //will need to update to reflect color tags given to random (thermal/lbt) partons [**]
3422  if(considering[0].id()>0){formedhadron.add_col(considering[0].col()); formedhadron.add_col(considering[1].acol());}
3423  else{formedhadron.add_col(considering[1].col()); formedhadron.add_col(considering[0].acol());}
3424 
3425  //need to choose *what* hadron we've formed... base this on the parton id's, mass, & if excited
3426  set_meson_id(considering, formedhadron, angular_qnum, radial_qnum);
3427 
3428  //need to add the hadron to the collection
3429  HH_hadrons.add(formedhadron);
3430 
3431  //now that we've formed the hadron, need to set ALL (both) the 'considering' flags to used
3432  showerquarks[element[0]].status(1); showerquarks[element[0]].is_used(true);
3433  if(perm2[q2]>0){showerquarks[element[1]].status(1); showerquarks[element[1]].is_used(true);}
3434  else{ HH_thermal[-element[1]].status(1); HH_thermal[-element[1]].is_used(true);}
3435 
3436  //now that we've formed the hadron, break to first loop here!
3437  madehadron = true; considering.clear();
3438  break;
3439  }
3440  }
3441 
3442  //if we've formed a hadron - break to first loop
3443  if(madehadron){break;}
3444 
3445  //since we CAN'T form a baryon on this try, need to revert the second quark 'considering' used flag
3446  if(perm2[q2]>0){showerquarks[element[1]].status(0);}
3447  else{ HH_thermal[-element[1]].status(0);}
3448 
3449  //and remove the second entry in considering (putting in if statement in case we tried and failed to make a hadron;
3450  considering.partons.pop_back();
3451  }
3452  //if we've formed a hadron - continue to next parton in first loop...
3453  if(madehadron){continue;}
3454 
3455  //since we've not formed a hadron with the first quark, need to revert the first quark 'considering' used flag
3456  //only need to reset these for shower quarks as the first quark cannot be a thermal quark
3457  //and remove the first(only) entry in considering
3458  showerquarks[element[0]].status(0); considering.partons.pop_back();
3459  }
3460 
3461  //all possibilities have been considered, all used quark flags for showerquarks are set appropriately
3462  //time for cleanup
3463 
3464  //set the used quarks in the original shower to reflect that they were used in reco module and that they were actually used
3465  //set the fully used gluons in the original shower to reflect that they were used in reco module and that they were actually used
3466  //set the partially used gluons in the original shower to reflect that they were used in reco module and that they were actually used
3467  //give used quarks and fully used gluons a status of '1'; give partially used gluons a status of '-1'
3468  //stick all unused quarks and 'completely' unused gluons into remnants (make sure to set the parents to the original shower partons appropriately)
3469  //write updated string information into shower, so that it is set properly in remnants
3470  //for the thermal array, all the used flags should already be set (and have a status of '1')
3471  //if this is used in a loop (as the original version should be doing) - those will have to be reset before reuse
3472  //otherwise, this is perfect for medium feedback
3473 
3474  //using quarks in showerquarks to set the flags appropriately for partons in shower
3475  for(int i=0; i<showerquarks.num(); ++i){
3476  //if we have a quark in the original shower
3477  if((std::abs(HH_showerptns[showerquarks[i].par()].id()) <= 5) && (showerquarks[i].is_used())){
3478  HH_showerptns[showerquarks[i].par()].is_used(true);
3479  HH_showerptns[showerquarks[i].par()].status(1);
3480  HH_showerptns[showerquarks[i].par()].used_reco(true);
3481  }
3482  //if this quark is from a split gluon in the original shower
3483  else if(std::abs(HH_showerptns[showerquarks[i].par()].id()) == 21 && showerquarks[i].is_used()){
3484  //if this is the first used quark in a splitting, set the parent gluon to used, and status of -1
3485  if(HH_showerptns[showerquarks[i].par()].status() == -99){
3486  HH_showerptns[showerquarks[i].par()].status(-1);
3487  HH_showerptns[showerquarks[i].par()].is_used(true);
3488  HH_showerptns[showerquarks[i].par()].used_reco(true);
3489  }
3490  //if this is the second (last) used quark in a splitting, set the status to 1
3491  else if(HH_showerptns[showerquarks[i].par()].status() == -1){
3492  HH_showerptns[showerquarks[i].par()].status(1);
3493  }
3494  //remove this check if it never throws.
3495  else{JSWARN << "SOMETHING HAS GONE VERY WRONG WITH REFORMING GLUON IN POS: " << showerquarks[i].par(); int val; showerquarks[i].par(0);}
3496  }
3497  }
3498  //need to run back through shower; if there are any gluons that didn't get used at all in the shower - restore them (and output to remnants below)
3499  for(int i=0; i<HH_showerptns.num(); ++i){
3500  if(HH_showerptns[i].status() == -99){
3501  HH_showerptns[i].is_decayedglu(false);
3502  HH_showerptns[i].status(0);
3503  }
3504  }
3505 
3506  //need to update string information in shower from showerquarks
3507  for(int i=0; i<HH_showerptns.num(); ++i){
3508  if(!HH_showerptns[i].is_used()){
3509  for(int j=0; j<showerquarks.num(); ++j){
3510  if(showerquarks[j].par() == i && !showerquarks[j].is_used()){
3511  HH_showerptns[i].string_id( showerquarks[j].string_id());
3512  HH_showerptns[i].is_strendpt( showerquarks[j].is_strendpt());
3513  HH_showerptns[i].pos_str( showerquarks[j].pos_str());
3514  HH_showerptns[i].endpt_id( showerquarks[j].endpt_id());
3515  break;
3516  }
3517  }
3518  }
3519  }
3520  //now all the partons in shower have had flags appropriately set; the 'partially' used gluons have a status of -1
3521 
3522  //TODO: here we need new function to find thermal sibling for gluon
3523  //sol 1 : gluon loops.
3524  //sol 2 : decay gluon find pairs.{concern : energy conservation violated}
3525  //sol 3 : find two theraml siblings for gluon. declare fincloserepl twice. first pick quark and antiquarks to the 2nd.--> this is chosen
3526  for(int i = 0; i < HH_showerptns.num(); i++){
3527  if(HH_showerptns[i].is_used()){continue;}
3528  if(HH_showerptns[i].id() == 21 && HH_showerptns[i].col() == 0 && HH_showerptns[i].acol() == 0){
3529  int sel_out[2] = { 0 , 0 };
3530  findcloserepl_glu(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal, sel_out);
3531  if(sel_out[0] == 999999999 || sel_out[1] == 999999999){
3532  HHparton fakeg = HH_showerptns[i]; fakeg.id(21); fakeg.acol(++maxtag); fakeg.col(++maxtag);
3533  fakeg.mass(1e-6);
3534  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3535  fakeg.px(fake_pT * cos(fake_phi)); fakeg.py(fake_pT * sin(fake_phi));
3536  fakeg.pz(0.);
3537  fakeg.e(std::sqrt(fakeg.px()*fakeg.px() + fakeg.py()*fakeg.py() + fakeg.pz()*fakeg.pz() + fakeg.mass()*fakeg.mass()));
3538  fakeg.orig(-1); fakeg.is_remnant(true);
3539  fakeg.is_fakeparton(true);
3540  Extraparton.add(fakeg); HH_showerptns[i].col(fakeg.acol()); HH_showerptns[i].acol(fakeg.col());
3541  }else if(sel_out[0] > 0){
3542  HH_showerptns[sel_out[0]-1].col(++maxtag);
3543  HH_showerptns[i].acol(maxtag);
3544  }else if(sel_out[0] < 0){
3545  HH_thermal[-sel_out[0]-1].col(++maxtag);
3546  HH_showerptns[i].acol(maxtag);
3547  }
3548 
3549  if(sel_out[1] > 0 && sel_out[1] != 999999999 && sel_out[0] != 999999999){
3550  HH_showerptns[sel_out[1]-1].acol(++maxtag);
3551  HH_showerptns[i].col(maxtag);
3552  }else if(sel_out[1] < 0 && sel_out[1] != 999999999 && sel_out[0] != 999999999){
3553  HH_thermal[-sel_out[1]-1].acol(++maxtag);
3554  HH_showerptns[i].col(maxtag);
3555  }
3556  }else if(HH_showerptns[i].id() == 21 && (HH_showerptns[i].col() == 0 || HH_showerptns[i].acol() == 0)){ //gluon that needs a single quark to fix
3557  if(HH_showerptns[i].col() == 0){
3558  HH_showerptns[i].id(1); //need to temporarily pretend gluon is a quark, swap back id after...
3559  int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3560  HH_showerptns[i].id(21);
3561  if(loc == 999999999){
3562  double fid = (ran() > 0.5) ? -1 : -2;
3563  HHparton fakep = HH_showerptns[i]; fakep.id(fid); fakep.acol(++maxtag);
3564  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3565  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3566  if (number_p_fake == 0 || number_p_fake == 2){
3567  fakep.pz(-p_fake);
3568  } else if (number_p_fake == 1 || number_p_fake == 3) {
3569  fakep.pz(p_fake);
3570  } else {fakep.pz(0.);}
3571  number_p_fake++;
3572  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3573  fakep.orig(-1); fakep.is_remnant(true);
3574  fakep.is_fakeparton(true);
3575  Extraparton.add(fakep);
3576  }
3577  else if (loc > 0){HH_showerptns[loc - 1].acol(++maxtag); }
3578  else if(loc < 0){HH_thermal[-loc - 1].acol(++maxtag); }
3579 
3580  HH_showerptns[i].col(maxtag);
3581  }else if(HH_showerptns[i].acol() == 0){
3582  HH_showerptns[i].id(-1); //need to temporarily pretend gluon is an antiquark, swap back id after...
3583  int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3584  HH_showerptns[i].id(21);
3585  if(loc == 999999999){
3586  double fid = (ran() > 0.5) ? 1 : 2;
3587  HHparton fakep = HH_showerptns[i]; fakep.id(fid); fakep.col(++maxtag);
3588  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3589  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3590  if (number_p_fake == 0 || number_p_fake == 2){
3591  fakep.pz(-p_fake);
3592  } else if (number_p_fake == 1 || number_p_fake == 3) {
3593  fakep.pz(p_fake);
3594  } else {fakep.pz(0.);}
3595  number_p_fake++;
3596  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3597  fakep.orig(-1); fakep.is_remnant(true);
3598  fakep.is_fakeparton(true);
3599  Extraparton.add(fakep);
3600  }
3601  else if (loc > 0){HH_showerptns[loc - 1].col(++maxtag); }
3602  else if(loc < 0){HH_thermal[-loc - 1].col(++maxtag); }
3603 
3604  HH_showerptns[i].acol(maxtag);
3605  }
3606  }else if(HH_showerptns[i].id() > 0 && HH_showerptns[i].col() == 0){
3607  int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3608  if(loc == 999999999){
3609  double fid = (ran() > 0.5) ? -1 : -2;
3610  HHparton fakep = HH_showerptns[i]; fakep.id(fid); fakep.acol(++maxtag);
3611  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3612  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3613  if (number_p_fake == 0 || number_p_fake == 2){
3614  fakep.pz(-p_fake);
3615  } else if (number_p_fake == 1 || number_p_fake == 3) {
3616  fakep.pz(p_fake);
3617  } else {fakep.pz(0.);}
3618  number_p_fake++;
3619  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3620  fakep.orig(-1); fakep.is_remnant(true);
3621  fakep.is_fakeparton(true);
3622  Extraparton.add(fakep);
3623  }
3624  else if (loc > 0){HH_showerptns[loc - 1].acol(++maxtag); }
3625  else if(loc < 0){HH_thermal[-loc - 1].acol(++maxtag); }
3626 
3627  HH_showerptns[i].col(maxtag);
3628  }else if(HH_showerptns[i].id() < 0 && HH_showerptns[i].acol() == 0){
3629  int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3630  if(loc == 999999999){
3631  double fid = (ran() > 0.5) ? 1 : 2;
3632  HHparton fakep = HH_showerptns[i]; fakep.id(fid); fakep.col(++maxtag);
3633  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3634  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3635  if (number_p_fake == 0 || number_p_fake == 2){
3636  fakep.pz(-p_fake);
3637  } else if (number_p_fake == 1 || number_p_fake == 3) {
3638  fakep.pz(p_fake);
3639  } else {fakep.pz(0.);}
3640  number_p_fake++;
3641  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3642  fakep.orig(-1); fakep.is_remnant(true);
3643  fakep.is_fakeparton(true);
3644  Extraparton.add(fakep);
3645  }
3646  else if (loc > 0){HH_showerptns[loc - 1].col(++maxtag); }
3647  else if(loc < 0){HH_thermal[-loc - 1].col(++maxtag); }
3648 
3649  HH_showerptns[i].acol(maxtag);
3650  }
3651  }
3652  //sticking all unused partons into remnants; keeping order intact (a partially used gluon is replaced with it's unused quark)
3653  for(int i=0; i < HH_showerptns.num(); ++i){
3654  //if unused parton, write into remnants
3655  if(HH_showerptns[i].status() == 0){
3656  HH_remnants.add(HH_showerptns[i]);
3657  HH_remnants[HH_remnants.num() - 1].par(i);
3658  HH_showerptns[i].is_remnant(true);
3659  }
3660  //if 'partially' used gluon, write unused daughter quark into remnants
3661  else if(HH_showerptns[i].status() == -1){
3662  //finding the unused quark for this gluon and adding it to remnants (have to loop over as we only keep track of parents, not daughters)
3663  for(int j=0; j<showerquarks.num(); ++j){if(showerquarks[j].par() == i && !showerquarks[j].is_used()){
3664  if(showerquarks[j].col() == 0 && showerquarks[j].id() > 0){ //quark with zero col tag is left,
3665  int loc = findcloserepl(showerquarks[j], j+1, true, true, HH_showerptns, HH_thermal );
3666  if(loc == 999999999){
3667  double fid = (ran() > 0.5) ? -1 : -2;
3668  HHparton fakep = showerquarks[j]; fakep.id(fid); fakep.acol(++maxtag);
3669  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3670  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3671  if (number_p_fake == 0 || number_p_fake == 2){
3672  fakep.pz(-p_fake);
3673  } else if (number_p_fake == 1 || number_p_fake == 3) {
3674  fakep.pz(p_fake);
3675  } else {fakep.pz(0.);}
3676  number_p_fake++;
3677  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3678  fakep.orig(-1); fakep.is_remnant(true);
3679  fakep.is_fakeparton(true);
3680  Extraparton.add(fakep);
3681  }
3682  else if (loc > 0){HH_showerptns[loc - 1].acol(++maxtag); }
3683  else if(loc < 0){HH_thermal[-loc - 1].acol(++maxtag); }
3684 
3685  showerquarks[j].col(maxtag);
3686  }else if(showerquarks[j].acol() == 0 && showerquarks[j].id() < 0){ //antiquark with zero col tag is left,
3687  int loc = findcloserepl(showerquarks[j], j+1, true, true, HH_showerptns, HH_thermal );
3688  if(loc == 999999999){
3689  double fid = (ran() > 0.5) ? 1 : 2;
3690  HHparton fakep = showerquarks[j]; fakep.id(fid); fakep.col(++maxtag);
3691  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3692  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3693  if (number_p_fake == 0 || number_p_fake == 2){
3694  fakep.pz(-p_fake);
3695  } else if (number_p_fake == 1 || number_p_fake == 3) {
3696  fakep.pz(p_fake);
3697  } else {fakep.pz(0.);}
3698  number_p_fake++;
3699  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3700  fakep.orig(-1); fakep.is_remnant(true);
3701  fakep.is_fakeparton(true);
3702  Extraparton.add(fakep);
3703  }
3704  else if (loc > 0){HH_showerptns[loc - 1].col(++maxtag); }
3705  else if(loc < 0){HH_thermal[-loc - 1].col(++maxtag); }
3706 
3707  showerquarks[j].acol(maxtag);
3708  }
3709 
3710  HH_remnants.add(showerquarks[j]); break;
3711  }}
3712  HH_showerptns[i].is_remnant(true);
3713  }
3714  }
3715 
3716  //appending the thermal partons used in the string repair functionality into remnants
3717  for(int i=0; i < HH_thermal.num(); ++i){
3718  //if this thermal parton is ... then add it to the remnants collection
3719  if(HH_thermal[i].is_used()){
3720  HH_thermal[i].status(1);
3721  HH_thermal[i].used_reco(true);
3722  continue;
3723  }
3724  if(HH_thermal[i].col() > 0 || HH_thermal[i].acol() > 0){
3725  //std::cout << "Thermal parton added to remnants: " << HH_thermal[i].id() << "," << HH_thermal[i].col() << "," << HH_thermal[i].acol() << std::endl;
3726  HH_remnants.add(HH_thermal[i]);
3727  HH_remnants[HH_remnants.num() - 1].par(-i-1);
3728  HH_thermal[i].is_remnant(true);
3729  HH_thermal[i].is_used(true);
3730  }
3731  }
3732 
3733  for(int i = 0; i < Extraparton.num(); ++i ){
3734  HH_remnants.add(Extraparton[i]);
3735  Extraparton[i].is_used(true); // use the extrapartons during hadronizations of negative partons (background subtraction)
3736 
3737  if(Extraparton[i].id() == 21){
3738  HHparton fakep1 = Extraparton[i];
3739  fakep1.id(1); fakep1.acol(0);
3740  fakep1.px(fakep1.px()/2.); fakep1.py(fakep1.py()/2.); fakep1.pz(fakep1.pz()/2.); fakep1.mass(xmq);
3741  fakep1.e(std::sqrt(fakep1.px()*fakep1.px()+fakep1.py()*fakep1.py()+fakep1.pz()*fakep1.pz()+fakep1.mass()*fakep1.mass()));
3742 
3743  HHparton fakep2 = Extraparton[i];
3744  fakep2.id(-1); fakep2.col(0);
3745  fakep2.px(fakep2.px()/2.); fakep2.py(fakep2.py()/2.); fakep2.pz(fakep2.pz()/2.); fakep2.mass(xmq);
3746  fakep2.e(std::sqrt(fakep2.px()*fakep2.px()+fakep2.py()*fakep2.py()+fakep2.pz()*fakep2.pz()+fakep2.mass()*fakep2.mass()));
3747 
3748  HH_recomb_extrapartons.add(fakep1);
3749  HH_recomb_extrapartons.add(fakep2);
3750  } else {
3751  HH_recomb_extrapartons.add(Extraparton[i]);
3752  }
3753  }
3754 
3755  //hadrons have been recombined, and output to hadron collection
3756  //remnants have been collected, and output to remnant collection
3757  //shower partons have all been updated appropriately
3758  //thermal partons have all been updated appropriately - make sure that the thermal partons are reset before the recomb module is called again...
3759 
3760  //end of recombination routine
3761 }
3762 
3763 //sets id of formed baryon based on quark content, mass of quark system, and if the baryon formed into an excited state
3765 
3766  //assigning quark_ids in descending order to construct baryon id
3767  int id[3] = {qrks[0].id(), qrks[1].id(), qrks[2].id()};
3768  std::sort(id, id + 3, [](int a, int b) { return std::abs(a) > std::abs(b); });
3769 
3770  /*//http://pdg.lbl.gov/2017/listings/contents_listings.html
3771  double mdelta, msigma, mlambda, mxi, mdelE, msigmaE, mxiE, momega;
3772  mdelta = 1.232;
3773  msigma = 1.190;
3774  msigmaE = 1.382;
3775  mlambda = 1.115;
3776  mxi = 1.315;
3777  mxiE = 1.530;
3778  momega = 1.672;
3779  // ^^^^^ MIGHT NOT NEED MASSES BUT KEEP FOR NOW ^^^^^^
3780  */
3781  //id and mass list:
3782  //ground state: (111, 222, 333 configurations prohibited...)
3783  // 2212, 2112 - .938 p,n
3784  // 3222, 3212, 3112 - 1.190 sigma; 3122 - 1.115 lambda
3785  // 3322, 3312 - 1.315 xi
3786  //
3787  //excited:
3788  // 2224, 2214, 2114, 1114 - 1.232 delta
3789  // 3224, 3214, 3114 - 1.190 sigma;
3790  // 3324, 3314 - 1.315 xi
3791  // 3334 - 1.672 omega
3792  // ^^^^^ MIGHT NOT NEED BUT KEEP FOR NOW ^^^^^^
3793 
3794  if(id[0]==id[1] && id[0]==id[2]){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+4 );} // J=3/2 only
3795  else if(id[0]==id[1] || id[0]==id[2] || id[1]==id[2]){
3796  if(ran()>0.333){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+4 );} // J=3/2
3797  else{ had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+2 );}
3798  }
3799  else{
3800  double prb = ran();
3801  if( prb>0.333){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+4 );} // J=3/2
3802  else if(prb>0.166){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+2 );} // J=1/2 higher mass
3803  else{ had.id( 1000*std::abs(id[0]) + 10*std::abs(id[1]) + 100*std::abs(id[2])+2 );} // J=1/2 lower mass
3804  } // note the swap of quark index in last line
3805 
3806  // This would be how to make excited N, Delta and Lambda. RIGHT NOW DISABLED IN FIRST IF STATEMENT
3807  //there are no excited baryon codes of this form; there are only spin excited states in PYTHIA's ParticleData class
3808  //if(false && had.is_excited){
3809  // if(had.id == 2212 || had.id == 2112 || had.id == 2214 || had.id == 2114 || had.id == 2224 || had.id ==1114 || had.id == 3122){
3810  // had.id += 100000; // This needs to be adjusted to make the actual excited baryon codes
3811  // }
3812  //}
3813 
3814  had.id(had.id() * (id[0] < 0 ? -1 : 1));
3815  return;
3816 }
3817 
3818 //sets id of formed meson based on quark content, mass of quark system, and if the meson formed into an excited state
3820 
3821  //assigning quark_ids in descending order to construct meson id
3822  int id[2] = {qrks[0].id(), qrks[1].id()};
3823  if(std::abs(qrks[1].id()) > std::abs(qrks[0].id())){
3824  std::swap(id[0], id[1]);
3825  }
3826 
3827  // Don't need the following any more
3828  // double mass_pi0, mass_eta, mass_omegam, mass_etap, mass_phi; //mass_rho;
3829  // mass_pi0 = 0.1349770;
3830  // mass_eta = 0.547862;
3831  // mass_rho = 0.7690;
3832  // mass_omegam = 0.78265;
3833  // mass_etap = 0.95778;
3834  // mass_phi = 1.019460;
3836 
3837  int baseid = 0;
3838 
3839  // Determine spin quantum number statistically
3840  int spin_qnum = (ran() > 0.25) ? 1 : 0;
3841 
3842  // Determine total angular momentum statistically
3843  int j_qnum = spin_qnum;
3844  if(l > 0 && spin_qnum == 1){
3845  double random = ran();
3846 
3847  if((2.*l-1.)/(3.*(2.*l+1.)) >= random){j_qnum = l - 1;}
3848  else if(1./3. + (2.*l-1.)/(3.*(2.*l+1.)) >= random){j_qnum = l;}
3849  else{j_qnum = l + 1;}
3850  }
3851  else if (spin_qnum == 0){j_qnum = l;}
3852 
3853  // All meson quantum numbers are now known
3854 
3855  int basesign = 1;
3856  //if isospin I3=0
3857  if(id[0] == -id[1]){
3858  if(ran() > 0.25){ //spin triplet
3859  if(std::abs(id[0])==5){baseid = 550;} // Upsilon
3860  if(std::abs(id[0])==4){baseid = 440;} // J/psi
3861  if(std::abs(id[0])==3){baseid = 330;} // phi
3862  if((std::abs(id[0])==1) || (std::abs(id[0]) == 2)){
3863  if(ran()>0.5){baseid = 220;} else{baseid = 110;}
3864  } // omega and rho
3865  }
3866  else{ // spin singlet
3867  if(std::abs(id[0])==5){baseid = 550; } // etaB
3868  if(std::abs(id[0])==4){baseid = 440; } // etac
3869  if(std::abs(id[0])==3){if(ran()>0.666){baseid = 330;} else{baseid = 220;}} // eta' and eta
3870  if(std::abs(id[0])<3){
3871  double prb = ran();
3872  if(prb>0.5){baseid = 110;} // pi0
3873  else if(prb>0.333){baseid = 220;} // eta
3874  else{baseid = 330;} // eta'
3875  }
3876  }
3877  }
3878  // if isospin I3 not 0
3879  else{
3880  baseid = 100*std::abs(id[0])+10*std::abs(id[1]);
3881  if(id[0]%2 == 0){basesign = 2*std::signbit(-id[0])-1;}
3882  else{ basesign = 2*std::signbit( id[0])-1;}
3883  }
3884 
3885  // Put everything together: first digit (from the right)
3886  if(j_qnum < 5){baseid += 2*j_qnum + 1;}
3887  else{baseid += 8;}
3888 
3889  // 5th digit
3890  if(l > 0 && spin_qnum == 0){baseid += 10000;}
3891  else if(l > 0 && spin_qnum == 1 && l == j_qnum){baseid += 20000;}
3892  else if(l > 1 && spin_qnum == 1 && l == j_qnum + 1){baseid += 30000;}
3893  else if(l == 1 && spin_qnum == 1 && l == j_qnum + 1){baseid += 10000;}
3894 
3895  // 6th digit
3896  if(k < 10){baseid += k*100000;}
3897  else{baseid += 900000;}
3898 
3899  // If we don't want Goldstone bosons convert them to vector mesons here
3900  if(!goldstonereco){
3901  if(baseid == 211){baseid = 213;} //fixed pi+- -> rho+-
3902  if(baseid == 311){baseid = 313;} // fixed for K+- -> K*+-
3903  if(baseid == 321){baseid = 323;} // fixed for K0 -> K*0
3904  if(baseid == 111){baseid = 113;} //fixed for pi0 -> rho0
3905  }
3906 
3907  baseid *= basesign;
3908 
3909  had.id( baseid );
3910  return;
3911 }
3912 
3913 //gluon decay function
3915 
3916  HHparton q1, q2;
3917  //these are placeholders - might want to instead use values directly from partons...
3918  double qmass, glu_e;
3919 
3920  //if set to already be not on-shell, but not initially set!
3921  //glu.mass = sqrt(glu.e()*glu.e() - glu.px()*glu.px() - glu.py()*glu.py() - glu.pz()*glu.pz());
3922  //glu_e = glu.e();
3923  glu_e = sqrt(glu.mass()*glu.mass() + glu.px()*glu.px() + glu.py()*glu.py() + glu.pz()*glu.pz());
3924 
3925  //choosing qqbar ids (u, d, or s)
3926  //assuming that xms >= xmq (bad things *could* happen if not...)
3927  if(glu.mass() > 2.*xms){
3928  //******** ratio = Gamma(g->ssbar)/Gamma(g->uubar, ddbar) ******
3929  double ratio = 0.5*sqrt((glu.mass()*glu.mass()-4.*xms*xms)/(glu.mass()*glu.mass()-4.*xmq*xmq))*((glu.mass()*glu.mass()+2.*xms*xms)/(glu.mass()*glu.mass()+2.*xmq*xmq));
3930  double prob = ran();
3931  if(prob <= ratio/(1.+ratio)){qmass = xms; q1.id(3); q2.id(-3); q1.mass(xms); q2.mass(xms);}
3932  else if((prob > ratio/(1.+ratio)) && (prob <= (0.5+ratio)/(1.+ratio))){qmass = xmq; q1.id(1); q2.id(-1); q1.mass(xmq); q2.mass(xmq);}
3933  else{ /*if (prob > (0.5+ratio)/(1.+ratio))*/ qmass = xmq; q1.id(2); q2.id(-2); q1.mass(xmq); q2.mass(xmq);}
3934  }else{
3935  double prob = ran();
3936  if(prob <= 0.5){qmass = xmq; q1.id(1); q2.id(-1); q1.mass(xmq); q2.mass(xmq);}
3937  else{ qmass = xmq; q1.id(2); q2.id(-2); q1.mass(xmq); q2.mass(xmq);}
3938  }
3939 
3940  //gluon velocity
3941  FourVector Betag;
3942  Betag.Set(-glu.px()/glu_e,-glu.py()/glu_e,-glu.pz()/glu_e,0.);
3943  double sum2 = Betag.x()*Betag.x() + Betag.y()*Betag.y() + Betag.z()*Betag.z();
3944  if(sum2 < 1.){Betag.Set(Betag.x(),Betag.y(),Betag.z(),1./sqrt(1.-sum2));}
3945 
3946  //setting the q-qbar momenta, starting in gluon rest frame
3947  FourVector Pq_CM, Pq1, Pq2;
3948  double pq = (glu.mass() > 2.*qmass) ? sqrt(glu.mass()*glu.mass()/4. - qmass*qmass) : 0.;
3949  double theta = acos(1.-2.*ran()); double phi = 2*pi*ran();
3950  Pq_CM.Set(pq*sin(theta)*cos(phi),pq*sin(theta)*sin(phi),pq*cos(theta),sqrt(qmass*qmass+pq*pq));
3951  Pq1 = HHboost(Betag,Pq_CM);
3952  Pq_CM.Set(-Pq_CM.x(),-Pq_CM.y(),-Pq_CM.z(),Pq_CM.t());
3953  Pq2 = HHboost(Betag,Pq_CM);
3954  q1.P(Pq1); q2.P(Pq2);
3955  q1.col(glu.col()); q2.acol(glu.acol());
3956 
3957  // propagate quarks
3958  FourVector position1;
3959  FourVector position2;
3960  position1.Set(glu.x()+(Pq1.x() / qmass)*part_prop,glu.y()+(Pq1.y() / qmass)*part_prop,glu.z()+(Pq1.z() / qmass)*part_prop,glu.x_t()+part_prop);
3961  position2.Set(glu.x()+(Pq2.x() / qmass)*part_prop,glu.y()+(Pq2.y() / qmass)*part_prop,glu.z()+(Pq2.z() / qmass)*part_prop,glu.x_t()+part_prop);
3962  q1.pos(position1); q2.pos(position2);
3963 
3964  qrks.add(q1); qrks.add(q2);
3965 }
3966 
3967 //finding a thermal sibling for a thermal parton in therm
3969  if(!therm[therm[ithm].sibling()].is_used() && (therm[therm[ithm].sibling()].string_id() < 0) && (ithm != therm[ithm].sibling())){return therm[ithm].sibling();}
3970  int qrk_close = -1; double dist2min = 999999999999.;
3971  for(int i=0;i<therm.num();++i){
3972  if((therm[ithm].id() * therm[i].id() > 0) || therm[i].is_used()){continue;}
3973  double distnow = therm[ithm].posDif2(therm[i]) + (therm[ithm].x_t()-therm[i].x_t())*(therm[ithm].x_t()-therm[i].x_t());
3974  if(distnow < dist2min){qrk_close = i; dist2min = distnow;}
3975  }
3976  if(qrk_close == -1){qrk_close = ithm;}
3977  return qrk_close;
3978 }
3979 
3980 int HybridHadronization::findcloserepl(HHparton ptn, int iptn, bool lbt, bool thm, parton_collection& sh_lbt, parton_collection& therm){
3981 
3982  //should not happen
3983  if(iptn == 0 || ptn.id() == 21){throw std::runtime_error ("Parton index is incorrect (should not be 0 or gluon)");}
3984 
3985  //if the parton is thermal, and we're only looking at thermal partons, and the sibling was already found & not used, then return that.
3986  if((iptn<0) && thm && !lbt && !therm[ptn.sibling()].is_used() &&
3987  (((therm[ptn.sibling()].id() > 0) && (therm[ptn.sibling()].col() != 0)) || ((therm[ptn.sibling()].id() < 0) && (therm[ptn.sibling()].acol() != 0))) &&
3988  (iptn+1 != ptn.sibling())){return ptn.sibling();}
3989 
3990  //initializing vars
3991  int qrk_close = 999999999; double dist2min = 999999999999.;
3992  //checking thermal partons for closest parton
3993  if(thm){for(int i=0;i<therm.num();++i){
3994  //if the parton's color tag is not 0, then skip (is already repairing a string)
3995  if(((therm[i].id() > 0) && (therm[i].col() != 0)) || ((therm[i].id() < 0) && (therm[i].acol() != 0))){continue;}
3996  //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
3997  if((ptn.id() * therm[i].id() > 0) || therm[i].is_used() || ((iptn<0) && (-i == iptn+1))){continue;}
3998  double distnow = ptn.posDif2(therm[i]) + (ptn.x_t()-therm[i].x_t())*(ptn.x_t()-therm[i].x_t());
3999  if(distnow < dist2min){qrk_close = -i-1; dist2min = distnow;}
4000  }}
4001  //checking lbt partons for closest parton
4002  if(lbt){for(int i=0;i<sh_lbt.num();++i){
4003  //if gluon, skip
4004  if(sh_lbt[i].id() == 21){continue;}
4005  //if the parton's color tag is not 0, then skip (not an lbt/martini? parton)
4006  if(((sh_lbt[i].id() > 0) && (sh_lbt[i].col() != 0)) || ((sh_lbt[i].id() < 0) && (sh_lbt[i].acol() != 0))){continue;}
4007  //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4008  if((ptn.id() * sh_lbt[i].id() > 0) || sh_lbt[i].is_used() || ((iptn>0) && (i == iptn-1))){continue;}
4009  double distnow = ptn.posDif2(sh_lbt[i]) + (ptn.x_t()-sh_lbt[i].x_t())*(ptn.x_t()-sh_lbt[i].x_t());
4010  if(distnow < dist2min){qrk_close = i+1; dist2min = distnow;}
4011  }}
4012 
4013  //positive return values indicate an lbt parton in the shower was found (the (i-1)th parton)
4014  //negative return values indicate a thermal parton was found (the -(i+1)th parton)
4015  return qrk_close;
4016 }
4017 
4018 //version to handle finding a q-qbar pair for lbt gluons
4019 void HybridHadronization::findcloserepl_glu(HHparton ptn, int iptn, bool lbt, bool thm, parton_collection& sh_lbt, parton_collection& therm, int sel_out[]){
4020 
4021  //should not happen
4022  if(iptn == 0 || ptn.id() != 21){throw std::runtime_error ("Parton index is incorrect (should not be 0, or anything other than gluon)");}
4023  if(ptn.is_thermal()){throw std::runtime_error ("Parton is thermal (should not be so)");}
4024 
4025  //initializing vars
4026  int qrk_close = 999999999; double dist2min = 999999999999.;
4027  //checking thermal partons for closest quark
4028  if(thm){for(int i=0;i<therm.num();++i){
4029  //if the parton's color tag is not 0, then skip (is already repairing a string), or skip if antiquark
4030  if(((therm[i].id() > 0) && (therm[i].col() != 0)) || (therm[i].id() < 0)){continue;}
4031  //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4032  if(therm[i].is_used() || ((iptn<0) && (-i == iptn+1))){continue;}
4033  double distnow = ptn.posDif2(therm[i]) + (ptn.x_t()-therm[i].x_t())*(ptn.x_t()-therm[i].x_t());
4034  if(distnow < dist2min){qrk_close = -i-1; dist2min = distnow;}
4035  }}
4036  //checking lbt partons for closest parton
4037  if(lbt){for(int i=0;i<sh_lbt.num();++i){
4038  //if gluon, skip
4039  if(sh_lbt[i].id() == 21){continue;}
4040  //if the parton's color tag is not 0, then skip (not an lbt/martini? parton), or skip if antiquark
4041  if(((sh_lbt[i].id() > 0) && (sh_lbt[i].col() != 0)) || (sh_lbt[i].id() < 0)){continue;}
4042  //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4043  if(sh_lbt[i].is_used() || ((iptn>0) && (i == iptn-1))){continue;}
4044  double distnow = ptn.posDif2(sh_lbt[i]) + (ptn.x_t()-sh_lbt[i].x_t())*(ptn.x_t()-sh_lbt[i].x_t());
4045  if(distnow < dist2min){qrk_close = i+1; dist2min = distnow;}
4046  }}
4047 
4048  //positive return values indicate an lbt parton in the shower was found (the (i-1)th parton)
4049  //negative return values indicate a thermal parton was found (the -(i+1)th parton)
4050  sel_out[0]=qrk_close;
4051 
4052  qrk_close = 999999999; dist2min = 999999999999.;
4053  //checking thermal partons for closest antiquark
4054  if(thm){for(int i=0;i<therm.num();++i){
4055  //if the parton's color tag is not 0, then skip (is already repairing a string), or skip if quark
4056  if((therm[i].id() > 0) || ((therm[i].id() < 0) && (therm[i].acol() != 0))){continue;}
4057  //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4058  if(therm[i].is_used() || ((iptn<0) && (-i == iptn+1))){continue;}
4059  double distnow = ptn.posDif2(therm[i]) + (ptn.x_t()-therm[i].x_t())*(ptn.x_t()-therm[i].x_t());
4060  if(distnow < dist2min){qrk_close = -i-1; dist2min = distnow;}
4061  }}
4062  //checking lbt partons for closest parton
4063  if(lbt){for(int i=0;i<sh_lbt.num();++i){
4064  //if gluon, skip
4065  if(sh_lbt[i].id() == 21){continue;}
4066  //if the parton's color tag is not 0, then skip (not an lbt/martini? parton), or skip if quark
4067  if((sh_lbt[i].id() > 0) || ((sh_lbt[i].id() < 0) && (sh_lbt[i].acol() != 0))){continue;}
4068  //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4069  if(sh_lbt[i].is_used() || ((iptn>0) && (i == iptn-1))){continue;}
4070  double distnow = ptn.posDif2(sh_lbt[i]) + (ptn.x_t()-sh_lbt[i].x_t())*(ptn.x_t()-sh_lbt[i].x_t());
4071  if(distnow < dist2min){qrk_close = i+1; dist2min = distnow;}
4072  }}
4073 
4074  //positive return values indicate an lbt parton in the shower was found (the (i-1)th parton)
4075  //negative return values indicate a thermal parton was found (the -(i+1)th parton)
4076  sel_out[1]=qrk_close;
4077 }
4078 
4079 //prepares remnant partons/strings for PYTHIA string hadronization
4080 //sorts strings, ensures strings are in 'valid' configurations, assigns color/anticolor tags
4081 //TODO: this might be where to use thermal partons to enforce color neutrality
4082 void HybridHadronization::stringprep(parton_collection& SP_remnants, parton_collection& SP_prepremn, bool cutstr){
4083  //dignostic measure
4084  /*std::cout <<endl<<"below is all the colors in the Tempjunction lists"<<endl;
4085  for(int ijunc=0; ijunc<Tempjunctions.size(); ijunc++){
4086  std::cout <<" { "<<Tempjunctions.at(ijunc).at(0).at(0)<<" , "<<Tempjunctions.at(ijunc).at(1).at(1)<<" , "<<Tempjunctions.at(ijunc).at(2).at(1)<<" , "<<Tempjunctions.at(ijunc).at(3).at(1)<<" } "<<endl;
4087  std::cout <<"col/acol: (" << Tempjunctions.at(ijunc).at(1).at(0) << "," << Tempjunctions.at(ijunc).at(2).at(0) << "," << Tempjunctions.at(ijunc).at(3).at(0) << ")" << std::endl;
4088  }*/
4089  //Declare essential vectors for string repair
4090  vector<vector<vector<HHparton>>> JuncStructure;
4091  vector<vector<HHparton>> JuncLegs; // vector of all junction ( Junction Num, Leg1, Leg2, Leg3)
4092  vector<HHparton> Leg1; // partons in the legs for juncion formation
4093  vector<HHparton> Leg2;
4094  vector<HHparton> Leg3;
4095  vector<int> Legconsidering;//address of partons in SP_remnants
4096  vector<vector<vector<int>>> IMStructure1; //Intermediate structure for saving the indices in Tempjunction and Corresponding Leg Number, this will be used for cutting string for appending info to PYTHIA
4097  vector<vector<int>> IMStructure2; // this will contain Tempjunction Indice and -+1 and leg numbers
4098  //ex. 2nd lef in 3rd temp anti junction is same as 1st leg 2nd tempjunction. 3,-1,0,0 3,1,2,0 would be saved in the vectorIMS1
4099  vector<int> IMStructure3; // 4 element vector of Tempjunction order, kind and leg address in JuncStructure vector
4100  vector<vector<HHparton>> Recombearly1; //these partons are in the junction with three or two shared legs with others , and they will be recombined into baryon to cut? or arrange the string for PYTHIA to understand input come from this code
4101  vector<HHparton> Recombearly2;
4102  vector<vector<vector<HHparton>>> Dijunction1; // these partons are in the junction with two legs shared legs!
4103  vector<vector<HHparton>> Dijunction2;
4104  //Vector of Indices for Dijunction1 vector to be ordered for invoking Pythia
4105  vector<vector<int>> DijunctionInfo1;
4106  vector<int> DijunctionInfo2; // { -1: antiJ, +1 : J , 0 : shared leg}
4107  //these tags should be assigned to corresponding legs in Dijunction1 vector! so DijunctionInfo2 has five elements{since, dijunction structure has five legs!}
4108 
4109 
4110  vector<vector<vector<HHparton>>> Singlejunction1; // easiest case! just single string
4111  vector<vector<HHparton>> Singlejunction2;
4112  vector<vector<HHparton>> Tailoredstring1; // when there are the junction with two shared legs, it also should be recombined into baryon and one string will remain after, which would be saved in this vector
4113  vector<HHparton> Tailoredstring2;
4114  vector<int> realjuncindice; // vector to save the indice of Tempjunction when real junction is formed by three initiating particle
4115 
4116  vector<HHparton> finalstring; // final space for all of the remnant particles being corrected by fake parton addition
4117 
4118  /*JSINFO << "SP_remnants before stringprep:";
4119  for(int irem=0; irem < SP_remnants.num(); ++irem) {
4120  std::cout << SP_remnants[irem].id() << "," << SP_remnants[irem].col() << "," << SP_remnants[irem].acol() << std::endl;
4121  }*/
4122 
4123  // Tempjunctions missing partons? Add thermal or fake
4124  // find the maximum (anti-)color tag in the remnants list and the tempjunctions
4125  int maxtag = 0;
4126  for(int irem=0; irem < SP_remnants.num(); ++irem) {
4127  if(SP_remnants[irem].col() > maxtag) {
4128  maxtag = SP_remnants[irem].col();
4129  }
4130  if(SP_remnants[irem].acol() > maxtag) {
4131  maxtag = SP_remnants[irem].acol();
4132  }
4133  }
4134  for(int ijunc=0; ijunc < Tempjunctions.size(); ++ijunc) {
4135  if(Tempjunctions.at(ijunc).at(1).at(1) > maxtag) {
4136  maxtag = Tempjunctions.at(ijunc).at(1).at(1);
4137  }
4138  if(Tempjunctions.at(ijunc).at(2).at(1) > maxtag) {
4139  maxtag = Tempjunctions.at(ijunc).at(2).at(1);
4140  }
4141  if(Tempjunctions.at(ijunc).at(3).at(1) > maxtag) {
4142  maxtag = Tempjunctions.at(ijunc).at(3).at(1);
4143  }
4144  }
4145 
4146  HHparton tempparton1;
4147  HHparton tempparton2;
4148  HHparton tempparton3;
4149  for(int ijunc=0; ijunc < Tempjunctions.size(); ++ijunc) {
4150  int i1 = 0; int i2 = 0; int i3 = 0;
4151 
4152  // First try to match to remant parton color/anticolor tags and write matching parton index into tag
4153  for(int irem=0; irem < SP_remnants.num(); ++irem) {
4154  if(Tempjunctions.at(ijunc).at(0).at(0) == -1) {
4155  if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(1).at(1) && Tempjunctions.at(ijunc).at(1).at(1) != 0) {i1 = irem+1;}
4156  if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(2).at(1) && Tempjunctions.at(ijunc).at(2).at(1) != 0) {i2 = irem+1;}
4157  if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(3).at(1) && Tempjunctions.at(ijunc).at(3).at(1) != 0) {i3 = irem+1;}
4158  }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4159  if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(1).at(1) && Tempjunctions.at(ijunc).at(1).at(1) != 0) {i1 = irem+1;}
4160  if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(2).at(1) && Tempjunctions.at(ijunc).at(2).at(1) != 0) {i2 = irem+1;}
4161  if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(3).at(1) && Tempjunctions.at(ijunc).at(3).at(1) != 0) {i3 = irem+1;}
4162  }
4163  }
4164 
4165  // Now try to find partners in another temp junction, store junction and leg number as a negative tag
4166  for(int ijunc2=ijunc+1; ijunc2 < Tempjunctions.size(); ++ijunc2) {
4167  if((Tempjunctions.at(ijunc).at(0).at(0) == -1 && Tempjunctions.at(ijunc2).at(0).at(0) == 1) || (Tempjunctions.at(ijunc).at(0).at(0) == 1 && Tempjunctions.at(ijunc2).at(0).at(0) == -1)) {
4168  for(int ileg=1; ileg <= 3; ++ileg) {
4169  if(Tempjunctions.at(ijunc2).at(ileg).at(1) == Tempjunctions.at(ijunc).at(1).at(1) && Tempjunctions.at(ijunc).at(1).at(1) != 0) {i1 = -ijunc2*10-ileg;}
4170  if(Tempjunctions.at(ijunc2).at(ileg).at(1) == Tempjunctions.at(ijunc).at(2).at(1) && Tempjunctions.at(ijunc).at(2).at(1) != 0) {i2 = -ijunc2*10-ileg;}
4171  if(Tempjunctions.at(ijunc2).at(ileg).at(1) == Tempjunctions.at(ijunc).at(3).at(1) && Tempjunctions.at(ijunc).at(3).at(1) != 0) {i3 = -ijunc2*10-ileg;}
4172  }
4173  }else{
4174  bool warning = false;
4175  for (int ileg=1; ileg <= 3; ++ileg) {
4176  for (int jleg=1; jleg <= 3; ++jleg) {
4177  if (Tempjunctions.at(ijunc).at(ileg).at(1) == Tempjunctions.at(ijunc2).at(jleg).at(1)) {
4178  warning = true;
4179  }
4180  }
4181  }
4182  if(warning) {
4183  JSWARN << "There is a junction pair which is not junction-antijunction, but junction-junction or antijunction-antijunction. This should not happen!";
4184  }
4185  }
4186  }
4187 
4188  // define temporary parton to be used in findclosereplica
4189  if(i1 <= 0) {
4190  if(i2 > 0){
4191  tempparton1 = SP_remnants[i2-1];
4192  if(std::abs(tempparton1.id()) < 6){ // no change of colors here, they are not important in findclosereplica
4193  tempparton1.id(-tempparton1.id());
4194  }
4195  }else if(i3 > 0){
4196  tempparton1 = SP_remnants[i3-1];
4197  if(std::abs(tempparton1.id()) < 6){
4198  tempparton1.id(-tempparton1.id());
4199  }
4200  }else{ // should be very rare: junction with 3 ghost legs
4201  tempparton1 = SP_remnants[0];
4202  if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && std::abs(tempparton1.id()) < 6 && tempparton1.id() < 0){
4203  tempparton1.id(-tempparton1.id());
4204  } else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && std::abs(tempparton1.id()) < 6 && tempparton1.id() > 0){
4205  tempparton1.id(-tempparton1.id());
4206  }
4207  }
4208  }
4209  if(i2 <= 0) {
4210  if(i1 > 0){
4211  tempparton2 = SP_remnants[i1-1];
4212  if(std::abs(tempparton2.id()) < 6){ // no change of colors here, they are not important in findclosereplica
4213  tempparton2.id(-tempparton2.id());
4214  }
4215  }else if(i3 > 0){
4216  tempparton2 = SP_remnants[i3-1];
4217  if(std::abs(tempparton2.id()) < 6){
4218  tempparton2.id(-tempparton2.id());
4219  }
4220  }else{ // should be very rare: junction with 3 ghost legs
4221  tempparton2 = SP_remnants[0];
4222  if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && std::abs(tempparton2.id()) < 6 && tempparton2.id() < 0){
4223  tempparton2.id(-tempparton2.id());
4224  } else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && std::abs(tempparton2.id()) < 6 && tempparton2.id() > 0){
4225  tempparton2.id(-tempparton2.id());
4226  }
4227  }
4228  }
4229  if(i3 <= 0) {
4230  if(i1 > 0){
4231  tempparton3 = SP_remnants[i1-1];
4232  if(std::abs(tempparton3.id()) < 6){ // no change of colors here, they are not important in findclosereplica
4233  tempparton3.id(-tempparton3.id());
4234  }
4235  }else if(i2 > 0){
4236  tempparton3 = SP_remnants[i2-1];
4237  if(std::abs(tempparton3.id()) < 6){
4238  tempparton3.id(-tempparton3.id());
4239  }
4240  }else{ // should be very rare: junction with 3 ghost legs
4241  tempparton3 = SP_remnants[0];
4242  if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && std::abs(tempparton3.id()) < 6 && tempparton3.id() < 0){
4243  tempparton3.id(-tempparton3.id());
4244  } else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && std::abs(tempparton3.id()) < 6 && tempparton3.id() > 0){
4245  tempparton3.id(-tempparton3.id());
4246  }
4247  }
4248  }
4249 
4250  if(i1 == 0 || i2 == 0 || i3 == 0){
4251  Tempjunctions.at(ijunc).at(0).at(1) = 1; // at least one thermal parton in (anti-)junction
4252  }
4253 
4254  // Now find partons to add to missing junction legs; either thermal or fake
4255  if(i1 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1) {
4256  int loc = 0;
4257  if(tempparton1.id() == 21) {
4258  tempparton1.id(1);
4259  loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
4260  tempparton1.id(21);
4261  }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
4262  if(loc == 999999999 || loc > 0) {
4263  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
4264  HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(0);
4265  if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4266  fakep.set_anti_color(Tempjunctions.at(ijunc).at(1).at(1));
4267  } else {
4268  fakep.set_anti_color(++maxtag);
4269  Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4270  }
4271  if(std::abs(fakep.id()) < 3) {
4272  fakep.mass(xmq);
4273  } else {fakep.mass(xms);}
4274  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4275  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4276  if (number_p_fake == 0 || number_p_fake == 2){
4277  fakep.pz(-p_fake);
4278  } else if (number_p_fake == 1 || number_p_fake == 3) {
4279  fakep.pz(p_fake);
4280  } else {fakep.pz(0.);}
4281  number_p_fake++;
4282  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4283  fakep.orig(-1); fakep.is_remnant(true);
4284  fakep.is_fakeparton(true);
4285  SP_remnants.add(fakep);
4286  }else if(loc < 0) {
4287  if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4288  HH_thermal[-loc-1].acol(Tempjunctions.at(ijunc).at(1).at(1));
4289  } else {
4290  HH_thermal[-loc-1].acol(++maxtag);
4291  Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4292  }
4293  HH_thermal[-loc-1].col(0);
4294  HH_thermal[-loc-1].is_used(true);
4295  HH_thermal[-loc-1].is_remnant(true);
4296  SP_remnants.add(HH_thermal[-loc-1]);
4297  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4298  }
4299  }
4300 
4301  if(i2 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4302  int loc = 0;
4303  if(tempparton2.id() == 21) {
4304  tempparton2.id(1);
4305  loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);
4306  tempparton2.id(21);
4307  }else{loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);}
4308  if(loc == 999999999 || loc > 0) {
4309  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
4310  HHparton fakep = tempparton2; fakep.id(fid); fakep.set_color(0);
4311  if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4312  fakep.set_anti_color(Tempjunctions.at(ijunc).at(2).at(1));
4313  } else {
4314  fakep.set_anti_color(++maxtag);
4315  Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4316  }
4317  if(std::abs(fakep.id()) < 3) {
4318  fakep.mass(xmq);
4319  } else {fakep.mass(xms);}
4320  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4321  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4322  if (number_p_fake == 0 || number_p_fake == 2){
4323  fakep.pz(-p_fake);
4324  } else if (number_p_fake == 1 || number_p_fake == 3) {
4325  fakep.pz(p_fake);
4326  } else {fakep.pz(0.);}
4327  number_p_fake++;
4328  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4329  fakep.orig(-1); fakep.is_remnant(true);
4330  fakep.is_fakeparton(true);
4331  SP_remnants.add(fakep);
4332  }else if(loc < 0) {
4333  if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4334  HH_thermal[-loc-1].acol(Tempjunctions.at(ijunc).at(2).at(1));
4335  } else {
4336  HH_thermal[-loc-1].acol(++maxtag);
4337  Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4338  }
4339  HH_thermal[-loc-1].col(0);
4340  HH_thermal[-loc-1].is_used(true);
4341  HH_thermal[-loc-1].is_remnant(true);
4342  SP_remnants.add(HH_thermal[-loc-1]);
4343  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4344  }
4345  }
4346 
4347  if(i3 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1) {
4348  int loc = 0;
4349  if(tempparton3.id() == 21) {
4350  tempparton3.id(1);
4351  loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);
4352  tempparton3.id(21);
4353  }else{loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);}
4354  if(loc == 999999999 || loc > 0) {
4355  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
4356  HHparton fakep = tempparton3; fakep.id(fid); fakep.set_color(0);
4357  if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4358  fakep.set_anti_color(Tempjunctions.at(ijunc).at(3).at(1));
4359  } else {
4360  fakep.set_anti_color(++maxtag);
4361  Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4362  }
4363  if(std::abs(fakep.id()) < 3) {
4364  fakep.mass(xmq);
4365  } else {fakep.mass(xms);}
4366  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4367  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4368  if (number_p_fake == 0 || number_p_fake == 2){
4369  fakep.pz(-p_fake);
4370  } else if (number_p_fake == 1 || number_p_fake == 3) {
4371  fakep.pz(p_fake);
4372  } else {fakep.pz(0.);}
4373  number_p_fake++;
4374  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4375  fakep.orig(-1); fakep.is_remnant(true);
4376  fakep.is_fakeparton(true);
4377  SP_remnants.add(fakep);
4378  }else if(loc < 0) {
4379  if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4380  HH_thermal[-loc-1].acol(Tempjunctions.at(ijunc).at(3).at(1));
4381  } else {
4382  HH_thermal[-loc-1].acol(++maxtag);
4383  Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4384  }
4385  HH_thermal[-loc-1].col(0);
4386  HH_thermal[-loc-1].is_used(true);
4387  HH_thermal[-loc-1].is_remnant(true);
4388  SP_remnants.add(HH_thermal[-loc-1]);
4389  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4390  }
4391  }
4392 
4393  if(i1 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4394  int loc = 0;
4395  if(tempparton1.id() == 21) {
4396  tempparton1.id(-1);
4397  loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
4398  tempparton1.id(21);
4399  }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
4400  if(loc == 999999999 || loc > 0) {
4401  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
4402  HHparton fakep = tempparton1; fakep.id(fid);
4403  fakep.set_anti_color(0);
4404  if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4405  fakep.set_color(Tempjunctions.at(ijunc).at(1).at(1));
4406  } else {
4407  fakep.set_color(++maxtag);
4408  Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4409  }
4410  if(std::abs(fakep.id()) < 3) {
4411  fakep.mass(xmq);
4412  } else {fakep.mass(xms);}
4413  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4414  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4415  if (number_p_fake == 0 || number_p_fake == 2){
4416  fakep.pz(-p_fake);
4417  } else if (number_p_fake == 1 || number_p_fake == 3) {
4418  fakep.pz(p_fake);
4419  } else {fakep.pz(0.);}
4420  number_p_fake++;
4421  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4422  fakep.orig(-1); fakep.is_remnant(true);
4423  fakep.is_fakeparton(true);
4424  SP_remnants.add(fakep);
4425  }else if(loc < 0) {
4426  if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4427  HH_thermal[-loc-1].col(Tempjunctions.at(ijunc).at(1).at(1));
4428  } else {
4429  HH_thermal[-loc-1].col(++maxtag);
4430  Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4431  }
4432  HH_thermal[-loc-1].acol(0);
4433  HH_thermal[-loc-1].is_used(true);
4434  HH_thermal[-loc-1].is_remnant(true);
4435  SP_remnants.add(HH_thermal[-loc-1]);
4436  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4437  }
4438  }
4439 
4440  if(i2 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4441  int loc = 0;
4442  if(tempparton2.id() == 21) {
4443  tempparton2.id(-1);
4444  loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);
4445  tempparton2.id(21);
4446  }else{loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);}
4447  if(loc == 999999999 || loc > 0) {
4448  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
4449  HHparton fakep = tempparton2; fakep.id(fid);
4450  fakep.set_anti_color(0);
4451  if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4452  fakep.set_color(Tempjunctions.at(ijunc).at(2).at(1));
4453  } else {
4454  fakep.set_color(++maxtag);
4455  Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4456  }
4457  if(std::abs(fakep.id()) < 3) {
4458  fakep.mass(xmq);
4459  } else {fakep.mass(xms);}
4460  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4461  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4462  if (number_p_fake == 0 || number_p_fake == 2){
4463  fakep.pz(-p_fake);
4464  } else if (number_p_fake == 1 || number_p_fake == 3) {
4465  fakep.pz(p_fake);
4466  } else {fakep.pz(0.);}
4467  number_p_fake++;
4468  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4469  fakep.orig(-1); fakep.is_remnant(true);
4470  fakep.is_fakeparton(true);
4471  SP_remnants.add(fakep);
4472  }else if(loc < 0) {
4473  if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4474  HH_thermal[-loc-1].col(Tempjunctions.at(ijunc).at(2).at(1));
4475  } else {
4476  HH_thermal[-loc-1].col(++maxtag);
4477  Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4478  }
4479  HH_thermal[-loc-1].acol(0);
4480  HH_thermal[-loc-1].is_used(true);
4481  HH_thermal[-loc-1].is_remnant(true);
4482  SP_remnants.add(HH_thermal[-loc-1]);
4483  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4484  }
4485  }
4486 
4487  if(i3 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4488  int loc = 0;
4489  if(tempparton3.id() == 21) {
4490  tempparton3.id(-1);
4491  loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);
4492  tempparton3.id(21);
4493  }else{loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);}
4494  if(loc == 999999999 || loc > 0) {
4495  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
4496  HHparton fakep = tempparton3; fakep.id(fid);
4497  fakep.set_anti_color(0);
4498  if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4499  fakep.set_color(Tempjunctions.at(ijunc).at(3).at(1));
4500  } else {
4501  fakep.set_color(++maxtag);
4502  Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4503  }
4504  if(std::abs(fakep.id()) < 3) {
4505  fakep.mass(xmq);
4506  } else {fakep.mass(xms);}
4507  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4508  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4509  if (number_p_fake == 0 || number_p_fake == 2){
4510  fakep.pz(-p_fake);
4511  } else if (number_p_fake == 1 || number_p_fake == 3) {
4512  fakep.pz(p_fake);
4513  } else {fakep.pz(0.);}
4514  number_p_fake++;
4515  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4516  fakep.orig(-1); fakep.is_remnant(true);
4517  fakep.is_fakeparton(true);
4518  SP_remnants.add(fakep);
4519  }else if(loc < 0) {
4520  if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4521  HH_thermal[-loc-1].col(Tempjunctions.at(ijunc).at(3).at(1));
4522  } else {
4523  HH_thermal[-loc-1].col(++maxtag);
4524  Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4525  }
4526  HH_thermal[-loc-1].acol(0);
4527  HH_thermal[-loc-1].is_used(true);
4528  HH_thermal[-loc-1].is_remnant(true);
4529  SP_remnants.add(HH_thermal[-loc-1]);
4530  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4531  }
4532  }
4533 
4534  // Add fake gluons (no beam energies) between junctions with empty connecting legs [handling could be improved later]
4535  if(i1 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4536  int jleg = ((-i1) % 10);
4537  int jjunc = ((-i1)-jleg)/10;
4538  HHparton fakep = tempparton1; fakep.id(21);
4539  fakep.set_color(++maxtag);
4540  fakep.set_anti_color(Tempjunctions.at(ijunc).at(1).at(1));
4541  fakep.mass(1e-2); // 10 MeV "accuracy"
4542  Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4543  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4544  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4545  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4546  fakep.orig(-1); fakep.is_remnant(true);
4547  fakep.is_fakeparton(true);
4548  SP_remnants.add(fakep);
4549  }
4550 
4551  if(i2 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4552  int jleg = ((-i2) % 10);
4553  int jjunc = ((-i2)-jleg)/10;
4554  HHparton fakep = tempparton2; fakep.id(21);
4555  fakep.set_color(++maxtag);
4556  fakep.set_anti_color(Tempjunctions.at(ijunc).at(2).at(1));
4557  fakep.mass(1e-2);
4558  Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4559  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4560  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4561  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4562  fakep.orig(-1); fakep.is_remnant(true);
4563  fakep.is_fakeparton(true);
4564  SP_remnants.add(fakep);
4565  }
4566 
4567  if(i3 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4568  int jleg = ((-i3) % 10);
4569  int jjunc = ((-i3)-jleg)/10;
4570  HHparton fakep = tempparton3; fakep.id(21);
4571  fakep.set_color(++maxtag);
4572  fakep.set_anti_color(Tempjunctions.at(ijunc).at(3).at(1));
4573  fakep.mass(1e-2);
4574  Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4575  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4576  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4577  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4578  fakep.orig(-1); fakep.is_remnant(true);
4579  fakep.is_fakeparton(true);
4580  SP_remnants.add(fakep);
4581  }
4582 
4583  if(i1 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1 ) {
4584  int jleg = ((-i1) % 10);
4585  int jjunc = ((-i1)-jleg)/10;
4586  HHparton fakep = tempparton1; fakep.id(21);
4587  fakep.set_anti_color(++maxtag);
4588  fakep.set_color(Tempjunctions.at(ijunc).at(1).at(1));
4589  fakep.mass(1e-2);
4590  Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4591  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4592  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4593  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4594  fakep.orig(-1); fakep.is_remnant(true);
4595  fakep.is_fakeparton(true);
4596  SP_remnants.add(fakep);
4597  }
4598 
4599  if(i2 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1 ) {
4600  int jleg = ((-i2) % 10);
4601  int jjunc = ((-i2)-jleg)/10;
4602  HHparton fakep = tempparton2; fakep.id(21);
4603  fakep.set_anti_color(++maxtag);
4604  fakep.set_color(Tempjunctions.at(ijunc).at(2).at(1));
4605  fakep.mass(1e-2);
4606  Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4607  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4608  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4609  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4610  fakep.orig(-1); fakep.is_remnant(true);
4611  fakep.is_fakeparton(true);
4612  SP_remnants.add(fakep);
4613  }
4614 
4615  if(i3 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1 ) {
4616  int jleg = ((-i3) % 10);
4617  int jjunc = ((-i3)-jleg)/10;
4618  HHparton fakep = tempparton3; fakep.id(21);
4619  fakep.set_anti_color(++maxtag);
4620  fakep.set_color(Tempjunctions.at(ijunc).at(3).at(1));
4621  fakep.mass(1e-2);
4622  Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4623  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4624  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4625  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4626  fakep.orig(-1); fakep.is_remnant(true);
4627  fakep.is_fakeparton(true);
4628  SP_remnants.add(fakep);
4629  }
4630  }
4631 
4632  // repair all strings (add missing partons)
4633  for(int ptn1 = 0; ptn1 < SP_remnants.num(); ptn1++) {
4634  bool colors_match = false;
4635  bool anti_colors_match = false;
4636  int ptn1_col = SP_remnants[ptn1].col();
4637  int ptn1_acol = SP_remnants[ptn1].acol();
4638  for(int ptn2 = 0; ptn2 < SP_remnants.num(); ptn2++) {
4639  int ptn2_acol = SP_remnants[ptn2].acol();
4640  int ptn2_col = SP_remnants[ptn2].col();
4641  if(ptn1_col == ptn2_acol) {colors_match = true;}
4642  if(ptn1_acol == ptn2_col) {anti_colors_match = true;}
4643  }
4644  if(!colors_match || !anti_colors_match) {
4645  for(int ijunc = 0; ijunc < Tempjunctions.size(); ijunc++) {
4646  if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && (ptn1_col == Tempjunctions.at(ijunc).at(1).at(1) || ptn1_col == Tempjunctions.at(ijunc).at(2).at(1) || ptn1_col == Tempjunctions.at(ijunc).at(3).at(1))) {
4647  colors_match = true;
4648  }
4649  if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && (ptn1_acol == Tempjunctions.at(ijunc).at(1).at(1) || ptn1_acol == Tempjunctions.at(ijunc).at(2).at(1) || ptn1_acol == Tempjunctions.at(ijunc).at(3).at(1))) {
4650  anti_colors_match = true;
4651  }
4652  }
4653  }
4654  if(!colors_match && SP_remnants[ptn1].id() > 0) {
4655  int loc = 0;
4656  if(SP_remnants[ptn1].id() == 21){
4657  SP_remnants[ptn1].id(1);
4658  loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);
4659  SP_remnants[ptn1].id(21);
4660  }else{loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);}
4661 
4662  if(loc == 999999999 || loc > 0){
4663  int fid = (ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3;
4664  HHparton fakep = SP_remnants[ptn1]; fakep.id(fid); fakep.set_color(0); fakep.set_anti_color(ptn1_col);
4665  if(std::abs(fakep.id()) < 3) {
4666  fakep.mass(xmq);
4667  } else {fakep.mass(xms);}
4668  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4669  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4670  if (number_p_fake == 0 || number_p_fake == 2){
4671  fakep.pz(-p_fake);
4672  } else if (number_p_fake == 1 || number_p_fake == 3) {
4673  fakep.pz(p_fake);
4674  } else {fakep.pz(0.);}
4675  number_p_fake++;
4676  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4677  fakep.orig(-1); fakep.is_remnant(true);
4678  fakep.is_fakeparton(true);
4679  SP_remnants.add(fakep);
4680  }else if(loc < 0){
4681  HH_thermal[-loc-1].acol(ptn1_col);
4682  HH_thermal[-loc-1].col(0);
4683  HH_thermal[-loc-1].is_used(true);
4684  HH_thermal[-loc-1].is_remnant(true);
4685  SP_remnants.add(HH_thermal[-loc-1]);
4686  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4687  }
4688  }
4689  if(!anti_colors_match && (SP_remnants[ptn1].id() < 0 || SP_remnants[ptn1].id() == 21)) {
4690  int loc = 0;
4691  if(SP_remnants[ptn1].id() == 21){
4692  SP_remnants[ptn1].id(-1);
4693  loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);
4694  SP_remnants[ptn1].id(21);
4695  }else{loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);}
4696 
4697  if(loc == 999999999 || loc > 0){
4698  int fid = (ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3;
4699  HHparton fakep = SP_remnants[ptn1]; fakep.id(fid); fakep.set_color(ptn1_acol); fakep.set_anti_color(0);
4700  if(std::abs(fakep.id()) < 3) {
4701  fakep.mass(xmq);
4702  } else {fakep.mass(xms);}
4703  double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4704  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4705  if (number_p_fake == 0 || number_p_fake == 2){
4706  fakep.pz(-p_fake);
4707  } else if (number_p_fake == 1 || number_p_fake == 3) {
4708  fakep.pz(p_fake);
4709  } else {fakep.pz(0.);}
4710  number_p_fake++;
4711  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4712  fakep.orig(-1); fakep.is_remnant(true);
4713  fakep.is_fakeparton(true);
4714  SP_remnants.add(fakep);
4715  }else if(loc < 0){
4716  HH_thermal[-loc-1].col(ptn1_acol);
4717  HH_thermal[-loc-1].acol(0);
4718  HH_thermal[-loc-1].is_used(true);
4719  HH_thermal[-loc-1].is_remnant(true);
4720  SP_remnants.add(HH_thermal[-loc-1]);
4721  SP_remnants[SP_remnants.num()-1].par(-loc-1);
4722  }
4723  }
4724  }
4725 
4726  set_initial_parton_masses(SP_remnants);
4727 
4728  for(int ijunc=0; ijunc < Tempjunctions.size(); ++ijunc) { //Let's make Legs for Final string by verifying Tempjunctions! starting from the kind of junction(-1 or +1)
4729  //std::cout <<endl<<endl<<" Let's see candidates for (anti)junction "<<endl;
4730  //std::cout <<" Candidate " << ijunc+1 <<endl;
4731  //std::cout <<" [ ( " << Tempjunctions.at(ijunc).at(0).at(0) <<" , " << Tempjunctions.at(ijunc).at(0).at(1) <<" ), " ;
4732  //std::cout <<" ( " << Tempjunctions.at(ijunc).at(1).at(0) <<" , " << Tempjunctions.at(ijunc).at(1).at(1) <<" ), " ;
4733  //std::cout <<" ( " << Tempjunctions.at(ijunc).at(2).at(0) <<" , " << Tempjunctions.at(ijunc).at(2).at(1) <<" ), " ;
4734  //std::cout <<" ( " << Tempjunctions.at(ijunc).at(3).at(0) <<" , " << Tempjunctions.at(ijunc).at(3).at(1) <<" ), " ;
4735  //std::cout <<" ] "<<endl;
4736 
4737  //std::cout <<endl<<" I'm Working !! from line 2027" <<endl;
4738  vector<int> correction; // for the case of 1 or 2 initiating particles, we need to remember the partons and get the used_junction tag to the original
4739  if(Tempjunctions.at(ijunc).at(0).at(0) == -1) { // check anti-color tags in SP_remnants partons!! to form anti-junction
4740  for(int irem=0; irem < SP_remnants.num(); ++irem) { // searching through all remnant particles
4741  //std::cout <<endl<<" Let's see " << irem+1 <<"th remnant particle with "<< "pid : " << SP_remnants[irem].pid() <<" color : "<< SP_remnants[irem].col()<< " anti-color : " << SP_remnants[irem].acol() <<endl;
4742  if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(1).at(1)){
4743  Leg1.push_back(SP_remnants[irem]);
4744  correction.push_back(irem);
4745  SP_remnants[irem].used_junction(true);
4746  //std::cout <<endl<<" Leg 1 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].acol()<<endl<<endl;
4747  Legconsidering.push_back(irem);
4748  }
4749  if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(2).at(1)){
4750  Leg2.push_back(SP_remnants[irem]);
4751  correction.push_back(irem);
4752  SP_remnants[irem].used_junction(true);
4753  //std::cout <<endl<<" Leg 2 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].acol()<<endl<<endl;
4754  Legconsidering.push_back(irem);
4755  }
4756  if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(3).at(1)){
4757  Leg3.push_back(SP_remnants[irem]);
4758  correction.push_back(irem);
4759  SP_remnants[irem].used_junction(true);
4760  //std::cout <<endl<<" Leg 3 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].acol()<<endl<<endl;
4761  Legconsidering.push_back(irem);
4762  }
4763  if(Legconsidering.size() !=3 ){// if only one or two particles found in remnants, we need to set the tag to the original
4764  for(int icor = 0; icor < correction.size(); icor++){
4765  SP_remnants[correction.at(icor)].used_junction(false);
4766  //dignostic measure
4767  //std::cout <<endl<<"the "<<icor<<" th particle with color tag of "<<SP_remnants[icor].col()<<" , "<<SP_remnants[icor].acol()<<" are turned into unused particle"<<endl;
4768  }
4769  correction.clear();
4770  }
4771  }
4772  }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1) { // check color tags in SP_remnants partons!! to form junction
4773  for(int irem=0; irem < SP_remnants.num(); ++irem) { // searching through all remnant particles
4774  //std::cout <<endl<<" Let's see " << irem+1 <<"th remnant particle with "<< "pid : " << SP_remnants[irem].pid() <<" color : "<< SP_remnants[irem].col()<< " anti-color : " << SP_remnants[irem].acol() <<endl;
4775  if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(1).at(1)){
4776  Leg1.push_back(SP_remnants[irem]);
4777  correction.push_back(irem);
4778  SP_remnants[irem].used_junction(true);
4779  Legconsidering.push_back(irem);
4780  //std::cout <<endl<<" Leg 1 has initiating particle "<<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].col()<<endl<<endl;
4781  }
4782  if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(2).at(1)){
4783  Leg2.push_back(SP_remnants[irem]);
4784  correction.push_back(irem);
4785  SP_remnants[irem].used_junction(true);
4786  //std::cout <<endl<<" Leg 2 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].col()<<endl<<endl;
4787  Legconsidering.push_back(irem);
4788  }
4789  if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(3).at(1)){
4790  Leg3.push_back(SP_remnants[irem]);
4791  correction.push_back(irem);
4792  SP_remnants[irem].used_junction(true);
4793  //std::cout <<endl<<" Leg 3 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].col()<<endl<<endl;
4794  Legconsidering.push_back(irem);
4795  }
4796  if(Legconsidering.size() !=3 ){
4797  for(int icor = 0; icor < correction.size(); icor++){
4798  SP_remnants[correction.at(icor)].used_junction(false);
4799  //dignostic measure
4800  //std::cout <<endl<<"the "<<icor<<" th particle with color tag of "<<SP_remnants[icor].col()<<" , "<<SP_remnants[icor].acol()<<" are turned into unused particle"<<endl;
4801  }
4802  correction.clear();
4803  }
4804  }
4805  }
4806 
4807  if(Legconsidering.size() == 3) {
4808  realjuncindice.push_back(ijunc);
4809  //std::cout <<endl<<"the indice added for string repair : "<<ijunc<<endl;
4810  if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && Leg1.at(0).col() != 0 && Leg1.at(0).acol() != 0){ // starting to form the Leg1 for anti_junction by Color Tag Tracing. If first particle is (anti)quark, no need to trace
4811  for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4812  for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4813  if( (Leg1.back().col() != 0) && (Leg1.back().col() == SP_remnants[icf].acol()) ){
4814  //std::cout <<endl<<"particle added to Leg 1 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4815  Leg1.push_back(SP_remnants[icf]);
4816  SP_remnants[icf].used_junction(true);
4817  }
4818  if( Leg1.back().col() == 0 || Leg1.back().acol() == 0 ){ break; }
4819  }
4820  }
4821  }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && Leg1.at(0).col() != 0 && Leg1.at(0).acol() != 0){ // starting to form the Leg1 junction by Color Tag Tracing. If first particle is quark, no need to trace
4822  for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4823  for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4824  if( (Leg1.back().acol() != 0) && (Leg1.back().acol() == SP_remnants[icf].col()) ){
4825  //std::cout <<endl<<"particle added to Leg 1 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4826  Leg1.push_back(SP_remnants[icf]);
4827  SP_remnants[icf].used_junction(true);
4828  }
4829  if(Leg1.back().col() == 0 || Leg1.back().acol() == 0){break;}
4830  }
4831  }
4832  }
4833 
4834  if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && Leg2.at(0).col() != 0 && Leg2.at(0).acol() != 0){ // starting to form the Leg2 for anti_junction by Color Tag Tracing. If first particle is (anti)quark, no need to trace
4835  for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4836  for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4837  if( ( Leg2.back().col() != 0 ) && (Leg2.back().col() == SP_remnants[icf].acol()) ){
4838  //std::cout <<endl<<"particle added to Leg 2 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4839  Leg2.push_back(SP_remnants[icf]);
4840  SP_remnants[icf].used_junction(true);
4841  }
4842  if( Leg2.back().col() == 0 || Leg2.back().acol() == 0){break;}
4843  }
4844  }
4845  }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && Leg2.at(0).col() != 0 && Leg2.at(0).acol() != 0){ // starting to form the Leg2 junction by Color Tag Tracing. If first particle is quark, no need to trace
4846  for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4847  for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4848  if( (Leg2.back().acol() != 0) && (Leg2.back().acol() == SP_remnants[icf].col()) ){
4849  //std::cout <<endl<<"particle added to Leg 2 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4850  Leg2.push_back(SP_remnants[icf]);
4851  SP_remnants[icf].used_junction(true);
4852  }
4853  if( Leg2.back().col() == 0 || Leg2.back().acol() == 0){break;}
4854  }
4855  }
4856  }
4857 
4858  if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && Leg3.at(0).col() != 0 && Leg3.at(0).acol() != 0){ // starting to form the Leg3 for anti_junction by Color Tag Tracing. If first particle is (anti)quark, no need to trace
4859  for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4860  for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4861  if( (Leg3.back().col() != 0) && (Leg3.back().col() == SP_remnants[icf].acol()) ){
4862  //std::cout <<endl<<"particle added to Leg 3 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4863  Leg3.push_back(SP_remnants[icf]);
4864  SP_remnants[icf].used_junction(true);
4865  }
4866  if( Leg3.back().col() == 0 || Leg3.back().acol() == 0){break;}
4867  }
4868  }
4869  }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && Leg3.at(0).col() != 0 && Leg3.at(0).acol() != 0){ // starting to form the Leg3 junction by Color Tag Tracing. If first particle is quark, no need to trace
4870  for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4871  for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4872  //std::cout <<"candidate particle is "<<SP_remnants[icf].pid()<<" , "<<SP_remnants[icf].col()<<" , "<<SP_remnants[icf].acol()<<" , "<<SP_remnants[icf].used_junction()<<endl;
4873  //std::cout <<"and standard particle is "<<Leg3.back().pid()<<" , "<<Leg3.back().col()<<" , "<<Leg3.back().acol()<<" , "<<Leg3.back().used_junction()<<endl;
4874  if( (Leg3.back().acol() != 0) && (Leg3.back().acol() == SP_remnants[icf].col()) ){
4875  //std::cout <<endl<<"particle added to Leg 3 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4876  Leg3.push_back(SP_remnants[icf]);
4877  SP_remnants[icf].used_junction(true);
4878  }
4879  if( Leg3.back().col() == 0 || Leg3.back().acol() == 0 ){break;}
4880  }
4881  }
4882  }
4883  JuncLegs.push_back(Leg1);
4884  JuncLegs.push_back(Leg2);
4885  JuncLegs.push_back(Leg3);
4886  JuncStructure.push_back(JuncLegs); // now junction structure with three complete legs is saved, so clear previous infos for considering next junction candidate.
4887  }
4888  JuncLegs.clear();
4889  Leg1.clear();
4890  Leg2.clear();
4891  Leg3.clear();
4892  Legconsidering.clear();
4893  }
4894 
4895  //So far, all the information for (Anti)Junction and Legs are formed by color tag tracing. Let's Check this out
4896  //dignostic measure
4897  /*for(int ijuncstr=0; ijuncstr < JuncStructure.size(); ++ijuncstr) {
4898  std::cout <<endl<<endl<<" Let's see Temporary junction structure "<<endl;
4899  std::cout <<" Temp Junction :" << ijuncstr+1 <<endl;
4900  std::cout <<"Leg 1 : [ ";
4901  for(int ileg1=0; ileg1 < JuncStructure.at(ijuncstr).at(0).size(); ++ileg1){
4902  std::cout <<" ( " << JuncStructure.at(ijuncstr).at(0)[ileg1].col() <<" , " << JuncStructure.at(ijuncstr).at(0)[ileg1].acol() <<" ), " ;
4903  }
4904  std::cout <<" ] " <<endl;
4905  std::cout <<"Leg 2 : [ ";
4906  for(int ileg2=0; ileg2 < JuncStructure.at(ijuncstr).at(1).size(); ++ileg2){
4907  std::cout <<" ( " << JuncStructure.at(ijuncstr).at(1)[ileg2].col() <<" , " << JuncStructure.at(ijuncstr).at(1)[ileg2].acol() <<" ), " ;
4908  }
4909  std::cout <<" ] " <<endl;
4910  std::cout <<"Leg 3 : [ ";
4911  for(int ileg3=0; ileg3 < JuncStructure.at(ijuncstr).at(2).size(); ++ileg3){
4912  std::cout <<" ( " << JuncStructure.at(ijuncstr).at(2)[ileg3].col() <<" , " << JuncStructure.at(ijuncstr).at(2)[ileg3].acol() <<" ), " ;
4913  }
4914  std::cout <<" ] " <<endl;
4915  }*/
4916 
4917  // Now, we will find the shared legs and sorting them into the corresponding vectors, the information from JuncStructure vector and realjuncindice vector work together here.
4918  // if the tags of first particle in a string and end particle in another string are same, they are shared Leg!!
4919  for(int irep1 = 0; irep1 < JuncStructure.size(); irep1++){
4920  IMStructure3.push_back(realjuncindice.at(irep1));
4921  IMStructure3.push_back(Tempjunctions.at(realjuncindice.at(irep1)).at(0).at(0));
4922  IMStructure3.push_back(irep1);// room for other usage
4923  IMStructure3.push_back(0); // tag 1: dijinction, tag0: other cases
4924  IMStructure2.push_back(IMStructure3);
4925  IMStructure3.clear();
4926  for(int irep2 = 0; irep2 < 3; irep2++){
4927  for(int irep3 = 0; irep3 < JuncStructure.size(); irep3++){
4928  for(int irep4 = 0; irep4 < 3; irep4++){
4929  if( (irep1 != irep3) && (JuncStructure.at(irep1).at(irep2).at(0).col() == JuncStructure.at(irep3).at(irep4).back().col()) &&
4930  (JuncStructure.at(irep1).at(irep2).at(0).acol() == JuncStructure.at(irep3).at(irep4).back().acol())){
4931  IMStructure3.push_back(irep1);
4932  IMStructure3.push_back(irep2);
4933  IMStructure3.push_back(irep3);
4934  IMStructure3.push_back(irep4); // the first pair means irep2_th Leg in irep1_th junction is linked with irep4_th Leg in irep3_th Tempjunction
4935  IMStructure2.push_back(IMStructure3);
4936  IMStructure3.clear();
4937  }
4938  }
4939  }
4940  }
4941  IMStructure1.push_back(IMStructure2);
4942  IMStructure2.clear();
4943  }
4944 
4945  //dignostic measure!
4946  /*JSINFO << "First IMStructure printout";
4947  std::cout <<endl;
4948  for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
4949  for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
4950  std::cout <<" ( ";
4951  for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
4952  std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
4953  }
4954  std::cout <<" ) ";
4955  }
4956  std::cout <<endl;
4957  }*/
4958 
4959  // create a vector containing 0 if the (anti-)junction contains only shower partons, 1 if at least one thermal
4960  // this is only for the ones in Recombearly1
4961  std::vector<int> thermal_parton_junction;
4962 
4963  //since the relation between junctions is defined, Let's sorting Junctions based on shared legs
4964  for(int iloop1 = 0; iloop1 < IMStructure1.size(); iloop1++){
4965  //structure for 3-shared particles find shared legs and tossing them into the baryon formation
4966  if(IMStructure1.at(iloop1).size() == 4){
4967  for(int iloop2 = 1; iloop2 < IMStructure1.at(iloop1).size(); iloop2++){
4968  for(int iloop3 = 0; iloop3 < IMStructure1.size(); iloop3++){
4969  for(int iloop4 = 1; iloop4 < IMStructure1.at(iloop3).size(); iloop4++){
4970  if( (IMStructure1.at(iloop1).at(iloop2).at(2) == IMStructure1.at(iloop3).at(iloop4).at(0)) &&
4971  (IMStructure1.at(iloop1).at(iloop2).at(3) == IMStructure1.at(iloop3).at(iloop4).at(1)) ){
4972  vector<int> testing;
4973  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(2));
4974  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(3));
4975  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(0));
4976  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(1)); //now temporary vector is created by this procedure.
4977  std::vector<vector<int>>::iterator it = std::find(IMStructure1.at(iloop3).begin(), IMStructure1.at(iloop3).end(), testing);
4978  IMStructure1.at(iloop3).erase(it);
4979  testing.clear(); //now the one of the leg is eliminated in the list, so there is no overlapped leg to be tossed into baryon formation list.
4980  }
4981  if((JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).col() != 0) &&
4982  (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).acol() != 0) &&
4983  (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col() != 0) &&
4984  (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol() != 0)) {
4985  parton_collection tempqpair;
4986  gluon_decay(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0), tempqpair ); // the first particle has col tag and the second had acol tag
4987  //std::vector<HHparton>::iterator tempit1 = JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).begin();
4988  //JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).erase(tempit1);
4989  if(IMStructure1.at(iloop1).at(0).at(1) == -1){
4990  Recombearly2.push_back(tempqpair[1]); //add anti-particle to form anti baryon
4991  //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
4992  //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
4993  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
4994  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[0]); // add remain parton to the original leg
4995  //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
4996  //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
4997  }
4998  if(IMStructure1.at(iloop1).at(0).at(1) == 1){
4999  Recombearly2.push_back(tempqpair[0]); //add particle to form baryon
5000  //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
5001  //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
5002  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
5003  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[1]); // add remain parton to the original leg
5004  //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
5005  //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
5006  }
5007  tempqpair.clear();
5008  }
5009  }
5010  }
5011  }
5012  thermal_parton_junction.push_back(Tempjunctions.at(IMStructure1.at(iloop1).at(0).at(2)).at(0).at(1));
5013  IMStructure1.erase(IMStructure1.begin()+iloop1); // erase the junction with three shared legs from the IMStructure
5014  iloop1--;
5015  Recombearly1.push_back(Recombearly2);
5016  Recombearly2.clear();
5017  }
5018  }
5019 
5020  //One thing to remind : JuncStructure has information of parton class, and IMStructure has informations about these partons or junctions with same indice with JuncStructure
5021  for(int iloop1 = 0; iloop1 < IMStructure1.size(); iloop1++){
5022  if(IMStructure1.at(iloop1).size() == 3){ // 2-shared leg case {basic info, shared leg1's info, shared leg2's info}
5023  // loop for pop out the unshared leg in the junction structure.
5024  int leftleg; // indice of unshared leg which will remain after the Early recombinaton
5025  int SI = 0; // Sum of the Indice of Leg{if 1 = 0+1, Leg3 is not shared, if 3 = 1+2, Leg 0 is not shared}
5026  for(int itail = 1; itail < IMStructure1.at(iloop1).size(); itail++){
5027  SI = SI + IMStructure1.at(iloop1).at(itail).at(1);
5028  }
5029  //std::cout <<endl<<"SI = "<<SI<<endl;
5030  vector<int> indicevec; // vector for indice, we could use if statement, but when if and for statement are repeated, possibly forced execution occurs regardless of if statement, so take most defensive measure.
5031  indicevec.push_back(2);
5032  indicevec.push_back(1);
5033  indicevec.push_back(0);
5034  leftleg = indicevec[SI-1];
5035  //below was tested, but showed forced execution{that is all of the Three statements executed so that left leg was always 0}
5036  //if(SI = 1 ){ leftleg = 2; SI = 0;}
5037  //if(SI = 2 ){ leftleg = 1; SI = 0;}
5038  //if(SI = 3 ){ leftleg = 0; SI = 0;}
5039  //std::cout <<endl<<"leftleg number is "<<leftleg<<endl;
5040 
5041  int jidentity = IMStructure1.at(iloop1).at(0).at(1); //junction identity 1 or -1 {junction or anti juncttion}
5042  //std::cout <<endl<<"junction identity is "<<jidentity<<endl;
5043  int juncnum = IMStructure1.at(iloop1).at(0).at(0); //junction number to be dealt with
5044  vector<HHparton> tempstring = JuncStructure.at(juncnum).at(leftleg); //declare the unshared leg.
5045  if(jidentity == 1 && tempstring.at(0).col() != 0 && tempstring.at(0).acol() != 0){
5046  parton_collection tempqpair;
5047  gluon_decay( tempstring.at(0), tempqpair);
5048  tempstring.erase(tempstring.begin());
5049  tempstring.insert(tempstring.begin() , tempqpair[1] );
5050  Tailoredstring1.push_back(tempstring);
5051  Recombearly2.push_back(tempqpair[0]);
5052  }else if(jidentity == -1 && tempstring.at(0).col() != 0 && tempstring.at(0).acol() != 0){
5053  parton_collection tempqpair;
5054  gluon_decay( tempstring.at(0), tempqpair);
5055  tempstring.erase(tempstring.begin());
5056  tempstring.insert(tempstring.begin() , tempqpair[0] );
5057  Tailoredstring1.push_back(tempstring);
5058  Recombearly2.push_back(tempqpair[1]);
5059  }else{
5060  Recombearly2.push_back(tempstring.at(0));
5061  }
5062  indicevec.clear();
5063 
5064  for(int iloop2 = 1; iloop2 < IMStructure1.at(iloop1).size(); iloop2++){
5065  for(int iloop3 = 0; iloop3 < IMStructure1.size(); iloop3++){
5066  for(int iloop4 = 1; iloop4 < IMStructure1.at(iloop3).size(); iloop4++){
5067  if( (IMStructure1.at(iloop1).at(iloop2).at(2) == IMStructure1.at(iloop3).at(iloop4).at(0)) &&
5068  (IMStructure1.at(iloop1).at(iloop2).at(3) == IMStructure1.at(iloop3).at(iloop4).at(1)) ){
5069  vector<int> testing;
5070  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(2));
5071  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(3));
5072  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(0));
5073  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(1)); //now temporary vector is created by this procedure.
5074  std::vector<vector<int>>::iterator it = std::find(IMStructure1.at(iloop3).begin(), IMStructure1.at(iloop3).end(), testing);
5075  IMStructure1.at(iloop3).erase(it);
5076  testing.clear(); //now the one of the leg is eliminated in the list, so there is no overlapped leg to be tossed into baryon formation list.
5077  }
5078  if((JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).col() != 0) &&
5079  (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).acol() != 0) &&
5080  (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col() != 0) &&
5081  (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol() != 0)) {
5082  parton_collection tempqpair;
5083  gluon_decay(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0), tempqpair ); // the first particle has col tag and the second had acol tag
5084  //std::vector<HHparton>::iterator tempit1 = JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).begin();
5085  //JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).erase(tempit1);
5086  if(IMStructure1.at(iloop1).at(0).at(1) == -1){
5087  Recombearly2.push_back(tempqpair[1]); //add anti-particle to form anti baryon
5088  //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
5089  //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
5090  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
5091  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[0]); // add remain parton to the original leg
5092  //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
5093  //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
5094  }
5095  if(IMStructure1.at(iloop1).at(0).at(1) == 1){
5096  Recombearly2.push_back(tempqpair[0]); //add particle to form baryon
5097  //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
5098  //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
5099  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
5100  JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[1]); // add remain parton to the original leg
5101  //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
5102  //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
5103  }
5104  }
5105  }
5106  }
5107  }
5108  thermal_parton_junction.push_back(Tempjunctions.at(IMStructure1.at(iloop1).at(0).at(2)).at(0).at(1));
5109  IMStructure1.erase(IMStructure1.begin()+iloop1); // erase the junction with three shared legs from the IMStructure
5110  iloop1--;
5111  Recombearly1.push_back(Recombearly2);
5112  Recombearly2.clear();
5113  }
5114  }
5115 
5116  /*std::cout <<endl;
5117  std::cout <<" number of early recombined baryons 1: "<<Recombearly1.size()<<endl;
5118  for(int ibary1 = 0; ibary1 < Recombearly1.size(); ibary1++){
5119  std::cout <<"the "<< ibary1 <<" st baryon is made of ";
5120  for(int ibary2 = 0; ibary2 < Recombearly1.at(ibary1).size(); ibary2++){
5121  std::cout <<" { "<<Recombearly1.at(ibary1).at(ibary2).col()<<" , "<< Recombearly1.at(ibary1).at(ibary2).acol() <<" } , ";
5122  }
5123  std::cout <<endl;
5124  }*/
5125 
5126  //dignostic measure{IMStructure1}
5127  /*JSINFO << "1.5 IMStructure printout";
5128  std::cout <<endl;
5129  for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
5130  for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
5131  std::cout <<" ( ";
5132  for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
5133  std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
5134  }
5135  std::cout <<" ) ";
5136  }
5137  std::cout <<endl;
5138  }*/
5139 
5140  for(int iloop1 = 0; iloop1 < IMStructure1.size(); iloop1++){
5141  if(IMStructure1.at(iloop1).size() == 2 && IMStructure1.at(iloop1).at(0).at(3) == 0){ // Dijunction Structure
5142  for(int iloop2 = 1; iloop2< IMStructure1.at(iloop1).size(); iloop2++){
5143  for(int iloop3 = 0; iloop3 < IMStructure1.size(); iloop3++){
5144  for(int iloop4 = 1; iloop4 < IMStructure1.at(iloop3).size(); iloop4++){
5145  if( (IMStructure1.at(iloop1).at(iloop2).at(2) == IMStructure1.at(iloop3).at(iloop4).at(0)) &&
5146  (IMStructure1.at(iloop1).at(iloop2).at(3) == IMStructure1.at(iloop3).at(iloop4).at(1)) ){ // the case where we found the shared legs pair.
5147  if(IMStructure1.at(iloop1).at(0).at(3) == 0) {
5148  for(int idijunc1 = 0; idijunc1 < 3; idijunc1++){ // first, put three legs of first junction
5149  Dijunction2.push_back(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(idijunc1));
5150  }
5151  for(int idijunc2 = 0; idijunc2 < 3; idijunc2++){ // second, exclude shared leg in second junction to be merged
5152  if( idijunc2 != IMStructure1.at(iloop1).at(iloop2).at(3)){
5153  Dijunction2.push_back(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(idijunc2));
5154  }
5155  }
5156  }
5157  Dijunction1.push_back(Dijunction2); //finally, five legs are added in the vector to form dijunction structure.
5158  Dijunction2.clear(); // clear temp vector for next procedure.
5159  IMStructure1.at(iloop1).at(0).pop_back();
5160  IMStructure1.at(iloop1).at(0).push_back(1); // tag representing dijunction structure.
5161  IMStructure1.at(iloop3).at(0).pop_back();
5162  IMStructure1.at(iloop3).at(0).push_back(1); // tag representing dijunction structure.
5163 
5164  vector<int> testing;
5165  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(2));
5166  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(3));
5167  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(0));
5168  testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(1)); //now temporary vector is created by this procedure.
5169  std::vector<vector<int>>::iterator it = std::find(IMStructure1.at(iloop3).begin(), IMStructure1.at(iloop3).end(), testing);
5170  IMStructure1.at(iloop3).erase(it);
5171  testing.clear();
5172  //now the one of the leg is eliminated in the list, so there is no overlapped leg to be tossed into baryon formation list.
5173  }
5174  }
5175  }
5176  }
5177  }
5178  }
5179 
5180  //dignostic measure{IMStructure1}
5181  /*JSINFO << "1.75 IMStructure printout";
5182  std::cout <<endl;
5183  for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
5184  for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
5185  std::cout <<" ( ";
5186  for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
5187  std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
5188  }
5189  std::cout <<" ) ";
5190  }
5191  std::cout <<endl;
5192  }*/
5193 
5194  for(int irepair = 0; irepair < IMStructure1.size(); irepair++) {
5195  if(IMStructure1.at(irepair).size() == 1 && IMStructure1.at(irepair).at(0).at(3) == 0 ){ // size one means there are no shared legs to the junction, so put them directly to the single junction vector
5196  Singlejunction2.push_back(JuncStructure.at(IMStructure1.at(irepair).at(0).at(2)).at(0));
5197  Singlejunction2.push_back(JuncStructure.at(IMStructure1.at(irepair).at(0).at(2)).at(1));
5198  Singlejunction2.push_back(JuncStructure.at(IMStructure1.at(irepair).at(0).at(2)).at(2));
5199  Singlejunction1.push_back(Singlejunction2);
5200  Singlejunction2.clear();
5201  }//After all, all these vectors of junction legs will be tossed into PYTHIA to be hadronized. before that we need to set Mother Daughter tag for PYTHIA
5202  } // collecting all single junctions
5203 
5204  //dignostic measure{IMStructure1}
5205  /*JSINFO << "Second IMStructure printout";
5206  std::cout <<endl;
5207  for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
5208  for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
5209  std::cout <<" ( ";
5210  for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
5211  std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
5212  }
5213  std::cout <<" ) ";
5214  }
5215  std::cout <<endl;
5216  }*/
5217 
5218  //now we need to form fake partons and baryons for appending particles to PYTHIA{for Dijunction Structure}
5219  //declaration of required Variables
5220  bool J = false;
5221  bool antiJ = false;
5222  bool bothJ = false;
5223  for(int idj1 = 0; idj1 < Dijunction1.size(); idj1++){ //searching dijunction
5224  for(int idj2 = 0; idj2 < Dijunction1.at(idj1).size(); idj2++){ //searching dijunction's leg
5225  //std::cout <<endl<<"let's check these particles "<<endl;
5226  //std::cout <<" { "<<Dijunction1.at(idj1).at(idj2).at(0).col()<<" , "<<Dijunction1.at(idj1).at(idj2).at(0).acol()<<" } "<<endl;
5227  //std::cout <<" { "<<Dijunction1.at(idj1).at(idj2).back().col()<<" , "<<Dijunction1.at(idj1).at(idj2).back().acol()<<" } "<<endl;
5228  for(int itpj1 = 0; itpj1 < IMStructure1.size(); itpj1++){ //searching Tempjunction
5229  for(int itpj2 = 1; itpj2 < Tempjunctions.at(itpj1).size(); itpj2++){ //searching color tags in tempjunction{ {_+1, 0 }, {_+1, tag1}, {_+1, tag2}, {_+1, tag3} }
5230  if(Dijunction1.at(idj1).at(idj2).at(0).col() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) || //check whether first or last particle has correponding color tags for J
5231  Dijunction1.at(idj1).at(idj2).back().col() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) ){
5232  J = true;
5233  }
5234  if(Dijunction1.at(idj1).at(idj2).at(0).acol() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) || //check whether first or last particle has correponding color tags for J
5235  Dijunction1.at(idj1).at(idj2).back().acol() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) ){
5236  antiJ = true;
5237  }
5238  }
5239  }
5240  if(J == true && antiJ == false){ // this leg is a part of junction
5241  DijunctionInfo2.push_back(1);
5242  }
5243  if(J == false && antiJ == true){ // this leg is a part of junction
5244  DijunctionInfo2.push_back(-1);
5245  }
5246  if(J == true && antiJ == true){
5247  bothJ = true;
5248  }
5249  if(bothJ){ //this leg is shared leg, so that fake parton shoud be added after all
5250  DijunctionInfo2.push_back(0);
5251  }
5252  J = false; //reseting variables to check other legs in Dijunction structure
5253  antiJ = false;
5254  bothJ = false;
5255  }
5256  DijunctionInfo1.push_back(DijunctionInfo2);
5257  DijunctionInfo2.clear();
5258  }//so far, vector about the information of dijunction structure is formed,{ so, we could put identity 1-leg first, and put identity-0 leg and -1 leg}
5259  //based on the information above, we need to add fake partons, which are used for telling pythia about the color flow{fake particle id is ignored, since we'll set
5260  // negative status flag}, with this color flow information, PYTHIA can detect J and anti-J
5261 
5262  //additional proceudre to change the configuration of shared leg by searching through dijunction1 and dijunction1info vectors
5263  // make sure that the shared leg is ordered from junction to antijunction, used later
5264  for(int ileg1 = 0 ; ileg1 < Dijunction1.size(); ileg1++){
5265  for(int ileg2 = 0; ileg2 < Dijunction1.at(ileg1).size(); ileg2++){
5266  bool needflip = false;
5267  if((DijunctionInfo1.at(ileg1).at(ileg2) == 0 && Dijunction1.at(ileg1).at(ileg2).size() != 1) &&
5268  (Dijunction1.at(ileg1).at(ileg2).at(0).col() == Dijunction1.at(ileg1).at(ileg2).at(1).acol()) ){ // In this case, we need to flip the order of the partons in this shared leg
5269  needflip = true;
5270  }
5271  if(needflip){
5272  std::reverse(Dijunction1.at(ileg1).at(ileg2).begin() , Dijunction1.at(ileg1).at(ileg2).end() );
5273  }
5274  needflip = false;
5275  }
5276  }
5277 
5278  //dignostic measure{DijunctionInfo1}
5279  /*std::cout <<endl;
5280  std::cout <<" DijunctionInfo Checking"<<endl;
5281  for(int icheck1 = 0; icheck1 < DijunctionInfo1.size(); icheck1++){
5282  std::cout <<" Let's Check all the elements! : ";
5283  for(int icheck2 = 0; icheck2 < DijunctionInfo1.at(icheck1).size(); icheck2++){
5284  std::cout <<DijunctionInfo1.at(icheck1).at(icheck2)<<" , ";
5285  }
5286  std::cout <<endl;
5287  }*/
5288 
5289  //dignostic measure{Dijunction1}
5290  /*std::cout <<endl;
5291  std::cout <<" List of Dijunction Structure"<<endl;
5292  for(int icheck1 = 0; icheck1 < Dijunction1.size(); icheck1++){
5293  std::cout <<" Dijunction : "<<icheck1<<endl;
5294  for(int icheck2 = 0 ; icheck2 < Dijunction1.at(icheck1).size(); icheck2++){
5295  std::cout <<" Leg "<<icheck2<<" : "<<"{ identity : "<< DijunctionInfo1.at(icheck1).at(icheck2)<<" } ";
5296  for(int icheck3 = 0; icheck3 < Dijunction1.at(icheck1).at(icheck2).size(); icheck3++){
5297  std::cout <<" ( "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).acol()<< " ) ";
5298  }
5299  std::cout <<endl;
5300  }
5301  }*/
5302 
5303  //dignostic measure{Singlejunction1}
5304  /*std::cout <<endl;
5305  std::cout <<" List of Single Junction Structure"<<endl;
5306  for(int icheck1 = 0; icheck1 < Singlejunction1.size(); icheck1++){
5307  std::cout <<" Single junction : "<<icheck1<<endl;
5308  for(int icheck2 = 0 ; icheck2 < Singlejunction1.at(icheck1).size(); icheck2++){
5309  std::cout <<" Leg "<<icheck2<<" : ";
5310  for(int icheck3 = 0; icheck3 < Singlejunction1.at(icheck1).at(icheck2).size(); icheck3++){
5311  std::cout <<" ( "<<Singlejunction1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Singlejunction1.at(icheck1).at(icheck2).at(icheck3).acol()<< " ) ";
5312  }
5313  std::cout <<endl;
5314  }
5315  }*/
5316 
5317  //For the validity with PYTHIA running, each Leg in Single or Dijunction Structure should have q or q-bar as endpoint particle, so checking whether the gluon is located at the endpoint of the Leg
5318  //Starting from Leg's in single junction.
5319  for(int is1 = 0; is1 < Singlejunction1.size(); is1++){
5320  HHparton p1 = Singlejunction1.at(is1).at(0).back(); //endpoint particle of first leg in is1_st Singlejunction1
5321  HHparton p2 = Singlejunction1.at(is1).at(1).back(); //endpoint particle of second leg in is1_st Singlejunction1
5322  HHparton p3 = Singlejunction1.at(is1).at(2).back(); //endpoint particle of third leg in is1_st Singlejunction1
5323 
5324  // basically, assume the junction. but check the id's of them and change identity of the condition for antijunction is meeted
5325  bool ajunction = false;
5326 
5327  if( p1.id() < 0 || p2.id() < 0 || p3.id() < 0){
5328  ajunction = true;
5329  }
5330 
5331  for(int is2 = 0; is2 < Singlejunction1.at(is1).size(); is2++){
5332  HHparton endpoint = Singlejunction1.at(is1).at(is2).back();
5333 
5334  if(endpoint.col() != 0 && endpoint.acol() != 0 && ajunction){
5335  int loc = 0;
5336  HHparton tempparton1 = endpoint;
5337  if(tempparton1.id() == 21) {
5338  tempparton1.id(1);
5339  loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5340  tempparton1.id(21);
5341  }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5342  if(loc == 999999999 || loc > 0) {
5343  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
5344  HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(0);
5345  fakep.set_anti_color(endpoint.col());
5346  if(std::abs(fakep.id()) < 3) {
5347  fakep.mass(xmq);
5348  } else {fakep.mass(xms);}
5349  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5350  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5351  if (number_p_fake == 0 || number_p_fake == 2){
5352  fakep.pz(-p_fake);
5353  } else if (number_p_fake == 1 || number_p_fake == 3) {
5354  fakep.pz(p_fake);
5355  } else {fakep.pz(0.);}
5356  number_p_fake++;
5357  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5358  fakep.orig(-1); fakep.is_remnant(true);
5359  fakep.is_fakeparton(true);
5360  SP_remnants.add(fakep);
5361  Singlejunction1.at(is1).at(is2).push_back(fakep);
5362  }else if(loc < 0) {
5363  HH_thermal[-loc-1].acol(endpoint.col());
5364  HH_thermal[-loc-1].col(0);
5365  HH_thermal[-loc-1].is_used(true);
5366  HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5367  SP_remnants[SP_remnants.num()-1].par(-loc-1);
5368  Singlejunction1.at(is1).at(is2).push_back(HH_thermal[-loc-1]);
5369  }
5370  }
5371  }
5372 
5373  for(int is3 = 0; is3 < Singlejunction1.at(is1).size(); is3++){
5374  HHparton endpoint = Singlejunction1.at(is1).at(is3).back();
5375 
5376  if(endpoint.col() != 0 && endpoint.acol() != 0 && !ajunction){
5377  int loc = 0;
5378  HHparton tempparton1 = endpoint;
5379  if(tempparton1.id() == 21) {
5380  tempparton1.id(-1);
5381  loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5382  tempparton1.id(21);
5383  }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5384  if(loc == 999999999 || loc > 0) {
5385  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
5386  HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(endpoint.acol());
5387  fakep.set_anti_color(0);
5388  if(std::abs(fakep.id()) < 3) {
5389  fakep.mass(xmq);
5390  } else {fakep.mass(xms);}
5391  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5392  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5393  if (number_p_fake == 0 || number_p_fake == 2){
5394  fakep.pz(-p_fake);
5395  } else if (number_p_fake == 1 || number_p_fake == 3) {
5396  fakep.pz(p_fake);
5397  } else {fakep.pz(0.);}
5398  number_p_fake++;
5399  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5400  fakep.orig(-1); fakep.is_remnant(true);
5401  fakep.is_fakeparton(true);
5402  SP_remnants.add(fakep);
5403  Singlejunction1.at(is1).at(is3).push_back(fakep);
5404  }else if(loc < 0) {
5405  HH_thermal[-loc-1].col(endpoint.acol());
5406  HH_thermal[-loc-1].acol(0);
5407  HH_thermal[-loc-1].is_used(true);
5408  HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5409  SP_remnants[SP_remnants.num()-1].par(-loc-1);
5410  Singlejunction1.at(is1).at(is3).push_back(HH_thermal[-loc-1]);
5411  }
5412  }
5413  }
5414  ajunction = false; //resetting the variable.
5415  }
5416 
5417  //Working for Leg's in dijunction structure.
5418  for(int idj1 = 0; idj1 < Dijunction1.size(); idj1++){
5419  for(int idj2 = 0; idj2 < Dijunction1.at(idj1).size(); idj2++){
5420  HHparton endpoint = Dijunction1.at(idj1).at(idj2).back();
5421 
5422  if(DijunctionInfo1.at(idj1).at(idj2) == -1 && endpoint.col() != 0 && endpoint.acol() != 0){
5423  int loc = 0;
5424  HHparton tempparton1 = endpoint;
5425  if(tempparton1.id() == 21) {
5426  tempparton1.id(1);
5427  loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5428  tempparton1.id(21);
5429  }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5430  if(loc == 999999999 || loc > 0) {
5431  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
5432  HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(0);
5433  fakep.set_anti_color(endpoint.col());
5434  if(std::abs(fakep.id()) < 3) {
5435  fakep.mass(xmq);
5436  } else {fakep.mass(xms);}
5437  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5438  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5439  if (number_p_fake == 0 || number_p_fake == 2){
5440  fakep.pz(-p_fake);
5441  } else if (number_p_fake == 1 || number_p_fake == 3) {
5442  fakep.pz(p_fake);
5443  } else {fakep.pz(0.);}
5444  number_p_fake++;
5445  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5446  fakep.orig(-1); fakep.is_remnant(true);
5447  fakep.is_fakeparton(true);
5448  SP_remnants.add(fakep);
5449  Dijunction1.at(idj1).at(idj2).push_back(fakep);
5450  }else if(loc < 0) {
5451  HH_thermal[-loc-1].acol(endpoint.col());
5452  HH_thermal[-loc-1].col(0);
5453  HH_thermal[-loc-1].is_used(true);
5454  HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5455  SP_remnants[SP_remnants.num()-1].par(-loc-1);
5456  Dijunction1.at(idj1).at(idj2).push_back(HH_thermal[-loc-1]);
5457  }
5458  }
5459  }
5460 
5461  for(int idj3 = 0; idj3 < Dijunction1.at(idj1).size(); idj3++){
5462  HHparton endpoint = Dijunction1.at(idj1).at(idj3).back();
5463 
5464  if(DijunctionInfo1.at(idj1).at(idj3) == 1 && endpoint.col() != 0 && endpoint.acol() != 0){
5465  int loc = 0;
5466  HHparton tempparton1 = endpoint;
5467  if(tempparton1.id() == 21) {
5468  tempparton1.id(-1);
5469  loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5470  tempparton1.id(21);
5471  }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5472  if(loc == 999999999 || loc > 0) {
5473  int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
5474  HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(endpoint.acol());
5475  fakep.set_anti_color(0);
5476  if(std::abs(fakep.id()) < 3) {
5477  fakep.mass(xmq);
5478  } else {fakep.mass(xms);}
5479  double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5480  fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5481  if (number_p_fake == 0 || number_p_fake == 2){
5482  fakep.pz(-p_fake);
5483  } else if (number_p_fake == 1 || number_p_fake == 3) {
5484  fakep.pz(p_fake);
5485  } else {fakep.pz(0.);}
5486  number_p_fake++;
5487  fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5488  fakep.orig(-1); fakep.is_remnant(true);
5489  fakep.is_fakeparton(true);
5490  SP_remnants.add(fakep);
5491  Dijunction1.at(idj1).at(idj3).push_back(fakep);
5492  }else if(loc < 0) {
5493  HH_thermal[-loc-1].col(endpoint.acol());
5494  HH_thermal[-loc-1].acol(0);
5495  HH_thermal[-loc-1].is_used(true);
5496  HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5497  SP_remnants[SP_remnants.num()-1].par(-loc-1);
5498  Dijunction1.at(idj1).at(idj3).push_back(HH_thermal[-loc-1]);
5499  }
5500  }
5501  }
5502  }
5503 
5504  //since the repeating is needed for completing the junction structure, It is inevitable that there are repeated particle in Recombeary1, It's complicated to explain, and useless to focus on.
5505  // so that just delete repeated particles by check color Tags
5506  for(int irb1 = 0; irb1 < Recombearly1.size(); irb1++){ // pick one baryon
5507  for(int irb2 = 0; irb2 < Recombearly1.at(irb1).size(); irb2++){ // pick one particle in baryon
5508  for(int irb3 = irb2+1; irb3 < Recombearly1.at(irb1).size(); irb3++){ // checking through all particles in baryon
5509  if( (Recombearly1.at(irb1).at(irb2).col() == Recombearly1.at(irb1).at(irb3).col()) &&
5510  Recombearly1.at(irb1).at(irb2).acol() == Recombearly1.at(irb1).at(irb3).acol()){
5511  Recombearly1.at(irb1).erase(Recombearly1.at(irb1).begin()+irb3);
5512  irb3--;
5513  }
5514  }
5515  }
5516  }
5517 
5518  //dignositic measure{early recombined baryon}
5519  /*std::cout <<endl;
5520  std::cout <<" number of early recombined baryons : "<<Recombearly1.size()<<endl;
5521  for(int ibary1 = 0; ibary1 < Recombearly1.size(); ibary1++){
5522  std::cout <<"the "<< ibary1 <<" st baryon is made of ";
5523  for(int ibary2 = 0; ibary2 < Recombearly1.at(ibary1).size(); ibary2++){
5524  std::cout <<" { "<<Recombearly1.at(ibary1).at(ibary2).col()<<" , "<< Recombearly1.at(ibary1).at(ibary2).acol()<<" , "<< Recombearly1.at(ibary1).at(ibary2).id()<<" , "<< Recombearly1.at(ibary1).at(ibary2).e() <<" } , ";
5525  }
5526  std::cout <<endl;
5527  }*/
5528 
5529  // force recombine baryons in Recombearly1
5530  for(int irb = 0; irb < Recombearly1.size(); irb++){
5531  double hbac2 = hbarc*hbarc;
5532 
5533  FourVector Pbaryon;
5534  Pbaryon.Set(
5535  Recombearly1.at(irb)[0].px()+Recombearly1.at(irb)[1].px()+Recombearly1.at(irb)[2].px(),
5536  Recombearly1.at(irb)[0].py()+Recombearly1.at(irb)[1].py()+Recombearly1.at(irb)[2].py(),
5537  Recombearly1.at(irb)[0].pz()+Recombearly1.at(irb)[1].pz()+Recombearly1.at(irb)[2].pz(),
5538  0.);
5539 
5540  //baryon(CM) velocity
5541  FourVector betaB; //really p[i]/e below
5542  betaB.Set(
5543  Pbaryon.x()/(Recombearly1.at(irb)[0].e()+Recombearly1.at(irb)[1].e()+Recombearly1.at(irb)[2].e()),
5544  Pbaryon.y()/(Recombearly1.at(irb)[0].e()+Recombearly1.at(irb)[1].e()+Recombearly1.at(irb)[2].e()),
5545  Pbaryon.z()/(Recombearly1.at(irb)[0].e()+Recombearly1.at(irb)[1].e()+Recombearly1.at(irb)[2].e()),
5546  0.);
5547  betaB.Set(
5548  betaB.x(),
5549  betaB.y(),
5550  betaB.z(),
5551  1./(sqrt(1. - (betaB.x()*betaB.x() + betaB.y()*betaB.y() + betaB.z()*betaB.z()))));
5552 
5553  //boosting into CM frame
5554  FourVector pos_BCM[3], p_BCM[3];
5555  pos_BCM[0] = Recombearly1.at(irb)[0].boost_pos(betaB);
5556  pos_BCM[1] = Recombearly1.at(irb)[1].boost_pos(betaB);
5557  pos_BCM[2] = Recombearly1.at(irb)[2].boost_pos(betaB);
5558  p_BCM[0] = Recombearly1.at(irb)[0].boost_P(betaB);
5559  p_BCM[1] = Recombearly1.at(irb)[1].boost_P(betaB);
5560  p_BCM[2] = Recombearly1.at(irb)[2].boost_P(betaB);
5561 
5562  //velocities in CM frame
5563  FourVector v_BCM[3];
5564  v_BCM[0].Set(p_BCM[0].x()/p_BCM[0].t(),p_BCM[0].y()/p_BCM[0].t(),p_BCM[0].z()/p_BCM[0].t(),0.); //these are really p[i]/e
5565  v_BCM[1].Set(p_BCM[1].x()/p_BCM[1].t(),p_BCM[1].y()/p_BCM[1].t(),p_BCM[1].z()/p_BCM[1].t(),0.);
5566  v_BCM[2].Set(p_BCM[2].x()/p_BCM[2].t(),p_BCM[2].y()/p_BCM[2].t(),p_BCM[2].z()/p_BCM[2].t(),0.);
5567 
5568  //propagating quarks until time of youngest quark
5569  double curtime = std::max(std::max(pos_BCM[0].t(), pos_BCM[1].t()), pos_BCM[2].t());
5570  FourVector cur_pos[3];
5571  cur_pos[0].Set(
5572  pos_BCM[0].x()+v_BCM[0].x()*(curtime-pos_BCM[0].t()),
5573  pos_BCM[0].y()+v_BCM[0].y()*(curtime-pos_BCM[0].t()),
5574  pos_BCM[0].z()+v_BCM[0].z()*(curtime-pos_BCM[0].t()),
5575  curtime);
5576  cur_pos[1].Set(
5577  pos_BCM[1].x()+v_BCM[1].x()*(curtime-pos_BCM[1].t()),
5578  pos_BCM[1].y()+v_BCM[1].y()*(curtime-pos_BCM[1].t()),
5579  pos_BCM[1].z()+v_BCM[1].z()*(curtime-pos_BCM[1].t()),
5580  curtime);
5581  cur_pos[2].Set(
5582  pos_BCM[2].x()+v_BCM[2].x()*(curtime-pos_BCM[2].t()),
5583  pos_BCM[2].y()+v_BCM[2].y()*(curtime-pos_BCM[2].t()),
5584  pos_BCM[2].z()+v_BCM[2].z()*(curtime-pos_BCM[2].t()),
5585  curtime);
5586 
5587  //finding position of CM at curtime
5588  FourVector pos_CM;
5589  pos_CM.Set(
5590  (cur_pos[0].x()*Recombearly1.at(irb)[0].mass()+cur_pos[1].x()*Recombearly1.at(irb)[1].mass()+cur_pos[2].x()*Recombearly1.at(irb)[2].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass()+Recombearly1.at(irb)[2].mass()),
5591  (cur_pos[0].y()*Recombearly1.at(irb)[0].mass()+cur_pos[1].y()*Recombearly1.at(irb)[1].mass()+cur_pos[2].y()*Recombearly1.at(irb)[2].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass()+Recombearly1.at(irb)[2].mass()),
5592  (cur_pos[0].z()*Recombearly1.at(irb)[0].mass()+cur_pos[1].z()*Recombearly1.at(irb)[1].mass()+cur_pos[2].z()*Recombearly1.at(irb)[2].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass()+Recombearly1.at(irb)[2].mass()),
5593  curtime);
5594 
5595  //finding position of baryon in lab frame
5596  betaB.Set(-betaB.x(),-betaB.y(),-betaB.z(),betaB.t());
5597  FourVector pos_lab = HHboost(betaB, pos_CM);
5598 
5599  //finding relative positions of partons in CM frame
5600  FourVector pos_rel_square[2];
5601  pos_rel_square[0].Set(
5602  (cur_pos[0].x()-cur_pos[1].x())/sqrt(2.),
5603  (cur_pos[0].y()-cur_pos[1].y())/sqrt(2.),
5604  (cur_pos[0].z()-cur_pos[1].z())/sqrt(2.),
5605  0.);
5606  pos_rel_square[1].Set(
5607  ((cur_pos[0].x()*Recombearly1.at(irb)[0].mass()+cur_pos[1].x()*Recombearly1.at(irb)[1].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass())-cur_pos[2].x())*sqrt(2./3.),
5608  ((cur_pos[0].y()*Recombearly1.at(irb)[0].mass()+cur_pos[1].y()*Recombearly1.at(irb)[1].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass())-cur_pos[2].y())*sqrt(2./3.),
5609  ((cur_pos[0].z()*Recombearly1.at(irb)[0].mass()+cur_pos[1].z()*Recombearly1.at(irb)[1].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass())-cur_pos[2].z())*sqrt(2./3.),
5610  0.);
5611 
5612  //so far, values to form a baryon are set, now make hadron objects based on this information
5613  //now we're forming the hadron
5614  HHhadron formedhadron;
5615  //setting the hadron values: is a recombined hadron, mass, and parents
5616  formedhadron.is_recohad(true);
5617  formedhadron.mass( p_BCM[0].t() + p_BCM[1].t() + p_BCM[2].t() );
5618 
5619  //setting hadron position and momentum vectors
5620  Pbaryon.Set(
5621  Pbaryon.x(),
5622  Pbaryon.y(),
5623  Pbaryon.z(),
5624  sqrt(Pbaryon.x()*Pbaryon.x() + Pbaryon.y()*Pbaryon.y() + Pbaryon.z()*Pbaryon.z() + formedhadron.mass()*formedhadron.mass()));
5625  formedhadron.pos(pos_lab);
5626  formedhadron.P(Pbaryon);
5627 
5628  //need to choose *what* hadron we've formed... base this on the parton id's, mass, & if excited
5629  //might want to do this differently? void f'n(partoncollection, formedhadron)?
5630  //since set_baryon_id function works with object of parton_colection class, make temporary parton_collection
5631  parton_collection tempobject; //since the generator resets all components, don't need to reset the vactors in it
5632  tempobject.add(Recombearly1.at(irb)[0]);
5633  tempobject.add(Recombearly1.at(irb)[1]);
5634  tempobject.add(Recombearly1.at(irb)[2]);
5635 
5636  set_baryon_id(tempobject, formedhadron);
5637 
5638  formedhadron.is_shth(thermal_parton_junction[irb]);
5639 
5640  //need to add the hadron to the collection
5641  HH_hadrons.add(formedhadron);
5642  }
5643 
5644  //from now we need re indexing a of the particles in SP_remnants by comparing color tag in Juncstructure component.
5645  //Maybe there would not be a problem in the used_junction value, but take most defensive measure for the possible error.
5646  std::vector<int> checking;
5647  bool indicecheck = false;
5648  for (int irem = 0; irem < SP_remnants.num(); irem++){
5649  for(int ijs1 = 0; ijs1 < JuncStructure.size(); ijs1++){
5650  for(int ijs2 = 0; ijs2 < JuncStructure.at(ijs1).size(); ijs2++){
5651  for(int ijs3 = 0; ijs3 < JuncStructure.at(ijs1).at(ijs2).size(); ijs3++){
5652  if( (SP_remnants[irem].col() == JuncStructure.at(ijs1).at(ijs2).at(ijs3).col()) &&
5653  (SP_remnants[irem].acol() == JuncStructure.at(ijs1).at(ijs2).at(ijs3).acol()) ){
5654  SP_remnants[irem].used_junction(true);
5655  checking.push_back(irem);
5656  }
5657  }
5658  }
5659  }
5660  }
5661  for (int irem = 0; irem < SP_remnants.num(); irem++){
5662  for(int icheck = 0; icheck < checking.size(); icheck++){
5663  if(irem == checking.at(icheck)){ indicecheck = true; }
5664  }
5665  if(indicecheck = false){
5666  SP_remnants[irem].used_junction(false);
5667  }
5668  }
5669  // Now set up for junction is done, let's check the left partons to establish string structure
5670 
5671 
5672  //std::cout <<endl<<"let's check left particles!"<<endl;
5673  /*for(int irp = 0 ; irp < SP_remnants.num(); irp++) {
5674  if(SP_remnants[irp].used_junction() == false){
5675  std::cout << "( "<<SP_remnants[irp].id()<<" , "<<SP_remnants[irp].col()<<" , "<<SP_remnants[irp].acol()<<" ) "<<endl;
5676  }
5677  }*/
5678 
5679  for(int ileft = 0; ileft < SP_remnants.num(); ileft++){
5680  if(SP_remnants[ileft].used_junction() == false){
5681  finalstring.push_back(SP_remnants[ileft]);
5682  }
5683  }
5684 
5685  // contains the chopped off legs of junctions
5686  for(int itail1 = 0; itail1 < Tailoredstring1.size(); itail1++ ){
5687  for(int itail2 = 0; itail2 < Tailoredstring1.at(itail1).size(); itail2++){
5688  finalstring.push_back(Tailoredstring1.at(itail1).at(itail2));
5689  }
5690  }
5691 
5692  //std::cout <<endl<<"check final particles!"<<endl;
5693  /*for(int ifin = 0; ifin < finalstring.size(); ifin++){
5694  std::cout << finalstring.at(ifin).id() << "," << finalstring.at(ifin).col() << "," << finalstring.at(ifin).acol() <<endl;
5695  }*/
5696 
5697  /*std::cout <<endl<<"check final particles!"<<endl;
5698  for(int ifin = 0; ifin < finalstring.size(); ifin++){
5699  std::cout <<" { "<< finalstring.at(ifin).col() << " , " << finalstring.at(ifin).acol() << " } "<<endl;
5700  }*/
5701 
5702  //so far, particles in finalstring are ready for being transfered into PYTHIA, since we don't need to set mother, daughter tag.
5703  //but, still need to care about single junction and dijunction system, especially for the mother daughter tag!
5704  // mother, daughter tags are working with the execution order{= order of being declared in pythia} so before tossing the datum to PYTHIA, rearrange order in the vector
5705  // declare the transit space for these particles, while moving onto vector to vector, partons are assigned mother, daughter tag tor PYTHIA running{definition of that tags are given well in main21.cc file in /installed pythia folder/bin/example/ }
5706  vector<vector<HHparton>> Transitdijunction1;
5707  vector<HHparton> Transitdijunction2; // two fake mother B, B-bar and fake q,qbar added and give mother daughter tags!
5708  vector<vector<vector<HHparton>>> Tempsorting1; // vectors for rearranging legs in dijunction{Desired arrangement : identity 1, 1, 0 , -1, -1}
5709  vector<vector<HHparton>> Tempsorting2;
5710  vector<vector<HHparton>> Transitsinglejunction1;
5711  vector<HHparton> Transitsinglejunction2;
5712  vector<HHparton> WaitingLineforPY; // final list of partons with complete M,D tag and col tags
5713 
5714  //set the value for incrementation in mother daughter tag.
5715  //and start from dijunction, first, check the identity{1: junction leg, -1: anti_junction leg, 0:shared leg}, since we'll read col tag first, consider identity=1 leg first and then 0, -1
5716  for(int dijuncfin1 = 0; dijuncfin1 < Dijunction1.size(); dijuncfin1++){ // Going to find shared leg and attach fake partons to the begin and the end of the leg
5717  for(int dijuncfin2= 0; dijuncfin2 < 5; dijuncfin2++){ //inspect through five legs
5718  if(DijunctionInfo1.at(dijuncfin1).at(dijuncfin2) == 0){ //check whether it's shared leg{identity =0} and add fakepartons to the first and second posittion in the vector
5719  HHparton fakeq;
5720  HHparton fakeqbar;
5721  fakeq.id(1); fakeq.set_color(Dijunction1.at(dijuncfin1).at(dijuncfin2).at(0).col());
5722  fakeq.PY_stat(-21); fakeq.mass(xmq); fakeq.e(xmq); fakeq.orig(-1);
5723  fakeq.px(0.); fakeq.py(0.); fakeq.pz(0.);
5724  int endpoint = Dijunction1.at(dijuncfin1).at(dijuncfin2).size() - 1;
5725  fakeqbar.id(-1); fakeqbar.set_anti_color(Dijunction1.at(dijuncfin1).at(dijuncfin2).at(endpoint).acol());
5726  fakeqbar.PY_stat(-21); fakeqbar.mass(xmq); fakeqbar.e(xmq); fakeqbar.orig(-1);
5727  fakeqbar.px(0.); fakeqbar.py(0.); fakeqbar.pz(0.);
5728  std::vector<HHparton>::iterator it2 = Dijunction1.at(dijuncfin1).at(dijuncfin2).begin();
5729  Dijunction1.at(dijuncfin1).at(dijuncfin2).insert(it2, fakeqbar);
5730  std::vector<HHparton>::iterator it1 = Dijunction1.at(dijuncfin1).at(dijuncfin2).begin();
5731  Dijunction1.at(dijuncfin1).at(dijuncfin2).insert(it1, fakeq);
5732  }
5733  }
5734  for(int isort1 = 0; isort1 < 5; isort1++){
5735  if(DijunctionInfo1.at(dijuncfin1).at(isort1) == 1){
5736  Tempsorting2.push_back(Dijunction1.at(dijuncfin1).at(isort1));
5737  }
5738  }
5739  for(int isort1 = 0; isort1 < 5; isort1++){
5740  if(DijunctionInfo1.at(dijuncfin1).at(isort1) == 0){
5741  Tempsorting2.push_back(Dijunction1.at(dijuncfin1).at(isort1));
5742  }
5743  }
5744  for(int isort1 = 0; isort1 < 5; isort1++){
5745  if(DijunctionInfo1.at(dijuncfin1).at(isort1) == -1){
5746  Tempsorting2.push_back(Dijunction1.at(dijuncfin1).at(isort1));
5747  }
5748  }
5749  Tempsorting1.push_back(Tempsorting2);
5750  Tempsorting2.clear();
5751  } //first looping to add fake partons is Finished, now sort the order of the legs to be identity 1,1,0,-1,-1
5752 
5753  //dignostic measure{Dijunction1}
5754  /*std::cout <<endl;
5755  std::cout <<" List of Dijunction Structure"<<endl;
5756  for(int icheck1 = 0; icheck1 < Dijunction1.size(); icheck1++){
5757  std::cout <<" Dijunction : "<<icheck1<<endl;
5758  for(int icheck2 = 0 ; icheck2 < Dijunction1.at(icheck1).size(); icheck2++){
5759  std::cout <<" Leg "<<icheck2<<" : "<<"{ identity : "<< DijunctionInfo1.at(icheck1).at(icheck2)<<" } ";
5760  for(int icheck3 = 0; icheck3 < Dijunction1.at(icheck1).at(icheck2).size(); icheck3++){
5761  std::cout <<" ( "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).acol()<< " ) ";
5762  }
5763  std::cout <<endl;
5764  }
5765  }*/
5766 
5767  //dignostic measure{Tempsorting}
5768  /*std::cout <<endl;
5769  std::cout <<" List of Dijunction Structure"<<endl;
5770  for(int icheck1 = 0; icheck1 < Tempsorting1.size(); icheck1++){
5771  std::cout <<" Tempsorted Dijunction1 : "<<icheck1<<endl;
5772  for(int icheck2 = 0 ; icheck2 < Tempsorting1.at(icheck1).size(); icheck2++){
5773  for(int icheck3 = 0; icheck3 < Tempsorting1.at(icheck1).at(icheck2).size(); icheck3++){
5774  std::cout <<" ( "<<Tempsorting1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Tempsorting1.at(icheck1).at(icheck2).at(icheck3).acol()<< " ) "<<" , "<<Tempsorting1.at(icheck1).at(icheck2).at(icheck3).x_t();
5775  }
5776  std::cout <<endl;
5777  }
5778  }*/
5779 
5780  // adding fake partons and sorting them with right order{Junctionleg1,2 shared leg, antijunctionleg1,2} is finished so far, Now form a fake mothers to prepare for PYTHIA
5781  for(int itag1 = 0; itag1 < Tempsorting1.size(); itag1++){
5782  //First, put fake B,Bbar into 1st and 2nd position of Transitdijunction2
5783  parton_collection FakeBaryonElements; // array of quarks in fake B
5784  parton_collection FakeAntibaryonElements; // array of anti quarks in fake Bbar
5785 
5786  FakeBaryonElements.add(Tempsorting1.at(itag1).at(0).back()); // quarks to form fake FakeBaryon
5787  FakeBaryonElements.add(Tempsorting1.at(itag1).at(1).back());
5788  FakeBaryonElements.add(Tempsorting1.at(itag1).at(2).at(0));
5789  // for the corrspondence with pdg particle id, sorting the these ids based on absolute value.
5790 
5791  for(int iswap = 0; iswap < 3; iswap++){
5792  if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[1].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[1]) ; }
5793  if(abs(FakeBaryonElements[1].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[1], FakeBaryonElements[0]) ; }
5794  if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[0]) ; }
5795  }
5796 
5797  FakeAntibaryonElements.add(Tempsorting1.at(itag1).at(2).at(1)); //anti quarks to form FakeAntiBaryon
5798  FakeAntibaryonElements.add(Tempsorting1.at(itag1).at(3).back());
5799  FakeAntibaryonElements.add(Tempsorting1.at(itag1).at(4).back());
5800 
5801  for(int iswap = 0; iswap < 3; iswap++){
5802  if(abs(FakeAntibaryonElements[2].id()) > abs(FakeAntibaryonElements[1].id())){ std::swap(FakeAntibaryonElements[2], FakeAntibaryonElements[1]) ; }
5803  if(abs(FakeAntibaryonElements[1].id()) > abs(FakeAntibaryonElements[0].id())){ std::swap(FakeAntibaryonElements[1], FakeAntibaryonElements[0]) ; }
5804  if(abs(FakeAntibaryonElements[2].id()) > abs(FakeAntibaryonElements[0].id())){ std::swap(FakeAntibaryonElements[2], FakeAntibaryonElements[0]) ; }
5805  }
5806 
5807  HHhadron store_id_hadron1;
5808  set_baryon_id(FakeBaryonElements, store_id_hadron1);
5809  HHhadron store_id_hadron2;
5810  set_baryon_id(FakeAntibaryonElements, store_id_hadron2);
5811 
5812  FakeBaryonElements.clear();
5813  FakeAntibaryonElements.clear();
5814 
5815  HHparton fakeB;
5816  HHparton fakeBbar;
5817  fakeB.id(store_id_hadron1.id());
5818  fakeB.PY_stat(-11);
5819  fakeB.mass(3*xmq);
5820  fakeB.e(3*xmq);
5821  fakeB.px(0.);
5822  fakeB.py(0.);
5823  fakeB.pz(0.);
5824 
5825  fakeBbar.id(store_id_hadron2.id());
5826  fakeBbar.PY_stat(-11);
5827  fakeBbar.mass(3*xmq);
5828  fakeBbar.e(3*xmq);
5829  fakeBbar.px(0.);
5830  fakeBbar.py(0.);
5831  fakeBbar.pz(0.);
5832 
5833  fakeB.PY_tag1(Tempsorting1.at(itag1).at(0).back().col());
5834  fakeB.PY_tag2(Tempsorting1.at(itag1).at(1).back().col());
5835  fakeB.PY_tag3(Tempsorting1.at(itag1).at(2).at(0).col());
5836 
5837  fakeBbar.PY_tag1(Tempsorting1.at(itag1).at(2).at(1).acol());
5838  fakeBbar.PY_tag2(Tempsorting1.at(itag1).at(3).back().acol());
5839  fakeBbar.PY_tag3(Tempsorting1.at(itag1).at(4).back().acol());
5840 
5841  //so far, we formed two fake partons, which would be at the center of Junction and Antijunction, Now put them 0th and 1st position of Transirdijunction1 vector
5842  Transitdijunction2.push_back(fakeB);
5843  Transitdijunction2.push_back(fakeBbar);
5844  Transitdijunction1.push_back(Transitdijunction2);
5845  Transitdijunction2.clear();
5846  }
5847 
5848  //the next step is to set M,D Tags
5849  int Intag = 0; // tag for internal M,D tagging process
5850  for(int iMD1 = 0; iMD1 < Tempsorting1.size(); iMD1++){ //after working in these Legs, we will return the partons to Transitdijunction1,
5851  // so far, the order in the vectors{Dijunction1, DijunctionInfo1, Tempsorting, Transitdijunction1} are unified, but the difference is the value in each vectors
5852  vector<HHparton> Leg1 = Tempsorting1.at(iMD1).at(0); // for convenience, reassigning legs in sorted dijunction structure.{identity 1,1,0,-1,-1}
5853  vector<HHparton> Leg2 = Tempsorting1.at(iMD1).at(1);
5854  vector<HHparton> Leg3 = Tempsorting1.at(iMD1).at(2);
5855  vector<HHparton> Leg4 = Tempsorting1.at(iMD1).at(3);
5856  vector<HHparton> Leg5 = Tempsorting1.at(iMD1).at(4);
5857  //starting from Leg1{identity1}
5858  for(int ileg1 = 0; ileg1 < Leg1.size(); ileg1++){
5859  Leg1.at(ileg1).PY_par1(0); // the mother of first leg1, 2 should be first fakebaryon{located 1st in the Transitdijunction2 vector!}
5860  Leg1.at(ileg1).PY_par2(0);
5861  Transitdijunction1.at(iMD1).push_back(Leg1.at(ileg1)); //toss Leg1 to the Transirdijunction1.at{iMD}, which would be the last step before WaitingLineforPY
5862  }
5863  for(int ileg2 = 0; ileg2 < Leg2.size(); ileg2++){
5864  Leg2.at(ileg2).PY_par1(0); // the mother of first leg1, 2 should be first fakebaryon{located 1st in the Transitdijunction2 vector!}
5865  Leg2.at(ileg2).PY_par2(0);
5866  Transitdijunction1.at(iMD1).push_back(Leg2.at(ileg2));
5867  }
5868  //for leg3, because of first and end fake particles, it goes differently from other legs
5869  Intag = 2 + Leg1.size() + Leg2.size(); // Previous tag + two fakemothers + Leg1 + Leg2
5870  //First of all, fake parton pairs are located for the convenience of MD tagging
5871  Leg3.at(0).PY_par1(0);//daughter of fakeB
5872  Leg3.at(0).PY_par2(0);
5873  Leg3.at(0).PY_dau1(Intag + Leg4.size() + Leg5.size() + 2); // daughter tags for gluons between two fake qqbar
5874  Leg3.at(0).PY_dau2(Intag + Leg4.size() + Leg5.size() + Leg3.size()- 1); // since
5875  Leg3.at(1).PY_par1(1);//daughter of fakeBbar
5876  Leg3.at(1).PY_par2(1);
5877  Leg3.at(1).PY_dau1(Intag + Leg4.size() + Leg5.size() + 2);
5878  Leg3.at(1).PY_dau2(Intag + Leg4.size() + Leg5.size() + Leg3.size()- 1);
5879 
5880  Transitdijunction1.at(iMD1).push_back(Leg3.at(0));
5881  Transitdijunction1.at(iMD1).push_back(Leg3.at(1)); // push first two fake partons and append remnants at the last, this is for convenience
5882 
5883  Transitdijunction1.at(iMD1).at(0).PY_dau1(2); // correcting daughter tags of fake B located at 0
5884  Transitdijunction1.at(iMD1).at(0).PY_dau2(Intag);
5885  Transitdijunction1.at(iMD1).at(1).PY_dau1(Intag + 1); //setting starting daughter tag of fakeBbar located at 1
5886  Transitdijunction1.at(iMD1).at(1).PY_dau2(Intag + 1 + Leg4.size() + Leg5.size() );
5887 
5888  for(int ileg4 = 0 ; ileg4 < Leg4.size(); ileg4++){
5889  Leg4.at(ileg4).PY_par1(1);
5890  Leg4.at(ileg4).PY_par2(1);
5891  Transitdijunction1.at(iMD1).push_back(Leg4.at(ileg4));
5892  }
5893  for(int ileg5 = 0 ; ileg5 < Leg5.size(); ileg5++){
5894  Leg5.at(ileg5).PY_par1(1);
5895  Leg5.at(ileg5).PY_par2(1);
5896  Transitdijunction1.at(iMD1).push_back(Leg5.at(ileg5));
5897  }
5898  for(int ileg3 = 2; ileg3 < Leg3.size(); ileg3++){ // mother tags for the gluons between two fake qqbar pair
5899  Leg3.at(ileg3).PY_par1(Intag);
5900  Leg3.at(ileg3).PY_par2(Intag + 1);
5901  Transitdijunction1.at(iMD1).push_back(Leg3.at(ileg3));
5902  }
5903  } // Inner tagging loop is finished for dijunction system,{That is, Information in Tempsorting1 is transfered to Transitdijunction1}
5904 
5905  //dignostic measure{Transitdijunction1}
5906  /*std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 "<< endl;
5907  for(int icheck1 = 0; icheck1 < Transitdijunction1.size(); icheck1++ ){
5908  for(int i = 0; i < Transitdijunction1.at(icheck1).size(); i++){
5909  vector<HHparton> temp = Transitdijunction1.at(icheck1);
5910  std::cout << i <<" "<< temp.at(i).id() <<" "<< temp.at(i).PY_stat() <<" "<< temp.at(i).PY_par1() <<" "<< temp.at(i).PY_par2() <<" "
5911  << temp.at(i).PY_dau1() <<" "<< temp.at(i).PY_dau2() << " ( "<< temp.at(i).col()<< " , " << temp.at(i).acol() << " ) " <<endl;
5912  }
5913  }*/
5914 
5915  //Now,start working on Single Junction System.
5916  for(int iSJ = 0; iSJ < Singlejunction1.size(); iSJ++){ // this process is for trasferring information from Singlejunction1 into Transitsinglejunction1, and finally they will be located at WaitingLineforPY
5917  //based on the partons at the end of each Leg, add fake mother baryon first.
5918  parton_collection FakeBaryonElements; // array of quarks in fake mother
5919 
5920  HHparton q1 = Singlejunction1.at(iSJ).at(0).back();
5921  HHparton q2 = Singlejunction1.at(iSJ).at(1).back();
5922  HHparton q3 = Singlejunction1.at(iSJ).at(2).back();
5923 
5924  HHparton q1fin = q1;
5925  HHparton q2fin = q2;
5926  HHparton q3fin = q3;
5927 
5928  FakeBaryonElements.add(q1fin); //add first particle in 1st leg in iSJ_st singlejunction
5929  FakeBaryonElements.add(q2fin); //add first particle in 2nd leg in iSJ_st singlejunction
5930  FakeBaryonElements.add(q3fin); //add first particle in 3rd leg in iSJ_st singlejunction
5931 
5932  // for the corrspondence with pdg particle id, sorting the these ids based on absolute value
5933  for(int iswap = 0; iswap < 3; iswap++){
5934  if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[1].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[1]) ; }
5935  if(abs(FakeBaryonElements[1].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[1], FakeBaryonElements[0]) ; }
5936  if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[0]) ; }
5937  }
5938 
5939  HHhadron store_id_hadron1;
5940  set_baryon_id(FakeBaryonElements, store_id_hadron1);
5941 
5942  int m_id = store_id_hadron1.id();
5943  if((q1.id() < 0 && m_id > 0) || (q1.id() > 0 && m_id < 0)){
5944  m_id *= -1;
5945  }
5946 
5947  HHparton fakeB;
5948  fakeB.id(m_id); fakeB.PY_stat(-11); fakeB.mass(3*xmq); fakeB.e(3*xmq);
5949  fakeB.px(0.); fakeB.py(0.); fakeB.pz(0.);
5950  if(q1.id() > 0){fakeB.PY_tag1(q1.col()); fakeB.PY_tag2(q2.col()); fakeB.PY_tag3(q3.col());}
5951  else{fakeB.PY_tag1(q1.acol()); fakeB.PY_tag2(q2.acol()); fakeB.PY_tag3(q3.acol());}
5952  Transitsinglejunction2.push_back(fakeB);
5953  Transitsinglejunction1.push_back(Transitsinglejunction2);
5954  Transitsinglejunction2.clear();
5955  } // so farfake mother is added to all single junction vectors{vectors of partons}, so we need to remember all execution number is incremented by one because of this fake baryons
5956 
5957  for(int iSJ = 0; iSJ < Singlejunction1.size(); iSJ++){
5958  vector<HHparton> Leg1 = Singlejunction1.at(iSJ).at(0);
5959  vector<HHparton> Leg2 = Singlejunction1.at(iSJ).at(1);
5960  vector<HHparton> Leg3 = Singlejunction1.at(iSJ).at(2);
5961 
5962  for(int ileg1 = 0; ileg1 < Leg1.size(); ileg1++ ){
5963  Leg1.at(ileg1).PY_par1(0); // setting the mother tag as zero, which indicates the first particle in the Transit
5964  Leg1.at(ileg1).PY_par2(0);
5965  Transitsinglejunction1.at(iSJ).push_back(Leg1.at(ileg1));
5966  }
5967  for(int ileg2 = 0; ileg2 < Leg2.size(); ileg2++ ){
5968  Leg2.at(ileg2).PY_par1(0); // setting the mother tag as zero, which indicates the first particle in the Transit
5969  Leg2.at(ileg2).PY_par2(0);
5970  Transitsinglejunction1.at(iSJ).push_back(Leg2.at(ileg2));
5971  }
5972  for(int ileg3 = 0; ileg3 < Leg3.size(); ileg3++ ){
5973  Leg3.at(ileg3).PY_par1(0); // setting the mother tag as zero, which indicates the first particle in the Transit
5974  Leg3.at(ileg3).PY_par2(0);
5975  Transitsinglejunction1.at(iSJ).push_back(Leg3.at(ileg3));
5976  }
5977  Transitsinglejunction1.at(iSJ).at(0).PY_dau1(1);//dau tag starting from 1 {after zero, which means fake mother baryon}
5978  Transitsinglejunction1.at(iSJ).at(0).PY_dau2(Leg1.size() + Leg2.size() + Leg3.size());//dau tag starting from 1 {after zero, which means fake mother baryon}
5979  }// At last, iSJ_st Singlejunction1 partons are moved to iSJ_st vector component in Transitsinglejunction1
5980 
5981  //dignostic measure{Transitsinglejunction1}
5982  /*std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 "<< endl;
5983  for(int icheck1 = 0; icheck1 < Transitsinglejunction1.size(); icheck1++ ){
5984  std::cout <<endl<<"SingleJunction : "<<icheck1<<endl;
5985  for(int i = 0; i < Transitsinglejunction1.at(icheck1).size(); i++){
5986  vector<HHparton> temp = Transitsinglejunction1.at(icheck1);
5987  std::cout << i <<" "<< temp.at(i).id() <<" "<< temp.at(i).PY_stat() <<" "<< temp.at(i).PY_par1() <<" "<< temp.at(i).PY_par2() <<" "
5988  << temp.at(i).PY_dau1() <<" "<< temp.at(i).PY_dau2() << " ( "<< temp.at(i).col()<< " , " << temp.at(i).acol() << " ) " <<endl;
5989  }
5990  }*/
5991 
5992  //dignostic measure{Dijunction1}
5993  /*std::cout <<endl;
5994  std::cout <<" List of Tempsorting for Dijunction"<<endl;
5995  for(int icheck1 = 0; icheck1 < Tempsorting1.size(); icheck1++){
5996  std::cout <<" Sorted Leg : "<<icheck1<<endl;
5997  for(int icheck2 = 0 ; icheck2 < Tempsorting1.at(icheck1).size(); icheck2++){
5998  std::cout <<" ( "<<Tempsorting1.at(icheck1).at(icheck2).col()<<" , "<<Tempsorting1.at(icheck1).at(icheck2).acol()<< " ) ";
5999  }
6000  std::cout <<endl;
6001  }*/
6002 
6003  //So far, M,D tags for each junction and dijunction structure are designated. and EP_conservation checking will be done through Transitdijunction1 and Transitsinglejunction1 vectors
6004  for(int itd1 = 0; itd1 < Transitdijunction1.size(); itd1++){
6005  /*JSINFO << "This is dijunction " << itd1+1 << " before:";
6006  for(int i = 0; i < Transitdijunction1.at(itd1).size(); i++){
6007  vector<HHparton> temp = Transitdijunction1.at(itd1);
6008  std::cout << i <<" "<< temp.at(i).id() <<" "<< temp.at(i).PY_stat() <<" "<< temp.at(i).PY_par1() <<" "<< temp.at(i).PY_par2() <<" "
6009  << temp.at(i).PY_dau1() <<" "<< temp.at(i).PY_dau2() << " ( "<< temp.at(i).col()<< " , " << temp.at(i).acol() << " ) "
6010  << " ( "<< temp.at(i).e()<< " , " << temp.at(i).px()<< " , " << temp.at(i).py()<< " , " << temp.at(i).pz() << " ) "
6011  << " ( "<< temp.at(i).t()<< " , " << temp.at(i).x()<< " , " << temp.at(i).y()<< " , " << temp.at(i).z() << " ) " << std::endl;
6012  }*/
6013  bool EP_conserved = false;
6014  while(!EP_conserved){
6015  EP_conserved = true;
6016  for(int i=0; i<Transitdijunction1.at(itd1).size(); ++i){
6017  if(Transitdijunction1[itd1][i].PY_stat() >= 0 && std::abs(Transitdijunction1[itd1][i].id()) < 1000){
6018  continue;
6019  }
6020  FourVector P_new(0.,0.,0.,0.);
6021  FourVector pos_new(0.,0.,0.,0.);
6022  int jmax = (Transitdijunction1[itd1][i].PY_dau2() > Transitdijunction1[itd1][i].PY_dau1()) ? Transitdijunction1[itd1][i].PY_dau2() : Transitdijunction1[itd1][i].PY_dau1();
6023  //JSINFO << "jmax = " << jmax;
6024  for(int j=Transitdijunction1[itd1][i].PY_dau1(); j<jmax+1; ++j){
6025  double n = double(j-Transitdijunction1[itd1][i].PY_dau1())+1.;
6026  //JSINFO << "n = " << n;
6027  //JSINFO << "transdijunct.x_t = "<<Transitdijunction1[itd1][j].x_t();
6028  //JSINFO << pos_new.t()+(Transitdijunction1[itd1][j].x_t()-pos_new.t())/n;
6029  P_new.Set(
6030  P_new.x()+Transitdijunction1[itd1][j].px(),
6031  P_new.y()+Transitdijunction1[itd1][j].py(),
6032  P_new.z()+Transitdijunction1[itd1][j].pz(),
6033  P_new.t()+Transitdijunction1[itd1][j].e());
6034  pos_new.Set(
6035  pos_new.x()+(Transitdijunction1[itd1][j].x()-pos_new.x())/n,
6036  pos_new.y()+(Transitdijunction1[itd1][j].y()-pos_new.y())/n,
6037  pos_new.z()+(Transitdijunction1[itd1][j].z()-pos_new.z())/n,
6038  pos_new.t()+(Transitdijunction1[itd1][j].x_t()-pos_new.t())/n);
6039  }
6040  //JSINFO << "p = (" << P_new.t() << ", " << P_new.y() << ", " << P_new.y() << ", " << P_new.z() << ")";
6041  //JSINFO << "x = (" << pos_new.t() << ", " << pos_new.y() << ", " << pos_new.y() << ", " << pos_new.z() << ")";
6042  if((dif2(P_new,Transitdijunction1[itd1][i].P())+(P_new.t()-Transitdijunction1[itd1][i].e())*(P_new.t()-Transitdijunction1[itd1][i].e()) > 0.00000001/*0.0001^2*/) ||
6043  (dif2(pos_new,Transitdijunction1[itd1][i].pos())+(pos_new.t()-Transitdijunction1[itd1][i].x_t())*(pos_new.t()-Transitdijunction1[itd1][i].x_t()) > 0.00000001)){
6044  Transitdijunction1[itd1][i].P(P_new);
6045  Transitdijunction1[itd1][i].pos(pos_new);
6046  Transitdijunction1[itd1][i].mass(
6047  Transitdijunction1[itd1][i].e()*Transitdijunction1[itd1][i].e()
6048  - Transitdijunction1[itd1][i].px()*Transitdijunction1[itd1][i].px()
6049  - Transitdijunction1[itd1][i].py()*Transitdijunction1[itd1][i].py()
6050  - Transitdijunction1[itd1][i].pz()*Transitdijunction1[itd1][i].pz());
6051  Transitdijunction1[itd1][i].mass( (Transitdijunction1[itd1][i].mass() >= 0.) ? sqrt(Transitdijunction1[itd1][i].mass()) : -sqrt(-Transitdijunction1[itd1][i].mass()) ); //don't need mass >0 for reco now
6052  EP_conserved = false;
6053  }
6054  }
6055  }
6056  for(int i=0; i<Transitdijunction1.at(itd1).size(); ++i){
6057  if((Transitdijunction1[itd1][i].PY_stat() == -21)){// && (Transitdijunction1[itd1][i].PY_dau2() > Transitdijunction1[itd1][i].PY_dau1())){
6058  Transitdijunction1[itd1][i].px(Transitdijunction1[itd1][i].px()/2.);
6059  Transitdijunction1[itd1][i].py(Transitdijunction1[itd1][i].py()/2.);
6060  Transitdijunction1[itd1][i].pz(Transitdijunction1[itd1][i].pz()/2.);
6061  Transitdijunction1[itd1][i].e( Transitdijunction1[itd1][i].e() /2.);
6062  Transitdijunction1[itd1][i].mass(Transitdijunction1[itd1][i].mass()/2.);
6063  }
6064  }
6065 
6066  /*JSINFO << "This is dijunction " << itd1+1 << " after:";
6067  for(int i = 0; i < Transitdijunction1.at(itd1).size(); i++){
6068  vector<HHparton> temp = Transitdijunction1.at(itd1);
6069  std::cout << i <<" "<< temp.at(i).id() <<" "<< temp.at(i).PY_stat() <<" "<< temp.at(i).PY_par1() <<" "<< temp.at(i).PY_par2() <<" "
6070  << temp.at(i).PY_dau1() <<" "<< temp.at(i).PY_dau2() << " ( "<< temp.at(i).col()<< " , " << temp.at(i).acol() << " ) "
6071  << " ( "<< temp.at(i).e()<< " , " << temp.at(i).px()<< " , " << temp.at(i).py()<< " , " << temp.at(i).pz() << " ) "
6072  << " ( "<< temp.at(i).t()<< " , " << temp.at(i).x()<< " , " << temp.at(i).y()<< " , " << temp.at(i).z() << " ) " << std::endl;
6073  }*/
6074  }
6075 
6076  //for transitsinglejunction1
6077  for(int its1 = 0; its1 < Transitsinglejunction1.size(); its1++){
6078  bool EP_conserved = false;
6079  while(!EP_conserved){
6080  EP_conserved = true;
6081  for(int i=0; i<Transitsinglejunction1.at(its1).size(); ++i){
6082  if(Transitsinglejunction1[its1][i].PY_stat() >= 0 && std::abs(Transitsinglejunction1[its1][i].id()) < 1000){continue;}
6083  FourVector P_new(0.,0.,0.,0.); FourVector pos_new(0.,0.,0.,0.);
6084  int jmax = (Transitsinglejunction1[its1][i].PY_dau2() > Transitsinglejunction1[its1][i].PY_dau1()) ? Transitsinglejunction1[its1][i].PY_dau2() : Transitsinglejunction1[its1][i].PY_dau1();
6085  for(int j=Transitsinglejunction1[its1][i].PY_dau1(); j<jmax+1; ++j){
6086  double n = double(j-Transitsinglejunction1[its1][i].PY_dau1())+1.;
6087  P_new.Set(P_new.x()+Transitsinglejunction1[its1][j].px(),P_new.y()+Transitsinglejunction1[its1][j].py(),P_new.z()+Transitsinglejunction1[its1][j].pz(),P_new.t()+Transitsinglejunction1[its1][j].e());
6088  pos_new.Set(pos_new.x()+(Transitsinglejunction1[its1][j].x()-pos_new.x())/n,pos_new.y()+(Transitsinglejunction1[its1][j].y()-pos_new.y())/n,pos_new.z()+(Transitsinglejunction1[its1][j].z()-pos_new.z())/n,pos_new.t()+(Transitsinglejunction1[its1][j].x_t()-pos_new.t())/n);
6089  }
6090  if((dif2(P_new,Transitsinglejunction1[its1][i].P())+(P_new.t()-Transitsinglejunction1[its1][i].e())*(P_new.t()-Transitsinglejunction1[its1][i].e()) > 0.00000001/*0.0001^2*/) ||
6091  (dif2(pos_new,Transitsinglejunction1[its1][i].pos())+(pos_new.t()-Transitsinglejunction1[its1][i].x_t())*(pos_new.t()-Transitsinglejunction1[its1][i].x_t()) > 0.00000001)){
6092  Transitsinglejunction1[its1][i].P(P_new); Transitsinglejunction1[its1][i].pos(pos_new);
6093  Transitsinglejunction1[its1][i].mass( Transitsinglejunction1[its1][i].e()*Transitsinglejunction1[its1][i].e()
6094  - Transitsinglejunction1[its1][i].px()*Transitsinglejunction1[its1][i].px() - Transitsinglejunction1[its1][i].py()*Transitsinglejunction1[its1][i].py() - Transitsinglejunction1[its1][i].pz()*Transitsinglejunction1[its1][i].pz() );
6095  Transitsinglejunction1[its1][i].mass( (Transitsinglejunction1[its1][i].mass() >= 0.) ? sqrt(Transitsinglejunction1[its1][i].mass()) : -sqrt(-Transitsinglejunction1[its1][i].mass()) ); //don't need mass >0 for reco now
6096  EP_conserved = false;
6097  }
6098  }
6099  }
6100  for(int i=0; i<Transitsinglejunction1.at(its1).size(); ++i){
6101  if((Transitsinglejunction1[its1][i].PY_stat() == -21)){// && (Transitsinglejunction1[its1][i].PY_dau2() > Transitsinglejunction1[its1][i].PY_dau1())){
6102  Transitsinglejunction1[its1][i].px(Transitsinglejunction1[its1][i].px()/2.);
6103  Transitsinglejunction1[its1][i].py(Transitsinglejunction1[its1][i].py()/2.);
6104  Transitsinglejunction1[its1][i].pz(Transitsinglejunction1[its1][i].pz()/2.);
6105  Transitsinglejunction1[its1][i].e( Transitsinglejunction1[its1][i].e() /2.);
6106  Transitsinglejunction1[its1][i].mass(Transitsinglejunction1[its1][i].mass()/2.);
6107  }
6108  }
6109  }
6110 
6111  // make sure that there is enough energy in the system, such that the dijunctions can be hadronized
6112  // this is a rare case
6113  for(int itagdij1 = 0; itagdij1 < Transitdijunction1.size(); itagdij1++ ){
6114  double baryon_mass_scaling = 1.25;
6115  double mass_baryons = Transitdijunction1.at(itagdij1).at(0).mass() + Transitdijunction1.at(itagdij1).at(1).mass();
6116  double m1 = pythia.particleData.m0(std::abs(Transitdijunction1.at(itagdij1).at(0).id()));
6117  double m2 = pythia.particleData.m0(std::abs(Transitdijunction1.at(itagdij1).at(1).id()));
6118  if(mass_baryons < baryon_mass_scaling*(m1+m2)){
6119  //find fake gluon
6120  double new_gluon_mass = 2.*xmq;
6121  for(int itagdij2 = 0; itagdij2 < Transitdijunction1.at(itagdij1).size(); itagdij2++){
6122  HHparton p = Transitdijunction1.at(itagdij1).at(itagdij2);
6123  if(p.id() == 21){
6124  new_gluon_mass = p.mass()+baryon_mass_scaling*(m1+m2)-mass_baryons;
6125  p.mass(new_gluon_mass);
6126  double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6127  p.e(energy_new);
6128  Transitdijunction1.at(itagdij1).at(itagdij2).mass(p.mass());
6129  Transitdijunction1.at(itagdij1).at(itagdij2).e(p.e());
6130  }
6131  }
6132  //find fake (anti-)quarks
6133  for(int itagdij2 = 0; itagdij2 < Transitdijunction1.at(itagdij1).size(); itagdij2++){
6134  HHparton p = Transitdijunction1.at(itagdij1).at(itagdij2);
6135  if(p.PY_stat() == -21 && std::abs(p.id()) < 6){
6136  p.mass(new_gluon_mass/2.);
6137  double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6138  p.e(energy_new);
6139  }
6140  if(p.PY_stat() == -11 && std::abs(p.id()) > 1000){
6141  p.mass(p.mass()+(baryon_mass_scaling*(m1+m2)-mass_baryons)/2.);
6142  double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6143  p.e(energy_new);
6144  }
6145  }
6146  }
6147  }
6148 
6149  for(int itagdij1 = 0; itagdij1 < Transitdijunction1.size(); itagdij1++ ){
6150  for(int itagdij2 = 0; itagdij2 < Transitdijunction1.at(itagdij1).size(); itagdij2++){
6151  WaitingLineforPY.push_back(Transitdijunction1.at(itagdij1).at(itagdij2));
6152  }
6153  }
6154 
6155  //dignostic measure{Transitdijunction1}
6156  /*int icheck2 = 0;
6157  std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 "<< endl;
6158  for(int icheck1 = 0; icheck1 < Transitdijunction1.size(); icheck1++ ){
6159  for(int i = 0; i < Transitdijunction1.at(icheck1).size(); i++){
6160  vector<HHparton> temp = Transitdijunction1.at(icheck1);
6161  std::cout << icheck2 <<" "<< temp.at(i).id() <<" "<< temp.at(i).PY_stat() <<" "<< temp.at(i).PY_par1() <<" "<< temp.at(i).PY_par2() <<" "
6162  << temp.at(i).PY_dau1() <<" "<< temp.at(i).PY_dau2() << " ( "<< temp.at(i).col()<< " , " << temp.at(i).acol() << " ) " <<endl;
6163  icheck2++;
6164  }
6165  }*/
6166 
6167  // make sure that there is enough energy in the system, such that the junctions can be hadronized
6168  // this is a rare case
6169  for(int itagsj1 = 0; itagsj1 < Transitsinglejunction1.size(); itagsj1++ ){
6170  double baryon_mass_scaling = 1.15;
6171  double mass_baryon = Transitsinglejunction1.at(itagsj1).at(0).mass();
6172  double m1 = pythia.particleData.m0(std::abs(Transitsinglejunction1.at(itagsj1).at(0).id()));
6173 
6174  if(mass_baryon < baryon_mass_scaling*m1){
6175  double baryon_mass_correction = baryon_mass_scaling*m1-mass_baryon;
6176  for(int itagsj2 = 0; itagsj2 < Transitsinglejunction1.at(itagsj1).size(); itagsj2++){
6177  if(std::abs(Transitsinglejunction1.at(itagsj1).at(itagsj2).id()) < 6){
6178  HHparton p = Transitsinglejunction1.at(itagsj1).at(itagsj2);
6179  p.mass(p.mass()+baryon_mass_correction/3.);
6180  double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6181  p.e(energy_new);
6182  Transitsinglejunction1.at(itagsj1).at(itagsj2).mass(p.mass());
6183  Transitsinglejunction1.at(itagsj1).at(itagsj2).e(p.e());
6184  }
6185  }
6186 
6187  HHparton p = Transitsinglejunction1.at(itagsj1).at(0);
6188  p.mass(baryon_mass_scaling*m1);
6189  double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6190  p.e(energy_new);
6191  Transitsinglejunction1.at(itagsj1).at(0).mass(p.mass());
6192  Transitsinglejunction1.at(itagsj1).at(0).e(p.e());
6193  }
6194  }
6195 
6196 
6197  for(int itagsj1 = 0; itagsj1 < Transitsinglejunction1.size(); itagsj1++ ){
6198  for(int itagsj2 = 0; itagsj2 < Transitsinglejunction1.at(itagsj1).size(); itagsj2++){
6199  WaitingLineforPY.push_back(Transitsinglejunction1.at(itagsj1).at(itagsj2));
6200  }
6201  }
6202 
6203  /*for(int i=0; i<WaitingLineforPY.size(); i++) {
6204  std::cout << WaitingLineforPY[i].id() << "," << WaitingLineforPY[i].col() << "," << WaitingLineforPY[i].acol() << "," << WaitingLineforPY[i].PY_par1() << "," << WaitingLineforPY[i].PY_par2() << std::endl;
6205  }*/
6206 
6207  for(int ifins = 0; ifins < finalstring.size(); ifins++){
6208  WaitingLineforPY.push_back(finalstring.at(ifins));
6209  }
6210 
6211  /*std::cout <<endl<<" Let's check final entry before PY!!"<<endl;
6212  std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 >> (col, acol) >> x_t"<< endl;
6213  for(int fincheck = 0; fincheck < WaitingLineforPY.size(); fincheck++){
6214  vector<HHparton> temp = WaitingLineforPY;
6215  std::cout << fincheck <<" "<< temp.at(fincheck).id() <<" "<< temp.at(fincheck).PY_stat() <<" "<< temp.at(fincheck).PY_par1() <<" "<< temp.at(fincheck).PY_par2() <<" "
6216  << temp.at(fincheck).PY_dau1() <<" "<< temp.at(fincheck).PY_dau2() << " ( "<< temp.at(fincheck).col()<< " , " << temp.at(fincheck).acol() << " ) " << temp.at(fincheck).x_t()<<endl;
6217  }*/
6218 
6219  for(int ifin = 0; ifin < WaitingLineforPY.size(); ifin++){
6220  SP_prepremn.add(WaitingLineforPY[ifin]);
6221  }
6222 
6223  Tempjunctions.clear(); // clear these informations for next running
6224  JuncStructure.clear();
6225  realjuncindice.clear();
6226  IMStructure1.clear();
6227  Dijunction1.clear();
6228  DijunctionInfo1.clear();
6229  Recombearly1.clear();
6230  Tailoredstring1.clear();
6231  finalstring.clear();
6232  Transitdijunction1.clear();
6233  Transitsinglejunction1.clear();
6234  WaitingLineforPY.clear();
6235  Tempsorting1.clear();
6236 }
6237 
6238 //function to hand partons/strings and hadron resonances (and various other color neutral and colored objects) to Pythia8
6240 
6241  Event& event = pythia.event;
6242 
6243  //should have been checked before call, but if there are no partons/hadrons to deal with, just exit without invoking pythia
6244  if(HH_pyremn.num() + HH_hadrons.num() == 0){return true;}
6245 
6246  //first things first, need to reindex py_remn; just need to increment ALL by one
6247  //also restoring original id for color octet particles (or other 'odd' colored particles)
6248  for(int i=0; i<HH_pyremn.num(); ++i){
6249  HH_pyremn[i].PY_par1(HH_pyremn[i].PY_par1()+1); HH_pyremn[i].PY_par2(HH_pyremn[i].PY_par2()+1);
6250  HH_pyremn[i].PY_dau1(HH_pyremn[i].PY_dau1()+1); HH_pyremn[i].PY_dau2(HH_pyremn[i].PY_dau2()+1);
6251  if(HH_pyremn[i].PY_origid() != 0) {HH_pyremn[i].id( HH_pyremn[i].PY_origid());}
6252  }
6253 
6254  bool need_hadronization = true; bool success = true;
6255  int attempt = 0;
6256  while(need_hadronization){
6257  //incrementing attempt number
6258  ++attempt;
6259 
6260  //resetting PYTHIA event record, so that this event can be filled
6261  event.reset();
6262  HH_pythia_hadrons.clear();
6263 
6264  //number of partons/hadrons/particles handed to pythia
6265  int size_input = 0;
6266 
6267  //keeping track of partons from py_remn and hadrons into the event
6268  std::vector<int> eve_to_had; eve_to_had.push_back(0);
6269 
6270  //filling PYTHIA event record with the partons from this event
6271  int dijuncflag = 0;
6272  bool case1 = true;
6273  bool case2 = true;
6274  bool case3 = true;
6275  bool case4 = true;
6276  bool case5 = true;
6277  bool case6 = true;
6278  for(int i=0; i<HH_pyremn.num(); ++i){
6279  // code part to hadronize junctions and dijunctions separately
6280  // if fake pythia baryon (=junction or anti-junction) increment by one
6281  if(abs(HH_pyremn[i].id()) > 1112 && HH_pyremn[i].PY_tag1() !=0 && HH_pyremn[i].PY_tag2() !=0 && HH_pyremn[i].PY_tag3() !=0) {
6282  dijuncflag++;
6283  }
6284  // this first part is for the hadronization of junctions/anti-junctions
6285  if((dijuncflag == 1 && abs(HH_pyremn[i].id())<100 && HH_pyremn[i].PY_par1() == 0 && HH_pyremn[i].PY_par2() == 0)
6286  || (dijuncflag == 2 && abs(HH_pyremn[i-1].id()) < 100)) {
6287  size_input = event.size()-1;
6288  //event.listJunctions();
6289  //event.list();
6290  case1 &= pythia.next();
6291  //event.list();
6292  set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case1,false,false);
6293  event.reset();
6294  eve_to_had.clear();
6295  if(dijuncflag == 1){dijuncflag=0;}
6296  if(dijuncflag == 2){dijuncflag=1;}
6297  }
6298  // if we are past two junctions, check if they are back-to-back;
6299  if(dijuncflag == 2) {
6300  if(abs(HH_pyremn[i-1].id())>1112){dijuncflag=3;} // if yes, increment to 3; we are now inside a dijunction
6301  else{dijuncflag = 1;} // no dijunction, must be a single one, step back to counter 1
6302  }
6303  // code red: we only reach this if we have reached the end of a dijunction; it's either another fake baryon or something without mother or daughter tags
6304  // this second part is for the hadronization of di-junctions
6305  if(dijuncflag == 4 || (HH_pyremn[i].PY_par1() == 0 && HH_pyremn[i].PY_par2() == 0 && HH_pyremn[i].PY_dau1() == 0 && HH_pyremn[i].PY_dau2() == 0 && dijuncflag == 3)) {
6306  // hadronize event here (which is only one dijunction); need to copy all the code that calls pythia AND refers to event.xxx up here
6307  size_input = event.size()-1;
6308  //event.listJunctions();
6309  //event.list();
6310  case2 &= pythia.next();
6311  //event.list();
6312  set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case2,false,false);
6313  event.reset();
6314  eve_to_had.clear();
6315  if(dijuncflag == 4){dijuncflag=1;}else{dijuncflag=0;}
6316  }
6317 
6318  //append( id, status, mother1, mother2, daughter1, daughter2, col, acol, px, py, pz, e, m)
6319  event.append(HH_pyremn[i].id(),HH_pyremn[i].PY_stat(),HH_pyremn[i].PY_par1(),HH_pyremn[i].PY_par2(),HH_pyremn[i].PY_dau1(),HH_pyremn[i].PY_dau2(),
6320  HH_pyremn[i].col(),HH_pyremn[i].acol(),HH_pyremn[i].px(),HH_pyremn[i].py(),HH_pyremn[i].pz(),HH_pyremn[i].e(),HH_pyremn[i].mass());
6321  //JSINFO << HH_pyremn[i].id()<<","<<HH_pyremn[i].PY_stat()<<","<<HH_pyremn[i].PY_par1()<<","<<HH_pyremn[i].PY_par2()<<","<<HH_pyremn[i].PY_dau1()<<","<<HH_pyremn[i].PY_dau2()<<","<<
6322  // HH_pyremn[i].col()<<","<<HH_pyremn[i].acol()<<","<<HH_pyremn[i].px()<<","<<HH_pyremn[i].py()<<","<<HH_pyremn[i].pz()<<","<<HH_pyremn[i].e()<<","<<HH_pyremn[i].mass();
6323  event[event.size()-1].vProd(HH_pyremn[i].x(), HH_pyremn[i].y(), HH_pyremn[i].z(), HH_pyremn[i].x_t());
6324  //for junction mother, adding junction to list manually for color tracing appendJunction(int kind, int col0, int col1, int col2);
6325  if(std::abs(event[event.size()-1].id()) > 1112){
6326  event.appendJunction(((event[event.size()-1].id()>0) ? 1 : 2), HH_pyremn[i].PY_tag1(), HH_pyremn[i].PY_tag2(), HH_pyremn[i].PY_tag3());
6327  }
6328  eve_to_had.push_back(-i-1);
6329  }
6330 
6331  size_input = event.size()-1;
6332  //make PYTHIA hadronize this event, if it fails then retry N=10 times... (PYTHIA can and will rarely fail, without concern)
6333  //if this fails more than 10 times, we may retry this event starting back before recombination (some number of times)
6334  //event.listJunctions();
6335  //event.list();
6336  case3 &= pythia.next();
6337  //event.list();
6338  set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case3,false,false);
6339  event.reset();
6340  eve_to_had.clear();
6341 
6342  //if we want to decay particles in pythia we have to do it separately for hadrons from recombination, otherwise the
6343  //information about the origin is lost
6344  //adding in hadrons/leptons/other colorless particles too...
6345  if(reco_hadrons_pythia){
6346  //reco hadrons
6347  for(int i=0; i<HH_hadrons.num(); ++i){
6348  if(HH_hadrons[i].is_final() && HH_hadrons[i].is_recohad() && HH_hadrons[i].is_shsh()){
6349  //to make sure mass is set appropriately
6350  double massnow = HH_hadrons[i].e()*HH_hadrons[i].e() -
6351  (HH_hadrons[i].px()*HH_hadrons[i].px() + HH_hadrons[i].py()*HH_hadrons[i].py() + HH_hadrons[i].pz()*HH_hadrons[i].pz());
6352  massnow = (massnow >= 0.) ? sqrt(massnow) : -sqrt(-massnow);
6353  event.append(HH_hadrons[i].id(),81,0,0,HH_hadrons[i].px(),HH_hadrons[i].py(),HH_hadrons[i].pz(),HH_hadrons[i].e(),massnow);
6354  event[event.size()-1].vProd(HH_hadrons[i].x(), HH_hadrons[i].y(), HH_hadrons[i].z(), HH_hadrons[i].x_t());
6355  eve_to_had.push_back(i+1);
6356  }
6357  }
6358  case4 &= pythia.next();
6359  set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case4,true,true);
6360  event.reset();
6361  eve_to_had.clear();
6362 
6363  for(int i=0; i<HH_hadrons.num(); ++i){
6364  if(HH_hadrons[i].is_final() && HH_hadrons[i].is_recohad() && HH_hadrons[i].is_shth()){
6365  //to make sure mass is set appropriately
6366  double massnow = HH_hadrons[i].e()*HH_hadrons[i].e() -
6367  (HH_hadrons[i].px()*HH_hadrons[i].px() + HH_hadrons[i].py()*HH_hadrons[i].py() + HH_hadrons[i].pz()*HH_hadrons[i].pz());
6368  massnow = (massnow >= 0.) ? sqrt(massnow) : -sqrt(-massnow);
6369  event.append(HH_hadrons[i].id(),81,0,0,HH_hadrons[i].px(),HH_hadrons[i].py(),HH_hadrons[i].pz(),HH_hadrons[i].e(),massnow);
6370  event[event.size()-1].vProd(HH_hadrons[i].x(), HH_hadrons[i].y(), HH_hadrons[i].z(), HH_hadrons[i].x_t());
6371  eve_to_had.push_back(i+1);
6372  }
6373  }
6374  case5 &= pythia.next();
6375  set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case5,true,false);
6376  event.reset();
6377  eve_to_had.clear();
6378 
6379  for(int i=0; i<HH_hadrons.num(); ++i){
6380  if(HH_hadrons[i].is_final() && !HH_hadrons[i].is_recohad()){
6381  //to make sure mass is set appropriately
6382  double massnow = HH_hadrons[i].e()*HH_hadrons[i].e() -
6383  (HH_hadrons[i].px()*HH_hadrons[i].px() + HH_hadrons[i].py()*HH_hadrons[i].py() + HH_hadrons[i].pz()*HH_hadrons[i].pz());
6384  massnow = (massnow >= 0.) ? sqrt(massnow) : -sqrt(-massnow);
6385  event.append(HH_hadrons[i].id(),81,0,0,HH_hadrons[i].px(),HH_hadrons[i].py(),HH_hadrons[i].pz(),HH_hadrons[i].e(),massnow);
6386  event[event.size()-1].vProd(HH_hadrons[i].x(), HH_hadrons[i].y(), HH_hadrons[i].z(), HH_hadrons[i].x_t());
6387  eve_to_had.push_back(i+1);
6388  }
6389  }
6390  case6 &= pythia.next();
6391  set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case6,false,false);
6392  event.reset();
6393  eve_to_had.clear();
6394  }
6395 
6396  if(!case1 || !case2 || !case3 || !case4 || !case5 || !case6){
6397  if(attempt > 4){need_hadronization = false; success = false; break;}
6398  continue;
6399  }
6400  //this event has been successfully hadronized (hopefully), put all final state particles into HH_pythia_hadrons; set is_final=true for these
6401  //this is done in set_spacetime_for_pythia_hadrons() and in DoHadronization all these Hadrons are written to HH_hadrons
6402  need_hadronization = false;
6403  }
6404  return success;
6405 }
6406 
6407 void HybridHadronization::set_spacetime_for_pythia_hadrons(Pythia8::Event &event, int &size_input, std::vector<int> &eve_to_had, int pythia_attempt, bool find_positions, bool is_recohadron, bool recohadron_shsh) {
6408  // directly return if hadronization in pythia failed, such that nothing is added to HH_pythia_hadrons
6409  if(!find_positions) {
6410  return;
6411  }
6412 
6413  vector<HHhadron> final_hadrons_from_pythia; // hadrons with preliminary set positions (average positions along string segment)
6414 
6415  vector<int> Case1_hadron_idx; // index of the hadron from case 1 below
6416  vector<int> Case1_parton1_idx; // index of the parton1 from case 1 below
6417  vector<int> Case1_parton2_idx; // index of the parton2 from case 1 below
6418 
6419  vector<int> Case2_hadron_idx; // index of the hadron from case 2 below
6420  vector<int> Case2_parton1_idx; // index of the parton1 from case 2 below
6421  vector<int> Case2_parton2_idx; // index of the parton2 from case 2 below
6422  vector<int> Case2_parton3_idx; // index of the parton3 from case 2 below
6423  vector<double> Case2_junction_center; // store the center position of the junction in element 0=t,1=x,2=y,3=z
6424  // this works only for the current implementation, where the junctions are handed over to pythia one after the other
6425 
6426 
6427  vector<int> Case3_hadron_idx; // index of the hadron from case 3 below
6428  vector<int> Case3_parton1_idx; // index of the parton1 from case 3 below
6429  vector<int> Case3_parton2_idx; // index of the parton2 from case 3 below
6430  vector<double> Case3_partons_center; // store the center position of the partons
6431 
6432  bool compute_more_precise_positions = true;
6433  bool warn_could_not_find_positions = false;
6434 
6435  for(int hadron_idx = 1; hadron_idx < event.size(); hadron_idx++) {
6436  if(event[hadron_idx].isFinal()) { //take only final hadrons from pythia
6437  //convert pythia hadron to HHhadron
6438  HHhadron hadron_out; //a number of other tags need to be set from the parent (either hadron or string)
6439  hadron_out.is_final(true);
6440  hadron_out.id(event[hadron_idx].id());
6441  hadron_out.mass(event[hadron_idx].m());
6442  hadron_out.px(event[hadron_idx].px());
6443  hadron_out.py(event[hadron_idx].py());
6444  hadron_out.pz(event[hadron_idx].pz());
6445  hadron_out.e(event[hadron_idx].e());
6446 
6447  //since using inbuilt pythia mother/daughter functions will segfault 'occasionally', going to code it in by hand.
6448  //this could probably be done more efficiently, but it's good enough for now...
6449  std::vector<int> mothers;
6450  //using a stack system to fill mothers
6451  std::vector<int> stack;
6452  //filling stack with initial mothers
6453  if((event[hadron_idx].mother1() < event[hadron_idx].mother2()) && (event[hadron_idx].mother1() > 0)
6454  && (std::abs(event[hadron_idx].status()) >= 81) && (std::abs(event[hadron_idx].status()) <= 86)){
6455  for(int hadron_parent = event[hadron_idx].mother1(); hadron_parent <= event[hadron_idx].mother2(); ++hadron_parent) {
6456  stack.push_back(hadron_parent);
6457  }
6458  }else if((event[hadron_idx].mother2() > 0) && (event[hadron_idx].mother1() != event[hadron_idx].mother2())) {
6459  stack.push_back(event[hadron_idx].mother1());
6460  stack.push_back(event[hadron_idx].mother2());
6461  }else if(event[hadron_idx].mother1() > 0) {
6462  stack.push_back(event[hadron_idx].mother1());
6463  }else{mothers.push_back(hadron_idx);} //setting it as its own mother if there are no mothers (pythia didn't decay a directly input hadron...)
6464 
6465  //filling the stack with any valid mothers of the 'current' stack element
6466  //then we check the 'current' stack element to see if it's a valid mother (0<element<=n_input), if so, we write it to mothers
6467  while(stack.size() > 0){
6468  int current = stack.back();
6469  stack.pop_back();
6470  if((event[current].mother1() < event[current].mother2()) && (event[current].mother1() > 0) &&
6471  (std::abs(event[current].status()) >= 81) && (std::abs(event[current].status()) <= 86)) {
6472  for(int hadron_parent = event[current].mother1(); hadron_parent <= event[current].mother2(); ++hadron_parent) {
6473  stack.push_back(hadron_parent);
6474  }
6475  }else if((event[current].mother2() > 0) && (event[current].mother1() != event[current].mother2())) {
6476  stack.push_back(event[current].mother1());
6477  stack.push_back(event[current].mother2());
6478  }else if(event[current].mother1() > 0) {
6479  stack.push_back(event[current].mother1());
6480  }
6481  if((current > 0) && (current <= size_input)) {mothers.push_back(current);}
6482  }
6483 
6484  //just in case...
6485  if(mothers.size() == 0) {mothers.push_back(hadron_idx);}
6486 
6487  //sorting and removing duplicate entries
6488  std::sort(mothers.begin(), mothers.end());
6489  mothers.erase(std::unique(mothers.begin(), mothers.end()), mothers.end());
6490 
6491  //first, using mothers to determine if this hadron was formed via recombination, or by string fragmentation
6492  if(mothers[0] <= HH_pyremn.num()){
6493  hadron_out.is_strhad(true);
6494  }else{
6495  hadron_out.is_recohad(true);
6496  }
6497 
6498  //lastly, using mothers (except fake) in original input to determine if this is a shower-shower or shower-thermal hadron
6499  bool is_therm(false);
6500  for(int hadron_parent = 0; hadron_parent < mothers.size(); ++hadron_parent) {
6501  if(mothers[hadron_parent] <= HH_pyremn.num()) {
6502  if(HH_pyremn[mothers[hadron_parent]-1].orig() != -1) {
6503  hadron_out.add_par(mothers[hadron_parent]-1);
6504  if(HH_pyremn[mothers[hadron_parent]-1].is_thermal()) {is_therm = true;}
6505  }
6506  }else if(mothers[hadron_parent] < size_input){ //shouldn't actually need to check, but doing so just in case.
6507  hadron_out.parh(eve_to_had[mothers[hadron_parent]]-1);
6508  if(HH_hadrons[hadron_out.parh()].is_shth()) {is_therm = true;}
6509  }
6510  }
6511  if(is_therm) {
6512  hadron_out.is_shth(true);
6513  }else{
6514  hadron_out.is_shsh(true);
6515  }
6516 
6517  if(is_recohadron && recohadron_shsh){
6518  hadron_out.is_recohad(true);
6519  hadron_out.is_shsh(true);
6520  hadron_out.is_shth(false);
6521  } else if(is_recohadron && !recohadron_shsh){
6522  hadron_out.is_recohad(true);
6523  hadron_out.is_shsh(false);
6524  hadron_out.is_shth(true);
6525  }
6526 
6527  int hadron_col = event[hadron_idx].col();
6528  int hadron_acol = event[hadron_idx].acol();
6529  bool info_found = false; bool col_known = false; bool acol_known = false;
6530 
6531  //3 main cases: col!=acol, col==acol!=0, col==acol==0
6532  if(hadron_col != hadron_acol) { //col!=acol -> this hadron should trace back to a single gluon; find it and grab its spacetime info
6533  for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6534  if(((HH_pyremn[irem].col() == hadron_col) && (HH_pyremn[irem].acol() == hadron_acol))
6535  || ((HH_pyremn[irem].col() == hadron_acol) && (HH_pyremn[irem].acol() == hadron_col))) {//alter for glu loops
6536  if(HH_pyremn[irem].PY_stat()<=0) {continue;}
6537  hadron_out.x(HH_pyremn[irem].x());
6538  hadron_out.y(HH_pyremn[irem].y());
6539  hadron_out.z(HH_pyremn[irem].z());
6540  hadron_out.x_t(HH_pyremn[irem].x_t());
6541  info_found = true;
6542  }
6543  }
6544  if(!info_found) {
6545  //this is bad; could either be a hadron from *multiple* segments, or still from a single gluon under color reconnections - OR BOTH!
6546  //this is a first-order handling to find all the intermediate partons using the input partons -
6547  //it really should be done using pythia's history, but should suffice for most cases, for now...
6548  //will apply Dijkstra to the partons in the current string to find the shortest path from hadron_col to hadron_acol
6549 
6550  //start by finding the partons with the col/acol tags
6551  int ptn1 = -1; int ptn2 = -1;
6552  for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6553  if((HH_pyremn[irem].col() == hadron_col) && (HH_pyremn[irem].PY_stat() > 0)) {ptn1 = irem;}
6554  if((HH_pyremn[irem].acol() == hadron_acol) && (HH_pyremn[irem].PY_stat() > 0)) {ptn2 = irem;}
6555  if((ptn1 >= 0) && (ptn2 >= 0)){break;}
6556  }
6557 
6558  //if ptn1 or ptn2 < 0, then we're giving up on this hadron (needs pythia history to properly reconstruct the mother parton(s))
6559  //otherwise, we'll trace along the string from one parton end to the other (using Dijkstra) to find all mother partons
6560  if((ptn1 >= 0) && (ptn2 >= 0)){
6561  //for 0th order approx, we'll just average the positions of the known parton ends
6562  double pos_x, pos_y, pos_z, pos_t; pos_x = 0.; pos_y = 0.; pos_z = 0.; pos_t = 0.;
6563  pos_x += HH_pyremn[ptn1].x(); pos_y += HH_pyremn[ptn1].y(); pos_z += HH_pyremn[ptn1].z(); pos_t += HH_pyremn[ptn1].x_t();
6564  pos_x += HH_pyremn[ptn2].x(); pos_y += HH_pyremn[ptn2].y(); pos_z += HH_pyremn[ptn2].z(); pos_t += HH_pyremn[ptn2].x_t();
6565  pos_x /= 2.; pos_y /= 2.; pos_z /= 2.; pos_t /= 2.;
6566  hadron_out.x(pos_x); hadron_out.y(pos_y); hadron_out.z(pos_z); hadron_out.x_t(pos_t);
6567  info_found = true;
6568  Case1_hadron_idx.push_back(hadron_idx);
6569  Case1_parton1_idx.push_back(ptn1);
6570  Case1_parton2_idx.push_back(ptn2);
6571  }
6572  }
6573  }else if((hadron_col == hadron_acol) && (hadron_col != 0)) { //col==acol -> this hadron traces back to a string segment; find the two partons and interpolate position
6574  //there are 2 cases here - an easy case where the color tags match the original partons, and a hard case where we need to trace history
6575  int ptn1 = 0; int ptn2 = 0; int ptn3 = 0;
6576  bool col_found = false; bool acol_found = false; bool ptn3_found = false;
6577  while(ptn1 < HH_pyremn.num()) {if((HH_pyremn[ptn1].col() == hadron_col) && (HH_pyremn[ptn1].PY_stat() > 0)) {col_found =true; break;} ++ptn1;}
6578  while(ptn2 < HH_pyremn.num()) {if((HH_pyremn[ptn2].acol() == hadron_acol)&& (HH_pyremn[ptn2].PY_stat() > 0)) {acol_found=true; break;} ++ptn2;}
6579 
6580  col_known = col_found; acol_known = acol_found;
6581  //if we don't find color/anticolor tags in input partons, we'll need to trace along pythia event/history to find either/both
6582  //we can grab what pythia claims are the mothers, then search that for the color tag, which should return ONE candidate
6583  //repeat this until event_i <= HH_pyremn.num() - this will be our input
6584  //would it be better to start at the beginning, grab everything that doesn't have a terminal color tag in a hadron, and trace those to respective hadron(s)?
6585 
6586  //since these *only* should happen in junction systems at the junction, use the junction list to find the other 2 color tags, then find those in orig. ptns!
6587  if(!col_found){
6588  //find the junction with matching color, grab the other 2
6589  int coll[2] = {0,0};
6590  for(int iJ = 0; iJ < pythia.event.sizeJunction(); ++iJ) {
6591  for(int iC = 0; iC < 3; ++iC) {
6592  if(pythia.event.colJunction(iJ,iC) == hadron_col) {
6593  if(iC == 0) {coll[0] = pythia.event.colJunction(iJ,1); coll[1] = pythia.event.colJunction(iJ,2);}
6594  else if(iC == 1) {coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,2);}
6595  else{coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,1);}
6596  col_found=true; break;
6597  }
6598  }
6599  if(col_found) {break;}
6600  }
6601  //since pythia refuses to keep track of initial junctions given to it, we'll do it manually
6602  if(!col_found) {
6603  for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6604  if(std::abs(HH_pyremn[irem].id()) > 1112) {
6605  if( HH_pyremn[irem].PY_tag1() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag2(); coll[1] = HH_pyremn[irem].PY_tag3(); col_found = true; break;}
6606  else if(HH_pyremn[irem].PY_tag2() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag3(); col_found = true; break;}
6607  else if(HH_pyremn[irem].PY_tag3() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag2(); col_found = true; break;}
6608  }
6609  }
6610  }
6611  //now we know the color tags needed, we look for them.
6612  if(col_found) {
6613  bool found_tags[2] = {0,0}; ptn1 = 0;
6614  while(ptn1<HH_pyremn.num()) {if((HH_pyremn[ptn1].acol() == coll[0]) && (HH_pyremn[ptn1].PY_stat() > 0)) {found_tags[0] = true; break;} ++ptn1;}
6615  while(ptn3<HH_pyremn.num()) {if((HH_pyremn[ptn3].acol() == coll[1]) && (HH_pyremn[ptn2].PY_stat() > 0)) {found_tags[1] = true; break;} ++ptn3;}
6616  if(found_tags[0] && found_tags[1]) {ptn3_found = true;}
6617  }
6618  }
6619  if(!acol_found) {
6620  //check to see if there's already 3 partons - if so, then we need a warning/error!
6621  if(ptn3_found) {JSWARN << "A hadron was found with more than 3 partonic parents for space-time info!";}
6622  //otherwise, works just like above...
6623  int coll[2] = {0,0};
6624  for(int iJ = 0; iJ < pythia.event.sizeJunction(); ++iJ) {
6625  for(int iC = 0; iC < 3; ++iC) {
6626  if(pythia.event.colJunction(iJ,iC) == hadron_acol) {
6627  if(iC == 0) {coll[0] = pythia.event.colJunction(iJ,1); coll[1] = pythia.event.colJunction(iJ,2);}
6628  else if(iC == 1) {coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,2);}
6629  else{coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,1);}
6630  acol_found = true; break;
6631  }
6632  }
6633  if(acol_found) {break;}
6634  }
6635  //since pythia refuses to keep track of initial junctions given to it, we'll do it manually
6636  if(!acol_found) {
6637  for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6638  if(std::abs(HH_pyremn[irem].id()) > 1112) {
6639  if( HH_pyremn[irem].PY_tag1() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag2(); coll[1] = HH_pyremn[irem].PY_tag3(); acol_found = true; break;}
6640  else if(HH_pyremn[irem].PY_tag2() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag3(); acol_found = true; break;}
6641  else if(HH_pyremn[irem].PY_tag3() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag2(); acol_found = true; break;}
6642  }
6643  }
6644  }
6645  //now we know the anti-color tags needed, we look for them.
6646  if(acol_found){
6647  bool found_tags[2] = {0,0}; ptn2 = 0;
6648  while(ptn2<HH_pyremn.num()){if((HH_pyremn[ptn2].col()==coll[0]) && (HH_pyremn[ptn1].PY_stat()>0)){found_tags[0]=true; break;} ++ptn2;}
6649  while(ptn3<HH_pyremn.num()){if((HH_pyremn[ptn3].col()==coll[1]) && (HH_pyremn[ptn2].PY_stat()>0)){found_tags[1]=true; break;} ++ptn3;}
6650  if(found_tags[0] && found_tags[1]){ptn3_found=true;}
6651  }
6652  }
6653 
6654  col_known = col_found; acol_known = acol_found;
6655  //turning off warning iff things work
6656  if(col_found && acol_found) {info_found = true;}
6657 
6658  //setting position from found partons
6659  double pos_x, pos_y, pos_z, pos_t; pos_x=0.; pos_y=0.; pos_z=0.; pos_t=0.;
6660  pos_x += HH_pyremn[ptn1].x(); pos_y += HH_pyremn[ptn1].y(); pos_z += HH_pyremn[ptn1].z(); pos_t += HH_pyremn[ptn1].x_t();
6661  pos_x += HH_pyremn[ptn2].x(); pos_y += HH_pyremn[ptn2].y(); pos_z += HH_pyremn[ptn2].z(); pos_t += HH_pyremn[ptn2].x_t();
6662  Case2_hadron_idx.push_back(hadron_idx);
6663  Case2_parton1_idx.push_back(ptn1);
6664  Case2_parton2_idx.push_back(ptn2);
6665  if(ptn3_found){
6666  pos_x += HH_pyremn[ptn3].x(); pos_y += HH_pyremn[ptn3].y(); pos_z += HH_pyremn[ptn3].z(); pos_t += HH_pyremn[ptn3].x_t();
6667  pos_x /= 3.; pos_y /= 3.; pos_z /= 3.; pos_t /= 3.;
6668  Case2_parton3_idx.push_back(ptn3);
6669  Case2_junction_center = {pos_t,pos_x,pos_y,pos_z};
6670  }else{
6671  pos_x /= 2.; pos_y /= 2.; pos_z /= 2.; pos_t /= 2.;
6672  Case2_parton3_idx.push_back(-1);
6673  }
6674  hadron_out.x(pos_x); hadron_out.y(pos_y); hadron_out.z(pos_z); hadron_out.x_t(pos_t);
6675  }else if((hadron_col == hadron_acol) && (hadron_col == 0)) { //col==acol==0 -> same as previous, but pythia didn't give color tag since this was from a short string q-qbar
6676  double avg_x, avg_y, avg_z, avg_t; avg_x=0.; avg_y=0.; avg_z=0.; avg_t=0.;
6677  int n_ptns = 0; //should come out to 2 in the end, but keeping track just in case.
6678  bool found_first_q_or_qbar = false; bool found_second_q_or_qbar = false;
6679  for(int imot = 0; imot < mothers.size(); ++imot) {
6680  if(mothers[imot] <= HH_pyremn.num()) {
6681  info_found = true; //if no mothers, then no position, and throw error!
6682  avg_x += HH_pyremn[mothers[imot]-1].x(); avg_y += HH_pyremn[mothers[imot]-1].y(); avg_z += HH_pyremn[mothers[imot]-1].z(); avg_t += HH_pyremn[mothers[imot]-1].x_t();
6683  ++n_ptns;
6684  if(std::abs(HH_pyremn[mothers[imot]-1].id()) < 7 && !found_first_q_or_qbar) {
6685  Case3_parton1_idx.push_back(mothers[imot]-1);
6686  found_first_q_or_qbar = true;
6687  } else if(std::abs(HH_pyremn[mothers[imot]-1].id()) < 7 && !found_second_q_or_qbar && found_first_q_or_qbar) {
6688  Case3_parton2_idx.push_back(mothers[imot]-1);
6689  found_second_q_or_qbar = true;
6690  }
6691  }
6692  }
6693  if(found_first_q_or_qbar && found_second_q_or_qbar) {
6694  Case3_hadron_idx.push_back(hadron_idx);
6695  }
6696  if(found_first_q_or_qbar && !found_second_q_or_qbar) {
6697  Case3_parton1_idx.pop_back();
6698  }
6699  if(n_ptns > 0) {
6700  avg_x /= double(n_ptns); avg_y /= double(n_ptns); avg_z /= double(n_ptns); avg_t /= double(n_ptns);
6701  Case3_partons_center = {avg_t,avg_x,avg_y,avg_z};
6702  }
6703  hadron_out.x(avg_x); hadron_out.y(avg_y); hadron_out.z(avg_z); hadron_out.x_t(avg_t);
6704  }
6705  if(!info_found) {
6706  compute_more_precise_positions = false;
6707  warn_could_not_find_positions = true;
6708  hadron_out.x(0.); hadron_out.y(0.); hadron_out.z(0.); hadron_out.x_t(0.);
6709  }
6710 
6711  //the mother procedure might skip some partons if there are junctions involved
6712  //this can be 'repaired' by taking a 'mother' parton, then checking over all the partons in its string! (both adding to parents / checking if thermal)
6713  //this is done in hadronization calling function, after invoke_py function is finished
6714  final_hadrons_from_pythia.push_back(hadron_out);
6715  }
6716  }
6717 
6718  //warn about not found position for hadrons only once per function call
6719  if(warn_could_not_find_positions && GetXMLElementInt({"Afterburner", "include_fragmentation_hadrons"}) == 1) {
6720  VERBOSE(2) << "Could not find the spacetime information for hadron in pythia event (string fragmentation attempt ="
6721  << pythia_attempt << "), set it to (0,0,0,0)";
6722  }
6723 
6724  //now let's do it a bit more precise and distribute the positions along the string segments instead of using the average
6725  if(compute_more_precise_positions) {
6726  //find the more precise positions for case 1
6727  //have to find the hadrons from the same string segment
6728  vector<int> Case1_unique_parton1_idx = Case1_parton1_idx;
6729  std::sort(Case1_unique_parton1_idx.begin(), Case1_unique_parton1_idx.end());
6730  Case1_unique_parton1_idx.erase(std::unique(Case1_unique_parton1_idx.begin(), Case1_unique_parton1_idx.end()), Case1_unique_parton1_idx.end());
6731  // go through string segments
6732  for(int string_seg = 0; string_seg < Case1_unique_parton1_idx.size(); string_seg++) {
6733  int segment_parton1_idx = Case1_unique_parton1_idx.at(string_seg);
6734 
6735  // select the hadrons from the string which need position modification
6736  vector<int> segment_hadron_idx;
6737  for(int iHad = 0; iHad < Case1_hadron_idx.size(); iHad++) {
6738  if(Case1_parton1_idx.at(iHad) == segment_parton1_idx) {
6739  segment_hadron_idx.push_back(iHad);
6740  }
6741  }
6742 
6743  // modify the hadron positions from the current string
6744  int number_hadrons_segment = segment_hadron_idx.size();
6745  if(number_hadrons_segment > 1) {
6746  for(int iHad = 0; iHad < number_hadrons_segment; iHad++) {
6747  int parton1_index = Case1_parton1_idx.at(segment_hadron_idx.at(iHad));
6748  int parton2_index = Case1_parton2_idx.at(segment_hadron_idx.at(iHad));
6749  int current_hadron_idx = segment_hadron_idx.at(iHad);
6750 
6751  //get the positions of the two partons at the ends of the string segment
6752  double pos_x_ptn1 = HH_pyremn[parton1_index].x();
6753  double pos_y_ptn1 = HH_pyremn[parton1_index].y();
6754  double pos_z_ptn1 = HH_pyremn[parton1_index].z();
6755  double pos_t_ptn1 = HH_pyremn[parton1_index].x_t();
6756  double pos_x_ptn2 = HH_pyremn[parton2_index].x();
6757  double pos_y_ptn2 = HH_pyremn[parton2_index].y();
6758  double pos_z_ptn2 = HH_pyremn[parton2_index].z();
6759  double pos_t_ptn2 = HH_pyremn[parton2_index].x_t();
6760 
6761  double delta_x = (pos_x_ptn2 - pos_x_ptn1) / (number_hadrons_segment+1);
6762  double delta_y = (pos_y_ptn2 - pos_y_ptn1) / (number_hadrons_segment+1);
6763  double delta_z = (pos_z_ptn2 - pos_z_ptn1) / (number_hadrons_segment+1);
6764  double delta_t = (pos_t_ptn2 - pos_t_ptn1) / (number_hadrons_segment+1);
6765 
6766  double had_x = pos_x_ptn1 + (iHad+1) * delta_x;
6767  double had_y = pos_y_ptn1 + (iHad+1) * delta_y;
6768  double had_z = pos_z_ptn1 + (iHad+1) * delta_z;
6769  double had_t = pos_t_ptn1 + (iHad+1) * delta_t;
6770 
6771  //set the hadron to the new position along the string segment
6772  final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6773  final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6774  final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6775  final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6776  }
6777  }
6778  }
6779 
6780  //find the more precise positions for case 2
6781  //have to find the hadrons from the same string segment
6782  vector<int> Case2_unique_parton1_idx = Case2_parton1_idx;
6783  std::sort(Case2_unique_parton1_idx.begin(), Case2_unique_parton1_idx.end());
6784  Case2_unique_parton1_idx.erase(std::unique(Case2_unique_parton1_idx.begin(), Case2_unique_parton1_idx.end()), Case2_unique_parton1_idx.end());
6785 
6786  // go through string segments or junction legs
6787  for(int string_seg = 0; string_seg < Case2_unique_parton1_idx.size(); string_seg++) {
6788  int segment_parton1_idx = Case2_unique_parton1_idx.at(string_seg);
6789 
6790  // select the hadrons from the string which need position modification
6791  vector<int> segment_hadron_idx;
6792  for(int iHad = 0; iHad < Case2_hadron_idx.size(); iHad++) {
6793  if(Case2_parton1_idx.at(iHad) == segment_parton1_idx) {
6794  segment_hadron_idx.push_back(iHad);
6795  }
6796  }
6797 
6798  // modify the hadron positions from the current string
6799  int number_hadrons_segment = segment_hadron_idx.size();
6800  if(number_hadrons_segment > 1) { // in case of a string segment use average position if only one hadron, in case of junction use center (nothing to do here)
6801  for(int iHad = 0; iHad < number_hadrons_segment; iHad++) {
6802  int parton1_index = Case2_parton1_idx.at(segment_hadron_idx.at(iHad));
6803  int parton2_index = Case2_parton2_idx.at(segment_hadron_idx.at(iHad));
6804  int parton3_index = Case2_parton3_idx.at(segment_hadron_idx.at(iHad));
6805  int current_hadron_idx = segment_hadron_idx.at(iHad);
6806 
6807  if((parton3_index == -1) && (Case2_junction_center.size() == 0)) { // this is the case where we have two partons at the string segment ends
6808  //get the positions of the two partons at the ends of the string segment
6809  double pos_x_ptn1 = HH_pyremn[parton1_index].x();
6810  double pos_y_ptn1 = HH_pyremn[parton1_index].y();
6811  double pos_z_ptn1 = HH_pyremn[parton1_index].z();
6812  double pos_t_ptn1 = HH_pyremn[parton1_index].x_t();
6813  double pos_x_ptn2 = HH_pyremn[parton2_index].x();
6814  double pos_y_ptn2 = HH_pyremn[parton2_index].y();
6815  double pos_z_ptn2 = HH_pyremn[parton2_index].z();
6816  double pos_t_ptn2 = HH_pyremn[parton2_index].x_t();
6817 
6818  double delta_x = (pos_x_ptn2 - pos_x_ptn1) / (number_hadrons_segment+1);
6819  double delta_y = (pos_y_ptn2 - pos_y_ptn1) / (number_hadrons_segment+1);
6820  double delta_z = (pos_z_ptn2 - pos_z_ptn1) / (number_hadrons_segment+1);
6821  double delta_t = (pos_t_ptn2 - pos_t_ptn1) / (number_hadrons_segment+1);
6822 
6823  double had_x = pos_x_ptn1 + (iHad+1) * delta_x;
6824  double had_y = pos_y_ptn1 + (iHad+1) * delta_y;
6825  double had_z = pos_z_ptn1 + (iHad+1) * delta_z;
6826  double had_t = pos_t_ptn1 + (iHad+1) * delta_t;
6827 
6828  //set the hadron to the new position along the string segment
6829  final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6830  final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6831  final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6832  final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6833  } else if(parton3_index > -1 && Case2_junction_center.size() != 0) { // this is the case with a junction / antijunction
6834  // compute the leg vectors (center is origin)
6835  vector<double> leg1_vec = {HH_pyremn[parton1_index].x_t()-Case2_junction_center[0],
6836  HH_pyremn[parton1_index].x()-Case2_junction_center[1],
6837  HH_pyremn[parton1_index].y()-Case2_junction_center[2],
6838  HH_pyremn[parton1_index].z()-Case2_junction_center[3]};
6839  vector<double> leg2_vec = {HH_pyremn[parton2_index].x_t()-Case2_junction_center[0],
6840  HH_pyremn[parton2_index].x()-Case2_junction_center[1],
6841  HH_pyremn[parton2_index].y()-Case2_junction_center[2],
6842  HH_pyremn[parton2_index].z()-Case2_junction_center[3]};
6843  vector<double> leg3_vec = {HH_pyremn[parton3_index].x_t()-Case2_junction_center[0],
6844  HH_pyremn[parton3_index].x()-Case2_junction_center[1],
6845  HH_pyremn[parton3_index].y()-Case2_junction_center[2],
6846  HH_pyremn[parton3_index].z()-Case2_junction_center[3]};
6847  double abs_leg1 = std::sqrt(leg1_vec[0]*leg1_vec[0] + leg1_vec[1]*leg1_vec[1] + leg1_vec[2]*leg1_vec[2] + leg1_vec[3]*leg1_vec[3]);
6848  double abs_leg2 = std::sqrt(leg2_vec[0]*leg2_vec[0] + leg2_vec[1]*leg2_vec[1] + leg2_vec[2]*leg2_vec[2] + leg2_vec[3]*leg2_vec[3]);
6849  double abs_leg3 = std::sqrt(leg3_vec[0]*leg3_vec[0] + leg3_vec[1]*leg3_vec[1] + leg3_vec[2]*leg3_vec[2] + leg3_vec[3]*leg3_vec[3]);
6850  if(abs_leg1 <= 1e-6 || abs_leg2 <= 1e-6 || abs_leg3 <= 1e-6) {continue;}
6851  double L = abs_leg1 + abs_leg2 + abs_leg3;
6852  double delta_l = L / (number_hadrons_segment + 1); // inter hadron distance
6853  double distance = delta_l + iHad; // center -> end leg1, center -> end leg2, center -> end leg3
6854  double had_t, had_x, had_y, had_z;
6855  if(distance <= abs_leg1) {
6856  had_t = leg1_vec[0] * (distance / abs_leg1);
6857  had_x = leg1_vec[1] * (distance / abs_leg1);
6858  had_y = leg1_vec[2] * (distance / abs_leg1);
6859  had_z = leg1_vec[3] * (distance / abs_leg1);
6860  } else if((abs_leg1 < distance) && (distance <= abs_leg1+abs_leg2)) {
6861  had_t = leg2_vec[0] * ((distance - abs_leg1) / abs_leg2);
6862  had_x = leg2_vec[1] * ((distance - abs_leg1) / abs_leg2);
6863  had_y = leg2_vec[2] * ((distance - abs_leg1) / abs_leg2);
6864  had_z = leg2_vec[3] * ((distance - abs_leg1) / abs_leg2);
6865  } else { // (abs_leg1+abs_leg2 < distance) && (distance <= L)
6866  had_t = leg3_vec[0] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6867  had_x = leg3_vec[1] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6868  had_y = leg3_vec[2] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6869  had_z = leg3_vec[3] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6870  }
6871  //set the hadron to the new position along the string segment
6872  final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6873  final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6874  final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6875  final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6876  }
6877  }
6878  }
6879  }
6880 
6881  //find the more precise positions for case 3
6882  //have to find the hadrons from the same string segment
6883  vector<int> Case3_unique_parton1_idx = Case3_parton1_idx;
6884  std::sort(Case3_unique_parton1_idx.begin(), Case3_unique_parton1_idx.end());
6885  Case3_unique_parton1_idx.erase(std::unique(Case3_unique_parton1_idx.begin(), Case3_unique_parton1_idx.end()), Case3_unique_parton1_idx.end());
6886  // go through string segments
6887  for(int string_seg = 0; string_seg < Case3_unique_parton1_idx.size(); string_seg++) {
6888  int segment_parton1_idx = Case3_unique_parton1_idx.at(string_seg);
6889 
6890  // select the hadrons from the string which need position modification
6891  vector<int> segment_hadron_idx;
6892  for(int iHad = 0; iHad < Case3_hadron_idx.size(); iHad++) {
6893  if(Case3_parton1_idx.at(iHad) == segment_parton1_idx) {
6894  segment_hadron_idx.push_back(iHad);
6895  }
6896  }
6897 
6898  // modify the hadron positions from the current string
6899  int number_hadrons_segment = segment_hadron_idx.size();
6900  if(number_hadrons_segment > 1) {
6901  for(int iHad = 0; iHad < number_hadrons_segment; iHad++) {
6902  int parton1_index = Case3_parton1_idx.at(segment_hadron_idx.at(iHad));
6903  int parton2_index = Case3_parton2_idx.at(segment_hadron_idx.at(iHad));
6904  int current_hadron_idx = segment_hadron_idx.at(iHad);
6905 
6906  vector<double> seg1_vec = {HH_pyremn[parton1_index].x_t()-Case3_partons_center[0],
6907  HH_pyremn[parton1_index].x()-Case3_partons_center[1],
6908  HH_pyremn[parton1_index].y()-Case3_partons_center[2],
6909  HH_pyremn[parton1_index].z()-Case3_partons_center[3]};
6910  vector<double> seg2_vec = {HH_pyremn[parton2_index].x_t()-Case3_partons_center[0],
6911  HH_pyremn[parton2_index].x()-Case3_partons_center[1],
6912  HH_pyremn[parton2_index].y()-Case3_partons_center[2],
6913  HH_pyremn[parton2_index].z()-Case3_partons_center[3]};
6914  double abs_seg1 = std::sqrt(seg1_vec[0]*seg1_vec[0] + seg1_vec[1]*seg1_vec[1] + seg1_vec[2]*seg1_vec[2] + seg1_vec[3]*seg1_vec[3]);
6915  double abs_seg2 = std::sqrt(seg2_vec[0]*seg2_vec[0] + seg2_vec[1]*seg2_vec[1] + seg2_vec[2]*seg2_vec[2] + seg2_vec[3]*seg2_vec[3]);
6916  if(abs_seg1 <= 1e-6 || abs_seg2 <= 1e-6) {continue;}
6917  double L = abs_seg1 + abs_seg2;
6918  double delta_l = L / (number_hadrons_segment + 1); // inter hadron distance
6919  double distance = delta_l + iHad; // center -> end seg1, center -> end seg2
6920  double had_t, had_x, had_y, had_z;
6921  if(distance <= abs_seg1) {
6922  had_t = seg1_vec[0] * (distance / abs_seg1);
6923  had_x = seg1_vec[1] * (distance / abs_seg1);
6924  had_y = seg1_vec[2] * (distance / abs_seg1);
6925  had_z = seg1_vec[3] * (distance / abs_seg1);
6926  } else { // (abs_leg1 < distance) && (distance <= abs_leg1+abs_leg2)
6927  had_t = seg2_vec[0] * ((distance - abs_seg1) / abs_seg2);
6928  had_x = seg2_vec[1] * ((distance - abs_seg1) / abs_seg2);
6929  had_y = seg2_vec[2] * ((distance - abs_seg1) / abs_seg2);
6930  had_z = seg2_vec[3] * ((distance - abs_seg1) / abs_seg2);
6931  }
6932  //set the hadron to the new position along the string segment
6933  final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6934  final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6935  final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6936  final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6937  }
6938  }
6939  }
6940  }
6941 
6942  //finally add the hadrons with position information to the HH_hadrons
6943  //the mother procedure might skip some partons if there are junctions involved
6944  //this can be 'repaired' by taking a 'mother' parton, then checking over all the partons in its string! (both adding to parents / checking if thermal)
6945  //this is done in hadronization calling function, after this invoke_py function is finished
6946  for(int hadron_idx = 0; hadron_idx < final_hadrons_from_pythia.size(); hadron_idx++) {
6947  HH_pythia_hadrons.add(final_hadrons_from_pythia[hadron_idx]);
6948  }
6949 }
6950 
6952  //to calc. E conservation violation
6953  //double Ebefore = 0.; double Eafter = 0.; double pTbefore = 0.; double pTafter = 0.;
6954  //for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){if(!HH_hadrons[iHad].is_final()){continue;} Ebefore += HH_hadrons[iHad].e(); pTbefore += HH_hadrons[iHad].pt();}
6955  //std::cout << std::setprecision(5);
6956  //std::ofstream eviol; std::ofstream echg; std::ofstream ptchg;
6957  //eviol.open("Evio_hadrons.dat", std::ios::app); echg.open("Echg_hadrons.dat", std::ios::app); ptchg.open("ptchg_hadrons.dat", std::ios::app);
6958 
6959  //hadron mass adjust
6960  double osf = 1e-6;
6961  for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){
6962  //if this isn't a final state hadron, there's no point in fixing it.
6963  if(!HH_hadrons[iHad].is_final()){continue;}
6964 
6965  //need hadron mass and pdg (pythia) mass to check
6966  double hadmass = HH_hadrons[iHad].mass();
6967  double m1 = pythia.particleData.m0(HH_hadrons[iHad].id());
6968  //if this hadron doesn't need to be fixed, then we skip it
6969  if(!(std::abs(hadmass - m1)/m1 > osf)){continue;}
6970 
6971  //this hadron needs fixing, so we prepare to find a partner hadron to adjust with it
6972  int partner = -1;
6973 
6974  //if this hadron has colors, then we can use that info to fix it
6975  if(HH_hadrons[iHad].cols.size() > 0){
6976  //looking through the hadron list to find another hadron with the same color tag.
6977  for(int jHad = 0; jHad < HH_hadrons.num(); ++jHad){
6978  if(!HH_hadrons[jHad].is_final()){continue;} //do not want a non-final hadron
6979  if(iHad == jHad){continue;} //needs to be a different hadron
6980  double m2 = pythia.particleData.m0(HH_hadrons[jHad].id());
6981  double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[jHad].e())*(HH_hadrons[iHad].e() + HH_hadrons[jHad].e())
6982  - (HH_hadrons[iHad].px() + HH_hadrons[jHad].px())*(HH_hadrons[iHad].px() + HH_hadrons[jHad].px())
6983  - (HH_hadrons[iHad].py() + HH_hadrons[jHad].py())*(HH_hadrons[iHad].py() + HH_hadrons[jHad].py())
6984  - (HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz()));
6985  // variabele to compute the squared momentum difference of the partners
6986  // if this is too small the mass adjustment procedure would fail
6987  double momentum_diff = (HH_hadrons[iHad].px()-HH_hadrons[jHad].px())*(HH_hadrons[iHad].px()-HH_hadrons[jHad].px())
6988  + (HH_hadrons[iHad].py()-HH_hadrons[jHad].py())*(HH_hadrons[iHad].py()-HH_hadrons[jHad].py())
6989  + (HH_hadrons[iHad].pz()-HH_hadrons[jHad].pz())*(HH_hadrons[iHad].pz()-HH_hadrons[jHad].pz());
6990  if(HH_hadrons[jHad].cols.size() > 0){//if this hadron has color tags, check
6991  //JSINFO << "iHad = " << iHad << ", jHad = " << jHad << ", momentum_diff = " << momentum_diff << ", pair_mass - m1 - m2 = " << pair_mass-m1-m2;
6992  for(int icol = 0; icol < HH_hadrons[iHad].cols.size(); ++icol){
6993  for(int jcol = 0; jcol < HH_hadrons[jHad].cols.size(); ++jcol){
6994  if(!(HH_hadrons[iHad].col(icol) == HH_hadrons[jHad].col(jcol)) || momentum_diff < 1e-6 || (pair_mass < m1+m2)){continue;} //color not matching
6995  //if the previous condition isn't met, that means the colors match!
6996  partner = jHad; break;
6997  }
6998  if(partner > -1){break;}
6999  }
7000  }
7001  if(partner > -1){break;}
7002  }
7003  }
7004 
7005  //ready to fix, if a partner has not been found, pick a close-by hadron
7006  //make sure that there is a relative momentum to reshuffle the masses
7007  if(partner == -1){
7008  //grabbing closest final state hadron before and after, if it exists
7009  int iprev = iHad-1; int inext = iHad+1;
7010  while(iprev >= 0){
7011  double m2 = pythia.particleData.m0(HH_hadrons[iprev].id());
7012  double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[iprev].e())*(HH_hadrons[iHad].e() + HH_hadrons[iprev].e())
7013  - (HH_hadrons[iHad].px() + HH_hadrons[iprev].px())*(HH_hadrons[iHad].px() + HH_hadrons[iprev].px())
7014  - (HH_hadrons[iHad].py() + HH_hadrons[iprev].py())*(HH_hadrons[iHad].py() + HH_hadrons[iprev].py())
7015  - (HH_hadrons[iHad].pz() + HH_hadrons[iprev].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[iprev].pz()));
7016  double momentum_diff = (HH_hadrons[iHad].px()-HH_hadrons[iprev].px())*(HH_hadrons[iHad].px()-HH_hadrons[iprev].px())
7017  + (HH_hadrons[iHad].py()-HH_hadrons[iprev].py())*(HH_hadrons[iHad].py()-HH_hadrons[iprev].py())
7018  + (HH_hadrons[iHad].pz()-HH_hadrons[iprev].pz())*(HH_hadrons[iHad].pz()-HH_hadrons[iprev].pz());
7019  if(HH_hadrons[iprev].is_final() && momentum_diff >= 1e-6 && pair_mass >= m1+m2){break;}
7020  --iprev;
7021  }
7022  while(inext < HH_hadrons.num()){
7023  double m2 = pythia.particleData.m0(HH_hadrons[inext].id());
7024  double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[inext].e())*(HH_hadrons[iHad].e() + HH_hadrons[inext].e())
7025  - (HH_hadrons[iHad].px() + HH_hadrons[inext].px())*(HH_hadrons[iHad].px() + HH_hadrons[inext].px())
7026  - (HH_hadrons[iHad].py() + HH_hadrons[inext].py())*(HH_hadrons[iHad].py() + HH_hadrons[inext].py())
7027  - (HH_hadrons[iHad].pz() + HH_hadrons[inext].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[inext].pz()));
7028  double momentum_diff = (HH_hadrons[iHad].px()-HH_hadrons[inext].px())*(HH_hadrons[iHad].px()-HH_hadrons[inext].px())
7029  + (HH_hadrons[iHad].py()-HH_hadrons[inext].py())*(HH_hadrons[iHad].py()-HH_hadrons[inext].py())
7030  + (HH_hadrons[iHad].pz()-HH_hadrons[inext].pz())*(HH_hadrons[iHad].pz()-HH_hadrons[inext].pz());
7031  if(HH_hadrons[inext].is_final() && momentum_diff >= 1e-6 && pair_mass >= m1+m2){break;}
7032  ++inext;
7033  }
7034 
7035  //if there is no closest before, then grab closest after
7036  //or if no closest after, then grab closest before
7037  //if both exist, grab the one that's closest, unless both are the same in which case grab the one after
7038  if(iprev < 0){partner = inext;}
7039  else if(inext >= HH_hadrons.num()){partner = iprev;}
7040  else{partner = (inext - iHad <= iHad - iprev) ? inext : iprev;}
7041 
7042  if((partner >= HH_hadrons.num()) || (partner < 0)) {partner = -1;}
7043  }
7044 
7045  //choose the hadron with the smallest pair_mass - m1 - m2 value
7046  if(partner == -1){
7047  double minimum = 1e6;
7048  int partner_temporary = -1;
7049  for(int jHad = 0; jHad < HH_hadrons.num(); ++jHad){
7050  if(!HH_hadrons[jHad].is_final()){continue;} //do not want a non-final hadron
7051  if(iHad == jHad){continue;} //needs to be a different hadron
7052  double m2 = pythia.particleData.m0(HH_hadrons[jHad].id());
7053  double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[jHad].e())*(HH_hadrons[iHad].e() + HH_hadrons[jHad].e())
7054  - (HH_hadrons[iHad].px() + HH_hadrons[jHad].px())*(HH_hadrons[iHad].px() + HH_hadrons[jHad].px())
7055  - (HH_hadrons[iHad].py() + HH_hadrons[jHad].py())*(HH_hadrons[iHad].py() + HH_hadrons[jHad].py())
7056  - (HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz()));
7057  if(std::abs(pair_mass-m1-m2) < minimum){
7058  minimum = std::abs(pair_mass-m1-m2);
7059  partner_temporary = jHad;
7060  }
7061  }
7062  if(partner_temporary != -1){
7063  partner = partner_temporary;
7064  }
7065  }
7066 
7067  //by now, a partner *must* have been chosen - unless there's only 1 hadron in the event, which is BAD.
7068  //time to fix.
7069  //if somehow everything failed, just skip this hadron...
7070  if(partner == -1){continue;}
7071 
7072  //std::cout << "H1_before: " << iHad << ", " << HH_hadrons[iHad].id() << ", " << HH_hadrons[iHad].px() << ", " << HH_hadrons[iHad].py() << ", " << HH_hadrons[iHad].pz() << ", " << HH_hadrons[iHad].e() << "\n";
7073  //std::cout << "H2_before: " << partner << ", " << HH_hadrons[partner].id() << ", " << HH_hadrons[partner].px() << ", " << HH_hadrons[partner].py() << ", " << HH_hadrons[partner].pz() << ", " << HH_hadrons[partner].e() << "\n";
7074 
7075  //Psys
7076  FourVector Psys;
7077  Psys.Set(HH_hadrons[iHad].px()+HH_hadrons[partner].px(),HH_hadrons[iHad].py()+HH_hadrons[partner].py(),HH_hadrons[iHad].pz()+HH_hadrons[partner].pz(),HH_hadrons[iHad].e()+HH_hadrons[partner].e());
7078 
7079  //CM velocity
7080  FourVector beta;
7081  beta.Set(Psys.x()/Psys.t(),Psys.y()/Psys.t(),Psys.z()/Psys.t(),0.);
7082  beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7083 
7084  //boosting into CM frame
7085  FourVector p_CM[2]; p_CM[0] = HH_hadrons[iHad].boost_P(beta); p_CM[1] = HH_hadrons[partner].boost_P(beta);
7086 
7087  //if E1 + E2 >= m1 + m2, shift momenta
7088  double m2 = pythia.particleData.m0(HH_hadrons[partner].id());
7089  double Etot = p_CM[0].t() + p_CM[1].t();
7090  if(Etot < m1 + m2 + 0.00001){Etot = m1 + m2 + 0.00001; /*eviol << Etot - (p_CM[0].t() + p_CM[1].t()) << "\n";*/}//can't shift, violating E/P cons.
7091  double E1 = Etot/2. + ((m1*m1)-(m2*m2))/(2.*Etot);
7092  double E2 = Etot/2. - ((m1*m1)-(m2*m2))/(2.*Etot);
7093  double pmag = sqrt(p_CM[0].x()*p_CM[0].x() + p_CM[0].y()*p_CM[0].y() + p_CM[0].z()*p_CM[0].z());
7094  double fac = sqrt(Etot*Etot/4. + ((m1*m1)-(m2*m2))*((m1*m1)-(m2*m2))/(4.*Etot*Etot) - ((m1*m1)+(m2*m2))/2.)/pmag;
7095 
7096  //rescaling in CM frame
7097  p_CM[0].Set(fac*p_CM[0].x(), fac*p_CM[0].y(), fac*p_CM[0].z(), E1);
7098  p_CM[1].Set(fac*p_CM[1].x(), fac*p_CM[1].y(), fac*p_CM[1].z(), E2);
7099 
7100  //boosting back and setting hadron E,P to fixed values
7101  beta.Set(-beta.x(), -beta.y(), -beta.z(), 0.);
7102  beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7103  FourVector p_fin[2]; p_fin[0] = HHboost(beta, p_CM[0]); p_fin[1] = HHboost(beta, p_CM[1]);
7104  HH_hadrons[iHad].P(p_fin[0]); HH_hadrons[partner].P(p_fin[1]);
7105  HH_hadrons[iHad].mass(m1);
7106  HH_hadrons[partner].mass(m2);
7107 
7108  //std::cout << "H1_after: " << iHad << ", " << HH_hadrons[iHad].id() << ", " << HH_hadrons[iHad].px() << ", " << HH_hadrons[iHad].py() << ", " << HH_hadrons[iHad].pz() << ", " << HH_hadrons[iHad].e() << "\n";
7109  //std::cout << "H2_after: " << partner << ", " << HH_hadrons[partner].id() << ", " << HH_hadrons[partner].px() << ", " << HH_hadrons[partner].py() << ", " << HH_hadrons[partner].pz() << ", " << HH_hadrons[partner].e() << "\n";
7110  }
7111 
7112  //calc. Etot after
7113  //for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){if(!HH_hadrons[iHad].is_final()){continue;} Eafter += HH_hadrons[iHad].e(); pTafter += HH_hadrons[iHad].pt();}
7114  //echg << Eafter-Ebefore << "\n"; ptchg << pTafter-pTbefore << "\n";
7115  //eviol.close(); echg.close(); ptchg.close();
7116 }
7117 
7119  //to calc. E conservation violation
7120  /*double Ebefore = 0.; double Eafter = 0.; double pTbefore = 0.; double pTafter = 0.;
7121  for(int iPart=0; iPart<HH_partons.num(); ++iPart){Ebefore += HH_partons[iPart].e(); pTbefore += HH_partons[iPart].pt();}
7122  std::cout << std::setprecision(5);
7123  std::ofstream eviol; std::ofstream echg; std::ofstream ptchg;
7124  eviol.open("Evio_partons.dat", std::ios::app); echg.open("Echg_partons.dat", std::ios::app); ptchg.open("ptchg_partons.dat", std::ios::app);*/
7125 
7126  // case for only one parton in the event -> force to parton mass
7127  if(HH_partons.num() == 1) {
7128  HHparton parton = HH_partons[0];
7129  if(std::abs(parton.id()) < 6 && parton.mass() < pythia.particleData.m0(std::abs(parton.id()))) { // quark case
7130  parton.mass(pythia.particleData.m0(std::abs(parton.id())));
7131  parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7132  HH_partons[0] = parton;
7133  } else if(parton.id() == 21 && parton.mass() < 2.*xmq + 0.001) { // gluon case (pythia has m_g = 0.)
7134  parton.mass(2.*xmq + 0.001);
7135  parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7136  HH_partons[0] = parton;
7137  }
7138  return;
7139  }
7140 
7141  //parton mass adjust
7142  double osf = 1e-6;
7143  for(int iPart=0; iPart<HH_partons.num(); ++iPart){
7144  //if this isn't a final state parton, there's no point in fixing it.
7145  if ((HH_partons[iPart].id() != 21) && (std::abs(HH_partons[iPart].id()) > 5)){continue;}
7146 
7147  //need parton mass and pdg (pythia) mass to check
7148  double partmass = HH_partons[iPart].mass();
7149  double m1 = 0.;
7150  if(HH_partons[iPart].id() == 21){
7151  m1 = 2.*xmq + 0.001;
7152  } else if(std::abs(HH_partons[iPart].id()) < 3) {
7153  m1 = xmq;
7154  } else if(std::abs(HH_partons[iPart].id()) == 3) {
7155  m1 = xms;
7156  } else if(std::abs(HH_partons[iPart].id()) == 4) {
7157  m1 = xmc;
7158  } else if(std::abs(HH_partons[iPart].id()) == 5) {
7159  m1 = xmb;
7160  }
7161 
7162  //if this parton doesn't need to be fixed, then we skip it
7163  if((std::abs(partmass - m1)/m1 < osf) && (std::abs(HH_partons[iPart].id()) < 6)){continue;}
7164 
7165  if((HH_partons[iPart].id() == 21) && (partmass > m1)){continue;}
7166 
7167  //this parton needs fixing, so we prepare to find a partner to adjust with it
7168  int partner = -1;
7169 
7170  //looking through the parton list to find another parton with the same color tag.
7171  for(int jPart=0; jPart<HH_partons.num(); ++jPart){
7172  if(iPart == jPart || (std::abs(HH_partons[iPart].id()) > 5 && std::abs(HH_partons[iPart].id()) < 7)){continue;} //needs to be a different parton
7173  double m2 = 0.;
7174  if ((HH_partons[jPart].id() == 21) && (HH_partons[jPart].mass() < 2.*xmq + 0.001)){
7175  m2 = 2.*xmq + 0.001;
7176  } else if ((HH_partons[jPart].id() == 21) && (HH_partons[jPart].mass() >= 2.*xmq + 0.001)){
7177  m2 = HH_partons[jPart].mass();
7178  } else if(std::abs(HH_partons[jPart].id()) < 3) {
7179  m2 = xmq;
7180  } else if(std::abs(HH_partons[jPart].id()) == 3) {
7181  m2 = xms;
7182  } else if(std::abs(HH_partons[jPart].id()) == 4) {
7183  m2 = xmc;
7184  } else if(std::abs(HH_partons[jPart].id()) == 5) {
7185  m2 = xmb;
7186  }
7187  double pair_mass = std::sqrt((HH_partons[iPart].e() + HH_partons[jPart].e())*(HH_partons[iPart].e() + HH_partons[jPart].e())
7188  - (HH_partons[iPart].px() + HH_partons[jPart].px())*(HH_partons[iPart].px() + HH_partons[jPart].px())
7189  - (HH_partons[iPart].py() + HH_partons[jPart].py())*(HH_partons[iPart].py() + HH_partons[jPart].py())
7190  - (HH_partons[iPart].pz() + HH_partons[jPart].pz())*(HH_partons[iPart].pz() + HH_partons[jPart].pz()));
7191  // variabele to compute the squared momentum difference of the partners
7192  // if this is too small the mass adjustment procedure would fail
7193  double momentum_diff = (HH_partons[iPart].px()-HH_partons[jPart].px())*(HH_partons[iPart].px()-HH_partons[jPart].px())
7194  + (HH_partons[iPart].py()-HH_partons[jPart].py())*(HH_partons[iPart].py()-HH_partons[jPart].py())
7195  + (HH_partons[iPart].pz()-HH_partons[jPart].pz())*(HH_partons[iPart].pz()-HH_partons[jPart].pz());
7196  if(((HH_partons[iPart].col() == HH_partons[jPart].acol()) || (HH_partons[iPart].acol() == HH_partons[jPart].col())) && (momentum_diff > 1e-6) && (pair_mass >= m1+m2)){
7197  if((HH_partons[jPart].id() == 21) && (HH_partons[jPart].mass() < 2.*xmq + 0.001)) {
7198  partner = jPart;
7199  break;
7200  } else if ((std::abs(HH_partons[jPart].id()) < 3) && (std::abs(HH_partons[jPart].mass() - xmq)/xmq > osf)) {
7201  partner = jPart;
7202  break;
7203  } else if ((std::abs(HH_partons[jPart].id()) == 3) && (std::abs(HH_partons[jPart].mass() - xms)/xms > osf)) {
7204  partner = jPart;
7205  break;
7206  } else if ((std::abs(HH_partons[jPart].id()) == 4) && (std::abs(HH_partons[jPart].mass() - xmc)/xmc > osf)) {
7207  partner = jPart;
7208  break;
7209  } else if ((std::abs(HH_partons[jPart].id()) == 5) && (std::abs(HH_partons[jPart].mass() - xmb)/xmb > osf)) {
7210  partner = jPart;
7211  break;
7212  }
7213  }
7214  }
7215 
7216  // candidate for a parton with the smallest energy loss (if no partner is found)
7217  int iPartnerCandidate = -1;
7218  double energy_loss_tracking = 1e6; // just a large number
7219 
7220  //ready to fix, if a partner has not been found, pick a close-by parton
7221  //make sure that there is a relative momentum to reshuffle the masses
7222  if(partner == -1){
7223  //grabbing closest parton before and after, if it exists
7224  int iprev = iPart-1; int inext = iPart+1;
7225  while(iprev >= 0){
7226  double m2 = 0.;
7227  if ((HH_partons[iprev].id() == 21) && (HH_partons[iprev].mass() < 2.*xmq + 0.001)){
7228  m2 = 2.*xmq + 0.001;
7229  } else if ((HH_partons[iprev].id() == 21) && (HH_partons[iprev].mass() >= 2.*xmq + 0.001)){
7230  m2 = HH_partons[iprev].mass();
7231  } else if(std::abs(HH_partons[iprev].id()) < 3) {
7232  m2 = xmq;
7233  } else if(std::abs(HH_partons[iprev].id()) == 3) {
7234  m2 = xms;
7235  } else if(std::abs(HH_partons[iprev].id()) == 4) {
7236  m2 = xmc;
7237  } else if(std::abs(HH_partons[iprev].id()) == 5) {
7238  m2 = xmb;
7239  }
7240  double pair_mass = std::sqrt((HH_partons[iPart].e() + HH_partons[iprev].e())*(HH_partons[iPart].e() + HH_partons[iprev].e())
7241  - (HH_partons[iPart].px() + HH_partons[iprev].px())*(HH_partons[iPart].px() + HH_partons[iprev].px())
7242  - (HH_partons[iPart].py() + HH_partons[iprev].py())*(HH_partons[iPart].py() + HH_partons[iprev].py())
7243  - (HH_partons[iPart].pz() + HH_partons[iprev].pz())*(HH_partons[iPart].pz() + HH_partons[iprev].pz()));
7244  double momentum_diff = (HH_partons[iPart].px()-HH_partons[iprev].px())*(HH_partons[iPart].px()-HH_partons[iprev].px())
7245  + (HH_partons[iPart].py()-HH_partons[iprev].py())*(HH_partons[iPart].py()-HH_partons[iprev].py())
7246  + (HH_partons[iPart].pz()-HH_partons[iprev].pz())*(HH_partons[iPart].pz()-HH_partons[iprev].pz());
7247  if((momentum_diff > 1e-6) && (pair_mass >= m1+m2) && (std::abs(HH_partons[iprev].id()) < 6 || HH_partons[iprev].id() == 21)){
7248  if(energy_loss_tracking > std::abs(pair_mass - m1 - m2)) {
7249  energy_loss_tracking = std::abs(pair_mass - m1 - m2);
7250  iPartnerCandidate = iprev;
7251  }
7252  break;
7253  }
7254  --iprev;
7255  }
7256  while(inext < HH_partons.num()){
7257  double m2 = 0.;
7258  if ((HH_partons[inext].id() == 21) && (HH_partons[inext].mass() < 2.*xmq + 0.001)){
7259  m2 = 2.*xmq + 0.001;
7260  } else if ((HH_partons[inext].id() == 21) && (HH_partons[inext].mass() >= 2.*xmq + 0.001)){
7261  m2 = HH_partons[inext].mass();
7262  } else if(std::abs(HH_partons[inext].id()) < 3) {
7263  m2 = xmq;
7264  } else if(std::abs(HH_partons[inext].id()) == 3) {
7265  m2 = xms;
7266  } else if(std::abs(HH_partons[inext].id()) == 4) {
7267  m2 = xmc;
7268  } else if(std::abs(HH_partons[inext].id()) == 5) {
7269  m2 = xmb;
7270  }
7271  double pair_mass = std::sqrt((HH_partons[iPart].e() + HH_partons[inext].e())*(HH_partons[iPart].e() + HH_partons[inext].e())
7272  - (HH_partons[iPart].px() + HH_partons[inext].px())*(HH_partons[iPart].px() + HH_partons[inext].px())
7273  - (HH_partons[iPart].py() + HH_partons[inext].py())*(HH_partons[iPart].py() + HH_partons[inext].py())
7274  - (HH_partons[iPart].pz() + HH_partons[inext].pz())*(HH_partons[iPart].pz() + HH_partons[inext].pz()));
7275  double momentum_diff = (HH_partons[iPart].px()-HH_partons[inext].px())*(HH_partons[iPart].px()-HH_partons[inext].px())
7276  + (HH_partons[iPart].py()-HH_partons[inext].py())*(HH_partons[iPart].py()-HH_partons[inext].py())
7277  + (HH_partons[iPart].pz()-HH_partons[inext].pz())*(HH_partons[iPart].pz()-HH_partons[inext].pz());
7278  if((momentum_diff > 1e-6) && (pair_mass >= m1+m2) && (std::abs(HH_partons[inext].id()) < 6 || HH_partons[inext].id() == 21)){
7279  if(energy_loss_tracking > std::abs(pair_mass - m1 - m2)) {
7280  energy_loss_tracking = std::abs(pair_mass - m1 - m2);
7281  iPartnerCandidate = inext;
7282  }
7283  break;
7284  }
7285  ++inext;
7286  }
7287 
7288  //if there is no closest before, then grab closest after
7289  //or if no closest after, then grab closest before
7290  //if both exist, grab the one that's closest, unless both are the same in which case grab the one after
7291  if(iprev < 0){partner = inext;}
7292  else if(inext >= HH_partons.num()){partner = iprev;}
7293  else{partner = (inext - iPart <= iPart - iprev) ? inext : iprev;}
7294 
7295  if((iPartnerCandidate >= HH_partons.num()) || (iPartnerCandidate < 0)){iPartnerCandidate = -1;}
7296  if((partner >= HH_partons.num()) || (partner < 0)) {partner = -1;}
7297  }
7298 
7299  //by now, a partner *must* have been chosen - unless there's only 1 parton in the event, which is BAD.
7300  //time to fix.
7301  //if somehow everything failed, just skip this parton and put it to its mass shell (here we have to accept the energy conservation violation)
7302  if(partner == -1 && iPartnerCandidate >= 0){
7303  partner = iPartnerCandidate;
7304  } else if(partner == -1 && iPartnerCandidate == -1) {
7305  HHparton parton = HH_partons[iPart];
7306  if(std::abs(parton.id()) < 6 && parton.mass() < pythia.particleData.m0(std::abs(parton.id()))) { // quark case
7307  parton.mass(pythia.particleData.m0(std::abs(parton.id())));
7308  parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7309  HH_partons[iPart] = parton;
7310  } else if(parton.id() == 21 && parton.mass() < 2.*xmq + 0.001) { // gluon case (pythia has m_g = 0.)
7311  parton.mass(2.*xmq + 0.001);
7312  parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7313  HH_partons[iPart] = parton;
7314  }
7315  continue;
7316  }
7317 
7318  //std::cout << "P1_before: " << iPart << ", " << HH_partons[iPart].id() << ", " << HH_partons[iPart].px() << ", " << HH_partons[iPart].py() << ", " << HH_partons[iPart].pz() << ", " << HH_partons[iPart].e() << ", " << HH_partons[iPart].mass() << "\n";
7319  //std::cout << "P2_before: " << partner << ", " << HH_partons[partner].id() << ", " << HH_partons[partner].px() << ", " << HH_partons[partner].py() << ", " << HH_partons[partner].pz() << ", " << HH_partons[partner].e() << ", " << HH_partons[partner].mass() << "\n";
7320 
7321  //Psys
7322  FourVector Psys;
7323  Psys.Set(HH_partons[iPart].px()+HH_partons[partner].px(),HH_partons[iPart].py()+HH_partons[partner].py(),HH_partons[iPart].pz()+HH_partons[partner].pz(),HH_partons[iPart].e()+HH_partons[partner].e());
7324 
7325  //CM velocity
7326  FourVector beta;
7327  beta.Set(Psys.x()/Psys.t(),Psys.y()/Psys.t(),Psys.z()/Psys.t(),0.);
7328  beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7329 
7330  //boosting into CM frame
7331  FourVector p_CM[2]; p_CM[0] = HH_partons[iPart].boost_P(beta); p_CM[1] = HH_partons[partner].boost_P(beta);
7332 
7333  //if E1 + E2 >= m1 + m2, shift momenta
7334  double m2 = 0.;
7335  if ((HH_partons[partner].id() == 21) && (HH_partons[partner].mass() < 2.*xmq + 0.001)){
7336  m2 = 2.*xmq + 0.001;
7337  } else if ((HH_partons[partner].id() == 21) && (HH_partons[partner].mass() >= 2.*xmq + 0.001)){
7338  m2 = HH_partons[partner].mass();
7339  } else if(std::abs(HH_partons[partner].id()) < 3) {
7340  m2 = xmq;
7341  } else if(std::abs(HH_partons[partner].id()) == 3) {
7342  m2 = xms;
7343  } else if(std::abs(HH_partons[partner].id()) == 4) {
7344  m2 = xmc;
7345  } else if(std::abs(HH_partons[partner].id()) == 5) {
7346  m2 = xmb;
7347  }
7348  double Etot = p_CM[0].t() + p_CM[1].t();
7349  if(Etot < m1 + m2 + 0.00001){Etot = m1 + m2 + 0.00001; /*eviol << Etot - (p_CM[0].t() + p_CM[1].t()) << "\n";*/}//can't shift, violating E/P cons.
7350  double E1 = Etot/2. + ((m1*m1)-(m2*m2))/(2.*Etot);
7351  double E2 = Etot/2. - ((m1*m1)-(m2*m2))/(2.*Etot);
7352  double pmag = sqrt(p_CM[0].x()*p_CM[0].x() + p_CM[0].y()*p_CM[0].y() + p_CM[0].z()*p_CM[0].z());
7353  double fac = sqrt(Etot*Etot/4. + ((m1*m1)-(m2*m2))*((m1*m1)-(m2*m2))/(4.*Etot*Etot) - ((m1*m1)+(m2*m2))/2.)/pmag;
7354  //std::cout << "Etot_orig = " << p_CM[0].t() + p_CM[1].t() << " Etot = " << Etot << " pmag = " << pmag << " fac = " << fac << std::endl;
7355 
7356  //rescaling in CM frame
7357  p_CM[0].Set(fac*p_CM[0].x(), fac*p_CM[0].y(), fac*p_CM[0].z(), E1);
7358  p_CM[1].Set(fac*p_CM[1].x(), fac*p_CM[1].y(), fac*p_CM[1].z(), E2);
7359 
7360  //boosting back and setting parton E,P to fixed values
7361  beta.Set(-beta.x(), -beta.y(), -beta.z(), 0.);
7362  beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7363  FourVector p_fin[2]; p_fin[0] = HHboost(beta, p_CM[0]); p_fin[1] = HHboost(beta, p_CM[1]);
7364  HH_partons[iPart].P(p_fin[0]); HH_partons[partner].P(p_fin[1]);
7365  HH_partons[iPart].mass(m1);
7366  HH_partons[partner].mass(m2);
7367 
7368  //std::cout << "P1_after: " << iPart << ", " << HH_partons[iPart].id() << ", " << HH_partons[iPart].px() << ", " << HH_partons[iPart].py() << ", " << HH_partons[iPart].pz() << ", " << HH_partons[iPart].e() << ", " << HH_partons[iPart].mass() << "\n";
7369  //std::cout << "P2_after: " << partner << ", " << HH_partons[partner].id() << ", " << HH_partons[partner].px() << ", " << HH_partons[partner].py() << ", " << HH_partons[partner].pz() << ", " << HH_partons[partner].e() << ", " << HH_partons[partner].mass() << "\n";
7370  }
7371 
7372  //calc. Etot after
7373  /*for(int iPart=0; iPart<HH_partons.num(); ++iPart){Eafter += HH_partons[iPart].e(); pTafter += HH_partons[iPart].pt();}
7374  echg << Eafter-Ebefore << "\n"; ptchg << pTafter-pTbefore << "\n";
7375  eviol.close(); echg.close(); ptchg.close();*/
7376 }
7377