20 double gluon_beta,
double gluon_pmin,
21 double quark_alpha,
double quark_beta,
22 double strange_supp,
double diquark_supp,
23 double sigma_perp,
double leading_frag_mean,
24 double leading_frag_width,
double stringz_a,
25 double stringz_b,
double string_sigma_T,
26 double factor_t_form,
bool use_yoyo_model,
27 double prob_proton_to_d_uu)
28 : pmin_gluon_lightcone_(gluon_pmin),
29 pow_fgluon_beta_(gluon_beta),
30 pow_fquark_alpha_(quark_alpha),
31 pow_fquark_beta_(quark_beta),
32 sigma_qperp_(sigma_perp),
33 leading_frag_mean_(leading_frag_mean),
34 leading_frag_width_(leading_frag_width),
35 kappa_tension_string_(string_tension),
36 additional_xsec_supp_(0.7),
37 time_formation_const_(time_formation),
38 soft_t_form_(factor_t_form),
40 use_yoyo_model_(use_yoyo_model),
41 prob_proton_to_d_uu_(prob_proton_to_d_uu) {
43 pythia_parton_ = make_unique<Pythia8::Pythia>(PYTHIA_XML_DIR,
false);
50 stringz_a, stringz_b, string_sigma_T);
53 pythia_hadron_ = make_unique<Pythia8::Pythia>(PYTHIA_XML_DIR,
false);
57 stringz_a, stringz_b, string_sigma_T);
68 for (
int imu = 0; imu < 3; imu++) {
77 double diquark_supp,
double stringz_a,
79 double string_sigma_T) {
81 pythia_in->readString(
"ParticleData:modeBreitWigner = 4");
84 pythia_in->readString(
"MultipartonInteractions:pTmin = 1.5");
85 pythia_in->readString(
"MultipartonInteractions:nSample = 10000");
87 pythia_in->readString(
"StringPT:sigma = " + std::to_string(string_sigma_T));
89 pythia_in->readString(
"StringFlav:probQQtoQ = " +
90 std::to_string(diquark_supp));
92 pythia_in->readString(
"StringFlav:probStoUD = " +
93 std::to_string(strange_supp));
95 pythia_in->readString(
"StringZ:aLund = " + std::to_string(stringz_a));
96 pythia_in->readString(
"StringZ:bLund = " + std::to_string(stringz_b));
99 pythia_in->readString(
"PDF:pSet = 13");
100 pythia_in->readString(
"PDF:pSetB = 13");
101 pythia_in->readString(
"PDF:piSet = 1");
102 pythia_in->readString(
"PDF:piSetB = 1");
103 pythia_in->readString(
"Beams:idA = 2212");
104 pythia_in->readString(
"Beams:idB = 2212");
105 pythia_in->readString(
"Beams:eCM = 10.");
108 pythia_in->readString(
"Random:setSeed = on");
110 pythia_in->readString(
"Print:quiet = on");
112 pythia_in->readString(
"HadronLevel:Decay = off");
115 int pdgid = ptype.pdgcode().get_decimal();
116 double mass_pole = ptype.mass();
117 double width_pole = ptype.width_at_pole();
119 if (pythia_in->particleData.isParticle(pdgid)) {
121 pythia_in->particleData.m0(pdgid, mass_pole);
122 pythia_in->particleData.mWidth(pdgid, width_pole);
123 }
else if (pdgid == 310 || pdgid == 130) {
125 pythia_in->particleData.m0(pdgid,
kaon_mass);
126 pythia_in->particleData.mWidth(pdgid, 0.);
131 pythia_in->readString(
"Check:epTolErr = 1e-6");
132 pythia_in->readString(
"Check:epTolWarn = 1e-8");
141 double p_pos_tot = 0.0, p_neg_tot = 0.0;
145 bstring += data.pdgcode().baryon_number();
147 const double pparallel = data.momentum().threevec() * evecLong;
148 p_pos_tot += (data.momentum().x0() + pparallel) /
sqrt2_;
149 p_neg_tot += (data.momentum().x0() - pparallel) /
sqrt2_;
158 std::vector<double> xvertex_pos, xvertex_neg;
159 xvertex_pos.resize(nfrag + 1);
160 xvertex_neg.resize(nfrag + 1);
166 for (
int i = 0; i < nfrag; i++) {
167 const double pparallel =
168 intermediate_particles[i].momentum().threevec() * evecLong;
173 (intermediate_particles[i].momentum().x0() + pparallel) /
177 const int ineg = nfrag - i - 1;
179 xvertex_neg[ineg + 1] -
180 (intermediate_particles[ineg].momentum().x0() - pparallel) /
189 for (
int i = 0; i < nfrag; i++) {
192 intermediate_particles[i].momentum().
LorentzBoost(-vstring);
193 intermediate_particles[i].set_4momentum(momentum);
197 double t_prod = (xvertex_pos[i] + xvertex_neg[i + 1]) /
sqrt2_;
199 t_prod, evecLong * (xvertex_pos[i] - xvertex_neg[i + 1]) /
sqrt2_);
202 fragment_position = fragment_position.
LorentzBoost(-vstring);
204 intermediate_particles[i].set_slow_formation_times(
209 double gamma_factor = 1.0 / std::sqrt(1 - (v_calc).sqr());
210 intermediate_particles[i].set_slow_formation_times(
224 massA_ = incoming[0].effective_mass();
225 massB_ = incoming[1].effective_mass();
227 plab_[0] = incoming[0].momentum();
228 plab_[1] = incoming[1].momentum();
261 double QTrn, QTrx, QTry;
262 double pabscomHX_sqr, massX;
271 if (mstrMin > mstrMax) {
277 QTrn = std::sqrt(QTrx * QTrx + QTry * QTry);
284 const bool foundPabsX = pabscomHX_sqr > QTrn * QTrn;
289 double sign_direction = is_AB_to_AX ? 1. : -1.;
293 (
evecBasisAB_[0] * std::sqrt(pabscomHX_sqr - QTrn * QTrn) +
295 const FourVector pstrHcom(std::sqrt(pabscomHX_sqr + massH * massH),
297 const FourVector pstrXcom(std::sqrt(pabscomHX_sqr + massX * massX),
305 is_AB_to_AX ?
pcom_[1].threevec() :
pcom_[0].threevec();
310 ParticleList new_intermediate_particles;
311 bool separate_fragment_baryon =
false;
313 fragment_string(idqX1, idqX2, massX, evec,
true, separate_fragment_baryon,
314 new_intermediate_particles);
335 const std::array<std::array<int, 2>, 2> &quarks,
336 const std::array<FourVector, 2> &pstr_com, std::array<double, 2> &m_str,
337 std::array<ThreeVector, 2> &evec_str) {
338 std::array<bool, 2> found_mass;
339 for (
int i = 0; i < 2; i++) {
340 found_mass[i] =
false;
342 m_str[i] = pstr_com[i].sqr();
343 m_str[i] = (m_str[i] > 0.) ? std::sqrt(m_str[i]) : 0.;
344 const double threshold =
pythia_hadron_->particleData.m0(quarks[i][0]) +
347 if (m_str[i] > threshold) {
348 found_mass[i] =
true;
364 evec_str[i] = prs.threevec() / prs.threevec().abs();
368 return found_mass[0] && found_mass[1];
372 const std::array<std::array<int, 2>, 2> &quarks,
373 const std::array<FourVector, 2> &pstr_com,
374 const std::array<double, 2> &m_str,
375 const std::array<ThreeVector, 2> &evec_str,
bool flip_string_ends,
376 bool separate_fragment_baryon) {
377 const std::array<FourVector, 2> ustr_com = {pstr_com[0] / m_str[0],
378 pstr_com[1] / m_str[1]};
379 for (
int i = 0; i < 2; i++) {
380 ParticleList new_intermediate_particles;
385 int nfrag =
fragment_string(quarks[i][0], quarks[i][1], m_str[i], evec,
386 flip_string_ends, separate_fragment_baryon,
387 new_intermediate_particles);
410 std::array<std::array<int, 2>, 2> quarks;
411 std::array<FourVector, 2> pstr_com;
412 std::array<double, 2> m_str;
413 std::array<ThreeVector, 2> evec_str;
423 const double xfracA =
425 const double xfracB =
430 const double QTrn = std::sqrt(QTrx * QTrx + QTry * QTry);
432 const double QPos = -QTrn * QTrn / (2. * xfracB *
PNegB_);
433 const double QNeg = QTrn * QTrn / (2. * xfracA *
PPosA_);
445 const bool found_masses =
450 const bool flip_string_ends =
true;
451 const bool separate_fragment_baryon =
false;
454 flip_string_ends, separate_fragment_baryon);
465 std::array<std::array<int, 2>, 2> quarks;
466 std::array<FourVector, 2> pstr_com;
467 std::array<double, 2> m_str;
468 std::array<ThreeVector, 2> evec_str;
471 int idqA1, idqA2, idqB1, idqB2;
475 const int bar_a =
PDGcodes_[0].baryon_number(),
478 (bar_a == 0 && bar_b == 1) ||
479 (bar_a == 0 && bar_b == 0)) {
480 quarks[0][0] = idqB1;
481 quarks[0][1] = idqA2;
482 quarks[1][0] = idqA1;
483 quarks[1][1] = idqB2;
484 }
else if (((bar_a == 0) && (bar_b == -1)) ||
487 quarks[0][0] = idqA1;
488 quarks[0][1] = idqB2;
489 quarks[1][0] = idqB1;
490 quarks[1][1] = idqA2;
492 std::stringstream ss;
493 ss <<
" StringProcess::next_NDiff : baryonA = " << bar_a
494 <<
", baryonB = " << bar_b;
495 throw std::runtime_error(ss.str());
503 const double QTrn = std::sqrt(QTrx * QTrx + QTry * QTry);
505 const double QPos = -QTrn * QTrn / (2. * xfracB *
PNegB_);
506 const double QNeg = QTrn * QTrn / (2. * xfracA *
PPosA_);
507 const double dPPos = -xfracA *
PPosA_ - QPos;
508 const double dPNeg = xfracB *
PNegB_ - QNeg;
515 m_str[0] = pstr_com[0].sqr();
522 const bool found_masses =
527 const bool flip_string_ends =
false;
528 const bool separate_fragment_baryon =
true;
531 flip_string_ends, separate_fragment_baryon);
537 const auto &log = logger<LogArea::Pythia>();
544 std::array<int, 2> pdg_for_pythia;
545 std::array<std::array<int, 5>, 2> excess_quark;
546 std::array<std::array<int, 5>, 2> excess_antiq;
547 for (
int i = 0; i < 2; i++) {
548 for (
int j = 0; j < 5; j++) {
549 excess_quark[i][j] = 0;
550 excess_antiq[i][j] = 0;
555 log.debug(
" incoming particle ", i,
" : ",
PDGcodes_[i],
556 " is mapped onto ", pdg_for_pythia[i]);
558 PdgCode pdgcode_for_pythia(std::to_string(pdg_for_pythia[i]));
563 log.debug(
" excess_quark[", i,
"] = (", excess_quark[i][0],
", ",
564 excess_quark[i][1],
", ", excess_quark[i][2],
", ",
565 excess_quark[i][3],
", ", excess_quark[i][4],
")");
566 log.debug(
" excess_antiq[", i,
"] = (", excess_antiq[i][0],
", ",
567 excess_antiq[i][1],
", ", excess_antiq[i][2],
", ",
568 excess_antiq[i][3],
", ", excess_antiq[i][4],
")");
575 bool same_initial_state = previous_idA == pdg_for_pythia[0] &&
576 previous_idB == pdg_for_pythia[1] &&
587 log.debug(
"Pythia initialized with ", pdg_for_pythia[0],
" + ",
588 pdg_for_pythia[1],
" at CM energy [GeV] ",
sqrtsAB_);
590 throw std::runtime_error(
"Pythia failed to initialize.");
599 log.debug(
"pythia_parton_ : rndm is initialized with seed ", seed_new);
603 log.debug(
"Pythia hard event created");
605 log.debug(
"Pythia final state computed, success = ", final_state_success);
606 if (!final_state_success) {
610 ParticleList new_intermediate_particles;
611 ParticleList new_non_hadron_particles;
613 Pythia8::Vec4 pSum = 0.;
636 std::array<int, 3> col;
637 for (
int j = 0; j < 3; j++) {
650 bool correct_constituents =
652 if (!correct_constituents) {
653 log.debug(
"failed to find correct partonic constituents.");
659 while (ipart < npart) {
664 log.debug(
"PDG ID from Pythia: ", pdgid);
666 log.debug(
"4-momentum from Pythia: ", momentum);
670 log.warn(
"PDG ID ", pdgid,
671 " does not exist in ParticleType - start over.");
672 final_state_success =
false;
681 bool hadronize_success =
false;
682 bool find_forward_string =
true;
683 log.debug(
"Hard non-diff: partonic process gives ",
690 log.debug(
" Dummy event in hard string routine failed.");
691 hadronize_success =
false;
708 log.debug(
"Pythia hadronized, success = ", hadronize_success);
710 new_intermediate_particles.clear();
711 if (hadronize_success) {
712 for (
int i = 0; i < event_hadron.size(); i++) {
713 if (event_hadron[i].isFinal()) {
714 int pythia_id = event_hadron[i].id();
715 log.debug(
"PDG ID from Pythia: ", pythia_id);
728 log.debug(
"4-momentum from Pythia: ", momentum);
729 log.debug(
"appending the particle ", pythia_id,
730 " to the intermediate particle list.");
731 bool found_ptype =
false;
732 if (event_hadron[i].isHadron()) {
734 new_intermediate_particles);
737 new_non_hadron_particles);
740 log.warn(
"PDG ID ", pythia_id,
741 " does not exist in ParticleType - start over.");
742 hadronize_success =
false;
750 if (!hadronize_success) {
759 find_forward_string = !find_forward_string;
762 if (hadronize_success) {
765 data.set_cross_section_scaling_factor(1.);
773 return hadronize_success;
778 std::array<int, 5> &excess_quark,
779 std::array<int, 5> &excess_antiq) {
782 std::array<int, 3> qcontent_actual = pdg_actual.
quark_content();
783 std::array<int, 3> qcontent_mapped = pdg_mapped.
quark_content();
785 excess_quark = {0, 0, 0, 0, 0};
786 excess_antiq = {0, 0, 0, 0, 0};
787 for (
int i = 0; i < 3; i++) {
788 if (qcontent_actual[i] > 0) {
789 int j = qcontent_actual[i] - 1;
790 excess_quark[j] += 1;
793 if (qcontent_mapped[i] > 0) {
794 int j = qcontent_mapped[i] - 1;
795 excess_quark[j] -= 1;
798 if (qcontent_actual[i] < 0) {
799 int j = std::abs(qcontent_actual[i]) - 1;
800 excess_antiq[j] += 1;
803 if (qcontent_mapped[i] < 0) {
804 int j = std::abs(qcontent_mapped[i]) - 1;
805 excess_antiq[j] -= 1;
811 Pythia8::Particle &particle, std::array<int, 5> &excess_constituent) {
812 const auto &log = logger<LogArea::Pythia>();
815 if (!particle.isQuark() && !particle.isDiquark()) {
820 const std::array<int, 5> excess_null = {0, 0, 0, 0, 0};
821 if (excess_constituent == excess_null) {
826 std::array<int, 2> pdgid = {0, 0};
829 if (particle.isQuark()) {
831 pdgid[0] = particle.id();
832 }
else if (particle.isDiquark()) {
837 for (
int iq = 0; iq < nq; iq++) {
838 int jq = std::abs(pdgid[iq]) - 1;
840 std::vector<int> k_found;
843 if (excess_constituent[jq] < 0) {
844 for (
int k = 0; k < 5; k++) {
846 if (k != jq && excess_constituent[k] > 0) {
847 k_found.push_back(k);
853 if (k_found.size() > 0) {
856 k_select = k_found[l];
859 pdgid[iq] = pdgid[iq] > 0 ? k_select + 1 : -(k_select + 1);
860 excess_constituent[jq] += 1;
861 excess_constituent[k_select] -= 1;
866 if (particle.isQuark()) {
867 pdgid_new = pdgid[0];
868 }
else if (particle.isDiquark()) {
869 if (std::abs(pdgid[0]) < std::abs(pdgid[1])) {
870 std::swap(pdgid[0], pdgid[1]);
873 pdgid_new = std::abs(pdgid[0]) * 1000 + std::abs(pdgid[1]) * 100;
874 if (std::abs(pdgid[0]) == std::abs(pdgid[1])) {
877 pdgid_new += spin_deg;
880 if (particle.id() < 0) {
884 log.debug(
" parton id = ", particle.id(),
" is converted to ", pdgid_new);
887 Pythia8::Vec4 pquark = particle.p();
889 double e_new = std::sqrt(mass_new * mass_new + pquark.pAbs() * pquark.pAbs());
891 particle.id(pdgid_new);
893 particle.m(mass_new);
897 Pythia8::Event &event_intermediate, std::array<int, 5> &nquark_total,
898 std::array<int, 5> &nantiq_total) {
899 for (
int iflav = 0; iflav < 5; iflav++) {
900 nquark_total[iflav] = 0;
901 nantiq_total[iflav] = 0;
904 for (
int ip = 1; ip < event_intermediate.size(); ip++) {
905 if (!event_intermediate[ip].isFinal()) {
908 const int pdgid = event_intermediate[ip].id();
911 for (
int iflav = 0; iflav < 5; iflav++) {
912 nquark_total[iflav] +=
917 for (
int iflav = 0; iflav < 5; iflav++) {
918 nantiq_total[iflav] +=
pythia_hadron_->particleData.nQuarksInCode(
919 std::abs(pdgid), iflav + 1);
926 Pythia8::Event &event_intermediate, std::array<int, 5> &nquark_total,
927 std::array<int, 5> &nantiq_total,
bool sign_constituent,
928 std::array<std::array<int, 5>, 2> &excess_constituent) {
929 const auto &log = logger<LogArea::Pythia>();
931 Pythia8::Vec4 pSum = event_intermediate[0].p();
937 for (
int iflav = 0; iflav < 5; iflav++) {
944 excess_constituent[0][iflav] + excess_constituent[1][iflav];
945 if (sign_constituent) {
946 nquark_final += nquark_total[iflav];
948 nquark_final += nantiq_total[iflav];
953 bool enough_quark = nquark_final >= 0;
957 log.debug(
" not enough constituents with flavor ", iflav + 1,
958 " : try to split a gluon to qqbar.");
959 for (
int ic = 0; ic < std::abs(nquark_final); ic++) {
963 if (excess_constituent[0][iflav] < 0) {
972 for (
int ip = 2; ip < event_intermediate.size(); ip++) {
973 if (!event_intermediate[ip].isFinal() ||
974 !event_intermediate[ip].isGluon()) {
978 const double y_gluon_current = event_intermediate[ip].y();
979 const double y_gluon_forward = event_intermediate[iforward].y();
980 if ((ih_mod == 0 && y_gluon_current > y_gluon_forward) ||
981 (ih_mod == 1 && y_gluon_current < y_gluon_forward)) {
986 if (!event_intermediate[iforward].isGluon()) {
987 log.debug(
"There is no gluon to split into qqbar.");
992 Pythia8::Vec4 pgluon = event_intermediate[iforward].p();
994 const int pdgid = iflav + 1;
996 const int status = event_intermediate[iforward].status();
1000 const int col = event_intermediate[iforward].col();
1001 const int acol = event_intermediate[iforward].acol();
1004 std::array<double, 2> px_quark;
1005 std::array<double, 2> py_quark;
1006 std::array<double, 2> pz_quark;
1008 std::array<double, 2> e_quark;
1010 std::array<Pythia8::Vec4, 2> pquark;
1012 const double sigma_qt_frag =
pythia_hadron_->parm(
"StringPT:sigma");
1017 for (
int isign = 0; isign < 2; isign++) {
1021 px_quark[isign] = 0.5 * pgluon.px() + (isign == 0 ? 1. : -1.) * qx;
1022 py_quark[isign] = 0.5 * pgluon.py() + (isign == 0 ? 1. : -1.) * qy;
1023 pz_quark[isign] = 0.5 * pgluon.pz();
1025 std::sqrt(mass * mass + px_quark[isign] * px_quark[isign] +
1026 py_quark[isign] * py_quark[isign] +
1027 pz_quark[isign] * pz_quark[isign]);
1028 pquark[isign] = Pythia8::Vec4(px_quark[isign], py_quark[isign],
1029 pz_quark[isign], e_quark[isign]);
1034 pSum += pquark[0] + pquark[1] - pgluon;
1036 event_intermediate.append(pdgid, status, col, 0, pquark[0], mass);
1037 event_intermediate.append(-pdgid, status, 0, acol, pquark[1], mass);
1039 event_intermediate.remove(iforward, iforward);
1041 log.debug(
" gluon at iforward = ", iforward,
" is splitted into ",
1042 pdgid,
",", -pdgid,
" qqbar pair.");
1045 nquark_total[iflav] += 1;
1046 nantiq_total[iflav] += 1;
1053 event_intermediate[0].p(pSum);
1054 event_intermediate[0].m(pSum.mCalc());
1060 std::array<int, 5> &nquark_total,
1061 std::array<std::array<int, 5>, 2> &excess_quark,
1062 std::array<std::array<int, 5>, 2> &excess_antiq) {
1063 const auto &log = logger<LogArea::Pythia>();
1065 for (
int iflav = 0; iflav < 5; iflav++) {
1072 nquark_total[iflav] + excess_quark[0][iflav] + excess_quark[1][iflav];
1076 bool enough_quark = nquark_final >= 0;
1078 if (!enough_quark) {
1079 log.debug(
" not enough constituents with flavor ", iflav + 1,
1080 " : try to modify excess of constituents.");
1081 for (
int ic = 0; ic < std::abs(nquark_final); ic++) {
1085 if (excess_quark[0][iflav] < 0) {
1093 excess_quark[ih_mod][iflav] += 1;
1094 excess_antiq[ih_mod][iflav] += 1;
1101 for (
int jflav = 0; jflav < 5; jflav++) {
1103 if (jflav != iflav && excess_quark[ih_mod][jflav] > 0) {
1106 excess_quark[ih_mod][jflav] -= 1;
1107 excess_antiq[ih_mod][jflav] -= 1;
1119 Pythia8::Event &event_intermediate,
1120 std::array<std::array<int, 5>, 2> &excess_quark,
1121 std::array<std::array<int, 5>, 2> &excess_antiq) {
1122 const auto &log = logger<LogArea::Pythia>();
1124 Pythia8::Vec4 pSum = event_intermediate[0].p();
1125 const double energy_init = pSum.e();
1126 log.debug(
" initial total energy [GeV] : ", energy_init);
1129 std::array<int, 5> nquark_total;
1130 std::array<int, 5> nantiq_total;
1135 event_intermediate, nquark_total, nantiq_total,
true, excess_quark);
1137 event_intermediate, nquark_total, nantiq_total,
false, excess_antiq);
1141 if (!split_for_quark || !split_for_antiq) {
1147 for (
int iflav = 0; iflav < 5; iflav++) {
1148 if (nquark_total[iflav] + excess_quark[0][iflav] + excess_quark[1][iflav] <
1150 log.debug(
"Not enough quark constituents of flavor ", iflav + 1);
1154 if (nantiq_total[iflav] + excess_antiq[0][iflav] + excess_antiq[1][iflav] <
1156 log.debug(
"Not enough antiquark constituents of flavor ", -(iflav + 1));
1161 for (
int ih = 0; ih < 2; ih++) {
1162 log.debug(
" initial excess_quark[", ih,
"] = (", excess_quark[ih][0],
", ",
1163 excess_quark[ih][1],
", ", excess_quark[ih][2],
", ",
1164 excess_quark[ih][3],
", ", excess_quark[ih][4],
")");
1165 log.debug(
" initial excess_antiq[", ih,
"] = (", excess_antiq[ih][0],
", ",
1166 excess_antiq[ih][1],
", ", excess_antiq[ih][2],
", ",
1167 excess_antiq[ih][3],
", ", excess_antiq[ih][4],
")");
1170 bool recovered_quarks =
false;
1171 while (!recovered_quarks) {
1174 std::array<bool, 2> find_forward = {
true,
false};
1175 const std::array<int, 5> excess_null = {0, 0, 0, 0, 0};
1176 std::array<int, 5> excess_total = excess_null;
1178 for (
int ih = 0; ih < 2; ih++) {
1179 int nfrag = event_intermediate.size();
1180 for (
int np_end = 0; np_end < nfrag - 1; np_end++) {
1187 pSum -= event_intermediate[iforward].p();
1189 if (event_intermediate[iforward].
id() > 0) {
1191 log.debug(
" excess_quark[", ih,
"] = (", excess_quark[ih][0],
", ",
1192 excess_quark[ih][1],
", ", excess_quark[ih][2],
", ",
1193 excess_quark[ih][3],
", ", excess_quark[ih][4],
")");
1196 log.debug(
" excess_antiq[", ih,
"] = (", excess_antiq[ih][0],
", ",
1197 excess_antiq[ih][1],
", ", excess_antiq[ih][2],
", ",
1198 excess_antiq[ih][3],
", ", excess_antiq[ih][4],
")");
1201 const int pdgid = event_intermediate[iforward].id();
1202 Pythia8::Vec4 pquark = event_intermediate[iforward].p();
1205 const int status = event_intermediate[iforward].status();
1206 const int color = event_intermediate[iforward].col();
1207 const int anticolor = event_intermediate[iforward].acol();
1210 event_intermediate.append(pdgid, status, color, anticolor, pquark,
1213 event_intermediate.remove(iforward, iforward);
1219 for (
int j = 0; j < 5; j++) {
1220 excess_total[j] += (excess_quark[ih][j] - excess_antiq[ih][j]);
1226 recovered_quarks = excess_total == excess_null;
1228 log.debug(
" valence quark contents of hadons are recovered.");
1230 log.debug(
" current total energy [GeV] : ", pSum.e());
1234 if (std::abs(pSum.e() - energy_init) <
really_small * energy_init) {
1238 double energy_current = pSum.e();
1240 for (
int i = 1; i < event_intermediate.size(); i++) {
1241 slope += event_intermediate[i].pAbs2() / event_intermediate[i].e();
1244 const double rescale_factor = 1. + (energy_init - energy_current) / slope;
1246 for (
int i = 1; i < event_intermediate.size(); i++) {
1247 const double px = rescale_factor * event_intermediate[i].px();
1248 const double py = rescale_factor * event_intermediate[i].py();
1249 const double pz = rescale_factor * event_intermediate[i].pz();
1250 const double pabs = rescale_factor * event_intermediate[i].pAbs();
1251 const double mass = event_intermediate[i].m();
1253 event_intermediate[i].px(px);
1254 event_intermediate[i].py(py);
1255 event_intermediate[i].pz(pz);
1256 event_intermediate[i].e(std::sqrt(mass * mass + pabs * pabs));
1257 pSum += event_intermediate[i].p();
1259 log.debug(
" parton momenta are rescaled by factor of ", rescale_factor);
1262 log.debug(
" final total energy [GeV] : ", pSum.e());
1265 event_intermediate[0].p(pSum);
1266 event_intermediate[0].m(pSum.mCalc());
1272 Pythia8::Event &event_intermediate,
1273 Pythia8::Event &event_hadronize) {
1274 const auto &log = logger<LogArea::Pythia>();
1276 Pythia8::Vec4 pSum = 0.;
1277 event_hadronize.reset();
1281 log.debug(
"Hard non-diff: iforward = ", iforward,
"(",
1282 event_intermediate[iforward].
id(),
")");
1284 pSum += event_intermediate[iforward].p();
1285 event_hadronize.append(event_intermediate[iforward]);
1287 int col_to_find = event_intermediate[iforward].acol();
1288 int acol_to_find = event_intermediate[iforward].col();
1289 event_intermediate.remove(iforward, iforward);
1290 log.debug(
"Hard non-diff: event_intermediate reduces in size to ",
1291 event_intermediate.size());
1294 while (col_to_find != 0 || acol_to_find != 0) {
1295 log.debug(
" col_to_find = ", col_to_find,
1296 ", acol_to_find = ", acol_to_find);
1299 for (
int i = 1; i < event_intermediate.size(); i++) {
1300 const int pdgid = event_intermediate[i].id();
1302 col_to_find != 0 && col_to_find == event_intermediate[i].col();
1304 acol_to_find != 0 && acol_to_find == event_intermediate[i].acol();
1306 log.debug(
" col_to_find ", col_to_find,
" from i ", i,
"(", pdgid,
1310 log.debug(
" acol_to_find ", acol_to_find,
" from i ", i,
"(", pdgid,
1314 if (found_col && !found_acol) {
1316 col_to_find = event_intermediate[i].acol();
1318 }
else if (!found_col && found_acol) {
1320 acol_to_find = event_intermediate[i].col();
1322 }
else if (found_col && found_acol) {
1331 event_intermediate.list();
1332 event_intermediate.listJunctions();
1333 event_hadronize.list();
1334 event_hadronize.listJunctions();
1335 if (col_to_find != 0) {
1336 log.error(
"No parton with col = ", col_to_find);
1338 if (acol_to_find != 0) {
1339 log.error(
"No parton with acol = ", acol_to_find);
1341 throw std::runtime_error(
"Hard string could not be identified.");
1343 pSum += event_intermediate[ifound].p();
1345 event_hadronize.append(event_intermediate[ifound]);
1347 event_intermediate.remove(ifound, ifound);
1348 log.debug(
"Hard non-diff: event_intermediate reduces in size to ",
1349 event_intermediate.size());
1355 event_hadronize[0].p(pSum);
1356 event_hadronize[0].m(pSum.mCalc());
1360 Pythia8::Event &event_intermediate,
1361 Pythia8::Event &event_hadronize) {
1362 const auto &log = logger<LogArea::Pythia>();
1364 event_hadronize.reset();
1372 const int kind = event_intermediate.kindJunction(0);
1373 bool sign_color = kind % 2 == 1;
1374 std::vector<int> col;
1375 for (
int j = 0; j < 3; j++) {
1376 col.push_back(event_intermediate.colJunction(0, j));
1378 event_hadronize.appendJunction(kind, col[0], col[1], col[2]);
1379 event_intermediate.eraseJunction(0);
1380 log.debug(
"junction (", col[0],
", ", col[1],
", ", col[2],
") with kind ",
1381 kind,
" will be handled.");
1383 bool found_string =
false;
1384 while (!found_string) {
1387 found_string =
true;
1388 for (
unsigned int j = 0; j < col.size(); j++) {
1389 found_string = found_string && col[j] == 0;
1391 if (!found_string) {
1394 log.debug(
" still has leg(s) unfinished.");
1395 sign_color = !sign_color;
1396 std::vector<int> junction_to_move;
1397 for (
int i = 0; i < event_intermediate.sizeJunction(); i++) {
1398 const int kind_new = event_intermediate.kindJunction(i);
1402 if (sign_color != (kind_new % 2 == 1)) {
1406 std::array<int, 3> col_new;
1407 for (
int k = 0; k < 3; k++) {
1408 col_new[k] = event_intermediate.colJunction(i, k);
1411 int n_legs_connected = 0;
1413 for (
unsigned int j = 0; j < col.size(); j++) {
1417 for (
int k = 0; k < 3; k++) {
1418 if (col[j] == col_new[k]) {
1419 n_legs_connected += 1;
1427 if (n_legs_connected > 0) {
1428 for (
int k = 0; k < 3; k++) {
1429 if (col_new[k] != 0) {
1430 col.push_back(col_new[k]);
1433 log.debug(
" junction ", i,
" (",
1434 event_intermediate.colJunction(i, 0),
", ",
1435 event_intermediate.colJunction(i, 1),
", ",
1436 event_intermediate.colJunction(i, 2),
") with kind ",
1437 kind_new,
" will be added.");
1438 junction_to_move.push_back(i);
1444 for (
unsigned int i = 0; i < junction_to_move.size(); i++) {
1445 unsigned int imove = junction_to_move[i] - i;
1446 const int kind_add = event_intermediate.kindJunction(imove);
1447 std::array<int, 3> col_add;
1448 for (
int k = 0; k < 3; k++) {
1449 col_add[k] = event_intermediate.colJunction(imove, k);
1452 event_hadronize.appendJunction(kind_add, col_add[0], col_add[1],
1455 event_intermediate.eraseJunction(imove);
1460 Pythia8::Vec4 pSum = event_hadronize[0].p();
1461 find_forward_string = pSum.pz() > 0.;
1465 Pythia8::Event &event_intermediate,
1466 Pythia8::Event &event_hadronize) {
1467 const auto &log = logger<LogArea::Pythia>();
1469 Pythia8::Vec4 pSum = event_hadronize[0].p();
1470 for (
unsigned int j = 0; j < col.size(); j++) {
1474 bool found_leg =
false;
1475 while (!found_leg) {
1477 for (
int i = 1; i < event_intermediate.size(); i++) {
1478 const int pdgid = event_intermediate[i].id();
1479 if (sign_color && col[j] == event_intermediate[i].col()) {
1480 log.debug(
" col[", j,
"] = ", col[j],
" from i ", i,
"(", pdgid,
1483 col[j] = event_intermediate[i].acol();
1485 }
else if (!sign_color && col[j] == event_intermediate[i].acol()) {
1486 log.debug(
" acol[", j,
"] = ", col[j],
" from i ", i,
"(", pdgid,
1489 col[j] = event_intermediate[i].col();
1496 if (event_intermediate.sizeJunction() == 0) {
1497 event_intermediate.list();
1498 event_intermediate.listJunctions();
1499 event_hadronize.list();
1500 event_hadronize.listJunctions();
1501 log.error(
"No parton with col = ", col[j],
1502 " connected with junction leg ", j);
1503 throw std::runtime_error(
"Hard string could not be identified.");
1506 pSum += event_intermediate[ifound].p();
1508 event_hadronize.append(event_intermediate[ifound]);
1510 event_intermediate.remove(ifound, ifound);
1511 log.debug(
"Hard non-diff: event_intermediate reduces in size to ",
1512 event_intermediate.size());
1522 event_hadronize[0].p(pSum);
1523 event_hadronize[0].m(pSum.mCalc());
1528 const auto &log = logger<LogArea::Pythia>();
1529 const std::array<FourVector, 2> ustrcom = {
FourVector(1., 0., 0., 0.),
1543 std::swap(baryon, antibaryon);
1545 if (baryon.
baryon_number() != 1 || antibaryon.baryon_number() != -1) {
1546 throw std::invalid_argument(
"Expected baryon-antibaryon pair.");
1550 constexpr
int n_q_types = 5;
1551 std::vector<int> qcount_bar, qcount_antibar;
1552 std::vector<int> n_combinations;
1553 bool no_combinations =
true;
1554 for (
int i = 0; i < n_q_types; i++) {
1556 qcount_antibar.push_back(-antibaryon.net_quark_number(i + 1));
1557 const int n_i = qcount_bar[i] * qcount_antibar[i];
1558 n_combinations.push_back(n_i);
1560 no_combinations =
false;
1566 if (no_combinations) {
1567 for (
int i = 0; i < 2; i++) {
1581 const int q_annihilate = discrete_distr() + 1;
1582 qcount_bar[q_annihilate - 1]--;
1583 qcount_antibar[q_annihilate - 1]--;
1586 std::vector<int> remaining_quarks, remaining_antiquarks;
1587 for (
int i = 0; i < n_q_types; i++) {
1588 for (
int j = 0; j < qcount_bar[i]; j++) {
1589 remaining_quarks.push_back(i + 1);
1591 for (
int j = 0; j < qcount_antibar[i]; j++) {
1592 remaining_antiquarks.push_back(-(i + 1));
1595 assert(remaining_quarks.size() == 2);
1596 assert(remaining_antiquarks.size() == 2);
1602 std::swap(remaining_quarks[0], remaining_quarks[1]);
1605 std::swap(remaining_antiquarks[0], remaining_antiquarks[1]);
1608 bool kin_threshold_satisfied =
true;
1609 for (
int i = 0; i < 2; i++) {
1610 const double mstr_min =
1613 if (mstr_min > mstr[i]) {
1614 kin_threshold_satisfied =
false;
1617 if (!kin_threshold_satisfied) {
1621 for (
int i = 0; i < 2; i++) {
1622 ParticleList new_intermediate_particles;
1626 fragment_string(remaining_quarks[i], remaining_antiquarks[i], mstr[i],
1627 evec,
true,
false, new_intermediate_particles);
1640 ThreeVector &evec_polar, std::array<ThreeVector, 3> &evec_basis) {
1641 if (std::abs(evec_polar.
x3()) < (1. - 1.0e-8)) {
1646 evec_basis[0] = evec_polar;
1648 theta = std::acos(evec_basis[0].x3());
1650 ex = evec_basis[0].x1();
1651 ey = evec_basis[0].x2();
1652 et = std::sqrt(ex * ex + ey * ey);
1654 phi = std::acos(ex / et);
1656 phi = -std::acos(ex / et);
1661 evec_basis[1].set_x1(cos(theta) * cos(phi));
1662 evec_basis[1].set_x2(cos(theta) * sin(phi));
1663 evec_basis[1].set_x3(-sin(theta));
1665 evec_basis[2].set_x1(-sin(phi));
1666 evec_basis[2].set_x2(cos(phi));
1667 evec_basis[2].set_x3(0.);
1670 if (evec_polar.
x3() > 0.) {
1692 assert((std::abs(diquark) > 1000) && (std::abs(diquark) < 5510) &&
1693 (std::abs(diquark) % 100 < 10));
1696 deg_spin = std::abs(diquark) % 10;
1698 const int sign_anti = diquark > 0 ? 1 : -1;
1701 q1 = sign_anti * (std::abs(diquark) - (std::abs(diquark) % 1000)) / 1000;
1702 q2 = sign_anti * (std::abs(diquark) % 1000 - deg_spin) / 100;
1706 assert((q1 > 0 && q2 > 0) || (q1 < 0 && q2 < 0));
1707 if (std::abs(q1) < std::abs(q2)) {
1710 int diquark = std::abs(q1 * 1000 + q2 * 100);
1715 return (q1 < 0) ? -diquark : diquark;
1762 std::swap(idq1, idq2);
1768 bool separate_fragment_baryon,
1769 ParticleList &intermediate_particles) {
1770 const auto &log = logger<LogArea::Pythia>();
1772 intermediate_particles.clear();
1774 log.debug(
"initial quark content for fragment_string : ", idq1,
", ", idq2);
1776 std::array<int, 2> idqIn;
1782 std::array<double, 2> m_const;
1784 for (
int i = 0; i < 2; i++) {
1786 bstring +=
pythia_hadron_->particleData.baryonNumberType(idqIn[i]);
1790 log.debug(
"baryon number of string times 3 : ", bstring);
1797 evecLong = -evecLong;
1800 if (m_const[0] + m_const[1] > mString) {
1801 throw std::runtime_error(
"String fragmentation: m1 + m2 > mString");
1803 Pythia8::Vec4 pSum = 0.;
1805 int number_of_fragments = 0;
1807 if (separate_fragment_baryon && (std::abs(bstring) == 3) &&
1808 (mString > m_const[0] + m_const[1] + 1.)) {
1813 const double ssbar_supp =
pythia_hadron_->parm(
"StringFlav:probStoUD");
1814 const double sigma_qt_frag =
pythia_hadron_->parm(
"StringPT:sigma");
1815 std::array<ThreeVector, 3> evec_basis;
1820 double QTrx, QTry, QTrn;
1823 double ppos_string_new, pneg_string_new;
1825 double mTrn_string_new;
1827 std::array<double, 2> m_trans;
1829 const int niter_max = 10000;
1831 bool found_leading_baryon =
false;
1832 while (!found_leading_baryon) {
1833 int idnew_qqbar = 0;
1851 id_diquark = std::abs(idq2);
1852 idqIn[1] = -idnew_qqbar;
1857 id_diquark = std::abs(idq1);
1858 idqIn[0] = idnew_qqbar;
1860 log.debug(
"quark constituents for leading baryon : ", idnew_qqbar,
", ",
1864 std::array<int, 5> frag_net_q;
1867 for (
int iq = 0; iq < 5; iq++) {
1869 (bstring > 0 ? 1 : -1) *
1870 (
pythia_hadron_->particleData.nQuarksInCode(idnew_qqbar, iq + 1) +
1873 const int frag_iso3 = frag_net_q[1] - frag_net_q[0];
1874 const int frag_strange = -frag_net_q[2];
1875 const int frag_charm = frag_net_q[3];
1876 const int frag_bottom = -frag_net_q[4];
1877 log.debug(
" conserved charges of leading baryon : iso3 = ", frag_iso3,
1878 ", strangeness = ", frag_strange,
", charmness = ", frag_charm,
1879 ", bottomness = ", frag_bottom);
1881 std::vector<int> pdgid_possible;
1882 std::vector<double> weight_possible;
1883 std::vector<double> weight_summed;
1889 (bstring > 0 ? 1 : -1) * std::abs(ptype.pdgcode().get_decimal());
1891 (bstring == 3 * ptype.pdgcode().baryon_number()) &&
1892 (frag_iso3 == ptype.pdgcode().isospin3()) &&
1893 (frag_strange == ptype.pdgcode().strangeness()) &&
1894 (frag_charm == ptype.pdgcode().charmness()) &&
1895 (frag_bottom == ptype.pdgcode().bottomness())) {
1896 const int spin_degeneracy = ptype.pdgcode().spin_degeneracy();
1897 const double mass_pole = ptype.mass();
1898 const double weight =
1899 static_cast<double>(spin_degeneracy) / mass_pole;
1900 pdgid_possible.push_back(pdgid);
1901 weight_possible.push_back(weight);
1903 log.debug(
" PDG id ", pdgid,
" is possible with weight ", weight);
1906 const int n_possible = pdgid_possible.size();
1907 weight_summed.push_back(0.);
1908 for (
int i = 0; i < n_possible; i++) {
1909 weight_summed.push_back(weight_summed[i] + weight_possible[i]);
1916 for (
int i = 0; i < n_possible; i++) {
1917 if ((uspc >= weight_summed[i]) && (uspc < weight_summed[i + 1])) {
1918 pdgid_frag = pdgid_possible[i];
1919 log.debug(
"PDG id ", pdgid_frag,
" selected for leading baryon.");
1924 const double mass_frag =
pythia_hadron_->particleData.mSel(pdgid_frag);
1929 log.debug(
"Transverse momentum (", QTrx,
", ", QTry,
1930 ") GeV selected for the leading baryon.");
1931 QTrn = std::sqrt(QTrx * QTrx + QTry * QTry);
1933 const double mTrn_frag = std::sqrt(QTrn * QTrn + mass_frag * mass_frag);
1942 bool xfrac_accepted =
false;
1943 while (!xfrac_accepted) {
1944 const double angle =
1955 const double xf_tmp =
1957 const double xf_env = (1. +
really_small) / (1. + xf_tmp * xf_tmp / 4.);
1958 const double xf_pdf = std::exp(-xf_tmp * xf_tmp / 2.);
1959 if (
random::uniform(0., xf_env) < xf_pdf && xfrac > 0. && xfrac < 1.) {
1960 xfrac_accepted =
true;
1967 const double ppos_frag = xfrac * mString /
sqrt2_;
1968 const double pneg_frag = 0.5 * mTrn_frag * mTrn_frag / ppos_frag;
1969 ppos_string_new = mString /
sqrt2_ - ppos_frag;
1970 pneg_string_new = mString /
sqrt2_ - pneg_frag;
1972 std::sqrt(std::max(0., 2. * ppos_string_new * pneg_string_new));
1977 for (
int i = 0; i < 2; i++) {
1983 m_trans[0] = m_const[0];
1987 m_trans[1] = std::sqrt(m_const[1] * m_const[1] + QTrn * QTrn);
1992 m_trans[0] = std::sqrt(m_const[0] * m_const[0] + QTrn * QTrn);
1995 m_trans[1] = m_const[1];
1998 if (mTrn_string_new > m_trans[0] + m_trans[1]) {
1999 found_leading_baryon =
true;
2002 evec_basis[0] * (ppos_frag - pneg_frag) /
sqrt2_ +
2003 evec_basis[1] * QTrx + evec_basis[2] * QTry);
2004 log.debug(
"appending the leading baryon ", pdgid_frag,
2005 " to the intermediate particle list.");
2009 intermediate_particles);
2011 log.error(
"PDG ID ", pdgid_frag,
" should exist in ParticleType.");
2012 throw std::runtime_error(
"string fragmentation failed.");
2014 number_of_fragments++;
2015 log.debug(
"proceed to the next step");
2018 if (iiter == niter_max) {
2025 std::array<double, 2> ppos_parton;
2027 std::array<double, 2> pneg_parton;
2035 const double pb_const =
2036 (mTrn_string_new * mTrn_string_new + m_trans[0] * m_trans[0] -
2037 m_trans[1] * m_trans[1]) /
2038 (4. * pneg_string_new);
2039 const double pc_const =
2040 0.5 * m_trans[0] * m_trans[0] * ppos_string_new / pneg_string_new;
2041 ppos_parton[0] = pb_const + (bstring > 0 ? -1. : 1.) *
2042 std::sqrt(pb_const * pb_const - pc_const);
2043 ppos_parton[1] = ppos_string_new - ppos_parton[0];
2047 for (
int i = 0; i < 2; i++) {
2048 pneg_parton[i] = 0.5 * m_trans[i] * m_trans[i] / ppos_parton[i];
2051 const int status = 1;
2052 int color, anticolor;
2054 Pythia8::Vec4 pquark;
2062 three_mom = evec_basis[0] * (ppos_parton[0] - pneg_parton[0]) /
sqrt2_;
2067 three_mom = evec_basis[0] * (ppos_parton[0] - pneg_parton[0]) /
sqrt2_ -
2068 evec_basis[1] * QTrx - evec_basis[2] * QTry;
2070 pquark =
set_Vec4((ppos_parton[0] + pneg_parton[0]) /
sqrt2_, three_mom);
2072 pythia_hadron_->event.append(idqIn[0], status, color, anticolor, pquark,
2082 three_mom = evec_basis[0] * (ppos_parton[1] - pneg_parton[1]) /
sqrt2_ -
2083 evec_basis[1] * QTrx - evec_basis[2] * QTry;
2087 three_mom = evec_basis[0] * (ppos_parton[1] - pneg_parton[1]) /
sqrt2_;
2089 pquark =
set_Vec4((ppos_parton[1] + pneg_parton[1]) /
sqrt2_, three_mom);
2091 pythia_hadron_->event.append(idqIn[1], status, color, anticolor, pquark,
2097 double sign_direction = 1.;
2098 if (bstring == -3) {
2102 sign_direction = -1;
2106 const double pCMquark =
pCM(mString, m_const[0], m_const[1]);
2107 const double E1 = std::sqrt(m_const[0] * m_const[0] + pCMquark * pCMquark);
2108 const double E2 = std::sqrt(m_const[1] * m_const[1] + pCMquark * pCMquark);
2110 ThreeVector direction = sign_direction * evecLong;
2113 const int status1 = 1, color1 = 1, anticolor1 = 0;
2114 Pythia8::Vec4 pquark =
set_Vec4(E1, -direction * pCMquark);
2116 pythia_hadron_->event.append(idqIn[0], status1, color1, anticolor1, pquark,
2119 const int status2 = 1, color2 = 0, anticolor2 = 1;
2120 pquark =
set_Vec4(E2, direction * pCMquark);
2122 pythia_hadron_->event.append(idqIn[1], status2, color2, anticolor2, pquark,
2126 log.debug(
"fragmenting a string with ", idqIn[0],
", ", idqIn[1]);
2131 if (successful_hadronization) {
2132 for (
int ipyth = 0; ipyth <
pythia_hadron_->event.size(); ipyth++) {
2143 log.debug(
"appending the fragmented hadron ", pythia_id,
2144 " to the intermediate particle list.");
2148 log.warn(
"PDG ID ", pythia_id,
2149 " does not exist in ParticleType - start over.");
2150 intermediate_particles.clear();
2154 number_of_fragments++;
2157 return number_of_fragments;
2164 double suppression_factor) {
2179 ParticleList &list) {
2180 assert(list.size() >= 2);
2181 int end = list.size() - 1;
2184 i1 <= end && !list[i1].pdgcode().contains_enough_valence_quarks(nq1);
2188 i2 >= 0 && !list[i2].pdgcode().contains_enough_valence_quarks(nq2);
2191 std::pair<int, int> indices(i1, i2);
2196 ParticleList &outgoing_particles,
2198 double suppression_factor) {
2201 data.set_cross_section_scaling_factor(0.0);
2204 std::sort(outgoing_particles.begin(), outgoing_particles.end(),
2207 j.momentum().velocity() * evecLong;
2210 switch (baryon_string) {
2224 throw std::runtime_error(
"string is neither mesonic nor baryonic");
2229 std::pair<int, int> i =
find_leading(nq1, nq2, outgoing_particles);
2230 std::pair<int, int> j =
find_leading(nq2, nq1, outgoing_particles);
2231 if (baryon_string == 0 && i.second - i.first < j.second - j.first) {
2234 suppression_factor);
2238 suppression_factor);
2258 throw std::runtime_error(
"StringProcess::pdg_map_for_pythia failed.");
std::array< int, 3 > quark_content() const
The return is always an array of three numbers, which are pdgcodes of quarks: 1 - d...
double additional_xsec_supp_
additional cross-section suppression factor to take coherence effect into account.
std::array< int, 2 > NpartString_
number of particles fragmented from strings
bool next_NDiffSoft()
Soft Non-diffractive process is modelled in accordance with dual-topological approach Capella:1978ig...
int net_quark_number(const int quark) const
Returns the net number of quarks with given flavour number For public use, see strangeness(), charmness(), bottomness() and isospin3().
The ThreeVector class represents a physical three-vector with the components .
double PPosA_
forward lightcone momentum p^{+} of incoming particle A in CM-frame [GeV]
static FourVector reorient(Pythia8::Particle &particle, std::array< ThreeVector, 3 > &evec_basis)
compute the four-momentum properly oriented in the lab frame.
T beta_a0(T xmin, T b)
Draws a random number from a beta-distribution with a = 0.
constexpr double really_small
Numerical error tolerance.
static Pythia8::Vec4 set_Vec4(double energy, const ThreeVector &mom)
Easy setter of Pythia Vec4 from SMASH.
double pmin_gluon_lightcone_
the minimum lightcone momentum scale carried by a gluon [GeV]
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
bool make_final_state_2strings(const std::array< std::array< int, 2 >, 2 > &quarks, const std::array< FourVector, 2 > &pstr_com, const std::array< double, 2 > &m_str, const std::array< ThreeVector, 2 > &evec_str, bool flip_string_ends, bool separate_fragment_baryon)
Prepare kinematics of two strings, fragment them and append to final_state.
FourVector LorentzBoost(const ThreeVector &v) const
Returns the FourVector boosted with velocity v.
int NpartFinal_
total number of final state particles
static void make_string_ends(const PdgCode &pdgcode_in, int &idq1, int &idq2, double xi)
make a random selection to determine partonic contents at the string ends.
int fragment_string(int idq1, int idq2, double mString, ThreeVector &evecLong, bool flip_string_ends, bool separate_fragment_baryon, ParticleList &intermediate_particles)
perform string fragmentation to determine species and momenta of hadrons by implementing PYTHIA 8...
void replace_constituent(Pythia8::Particle &particle, std::array< int, 5 > &excess_constituent)
Convert a partonic PYTHIA partice into the desired species and update the excess of constituents...
std::unique_ptr< Pythia8::Pythia > pythia_hadron_
PYTHIA object used in fragmentation.
std::array< FourVector, 2 > plab_
momenta of incoming particles in the lab frame [GeV]
int append_final_state(ParticleList &intermediate_particles, const FourVector &uString, const ThreeVector &evecLong)
compute the formation time and fill the arrays with final-state particles as described in Andersson:1...
void common_setup_pythia(Pythia8::Pythia *pythia_in, double strange_supp, double diquark_supp, double stringz_a, double stringz_b, double string_sigma_T)
Common setup of PYTHIA objects for soft and hard string routines.
static int pdg_map_for_pythia(PdgCode &pdg)
Take pdg code and map onto particle specie which can be handled by PYTHIA.
T pCM_sqr(const T sqrts, const T mass_a, const T mass_b) noexcept
std::array< PdgCode, 2 > PDGcodes_
PdgCodes of incoming particles.
void find_total_number_constituent(Pythia8::Event &event_intermediate, std::array< int, 5 > &nquark_total, std::array< int, 5 > &nantiq_total)
Compute how many quarks and antiquarks we have in the system, and update the correspoing arrays with ...
const FourVector & momentum() const
Get the particle's 4-momentum.
double prob_proton_to_d_uu_
Probability of splitting a nucleon into the quark flavour it has only once and a diquark it has twice...
int charge() const
The charge of the particle.
Pythia8::SigmaTotal pythia_sigmatot_
An object to compute cross-sections.
double PNegB_
backward lightcone momentum p^{-} of incoming particle B in CM-frame [GeV]
std::array< FourVector, 2 > pcom_
momenta of incoming particles in the center of mass frame [GeV]
void set_formation_time(const double &form_time)
Set the absolute formation time.
std::unique_ptr< Pythia8::Pythia > pythia_parton_
PYTHIA object used in hard string routine.
double sqrtsAB_
sqrt of Mandelstam variable s of collision [GeV]
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
void rearrange_excess(std::array< int, 5 > &nquark_total, std::array< std::array< int, 5 >, 2 > &excess_quark, std::array< std::array< int, 5 >, 2 > &excess_antiq)
Take total number of quarks and check if the system has enough constitents that need to be converted ...
static void quarks_from_diquark(int diquark, int &q1, int &q2, int °_spin)
find two quarks from a diquark.
static bool append_intermediate_list(int pdgid, FourVector momentum, ParticleList &intermediate_particles)
append new particle from PYTHIA to a specific particle list
static const ParticleTypeList & list_all()
void init(const ParticleList &incoming, double tcoll)
initialization feed intial particles, time of collision and gamma factor of the center of mass...
static int diquark_from_quarks(int q1, int q2)
Construct diquark from two quarks.
static void make_orthonormal_basis(ThreeVector &evec_polar, std::array< ThreeVector, 3 > &evec_basis)
compute three orthonormal basis vectors from unit vector in the longitudinal direction ...
T uniform_int(T min, T max)
Pythia8::Event event_intermediate_
event record for intermediate partonic state in the hard string routine
double kappa_tension_string_
string tension [GeV/fm]
double pow_fquark_alpha_
parameter for the quark distribution function
static void assign_all_scaling_factors(int baryon_string, ParticleList &outgoing_particles, const ThreeVector &evecLong, double suppression_factor)
Assign a cross section scaling factor to all outgoing particles.
void compute_incoming_lightcone_momenta()
compute the lightcone momenta of incoming particles where the longitudinal direction is set to be sam...
bool next_SDiff(bool is_AB_to_AX)
Single-diffractive process is based on single pomeron exchange described in Ingelman:1984ns.
bool use_yoyo_model_
Whether to calculate the string formation times from the yoyo-model.
static void assign_scaling_factor(int nquark, ParticleData &data, double suppression_factor)
Assign a cross section scaling factor to the given particle.
void compose_string_parton(bool find_forward_string, Pythia8::Event &event_intermediate, Pythia8::Event &event_hadronize)
Identify a set of partons, which are connected to form a color-neutral string, from a given PYTHIA ev...
bool next_DDiff()
Double-diffractive process ( A + B -> X + X ) is similar to the single-diffractive process...
void set_4momentum(const FourVector &momentum_vector)
Set the particle's 4-momentum directly.
ThreeVector vcomAB_
velocity three vector of the center of mass in the lab frame
ParticleList final_state_
final state array which must be accessed after the collision
bool pythia_parton_initialized_
Remembers if Pythia is initialized or not.
static std::pair< int, int > find_leading(int nq1, int nq2, ParticleList &list)
Find the leading string fragments.
double leading_frag_mean_
mean value of the fragmentation function for the leading baryons
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
double PNegA_
backward lightcone momentum p^{-} of incoming particle A in CM-frame [GeV]
constexpr double kaon_mass
Kaon mass in GeV.
double PPosB_
forward lightcone momentum p^{+} of incoming particle B in CM-frame [GeV]
static void convert_KaonLS(int &pythia_id)
convert Kaon-L or Kaon-S into K0 or Anti-K0
Discrete distribution with weight given by probability vector.
void find_junction_leg(bool sign_color, std::vector< int > &col, Pythia8::Event &event_intermediate, Pythia8::Event &event_hadronize)
Identify partons, which are associated with junction legs, from a given PYTHIA event record...
void compose_string_junction(bool &find_forward_string, Pythia8::Event &event_intermediate, Pythia8::Event &event_hadronize)
Identify a set of partons and junction(s), which are connected to form a color-neutral string...
FourVector ucomAB_
velocity four vector of the center of mass in the lab frame
double time_collision_
time of collision in the computational frame [fm]
bool set_mass_and_direction_2strings(const std::array< std::array< int, 2 >, 2 > &quarks, const std::array< FourVector, 2 > &pstr_com, std::array< double, 2 > &m_str, std::array< ThreeVector, 2 > &evec_str)
Determine string masses and directions in which strings are stretched.
T power(T n, T xMin, T xMax)
Draws a random number according to a power-law distribution ~ x^n.
double soft_t_form_
factor to be multiplied to formation times in soft strings
double leading_frag_width_
width of the fragmentation function for the leading baryons
bool restore_constituent(Pythia8::Event &event_intermediate, std::array< std::array< int, 5 >, 2 > &excess_quark, std::array< std::array< int, 5 >, 2 > &excess_antiq)
Take the intermediate partonic state from PYTHIA event with mapped hadrons and convert constituents i...
StringProcess(double string_tension, double time_formation, double gluon_beta, double gluon_pmin, double quark_alpha, double quark_beta, double strange_supp, double diquark_supp, double sigma_perp, double leading_frag_mean, double leading_frag_width, double stringz_a, double stringz_b, double string_sigma_T, double factor_t_form, bool use_yoyo_model, double prob_proton_to_d_uu)
Constructor, initializes pythia.
PdgCode pdgcode() const
Get the pdgcode of the particle.
double pow_fgluon_beta_
parameter for the gluon distribution function
double sqrt2_
square root of 2 ( )
constexpr int maximum_rndm_seed_in_pythia
The maximum value of the random seed used in PYTHIA.
std::array< ThreeVector, 3 > evecBasisAB_
Orthonormal basis vectors in the center of mass frame, where the 0th one is parallel to momentum of i...
int get_index_forward(bool find_forward, int np_end, Pythia8::Event &event)
Obtain index of the most forward or backward particle in a given PYTHIA event record.
double normal(const T &mean, const T &sigma)
Returns a random number drawn from a normal distribution.
bool next_BBbarAnn()
Baryon-antibaryon annihilation process Based on what UrQMD Bass:1998ca, Bleicher:1999xi does...
double sigma_qperp_
Transverse momentum spread of the excited strings.
void set_cross_section_scaling_factor(const double &xsec_scal)
Set the particle's initial cross_section_scaling_factor.
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
static void find_excess_constituent(PdgCode &pdg_actual, PdgCode &pdg_mapped, std::array< int, 5 > &excess_quark, std::array< int, 5 > &excess_antiq)
Compare the valence quark contents of the actual and mapped hadrons and evaluate how many more consti...
bool next_NDiffHard()
Hard Non-diffractive process is based on PYTHIA 8 with partonic showers and interactions.
double massB_
mass of incoming particle B [GeV]
ParticleData contains the dynamic information of a certain particle.
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
double time_formation_const_
constant proper time in the case of constant formation time [fm]
double massA_
mass of incoming particle A [GeV]
int baryon_number() const
bool splitting_gluon_qqbar(Pythia8::Event &event_intermediate, std::array< int, 5 > &nquark_total, std::array< int, 5 > &nantiq_total, bool sign_constituent, std::array< std::array< int, 5 >, 2 > &excess_constituent)
Take total number of quarks and check if the system has enough constituents that need to be converted...
double pow_fquark_beta_
parameter for the quark distribution function