27 using namespace Jetscape;
41 SetId(
"ColorlessHadronization");
51 std::string s = GetXMLElementText({
"JetHadronization",
"name"});
52 JSDEBUG << s <<
" to be initializied ...";
56 GetXMLElementDouble({
"JetHadronization",
"eCMforHadronization"});
59 take_recoil = GetXMLElementInt({
"JetHadronization",
"take_recoil"});
61 JSDEBUG <<
"Initialize ColorlessHadronization";
65 pythia.readString(
"Next:numberShowInfo = 0");
66 pythia.readString(
"Next:numberShowProcess = 0");
67 pythia.readString(
"Next:numberShowEvent = 0");
70 pythia.readString(
"ProcessLevel:all = off");
71 pythia.readString(
"PartonLevel:FSR=off");
74 std::string pythia_decays = GetXMLElementText({
"JetHadronization",
"pythia_decays"});
75 double tau0Max = 10.0;
76 double tau0Max_xml = GetXMLElementDouble({
"JetHadronization",
"tau0Max"});
77 if(tau0Max_xml >= 0){tau0Max = tau0Max_xml;}
78 else{
JSWARN <<
"tau0Max should be larger than 0. Set it to 10.";}
79 if(pythia_decays ==
"on"){
80 JSINFO <<
"Pythia decays are turned on for tau0Max < " << tau0Max;
81 pythia.readString(
"HadronLevel:Decay = on");
82 pythia.readString(
"ParticleDecays:limitTau0 = on");
83 pythia.readString(
"ParticleDecays:tau0Max = " +
std::to_string(tau0Max));
85 JSINFO <<
"Pythia decays are turned off";
86 pythia.readString(
"HadronLevel:Decay = off");
92 GetXMLElementText({
"JetHadronization",
"weak_decays"});
93 if (weak_decays ==
"off") {
94 JSINFO <<
"Hadron decays are turned off.";
95 JSWARN <<
"This parameter will be depracted at some point. Use 'pythia_decays' instead.\nOverwriting 'pythia_decays'.";
96 pythia.readString(
"HadronLevel:Decay = off");
97 }
else if(weak_decays ==
"on") {
98 JSINFO <<
"Hadron decays inside a range of 10 mm/c are turned on.";
99 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.";
100 pythia.readString(
"HadronLevel:Decay = on");
101 pythia.readString(
"ParticleDecays:limitTau0 = on");
102 pythia.readString(
"ParticleDecays:tau0Max = 10.0");
105 std::stringstream
lines;
106 lines << GetXMLElementText({
"JetHadronization",
"LinesToRead"},
false);
107 while (std::getline(lines, s,
'\n')) {
108 if (s.find_first_not_of(
" \t\v\f\r") == s.npos)
110 JSINFO <<
"Also reading in: " <<
s;
111 pythia.readString(s);
115 ZeroOneDistribution = std::uniform_real_distribution<double> { 0.0, 1.0 };
125 f->WriteComment(
"Hadronization Module : " + GetId());
131 VERBOSE(1) <<
"Start Hadronizing using PYTHIA Lund string model (does NOT "
132 "use color flow, needs to be tested)...";
133 Event &
event = pythia.event;
134 ParticleData &pdt = pythia.particleData;
137 for (
int want_pos = 1; want_pos >= 0; --want_pos) {
140 if (!take_recoil && want_pos == 0)
144 double random_direction = ZeroOneDistribution(*GetMt19937Generator());
145 if (random_direction>0.5) {
146 random_direction = 1.0;
148 random_direction = -1.0;
153 double rempz = random_direction*p_fake;
154 double reme = std::sqrt(std::pow(rempx, 2.) + std::pow(rempy, 2.) +
155 std::pow(rempz, 2.));
158 vector<shared_ptr<Parton>> pIn;
159 vector<vector<Parton>> shower_in;
160 for (
unsigned int ishower = 0; ishower <
shower.size(); ++ishower) {
162 for (
unsigned int ipart = 0; ipart <
shower.at(ishower).size(); ++ipart) {
163 p_sh.push_back(*(
shower[ishower][ipart]));
165 shower_in.push_back(p_sh);
167 for (
unsigned int ishower = 0; ishower < shower_in.size(); ++ishower) {
168 for (
unsigned int ipart = 0; ipart < shower_in[ishower].size(); ++ipart) {
171 if (take_recoil && shower_in[ishower][ipart].pstat() == 1) {
172 pIn.push_back(make_shared<Parton>(shower_in[ishower][ipart]));
174 if (shower_in[ishower][ipart].pstat() == 0) {
175 pIn.push_back(make_shared<Parton>(shower_in[ishower][ipart]));
177 if (shower_in[ishower][ipart].pstat() == 22) {
178 pIn.push_back(make_shared<Parton>(shower_in[ishower][ipart]));
181 if (take_recoil && shower_in[ishower][ipart].pstat() == -1 &&
183 pIn.push_back(make_shared<Parton>(shower_in[ishower][ipart]));
186 JSDEBUG <<
"Shower#" << ishower + 1
187 <<
". Number of partons to hadronize so far: " << pIn.size();
190 VERBOSE(1) <<
"# Positive Partons to hadronize: " << pIn.size();
192 VERBOSE(1) <<
"# Negative Partons to hadronize: " << pIn.size();
198 int col[pIn.size() + 2], acol[pIn.size() + 2], isdone[pIn.size() + 2];
199 memset(col, 0, (pIn.size() + 2) *
sizeof(
int)),
200 memset(acol, 0, (pIn.size() + 2) *
sizeof(
int)),
201 memset(isdone, 0, (pIn.size() + 2) *
sizeof(
int));
205 int isquark[pIn.size() + 2];
206 memset(isquark, 0, (pIn.size() + 2) *
sizeof(
int));
207 for (
unsigned int ipart = 0; ipart < pIn.size(); ++ipart) {
208 if (abs(pIn[ipart]->
pid()) <= 6) {
209 isquark[nquarks] = ipart;
213 JSDEBUG <<
"#Quarks = " << nquarks;
216 int nstrings = max(
int(
double(nquarks) / 2. + 0.6), 1);
217 JSDEBUG <<
"#Strings = " << nstrings;
221 int one_end[nstrings], two_end[nstrings];
226 pIn.push_back(std::make_shared<Parton>(0, 1, 0, p1, x1));
227 isquark[nquarks] = pIn.size() - 1;
229 isdone[pIn.size() - 1] = 1;
230 one_end[0] = pIn.size() - 1;
231 VERBOSE(1) <<
"Attached quark remnant flying down +Pz beam";
235 pIn.push_back(std::make_shared<Parton>(0, 1, 0, p2, x2));
236 isquark[nquarks] = pIn.size() - 1;
238 isdone[pIn.size() - 1] = 1;
239 two_end[istring] = pIn.size() - 1;
240 VERBOSE(1) <<
"Attached quark remnant flying down -Pz beam";
244 for (
unsigned int iquark = 0; iquark < nquarks; iquark++) {
245 if (isdone[isquark[iquark]] == 0) {
246 isdone[isquark[iquark]] = 1;
247 one_end[istring] = isquark[iquark];
248 double min_delR = 10000.;
250 for (
unsigned int jquark = 0; jquark < nquarks; jquark++) {
251 if (iquark == jquark)
253 int d_jquark = isquark[jquark];
254 if (isdone[d_jquark] == 0) {
255 fjcore::PseudoJet pf(pIn[d_jquark]->px(), pIn[d_jquark]->py(),
256 pIn[d_jquark]->pz(), pIn[d_jquark]->
e());
257 double delR = pIn[isquark[iquark]]->delta_R(pf);
259 min_delR = delR, partner = jquark;
263 isdone[isquark[partner]] = 1;
264 two_end[istring] = isquark[partner];
269 pIn.push_back(std::make_shared<Parton>(0, 1, 0, p, x));
270 isquark[nquarks] = pIn.size() - 1;
272 isdone[pIn.size() - 1] = 1;
273 two_end[istring] = pIn.size() - 1;
274 VERBOSE(1) <<
"Attached quark remnant flying down +Pz beam";
280 int my_string[pIn.size()];
281 memset(my_string, 0, pIn.size() *
sizeof(int));
282 for (
unsigned int ipart = 0; ipart < pIn.size(); ++ipart) {
283 if (pIn[ipart]->
pid() == 21) {
284 double min_delR = 100000.;
285 for (
int ns = 0;
ns < nstrings;
ns++) {
286 int fq = one_end[
ns];
287 int sq = two_end[
ns];
288 fjcore::PseudoJet pfq(pIn[fq]->px(), pIn[fq]->py(), pIn[fq]->pz(),
290 double f_delR = pIn[ipart]->delta_R(pfq);
291 fjcore::PseudoJet psq(pIn[sq]->px(), pIn[sq]->py(), pIn[sq]->pz(),
293 double s_delR = pIn[ipart]->delta_R(psq);
294 double delR = (f_delR + s_delR) / 2.;
296 my_string[ipart] =
ns, min_delR = delR;
303 for (
int ns = 0;
ns < nstrings;
ns++) {
304 int tquark = one_end[
ns];
305 if (pIn[tquark]->
pid() > 0)
306 col[tquark] = lab_col;
308 acol[tquark] = lab_col;
314 double min_delR = 100000.;
316 for (
unsigned int ipart = 0; ipart < pIn.size(); ++ipart) {
317 if (pIn[ipart]->
pid() == 21 && isdone[ipart] == 0 &&
318 my_string[ipart] ==
ns) {
320 fjcore::PseudoJet pf(pIn[ipart]->px(), pIn[ipart]->py(),
321 pIn[ipart]->pz(), pIn[ipart]->
e());
322 double delR = pIn[link]->delta_R(pf);
324 min_delR = delR, next_link = ipart;
328 isdone[next_link] = 1;
329 if (col[link] == lab_col - 1)
330 col[next_link] = lab_col, acol[next_link] = lab_col - 1;
332 col[next_link] = lab_col - 1, acol[next_link] = lab_col;
334 JSDEBUG <<
" Linked parton= " << next_link;
337 }
while (changes == 1);
339 if (col[link] == lab_col - 1)
340 col[two_end[
ns]] = 0, acol[two_end[
ns]] = lab_col - 1;
342 col[two_end[
ns]] = lab_col - 1, acol[two_end[
ns]] = 0;
345 for (
int iq = 0; iq < nquarks; ++iq) {
346 if (col[isquark[iq]] != 0) {
347 if (pIn[isquark[iq]]->
pid() < 0)
348 pIn[isquark[iq]]->set_id(-pIn[isquark[iq]]->
pid());
350 if (pIn[isquark[iq]]->
pid() > 0)
351 pIn[isquark[iq]]->set_id(-pIn[isquark[iq]]->
pid());
370 for (
unsigned int ipart = 0; ipart < pIn.size(); ++ipart) {
371 double px = pIn[ipart]->px();
372 double py = pIn[ipart]->py();
373 double pz = pIn[ipart]->pz();
374 double ee = pIn[ipart]->e();
375 for (
unsigned int j = ipart + 1;
j < pIn.size();
j++) {
376 double p2x = pIn[
j]->px();
377 double p2y = pIn[
j]->py();
378 double p2z = pIn[
j]->pz();
379 double e2e = pIn[
j]->e();
382 sqrt(pow(px - p2x, 2) + pow(py - p2y, 2) + pow(pz - p2z, 2));
385 if ((pz >= 0) && (p2z >= 0)) {
387 pIn[ipart]->reset_momentum(px, py, pz + f * Lambda_QCD,
389 2 * pz * f * Lambda_QCD +
390 f * Lambda_QCD * f * Lambda_QCD));
392 pIn[
j]->reset_momentum(p2x, p2y, p2z + f * Lambda_QCD,
393 sqrt(e2e * e2e + 2 * p2z * f * Lambda_QCD +
394 f * Lambda_QCD * f * Lambda_QCD));
395 }
else if ((pz >= 0) && (p2z < 0)) {
396 if (abs(pz) >= abs(p2z)) {
397 pIn[ipart]->reset_momentum(px, py, pz + f * Lambda_QCD,
399 2 * pz * f * Lambda_QCD +
400 f * Lambda_QCD * f * Lambda_QCD));
402 pIn[
j]->reset_momentum(p2x, p2y, p2z - f * Lambda_QCD,
403 sqrt(e2e * e2e - 2 * p2z * f * Lambda_QCD +
404 f * Lambda_QCD * f * Lambda_QCD));
405 }
else if ((pz < 0) && (p2z >= 0)) {
406 if (abs(pz) >= abs(p2z)) {
407 pIn[ipart]->reset_momentum(px, py, pz - f * Lambda_QCD,
409 2 * pz * f * Lambda_QCD +
410 f * Lambda_QCD * f * Lambda_QCD));
412 pIn[
j]->reset_momentum(p2x, p2y, p2z + f * Lambda_QCD,
413 sqrt(e2e * e2e + 2 * p2z * f * Lambda_QCD +
414 f * Lambda_QCD * f * Lambda_QCD));
416 if (abs(pz) >= abs(p2z)) {
417 pIn[ipart]->reset_momentum(px, py, pz - f * Lambda_QCD,
419 2 * pz * f * Lambda_QCD +
420 f * Lambda_QCD * f * Lambda_QCD));
422 pIn[
j]->reset_momentum(p2x, p2y, p2z - f * Lambda_QCD,
423 sqrt(e2e * e2e - 2 * p2z * f * Lambda_QCD +
424 f * Lambda_QCD * f * Lambda_QCD));
432 for (
unsigned int ipart = 0; ipart < pIn.size(); ++ipart) {
433 int ide = pIn[ipart]->pid();
434 double px = pIn[ipart]->px();
435 double py = pIn[ipart]->py();
436 double pz = pIn[ipart]->pz();
437 double ee = pIn[ipart]->e();
438 double mm = pdt.m0(
int(ide));
439 ee = std::sqrt(px * px + py * py + pz * pz + mm * mm);
440 if (col[ipart] == 0 && acol[ipart] == 0 && (ide == 21 || abs(ide) <= 6)) {
441 JSINFO <<
"Stopping because of colorless parton trying to be "
442 "introduced in PYTHIA string";
445 event.append(
int(ide), 23, col[ipart], acol[ipart], px, py, pz, ee, mm);
449 for (
unsigned int ipart = 0; ipart <
event.size(); ++ipart) {
450 if (
event[ipart].isFinal()) {
451 int ide = pythia.event[ipart].id();
452 FourVector p(pythia.event[ipart].px(), pythia.event[ipart].py(),
453 pythia.event[ipart].pz(), pythia.event[ipart].e());
457 std::make_shared<Hadron>(
Hadron(0, ide, 0,
p, x)));
460 std::make_shared<Hadron>(
Hadron(0, ide, -1,
p, x)));
466 VERBOSE(1) <<
"#Showers hadronized together: " <<
shower.size()
467 <<
". There are " << hOut.size() <<
" hadrons and "
468 << pOut.size() <<
" partons after PYTHIA Hadronization";