19 static constexpr
int LOutput = LogArea::Output::id;
22 double string_tension,
double time_formation,
double gluon_beta,
23 double gluon_pmin,
double quark_alpha,
double quark_beta,
24 double strange_supp,
double diquark_supp,
double sigma_perp,
25 double stringz_a_leading,
double stringz_b_leading,
double stringz_a,
26 double stringz_b,
double string_sigma_T,
double factor_t_form,
27 bool mass_dependent_formation_times,
double prob_proton_to_d_uu,
28 bool separate_fragment_baryon,
double popcorn_rate)
29 : pmin_gluon_lightcone_(gluon_pmin),
30 pow_fgluon_beta_(gluon_beta),
31 pow_fquark_alpha_(quark_alpha),
32 pow_fquark_beta_(quark_beta),
33 sigma_qperp_(sigma_perp),
34 stringz_a_leading_(stringz_a_leading),
35 stringz_b_leading_(stringz_b_leading),
36 stringz_a_produce_(stringz_a),
37 stringz_b_produce_(stringz_b),
38 kappa_tension_string_(string_tension),
39 additional_xsec_supp_(0.7),
40 time_formation_const_(time_formation),
41 soft_t_form_(factor_t_form),
43 mass_dependent_formation_times_(mass_dependent_formation_times),
44 prob_proton_to_d_uu_(prob_proton_to_d_uu),
45 separate_fragment_baryon_(separate_fragment_baryon) {
47 pythia_parton_ = make_unique<Pythia8::Pythia>(PYTHIA_XML_DIR,
false);
54 popcorn_rate, stringz_a, stringz_b, string_sigma_T);
57 pythia_hadron_ = make_unique<Pythia8::Pythia>(PYTHIA_XML_DIR,
false);
61 popcorn_rate, stringz_a, stringz_b, string_sigma_T);
73 for (
int imu = 0; imu < 3; imu++) {
83 double popcorn_rate,
double stringz_a,
85 double string_sigma_T) {
87 pythia_in->readString(
"ParticleData:modeBreitWigner = 4");
90 pythia_in->readString(
"MultipartonInteractions:pTmin = 1.5");
91 pythia_in->readString(
"MultipartonInteractions:nSample = 10000");
93 pythia_in->readString(
"StringPT:sigma = " + std::to_string(string_sigma_T));
95 pythia_in->readString(
"StringFlav:probQQtoQ = " +
96 std::to_string(diquark_supp));
98 pythia_in->readString(
"StringFlav:probStoUD = " +
99 std::to_string(strange_supp));
100 pythia_in->readString(
"StringFlav:popcornRate = " +
101 std::to_string(popcorn_rate));
103 pythia_in->readString(
"StringZ:aLund = " + std::to_string(stringz_a));
104 pythia_in->readString(
"StringZ:bLund = " + std::to_string(stringz_b));
107 pythia_in->readString(
"PDF:pSet = 13");
108 pythia_in->readString(
"PDF:pSetB = 13");
109 pythia_in->readString(
"PDF:piSet = 1");
110 pythia_in->readString(
"PDF:piSetB = 1");
111 pythia_in->readString(
"Beams:idA = 2212");
112 pythia_in->readString(
"Beams:idB = 2212");
113 pythia_in->readString(
"Beams:eCM = 10.");
116 pythia_in->readString(
"Random:setSeed = on");
118 pythia_in->readString(
"Print:quiet = on");
120 pythia_in->readString(
"HadronLevel:Decay = off");
123 int pdgid = ptype.pdgcode().get_decimal();
124 double mass_pole = ptype.mass();
125 double width_pole = ptype.width_at_pole();
127 if (pythia_in->particleData.isParticle(pdgid)) {
129 pythia_in->particleData.m0(pdgid, mass_pole);
130 pythia_in->particleData.mWidth(pdgid, width_pole);
131 }
else if (pdgid == 310 || pdgid == 130) {
133 pythia_in->particleData.m0(pdgid,
kaon_mass);
134 pythia_in->particleData.mWidth(pdgid, 0.);
139 pythia_in->readString(
"Check:epTolErr = 1e-6");
140 pythia_in->readString(
"Check:epTolWarn = 1e-8");
152 bstring += data.pdgcode().baryon_number();
165 for (
int i = 0; i < nfrag; i++) {
166 ThreeVector velocity = intermediate_particles[i].momentum().velocity();
167 double gamma = 1. / intermediate_particles[i].inverse_gamma();
170 intermediate_particles[i].momentum().
lorentz_boost(-vstring);
171 intermediate_particles[i].set_4momentum(momentum);
175 double tau_prod = M_SQRT2 * intermediate_particles[i].effective_mass() /
177 double t_prod = tau_prod * gamma;
181 fragment_position = fragment_position.
lorentz_boost(-vstring);
183 intermediate_particles[i].set_slow_formation_times(
188 double gamma_factor = 1.0 / std::sqrt(1 - (v_calc).sqr());
189 intermediate_particles[i].set_slow_formation_times(
203 massA_ = incoming[0].effective_mass();
204 massB_ = incoming[1].effective_mass();
206 plab_[0] = incoming[0].momentum();
207 plab_[1] = incoming[1].momentum();
240 double QTrn, QTrx, QTry;
241 double pabscomHX_sqr, massX;
250 if (mstrMin > mstrMax) {
256 QTrn = std::sqrt(QTrx * QTrx + QTry * QTry);
263 const bool foundPabsX = pabscomHX_sqr > QTrn * QTrn;
268 double sign_direction = is_AB_to_AX ? 1. : -1.;
272 (
evecBasisAB_[0] * std::sqrt(pabscomHX_sqr - QTrn * QTrn) +
274 const FourVector pstrHcom(std::sqrt(pabscomHX_sqr + massH * massH),
276 const FourVector pstrXcom(std::sqrt(pabscomHX_sqr + massX * massX),
284 is_AB_to_AX ?
pcom_[1].threevec() :
pcom_[0].threevec();
289 ParticleList new_intermediate_particles;
291 new_intermediate_particles);
312 const std::array<std::array<int, 2>, 2> &quarks,
313 const std::array<FourVector, 2> &pstr_com, std::array<double, 2> &m_str,
314 std::array<ThreeVector, 2> &evec_str) {
315 std::array<bool, 2> found_mass;
316 for (
int i = 0; i < 2; i++) {
317 found_mass[i] =
false;
319 m_str[i] = pstr_com[i].sqr();
320 m_str[i] = (m_str[i] > 0.) ? std::sqrt(m_str[i]) : 0.;
321 const double threshold =
pythia_hadron_->particleData.m0(quarks[i][0]) +
324 if (m_str[i] > threshold) {
325 found_mass[i] =
true;
341 evec_str[i] = prs.threevec() / prs.threevec().abs();
345 return found_mass[0] && found_mass[1];
349 const std::array<std::array<int, 2>, 2> &quarks,
350 const std::array<FourVector, 2> &pstr_com,
351 const std::array<double, 2> &m_str,
352 const std::array<ThreeVector, 2> &evec_str,
bool flip_string_ends,
353 bool separate_fragment_baryon) {
354 const std::array<FourVector, 2> ustr_com = {pstr_com[0] / m_str[0],
355 pstr_com[1] / m_str[1]};
356 for (
int i = 0; i < 2; i++) {
357 ParticleList new_intermediate_particles;
362 int nfrag =
fragment_string(quarks[i][0], quarks[i][1], m_str[i], evec,
363 flip_string_ends, separate_fragment_baryon,
364 new_intermediate_particles);
387 std::array<std::array<int, 2>, 2> quarks;
388 std::array<FourVector, 2> pstr_com;
389 std::array<double, 2> m_str;
390 std::array<ThreeVector, 2> evec_str;
400 const double xfracA =
402 const double xfracB =
407 const double QTrn = std::sqrt(QTrx * QTrx + QTry * QTry);
409 const double QPos = -QTrn * QTrn / (2. * xfracB *
PNegB_);
410 const double QNeg = QTrn * QTrn / (2. * xfracA *
PPosA_);
424 const bool found_masses =
429 const bool flip_string_ends =
true;
431 quarks, pstr_com, m_str, evec_str, flip_string_ends,
false);
442 std::array<std::array<int, 2>, 2> quarks;
443 std::array<FourVector, 2> pstr_com;
444 std::array<double, 2> m_str;
445 std::array<ThreeVector, 2> evec_str;
448 int idqA1, idqA2, idqB1, idqB2;
452 const int bar_a =
PDGcodes_[0].baryon_number(),
455 (bar_a == 0 && bar_b == 1) ||
456 (bar_a == 0 && bar_b == 0)) {
457 quarks[0][0] = idqB1;
458 quarks[0][1] = idqA2;
459 quarks[1][0] = idqA1;
460 quarks[1][1] = idqB2;
461 }
else if (((bar_a == 0) && (bar_b == -1)) ||
464 quarks[0][0] = idqA1;
465 quarks[0][1] = idqB2;
466 quarks[1][0] = idqB1;
467 quarks[1][1] = idqA2;
469 std::stringstream ss;
470 ss <<
" StringProcess::next_NDiff : baryonA = " << bar_a
471 <<
", baryonB = " << bar_b;
472 throw std::runtime_error(ss.str());
480 const double QTrn = std::sqrt(QTrx * QTrx + QTry * QTry);
482 const double QPos = -QTrn * QTrn / (2. * xfracB *
PNegB_);
483 const double QNeg = QTrn * QTrn / (2. * xfracA *
PPosA_);
484 const double dPPos = -xfracA *
PPosA_ - QPos;
485 const double dPNeg = xfracB *
PNegB_ - QNeg;
492 m_str[0] = pstr_com[0].sqr();
500 const bool found_masses =
505 const bool flip_string_ends =
false;
520 std::array<int, 2> pdg_for_pythia;
521 std::array<std::array<int, 5>, 2> excess_quark;
522 std::array<std::array<int, 5>, 2> excess_antiq;
523 for (
int i = 0; i < 2; i++) {
524 for (
int j = 0; j < 5; j++) {
525 excess_quark[i][j] = 0;
526 excess_antiq[i][j] = 0;
532 " is mapped onto ", pdg_for_pythia[i]);
534 PdgCode pdgcode_for_pythia(std::to_string(pdg_for_pythia[i]));
539 logg[
LPythia].debug(
" excess_quark[", i,
"] = (", excess_quark[i][0],
540 ", ", excess_quark[i][1],
", ", excess_quark[i][2],
541 ", ", excess_quark[i][3],
", ", excess_quark[i][4],
543 logg[
LPythia].debug(
" excess_antiq[", i,
"] = (", excess_antiq[i][0],
544 ", ", excess_antiq[i][1],
", ", excess_antiq[i][2],
545 ", ", excess_antiq[i][3],
", ", excess_antiq[i][4],
553 bool same_initial_state = previous_idA == pdg_for_pythia[0] &&
554 previous_idB == pdg_for_pythia[1] &&
565 logg[
LPythia].debug(
"Pythia initialized with ", pdg_for_pythia[0],
" + ",
566 pdg_for_pythia[1],
" at CM energy [GeV] ",
sqrtsAB_);
568 throw std::runtime_error(
"Pythia failed to initialize.");
577 logg[
LPythia].debug(
"pythia_parton_ : rndm is initialized with seed ",
584 logg[
LPythia].debug(
"Pythia final state computed, success = ",
585 final_state_success);
586 if (!final_state_success) {
590 ParticleList new_intermediate_particles;
591 ParticleList new_non_hadron_particles;
593 Pythia8::Vec4 pSum = 0.;
616 std::array<int, 3> col;
617 for (
int j = 0; j < 3; j++) {
630 bool correct_constituents =
632 if (!correct_constituents) {
633 logg[
LPythia].debug(
"failed to find correct partonic constituents.");
639 while (ipart < npart) {
644 logg[
LPythia].debug(
"PDG ID from Pythia: ", pdgid);
646 logg[
LPythia].debug(
"4-momentum from Pythia: ", momentum);
651 " does not exist in ParticleType - start over.");
652 final_state_success =
false;
661 bool hadronize_success =
false;
662 bool find_forward_string =
true;
663 logg[
LPythia].debug(
"Hard non-diff: partonic process gives ",
670 logg[
LPythia].debug(
" Dummy event in hard string routine failed.");
671 hadronize_success =
false;
688 logg[
LPythia].debug(
"Pythia hadronized, success = ", hadronize_success);
690 new_intermediate_particles.clear();
691 if (hadronize_success) {
692 for (
int i = 0; i < event_hadron.size(); i++) {
693 if (event_hadron[i].isFinal()) {
694 int pythia_id = event_hadron[i].id();
695 logg[
LPythia].debug(
"PDG ID from Pythia: ", pythia_id);
708 logg[
LPythia].debug(
"4-momentum from Pythia: ", momentum);
709 logg[
LPythia].debug(
"appending the particle ", pythia_id,
710 " to the intermediate particle list.");
711 bool found_ptype =
false;
712 if (event_hadron[i].isHadron()) {
714 new_intermediate_particles);
717 new_non_hadron_particles);
721 " does not exist in ParticleType - start over.");
722 hadronize_success =
false;
730 if (!hadronize_success) {
739 find_forward_string = !find_forward_string;
742 if (hadronize_success) {
745 data.set_cross_section_scaling_factor(1.);
753 return hadronize_success;
758 std::array<int, 5> &excess_quark,
759 std::array<int, 5> &excess_antiq) {
762 std::array<int, 3> qcontent_actual = pdg_actual.
quark_content();
763 std::array<int, 3> qcontent_mapped = pdg_mapped.
quark_content();
765 excess_quark = {0, 0, 0, 0, 0};
766 excess_antiq = {0, 0, 0, 0, 0};
767 for (
int i = 0; i < 3; i++) {
768 if (qcontent_actual[i] > 0) {
769 int j = qcontent_actual[i] - 1;
770 excess_quark[j] += 1;
773 if (qcontent_mapped[i] > 0) {
774 int j = qcontent_mapped[i] - 1;
775 excess_quark[j] -= 1;
778 if (qcontent_actual[i] < 0) {
779 int j = std::abs(qcontent_actual[i]) - 1;
780 excess_antiq[j] += 1;
783 if (qcontent_mapped[i] < 0) {
784 int j = std::abs(qcontent_mapped[i]) - 1;
785 excess_antiq[j] -= 1;
791 Pythia8::Particle &particle, std::array<int, 5> &excess_constituent) {
793 if (!particle.isQuark() && !particle.isDiquark()) {
798 const std::array<int, 5> excess_null = {0, 0, 0, 0, 0};
799 if (excess_constituent == excess_null) {
804 std::array<int, 2> pdgid = {0, 0};
807 if (particle.isQuark()) {
809 pdgid[0] = particle.id();
810 }
else if (particle.isDiquark()) {
815 for (
int iq = 0; iq < nq; iq++) {
816 int jq = std::abs(pdgid[iq]) - 1;
818 std::vector<int> k_found;
821 if (excess_constituent[jq] < 0) {
822 for (
int k = 0; k < 5; k++) {
824 if (k != jq && excess_constituent[k] > 0) {
825 k_found.push_back(k);
831 if (k_found.size() > 0) {
834 k_select = k_found[l];
837 pdgid[iq] = pdgid[iq] > 0 ? k_select + 1 : -(k_select + 1);
838 excess_constituent[jq] += 1;
839 excess_constituent[k_select] -= 1;
844 if (particle.isQuark()) {
845 pdgid_new = pdgid[0];
846 }
else if (particle.isDiquark()) {
847 if (std::abs(pdgid[0]) < std::abs(pdgid[1])) {
848 std::swap(pdgid[0], pdgid[1]);
851 pdgid_new = std::abs(pdgid[0]) * 1000 + std::abs(pdgid[1]) * 100;
852 if (std::abs(pdgid[0]) == std::abs(pdgid[1])) {
855 pdgid_new += spin_deg;
858 if (particle.id() < 0) {
862 logg[
LPythia].debug(
" parton id = ", particle.id(),
" is converted to ",
866 Pythia8::Vec4 pquark = particle.p();
868 double e_new = std::sqrt(mass_new * mass_new + pquark.pAbs() * pquark.pAbs());
870 particle.id(pdgid_new);
872 particle.m(mass_new);
876 Pythia8::Event &event_intermediate, std::array<int, 5> &nquark_total,
877 std::array<int, 5> &nantiq_total) {
878 for (
int iflav = 0; iflav < 5; iflav++) {
879 nquark_total[iflav] = 0;
880 nantiq_total[iflav] = 0;
883 for (
int ip = 1; ip < event_intermediate.size(); ip++) {
884 if (!event_intermediate[ip].isFinal()) {
887 const int pdgid = event_intermediate[ip].id();
890 for (
int iflav = 0; iflav < 5; iflav++) {
891 nquark_total[iflav] +=
896 for (
int iflav = 0; iflav < 5; iflav++) {
897 nantiq_total[iflav] +=
pythia_hadron_->particleData.nQuarksInCode(
898 std::abs(pdgid), iflav + 1);
905 Pythia8::Event &event_intermediate, std::array<int, 5> &nquark_total,
906 std::array<int, 5> &nantiq_total,
bool sign_constituent,
907 std::array<std::array<int, 5>, 2> &excess_constituent) {
908 Pythia8::Vec4 pSum = event_intermediate[0].p();
914 for (
int iflav = 0; iflav < 5; iflav++) {
921 excess_constituent[0][iflav] + excess_constituent[1][iflav];
922 if (sign_constituent) {
923 nquark_final += nquark_total[iflav];
925 nquark_final += nantiq_total[iflav];
930 bool enough_quark = nquark_final >= 0;
934 logg[
LPythia].debug(
" not enough constituents with flavor ", iflav + 1,
935 " : try to split a gluon to qqbar.");
936 for (
int ic = 0; ic < std::abs(nquark_final); ic++) {
940 if (excess_constituent[0][iflav] < 0) {
949 for (
int ip = 2; ip < event_intermediate.size(); ip++) {
950 if (!event_intermediate[ip].isFinal() ||
951 !event_intermediate[ip].isGluon()) {
955 const double y_gluon_current = event_intermediate[ip].y();
956 const double y_gluon_forward = event_intermediate[iforward].y();
957 if ((ih_mod == 0 && y_gluon_current > y_gluon_forward) ||
958 (ih_mod == 1 && y_gluon_current < y_gluon_forward)) {
963 if (!event_intermediate[iforward].isGluon()) {
964 logg[
LPythia].debug(
"There is no gluon to split into qqbar.");
969 Pythia8::Vec4 pgluon = event_intermediate[iforward].p();
971 const int pdgid = iflav + 1;
973 const int status = event_intermediate[iforward].status();
977 const int col = event_intermediate[iforward].col();
978 const int acol = event_intermediate[iforward].acol();
981 std::array<double, 2> px_quark;
982 std::array<double, 2> py_quark;
983 std::array<double, 2> pz_quark;
985 std::array<double, 2> e_quark;
987 std::array<Pythia8::Vec4, 2> pquark;
989 const double sigma_qt_frag =
pythia_hadron_->parm(
"StringPT:sigma");
994 for (
int isign = 0; isign < 2; isign++) {
998 px_quark[isign] = 0.5 * pgluon.px() + (isign == 0 ? 1. : -1.) * qx;
999 py_quark[isign] = 0.5 * pgluon.py() + (isign == 0 ? 1. : -1.) * qy;
1000 pz_quark[isign] = 0.5 * pgluon.pz();
1002 std::sqrt(mass * mass + px_quark[isign] * px_quark[isign] +
1003 py_quark[isign] * py_quark[isign] +
1004 pz_quark[isign] * pz_quark[isign]);
1005 pquark[isign] = Pythia8::Vec4(px_quark[isign], py_quark[isign],
1006 pz_quark[isign], e_quark[isign]);
1011 pSum += pquark[0] + pquark[1] - pgluon;
1013 event_intermediate.append(pdgid, status, col, 0, pquark[0], mass);
1014 event_intermediate.append(-pdgid, status, 0, acol, pquark[1], mass);
1016 event_intermediate.remove(iforward, iforward);
1018 logg[
LPythia].debug(
" gluon at iforward = ", iforward,
1019 " is splitted into ", pdgid,
",", -pdgid,
1023 nquark_total[iflav] += 1;
1024 nantiq_total[iflav] += 1;
1031 event_intermediate[0].p(pSum);
1032 event_intermediate[0].m(pSum.mCalc());
1038 std::array<int, 5> &nquark_total,
1039 std::array<std::array<int, 5>, 2> &excess_quark,
1040 std::array<std::array<int, 5>, 2> &excess_antiq) {
1041 for (
int iflav = 0; iflav < 5; iflav++) {
1048 nquark_total[iflav] + excess_quark[0][iflav] + excess_quark[1][iflav];
1052 bool enough_quark = nquark_final >= 0;
1054 if (!enough_quark) {
1055 logg[
LPythia].debug(
" not enough constituents with flavor ", iflav + 1,
1056 " : try to modify excess of constituents.");
1057 for (
int ic = 0; ic < std::abs(nquark_final); ic++) {
1061 if (excess_quark[0][iflav] < 0) {
1069 excess_quark[ih_mod][iflav] += 1;
1070 excess_antiq[ih_mod][iflav] += 1;
1077 for (
int jflav = 0; jflav < 5; jflav++) {
1079 if (jflav != iflav && excess_quark[ih_mod][jflav] > 0) {
1082 excess_quark[ih_mod][jflav] -= 1;
1083 excess_antiq[ih_mod][jflav] -= 1;
1095 Pythia8::Event &event_intermediate,
1096 std::array<std::array<int, 5>, 2> &excess_quark,
1097 std::array<std::array<int, 5>, 2> &excess_antiq) {
1098 Pythia8::Vec4 pSum = event_intermediate[0].p();
1099 const double energy_init = pSum.e();
1100 logg[
LPythia].debug(
" initial total energy [GeV] : ", energy_init);
1103 std::array<int, 5> nquark_total;
1104 std::array<int, 5> nantiq_total;
1109 event_intermediate, nquark_total, nantiq_total,
true, excess_quark);
1111 event_intermediate, nquark_total, nantiq_total,
false, excess_antiq);
1115 if (!split_for_quark || !split_for_antiq) {
1121 for (
int iflav = 0; iflav < 5; iflav++) {
1122 if (nquark_total[iflav] + excess_quark[0][iflav] + excess_quark[1][iflav] <
1124 logg[
LPythia].debug(
"Not enough quark constituents of flavor ",
1129 if (nantiq_total[iflav] + excess_antiq[0][iflav] + excess_antiq[1][iflav] <
1131 logg[
LPythia].debug(
"Not enough antiquark constituents of flavor ",
1137 for (
int ih = 0; ih < 2; ih++) {
1138 logg[
LPythia].debug(
" initial excess_quark[", ih,
"] = (",
1139 excess_quark[ih][0],
", ", excess_quark[ih][1],
", ",
1140 excess_quark[ih][2],
", ", excess_quark[ih][3],
", ",
1141 excess_quark[ih][4],
")");
1142 logg[
LPythia].debug(
" initial excess_antiq[", ih,
"] = (",
1143 excess_antiq[ih][0],
", ", excess_antiq[ih][1],
", ",
1144 excess_antiq[ih][2],
", ", excess_antiq[ih][3],
", ",
1145 excess_antiq[ih][4],
")");
1148 bool recovered_quarks =
false;
1149 while (!recovered_quarks) {
1152 std::array<bool, 2> find_forward = {
true,
false};
1153 const std::array<int, 5> excess_null = {0, 0, 0, 0, 0};
1154 std::array<int, 5> excess_total = excess_null;
1156 for (
int ih = 0; ih < 2; ih++) {
1157 int nfrag = event_intermediate.size();
1158 for (
int np_end = 0; np_end < nfrag - 1; np_end++) {
1165 pSum -= event_intermediate[iforward].p();
1167 if (event_intermediate[iforward].
id() > 0) {
1170 " excess_quark[", ih,
"] = (", excess_quark[ih][0],
", ",
1171 excess_quark[ih][1],
", ", excess_quark[ih][2],
", ",
1172 excess_quark[ih][3],
", ", excess_quark[ih][4],
")");
1176 " excess_antiq[", ih,
"] = (", excess_antiq[ih][0],
", ",
1177 excess_antiq[ih][1],
", ", excess_antiq[ih][2],
", ",
1178 excess_antiq[ih][3],
", ", excess_antiq[ih][4],
")");
1181 const int pdgid = event_intermediate[iforward].id();
1182 Pythia8::Vec4 pquark = event_intermediate[iforward].p();
1185 const int status = event_intermediate[iforward].status();
1186 const int color = event_intermediate[iforward].col();
1187 const int anticolor = event_intermediate[iforward].acol();
1190 event_intermediate.append(pdgid, status, color, anticolor, pquark,
1193 event_intermediate.remove(iforward, iforward);
1199 for (
int j = 0; j < 5; j++) {
1200 excess_total[j] += (excess_quark[ih][j] - excess_antiq[ih][j]);
1206 recovered_quarks = excess_total == excess_null;
1208 logg[
LPythia].debug(
" valence quark contents of hadons are recovered.");
1210 logg[
LPythia].debug(
" current total energy [GeV] : ", pSum.e());
1214 if (std::abs(pSum.e() - energy_init) <
really_small * energy_init) {
1218 double energy_current = pSum.e();
1220 for (
int i = 1; i < event_intermediate.size(); i++) {
1221 slope += event_intermediate[i].pAbs2() / event_intermediate[i].e();
1224 const double rescale_factor = 1. + (energy_init - energy_current) / slope;
1226 for (
int i = 1; i < event_intermediate.size(); i++) {
1227 const double px = rescale_factor * event_intermediate[i].px();
1228 const double py = rescale_factor * event_intermediate[i].py();
1229 const double pz = rescale_factor * event_intermediate[i].pz();
1230 const double pabs = rescale_factor * event_intermediate[i].pAbs();
1231 const double mass = event_intermediate[i].m();
1233 event_intermediate[i].px(px);
1234 event_intermediate[i].py(py);
1235 event_intermediate[i].pz(pz);
1236 event_intermediate[i].e(std::sqrt(mass * mass + pabs * pabs));
1237 pSum += event_intermediate[i].p();
1239 logg[
LPythia].debug(
" parton momenta are rescaled by factor of ",
1243 logg[
LPythia].debug(
" final total energy [GeV] : ", pSum.e());
1246 event_intermediate[0].p(pSum);
1247 event_intermediate[0].m(pSum.mCalc());
1253 Pythia8::Event &event_intermediate,
1254 Pythia8::Event &event_hadronize) {
1255 Pythia8::Vec4 pSum = 0.;
1256 event_hadronize.reset();
1260 logg[
LPythia].debug(
"Hard non-diff: iforward = ", iforward,
"(",
1261 event_intermediate[iforward].
id(),
")");
1263 pSum += event_intermediate[iforward].p();
1264 event_hadronize.append(event_intermediate[iforward]);
1266 int col_to_find = event_intermediate[iforward].acol();
1267 int acol_to_find = event_intermediate[iforward].col();
1268 event_intermediate.remove(iforward, iforward);
1269 logg[
LPythia].debug(
"Hard non-diff: event_intermediate reduces in size to ",
1270 event_intermediate.size());
1273 while (col_to_find != 0 || acol_to_find != 0) {
1274 logg[
LPythia].debug(
" col_to_find = ", col_to_find,
1275 ", acol_to_find = ", acol_to_find);
1278 for (
int i = 1; i < event_intermediate.size(); i++) {
1279 const int pdgid = event_intermediate[i].id();
1281 col_to_find != 0 && col_to_find == event_intermediate[i].col();
1283 acol_to_find != 0 && acol_to_find == event_intermediate[i].acol();
1285 logg[
LPythia].debug(
" col_to_find ", col_to_find,
" from i ", i,
"(",
1289 logg[
LPythia].debug(
" acol_to_find ", acol_to_find,
" from i ", i,
"(",
1293 if (found_col && !found_acol) {
1295 col_to_find = event_intermediate[i].acol();
1297 }
else if (!found_col && found_acol) {
1299 acol_to_find = event_intermediate[i].col();
1301 }
else if (found_col && found_acol) {
1310 event_intermediate.list();
1311 event_intermediate.listJunctions();
1312 event_hadronize.list();
1313 event_hadronize.listJunctions();
1314 if (col_to_find != 0) {
1315 logg[
LPythia].error(
"No parton with col = ", col_to_find);
1317 if (acol_to_find != 0) {
1318 logg[
LPythia].error(
"No parton with acol = ", acol_to_find);
1320 throw std::runtime_error(
"Hard string could not be identified.");
1322 pSum += event_intermediate[ifound].p();
1324 event_hadronize.append(event_intermediate[ifound]);
1326 event_intermediate.remove(ifound, ifound);
1328 "Hard non-diff: event_intermediate reduces in size to ",
1329 event_intermediate.size());
1335 event_hadronize[0].p(pSum);
1336 event_hadronize[0].m(pSum.mCalc());
1340 Pythia8::Event &event_intermediate,
1341 Pythia8::Event &event_hadronize) {
1342 event_hadronize.reset();
1350 const int kind = event_intermediate.kindJunction(0);
1351 bool sign_color = kind % 2 == 1;
1352 std::vector<int> col;
1353 for (
int j = 0; j < 3; j++) {
1354 col.push_back(event_intermediate.colJunction(0, j));
1356 event_hadronize.appendJunction(kind, col[0], col[1], col[2]);
1357 event_intermediate.eraseJunction(0);
1358 logg[
LPythia].debug(
"junction (", col[0],
", ", col[1],
", ", col[2],
1359 ") with kind ", kind,
" will be handled.");
1361 bool found_string =
false;
1362 while (!found_string) {
1365 found_string =
true;
1366 for (
unsigned int j = 0; j < col.size(); j++) {
1367 found_string = found_string && col[j] == 0;
1369 if (!found_string) {
1372 logg[
LPythia].debug(
" still has leg(s) unfinished.");
1373 sign_color = !sign_color;
1374 std::vector<int> junction_to_move;
1375 for (
int i = 0; i < event_intermediate.sizeJunction(); i++) {
1376 const int kind_new = event_intermediate.kindJunction(i);
1380 if (sign_color != (kind_new % 2 == 1)) {
1384 std::array<int, 3> col_new;
1385 for (
int k = 0; k < 3; k++) {
1386 col_new[k] = event_intermediate.colJunction(i, k);
1389 int n_legs_connected = 0;
1391 for (
unsigned int j = 0; j < col.size(); j++) {
1395 for (
int k = 0; k < 3; k++) {
1396 if (col[j] == col_new[k]) {
1397 n_legs_connected += 1;
1405 if (n_legs_connected > 0) {
1406 for (
int k = 0; k < 3; k++) {
1407 if (col_new[k] != 0) {
1408 col.push_back(col_new[k]);
1412 event_intermediate.colJunction(i, 0),
", ",
1413 event_intermediate.colJunction(i, 1),
", ",
1414 event_intermediate.colJunction(i, 2),
1415 ") with kind ", kind_new,
" will be added.");
1416 junction_to_move.push_back(i);
1422 for (
unsigned int i = 0; i < junction_to_move.size(); i++) {
1423 unsigned int imove = junction_to_move[i] - i;
1424 const int kind_add = event_intermediate.kindJunction(imove);
1425 std::array<int, 3> col_add;
1426 for (
int k = 0; k < 3; k++) {
1427 col_add[k] = event_intermediate.colJunction(imove, k);
1430 event_hadronize.appendJunction(kind_add, col_add[0], col_add[1],
1433 event_intermediate.eraseJunction(imove);
1438 Pythia8::Vec4 pSum = event_hadronize[0].p();
1439 find_forward_string = pSum.pz() > 0.;
1443 Pythia8::Event &event_intermediate,
1444 Pythia8::Event &event_hadronize) {
1445 Pythia8::Vec4 pSum = event_hadronize[0].p();
1446 for (
unsigned int j = 0; j < col.size(); j++) {
1450 bool found_leg =
false;
1451 while (!found_leg) {
1453 for (
int i = 1; i < event_intermediate.size(); i++) {
1454 const int pdgid = event_intermediate[i].id();
1455 if (sign_color && col[j] == event_intermediate[i].col()) {
1456 logg[
LPythia].debug(
" col[", j,
"] = ", col[j],
" from i ", i,
"(",
1459 col[j] = event_intermediate[i].acol();
1461 }
else if (!sign_color && col[j] == event_intermediate[i].acol()) {
1462 logg[
LPythia].debug(
" acol[", j,
"] = ", col[j],
" from i ", i,
"(",
1465 col[j] = event_intermediate[i].col();
1472 if (event_intermediate.sizeJunction() == 0) {
1473 event_intermediate.list();
1474 event_intermediate.listJunctions();
1475 event_hadronize.list();
1476 event_hadronize.listJunctions();
1477 logg[
LPythia].error(
"No parton with col = ", col[j],
1478 " connected with junction leg ", j);
1479 throw std::runtime_error(
"Hard string could not be identified.");
1482 pSum += event_intermediate[ifound].p();
1484 event_hadronize.append(event_intermediate[ifound]);
1486 event_intermediate.remove(ifound, ifound);
1488 "Hard non-diff: event_intermediate reduces in size to ",
1489 event_intermediate.size());
1499 event_hadronize[0].p(pSum);
1500 event_hadronize[0].m(pSum.mCalc());
1505 const std::array<FourVector, 2> ustrcom = {
FourVector(1., 0., 0., 0.),
1519 std::swap(baryon, antibaryon);
1521 if (baryon.
baryon_number() != 1 || antibaryon.baryon_number() != -1) {
1522 throw std::invalid_argument(
"Expected baryon-antibaryon pair.");
1526 constexpr
int n_q_types = 5;
1527 std::vector<int> qcount_bar, qcount_antibar;
1528 std::vector<int> n_combinations;
1529 bool no_combinations =
true;
1530 for (
int i = 0; i < n_q_types; i++) {
1532 qcount_antibar.push_back(-antibaryon.net_quark_number(i + 1));
1533 const int n_i = qcount_bar[i] * qcount_antibar[i];
1534 n_combinations.push_back(n_i);
1536 no_combinations =
false;
1542 if (no_combinations) {
1543 for (
int i = 0; i < 2; i++) {
1557 const int q_annihilate = discrete_distr() + 1;
1558 qcount_bar[q_annihilate - 1]--;
1559 qcount_antibar[q_annihilate - 1]--;
1562 std::vector<int> remaining_quarks, remaining_antiquarks;
1563 for (
int i = 0; i < n_q_types; i++) {
1564 for (
int j = 0; j < qcount_bar[i]; j++) {
1565 remaining_quarks.push_back(i + 1);
1567 for (
int j = 0; j < qcount_antibar[i]; j++) {
1568 remaining_antiquarks.push_back(-(i + 1));
1571 assert(remaining_quarks.size() == 2);
1572 assert(remaining_antiquarks.size() == 2);
1578 std::swap(remaining_quarks[0], remaining_quarks[1]);
1581 std::swap(remaining_antiquarks[0], remaining_antiquarks[1]);
1584 bool kin_threshold_satisfied =
true;
1585 for (
int i = 0; i < 2; i++) {
1586 const double mstr_min =
1589 if (mstr_min > mstr[i]) {
1590 kin_threshold_satisfied =
false;
1593 if (!kin_threshold_satisfied) {
1597 for (
int i = 0; i < 2; i++) {
1598 ParticleList new_intermediate_particles;
1602 fragment_string(remaining_quarks[i], remaining_antiquarks[i], mstr[i],
1603 evec,
true,
false, new_intermediate_particles);
1616 ThreeVector &evec_polar, std::array<ThreeVector, 3> &evec_basis) {
1619 if (std::abs(evec_polar.
x3()) < (1. - 1.0e-8)) {
1624 evec_basis[0] = evec_polar;
1626 theta = std::acos(evec_basis[0].x3());
1628 ex = evec_basis[0].x1();
1629 ey = evec_basis[0].x2();
1630 et = std::sqrt(ex * ex + ey * ey);
1632 phi = std::acos(ex / et);
1634 phi = -std::acos(ex / et);
1639 evec_basis[1].set_x1(std::cos(theta) * std::cos(phi));
1640 evec_basis[1].set_x2(std::cos(theta) * std::sin(phi));
1641 evec_basis[1].set_x3(-std::sin(theta));
1643 evec_basis[2].set_x1(-std::sin(phi));
1644 evec_basis[2].set_x2(std::cos(phi));
1645 evec_basis[2].set_x3(0.);
1648 if (evec_polar.
x3() > 0.) {
1659 assert(std::fabs(evec_basis[1] * evec_basis[2]) <
really_small);
1660 assert(std::fabs(evec_basis[2] * evec_basis[0]) <
really_small);
1661 assert(std::fabs(evec_basis[0] * evec_basis[1]) <
really_small);
1674 assert((std::abs(diquark) > 1000) && (std::abs(diquark) < 5510) &&
1675 (std::abs(diquark) % 100 < 10));
1678 deg_spin = std::abs(diquark) % 10;
1680 const int sign_anti = diquark > 0 ? 1 : -1;
1683 q1 = sign_anti * (std::abs(diquark) - (std::abs(diquark) % 1000)) / 1000;
1684 q2 = sign_anti * (std::abs(diquark) % 1000 - deg_spin) / 100;
1688 assert((q1 > 0 && q2 > 0) || (q1 < 0 && q2 < 0));
1689 if (std::abs(q1) < std::abs(q2)) {
1692 int diquark = std::abs(q1 * 1000 + q2 * 100);
1697 return (q1 < 0) ? -diquark : diquark;
1744 std::swap(idq1, idq2);
1750 bool separate_fragment_baryon,
1751 ParticleList &intermediate_particles) {
1753 intermediate_particles.clear();
1755 logg[
LPythia].debug(
"initial quark content for fragment_string : ", idq1,
1757 logg[
LPythia].debug(
"initial string mass (GeV) for fragment_string : ",
1760 std::array<int, 2> idqIn;
1766 std::array<double, 2> m_const;
1768 for (
int i = 0; i < 2; i++) {
1770 bstring +=
pythia_hadron_->particleData.baryonNumberType(idqIn[i]);
1774 logg[
LPythia].debug(
"baryon number of string times 3 : ", bstring);
1781 evecLong = -evecLong;
1784 if (m_const[0] + m_const[1] > mString) {
1785 throw std::runtime_error(
"String fragmentation: m1 + m2 > mString");
1787 Pythia8::Vec4 pSum = 0.;
1789 int number_of_fragments = 0;
1790 bool do_string_fragmentation =
false;
1794 double ppos_string_new, pneg_string_new;
1797 double QTrx_string_new, QTry_string_new, QTrn_string_new;
1799 double mTrn_string_new;
1801 double mass_string_new;
1805 double QTrx_add_pos, QTry_add_pos;
1808 double QTrx_add_neg, QTry_add_neg;
1820 std::array<ThreeVector, 3> evec_basis;
1823 if (separate_fragment_baryon && (std::abs(bstring) == 3) &&
1824 (mString > m_const[0] + m_const[1] + 1.)) {
1831 std::vector<int> pdgid_frag_prior;
1834 std::vector<FourVector> momentum_frag_prior;
1837 double QTrx_string_pos;
1839 double QTrx_string_neg;
1841 double QTry_string_pos;
1843 double QTry_string_neg;
1846 double QTrn_string_pos;
1849 double QTrn_string_neg;
1851 std::array<double, 2> m_trans;
1854 const int niter_max = 10000;
1855 bool found_leading_baryon =
false;
1856 for (
int iiter = 0; iiter < niter_max; iiter++) {
1858 pdgid_frag_prior.clear();
1859 momentum_frag_prior.clear();
1861 std::vector<int> pdgid_frag;
1862 std::vector<FourVector> momentum_frag;
1864 ppos_string_new = mString * M_SQRT1_2;
1865 pneg_string_new = mString * M_SQRT1_2;
1867 QTrx_string_pos = 0.;
1868 QTrx_string_neg = 0.;
1869 QTrx_string_new = 0.;
1870 QTry_string_pos = 0.;
1871 QTry_string_neg = 0.;
1872 QTry_string_new = 0.;
1874 Pythia8::FlavContainer flav_string_pos =
1875 bstring > 0 ? Pythia8::FlavContainer(idq2)
1876 : Pythia8::FlavContainer(idq1);
1878 Pythia8::FlavContainer flav_string_neg =
1879 bstring > 0 ? Pythia8::FlavContainer(idq1)
1880 : Pythia8::FlavContainer(idq2);
1882 bool found_forward_baryon =
false;
1884 bool done_forward_end =
false;
1887 bool energy_used_up =
false;
1888 while (!found_forward_baryon && !energy_used_up) {
1899 separate_fragment_baryon && from_forward && !done_forward_end,
1900 evec_basis, ppos_string_new, pneg_string_new, QTrx_string_pos,
1901 QTrx_string_neg, QTry_string_pos, QTry_string_neg, flav_string_pos,
1902 flav_string_neg, pdgid_frag, momentum_frag);
1908 QTrx_string_new = QTrx_string_pos + QTrx_string_neg;
1909 QTry_string_new = QTry_string_pos + QTry_string_neg;
1913 idqIn[0] = bstring > 0 ? flav_string_neg.id : flav_string_pos.id;
1914 idqIn[1] = bstring > 0 ? flav_string_pos.id : flav_string_neg.id;
1915 for (
int i = 0; i < 2; i++) {
1918 QTrn_string_pos = std::sqrt(QTrx_string_pos * QTrx_string_pos +
1919 QTry_string_pos * QTry_string_pos);
1920 QTrn_string_neg = std::sqrt(QTrx_string_neg * QTrx_string_neg +
1921 QTry_string_neg * QTry_string_neg);
1926 m_trans[0] = std::sqrt(m_const[0] * m_const[0] +
1927 QTrn_string_neg * QTrn_string_neg);
1931 m_trans[1] = std::sqrt(m_const[1] * m_const[1] +
1932 QTrn_string_pos * QTrn_string_pos);
1937 m_trans[0] = std::sqrt(m_const[0] * m_const[0] +
1938 QTrn_string_pos * QTrn_string_pos);
1942 m_trans[1] = std::sqrt(m_const[1] * m_const[1] +
1943 QTrn_string_neg * QTrn_string_neg);
1945 done_forward_end = done_forward_end || from_forward;
1946 found_forward_baryon =
1947 found_forward_baryon ||
1952 energy_used_up =
true;
1956 n_frag_prior += n_frag;
1957 for (
int i_frag = 0; i_frag < n_frag; i_frag++) {
1958 pdgid_frag_prior.push_back(pdgid_frag[i_frag]);
1959 momentum_frag_prior.push_back(momentum_frag[i_frag]);
1967 double mTsqr_string = 2. * ppos_string_new * pneg_string_new;
1968 mTrn_string_new = std::sqrt(mTsqr_string);
1969 QTrn_string_new = std::sqrt(QTrx_string_new * QTrx_string_new +
1970 QTry_string_new * QTry_string_new);
1971 if (mTrn_string_new < QTrn_string_new) {
1974 found_leading_baryon =
false;
1978 std::sqrt(mTsqr_string - QTrn_string_new * QTrn_string_new);
1982 if (mass_string_new > m_const[0] + m_const[1]) {
1983 do_string_fragmentation =
true;
1984 found_leading_baryon =
true;
1985 QTrx_add_pos = QTrx_string_pos;
1986 QTry_add_pos = QTry_string_pos;
1987 QTrx_add_neg = QTrx_string_neg;
1988 QTry_add_neg = QTry_string_neg;
1990 found_leading_baryon =
false;
1993 }
else if (n_frag == 2) {
1996 do_string_fragmentation =
false;
1997 found_leading_baryon =
true;
2001 if (found_leading_baryon) {
2005 if (found_leading_baryon) {
2008 for (
int i_frag = 0; i_frag < n_frag_prior; i_frag++) {
2009 logg[
LPythia].debug(
"appending the the fragmented hadron ",
2010 pdgid_frag_prior[i_frag],
2011 " to the intermediate particle list.");
2014 momentum_frag_prior[i_frag],
2015 intermediate_particles);
2017 logg[
LPythia].error(
"PDG ID ", pdgid_frag_prior[i_frag],
2018 " should exist in ParticleType.");
2019 throw std::runtime_error(
"string fragmentation failed.");
2021 number_of_fragments++;
2029 if (do_string_fragmentation) {
2030 mTrn_string_new = std::sqrt(2. * ppos_string_new * pneg_string_new);
2032 std::array<double, 2> ppos_parton;
2034 std::array<double, 2> pneg_parton;
2042 const double pb_const =
2043 (mTrn_string_new * mTrn_string_new + m_trans[0] * m_trans[0] -
2044 m_trans[1] * m_trans[1]) /
2045 (4. * pneg_string_new);
2046 const double pc_const =
2047 0.5 * m_trans[0] * m_trans[0] * ppos_string_new / pneg_string_new;
2048 ppos_parton[0] = pb_const + (bstring > 0 ? -1. : 1.) *
2049 std::sqrt(pb_const * pb_const - pc_const);
2050 ppos_parton[1] = ppos_string_new - ppos_parton[0];
2054 for (
int i = 0; i < 2; i++) {
2055 pneg_parton[i] = 0.5 * m_trans[i] * m_trans[i] / ppos_parton[i];
2058 const int status = 1;
2059 int color, anticolor;
2062 Pythia8::Vec4 pquark;
2082 bstring > 0 ? evec_basis[1] * (QTrx_string_neg - QTrx_add_neg) +
2083 evec_basis[2] * (QTry_string_neg - QTry_add_neg)
2084 : evec_basis[1] * (QTrx_string_pos - QTrx_add_pos) +
2085 evec_basis[2] * (QTry_string_pos - QTry_add_pos);
2087 evec_basis[0] * (ppos_parton[0] - pneg_parton[0]) * M_SQRT1_2 +
2089 const double E_quark =
2090 std::sqrt(m_const[0] * m_const[0] + three_mom.
sqr());
2091 pquark =
set_Vec4(E_quark, three_mom);
2093 pythia_hadron_->event.append(idqIn[0], status, color, anticolor, pquark,
2114 bstring > 0 ? evec_basis[1] * (QTrx_string_pos - QTrx_add_pos) +
2115 evec_basis[2] * (QTry_string_pos - QTry_add_pos)
2116 : evec_basis[1] * (QTrx_string_neg - QTrx_add_neg) +
2117 evec_basis[2] * (QTry_string_neg - QTry_add_neg);
2119 evec_basis[0] * (ppos_parton[1] - pneg_parton[1]) * M_SQRT1_2 +
2121 const double E_antiq =
2122 std::sqrt(m_const[1] * m_const[1] + three_mom.
sqr());
2123 pquark =
set_Vec4(E_antiq, three_mom);
2125 pythia_hadron_->event.append(idqIn[1], status, color, anticolor, pquark,
2129 do_string_fragmentation =
true;
2131 ppos_string_new = mString * M_SQRT1_2;
2132 pneg_string_new = mString * M_SQRT1_2;
2133 QTrx_string_new = 0.;
2134 QTry_string_new = 0.;
2135 QTrn_string_new = 0.;
2136 mTrn_string_new = mString;
2137 mass_string_new = mString;
2142 double sign_direction = 1.;
2143 if (bstring == -3) {
2147 sign_direction = -1;
2151 const double pCMquark =
pCM(mString, m_const[0], m_const[1]);
2152 const double E1 = std::sqrt(m_const[0] * m_const[0] + pCMquark * pCMquark);
2153 const double E2 = std::sqrt(m_const[1] * m_const[1] + pCMquark * pCMquark);
2155 ThreeVector direction = sign_direction * evecLong;
2158 const int status1 = 1, color1 = 1, anticolor1 = 0;
2159 Pythia8::Vec4 pquark =
set_Vec4(E1, -direction * pCMquark);
2161 pythia_hadron_->event.append(idqIn[0], status1, color1, anticolor1, pquark,
2164 const int status2 = 1, color2 = 0, anticolor2 = 1;
2165 pquark =
set_Vec4(E2, direction * pCMquark);
2167 pythia_hadron_->event.append(idqIn[1], status2, color2, anticolor2, pquark,
2171 if (do_string_fragmentation) {
2172 logg[
LPythia].debug(
"fragmenting a string with ", idqIn[0],
", ", idqIn[1]);
2177 if (!successful_hadronization) {
2184 pythia_hadron_->event, evec_basis, ppos_string_new, pneg_string_new,
2185 QTrx_string_new, QTry_string_new, QTrx_add_pos, QTry_add_pos,
2186 QTrx_add_neg, QTry_add_neg);
2187 if (!successful_kinematics) {
2191 for (
int ipyth = 0; ipyth <
pythia_hadron_->event.size(); ipyth++) {
2202 logg[
LPythia].debug(
"appending the fragmented hadron ", pythia_id,
2203 " to the intermediate particle list.");
2208 " does not exist in ParticleType - start over.");
2209 intermediate_particles.clear();
2213 number_of_fragments++;
2216 return number_of_fragments;
2220 bool from_forward,
bool separate_fragment_baryon,
2221 std::array<ThreeVector, 3> &evec_basis,
double &ppos_string,
2222 double &pneg_string,
double &QTrx_string_pos,
double &QTrx_string_neg,
2223 double &QTry_string_pos,
double &QTry_string_neg,
2224 Pythia8::FlavContainer &flav_string_pos,
2225 Pythia8::FlavContainer &flav_string_neg, std::vector<int> &pdgid_frag,
2226 std::vector<FourVector> &momentum_frag) {
2229 const int n_try = 10;
2231 momentum_frag.clear();
2233 if (ppos_string < 0. || pneg_string < 0.) {
2234 throw std::runtime_error(
"string has a negative lightcone momentum.");
2236 double mTsqr_string = 2. * ppos_string * pneg_string;
2238 double mTrn_string = std::sqrt(mTsqr_string);
2240 double QTrx_string_tot = QTrx_string_pos + QTrx_string_neg;
2241 double QTry_string_tot = QTry_string_pos + QTry_string_neg;
2242 double QTsqr_string_tot = std::fabs(QTrx_string_tot * QTrx_string_tot) +
2243 std::fabs(QTry_string_tot * QTry_string_tot);
2244 double QTrn_string_tot = std::sqrt(QTsqr_string_tot);
2245 if (mTrn_string < QTrn_string_tot) {
2249 double mass_string = std::sqrt(mTsqr_string - QTsqr_string_tot);
2250 logg[
LPythia].debug(
" Fragment off one hadron from a string ( ",
2251 flav_string_pos.id,
" , ", flav_string_neg.id,
2252 " ) with mass ", mass_string,
" GeV.");
2255 const double sigma_qt_frag =
pythia_hadron_->parm(
"StringPT:sigma");
2256 const double stop_string_mass =
2258 const double stop_string_smear =
2262 const double prob_enhance_qt =
2264 double fac_enhance_qt;
2268 fac_enhance_qt = 1.;
2282 logg[
LPythia].debug(
" Transverse momentum (", QTrx_new,
", ", QTry_new,
2283 ") GeV selected for the new qqbar pair.");
2292 double QTrx_had_1st =
2293 from_forward ? QTrx_string_pos + QTrx_new : QTrx_string_neg + QTrx_new;
2294 double QTry_had_1st =
2295 from_forward ? QTry_string_pos + QTry_new : QTry_string_neg + QTry_new;
2296 double QTrn_had_1st =
2297 std::sqrt(QTrx_had_1st * QTrx_had_1st + QTry_had_1st * QTry_had_1st);
2300 int pdgid_had_1st = 0;
2302 double mass_had_1st = 0.;
2305 Pythia8::FlavContainer flav_old =
2306 from_forward ? flav_string_pos : flav_string_neg;
2311 Pythia8::FlavContainer flav_new = Pythia8::FlavContainer(0);
2315 for (
int i_try = 0; i_try < n_try; i_try++) {
2320 if (pdgid_had_1st != 0) {
2323 logg[
LPythia].debug(
" number of tries of flavor selection : ",
2324 i_try + 1,
" in StringProcess::fragment_off_hadron.");
2328 if (pdgid_had_1st == 0) {
2332 " selected for the string end with ", flav_old.id);
2334 " selected for the (first) fragmented hadron.");
2335 bool had_1st_baryon =
pythia_hadron_->particleData.isBaryon(pdgid_had_1st);
2337 double mTrn_had_1st =
2338 std::sqrt(mass_had_1st * mass_had_1st + QTrn_had_1st * QTrn_had_1st);
2339 logg[
LPythia].debug(
" Transverse momentum (", QTrx_had_1st,
", ",
2341 ") GeV selected for the (first) fragmented hadron.");
2346 const double mass_min_to_continue =
2347 (stop_string_mass +
pythia_hadron_->particleData.m0(flav_new.id) +
2353 bool string_into_final_two = mass_string < mass_min_to_continue;
2354 if (string_into_final_two) {
2355 logg[
LPythia].debug(
" The string mass is below the mass threshold ",
2356 mass_min_to_continue,
2357 " GeV : finishing with two hadrons.");
2361 double ppos_had_1st = 0.;
2362 double pneg_had_1st = 0.;
2366 bool from_diquark_end =
2367 from_forward ?
pythia_hadron_->particleData.isDiquark(flav_string_pos.id)
2370 bool has_diquark_pos =
2374 if (string_into_final_two) {
2378 int pdgid_had_2nd = 0.;
2380 double mass_had_2nd = 0.;
2383 Pythia8::FlavContainer flav_new2 = Pythia8::FlavContainer(0);
2384 flav_new2.anti(flav_new);
2387 if (
pythia_hadron_->particleData.isDiquark(flav_string_neg.id) &&
2388 pythia_hadron_->particleData.isDiquark(flav_new2.id) && from_forward) {
2391 if (
pythia_hadron_->particleData.isDiquark(flav_string_pos.id) &&
2392 pythia_hadron_->particleData.isDiquark(flav_new2.id) && !from_forward) {
2395 for (
int i_try = 0; i_try < n_try; i_try++) {
2400 if (pdgid_had_2nd != 0) {
2406 if (pdgid_had_2nd == 0) {
2410 " selected for the (second) fragmented hadron.");
2411 bool had_2nd_baryon =
pythia_hadron_->particleData.isBaryon(pdgid_had_2nd);
2419 double QTrx_had_2nd =
2420 from_forward ? QTrx_string_neg - QTrx_new : QTrx_string_pos - QTrx_new;
2421 double QTry_had_2nd =
2422 from_forward ? QTry_string_neg - QTry_new : QTry_string_pos - QTry_new;
2423 double QTrn_had_2nd =
2424 std::sqrt(QTrx_had_2nd * QTrx_had_2nd + QTry_had_2nd * QTry_had_2nd);
2425 double mTrn_had_2nd =
2426 std::sqrt(mass_had_2nd * mass_had_2nd + QTrn_had_2nd * QTrn_had_2nd);
2427 logg[
LPythia].debug(
" Transverse momentum (", QTrx_had_2nd,
", ",
2429 ") GeV selected for the (second) fragmented hadron.");
2431 double ppos_had_2nd = 0.;
2432 double pneg_had_2nd = 0.;
2438 bool found_kinematics =
2441 separate_fragment_baryon && has_diquark_pos && had_1st_baryon,
2442 ppos_string, pneg_string, mTrn_had_1st, mTrn_had_2nd,
2443 ppos_had_1st, ppos_had_2nd, pneg_had_1st, pneg_had_2nd)
2445 separate_fragment_baryon && has_diquark_pos && had_2nd_baryon,
2446 ppos_string, pneg_string, mTrn_had_2nd, mTrn_had_1st,
2447 ppos_had_2nd, ppos_had_1st, pneg_had_2nd, pneg_had_1st);
2448 if (!found_kinematics) {
2455 QTrx_string_pos = 0.;
2456 QTry_string_pos = 0.;
2459 pdgid_frag.push_back(pdgid_had_1st);
2461 (ppos_had_1st + pneg_had_1st) * M_SQRT1_2,
2462 evec_basis[0] * (ppos_had_1st - pneg_had_1st) * M_SQRT1_2 +
2463 evec_basis[1] * QTrx_had_1st + evec_basis[2] * QTry_had_1st);
2464 momentum_frag.push_back(mom_had_1st);
2467 pdgid_frag.push_back(pdgid_had_2nd);
2469 (ppos_had_2nd + pneg_had_2nd) * M_SQRT1_2,
2470 evec_basis[0] * (ppos_had_2nd - pneg_had_2nd) * M_SQRT1_2 +
2471 evec_basis[1] * QTrx_had_2nd + evec_basis[2] * QTry_had_2nd);
2472 momentum_frag.push_back(mom_had_2nd);
2481 double stringz_a_use, stringz_b_use;
2484 if (separate_fragment_baryon && from_diquark_end && had_1st_baryon) {
2494 double xfrac =
sample_zLund(stringz_a_use, stringz_b_use, mTrn_had_1st);
2498 ppos_had_1st = xfrac * ppos_string;
2499 pneg_had_1st = 0.5 * mTrn_had_1st * mTrn_had_1st / ppos_had_1st;
2500 if (pneg_had_1st > pneg_string) {
2506 pneg_had_1st = xfrac * pneg_string;
2507 ppos_had_1st = 0.5 * mTrn_had_1st * mTrn_had_1st / pneg_had_1st;
2508 if (ppos_had_1st > ppos_string) {
2514 pdgid_frag.push_back(pdgid_had_1st);
2516 (ppos_had_1st + pneg_had_1st) * M_SQRT1_2,
2517 evec_basis[0] * (ppos_had_1st - pneg_had_1st) * M_SQRT1_2 +
2518 evec_basis[1] * QTrx_had_1st + evec_basis[2] * QTry_had_1st);
2519 momentum_frag.push_back(mom_had_1st);
2522 ppos_string -= ppos_had_1st;
2523 pneg_string -= pneg_had_1st;
2533 flav_string_pos.anti(flav_new);
2534 QTrx_string_pos = -QTrx_new;
2535 QTry_string_pos = -QTry_new;
2539 flav_string_neg.anti(flav_new);
2540 QTrx_string_neg = -QTrx_new;
2541 QTry_string_neg = -QTry_new;
2551 const int baryon_number =
2555 int pdgid_hadron = 0;
2558 Pythia8::FlavContainer flav1 = Pythia8::FlavContainer(idq1);
2559 Pythia8::FlavContainer flav2 = Pythia8::FlavContainer(idq2);
2560 const int n_try = 10;
2561 for (
int i_try = 0; i_try < n_try; i_try++) {
2563 if (pdgid_hadron != 0) {
2564 return pdgid_hadron;
2572 std::array<int, 5> frag_net_q;
2575 for (
int iq = 0; iq < 5; iq++) {
2577 pythia_hadron_->particleData.nQuarksInCode(std::abs(idq1), iq + 1);
2579 pythia_hadron_->particleData.nQuarksInCode(std::abs(idq2), iq + 1);
2580 nq1 = idq1 > 0 ? nq1 : -nq1;
2581 nq2 = idq2 > 0 ? nq2 : -nq2;
2582 frag_net_q[iq] = nq1 + nq2;
2584 const int frag_iso3 = frag_net_q[1] - frag_net_q[0];
2585 const int frag_strange = -frag_net_q[2];
2586 const int frag_charm = frag_net_q[3];
2587 const int frag_bottom = -frag_net_q[4];
2588 logg[
LPythia].debug(
" conserved charges : iso3 = ", frag_iso3,
2589 ", strangeness = ", frag_strange,
2590 ", charmness = ", frag_charm,
2591 ", bottomness = ", frag_bottom);
2593 std::vector<int> pdgid_possible;
2594 std::vector<double> weight_possible;
2595 std::vector<double> weight_summed;
2600 if (!ptype.is_hadron()) {
2603 const int pdgid = ptype.pdgcode().get_decimal();
2605 (baryon_number == 3 * ptype.pdgcode().baryon_number()) &&
2606 (frag_iso3 == ptype.pdgcode().isospin3()) &&
2607 (frag_strange == ptype.pdgcode().strangeness()) &&
2608 (frag_charm == ptype.pdgcode().charmness()) &&
2609 (frag_bottom == ptype.pdgcode().bottomness())) {
2610 const int spin_degeneracy = ptype.pdgcode().spin_degeneracy();
2611 const double mass_pole = ptype.mass();
2612 const double weight = static_cast<double>(spin_degeneracy) / mass_pole;
2613 pdgid_possible.push_back(pdgid);
2614 weight_possible.push_back(weight);
2616 logg[
LPythia].debug(
" PDG id ", pdgid,
" is possible with weight ",
2620 const int n_possible = pdgid_possible.size();
2621 weight_summed.push_back(0.);
2622 for (
int i = 0; i < n_possible; i++) {
2623 weight_summed.push_back(weight_summed[i] + weight_possible[i]);
2629 for (
int i = 0; i < n_possible; i++) {
2630 if ((uspc >= weight_summed[i]) && (uspc < weight_summed[i + 1])) {
2631 return pdgid_possible[i];
2648 bool end1_is_quark = idq1 > 0 &&
pythia_hadron_->particleData.isQuark(idq1);
2649 bool end1_is_antidiq =
2652 bool end2_is_antiq = idq2 < 0 &&
pythia_hadron_->particleData.isQuark(idq2);
2653 bool end2_is_diquark =
2657 if (end1_is_quark) {
2658 if (end2_is_antiq) {
2661 }
else if (end2_is_diquark) {
2667 }
else if (end1_is_antidiq) {
2668 if (end2_is_antiq) {
2681 std::array<int, 5> net_qnumber;
2682 for (
int iflav = 0; iflav < 5; iflav++) {
2683 net_qnumber[iflav] = 0;
2686 pythia_hadron_->particleData.nQuarksInCode(std::abs(idq1), iflav + 1);
2689 qnumber1 = -qnumber1;
2691 net_qnumber[iflav] += qnumber1;
2694 pythia_hadron_->particleData.nQuarksInCode(std::abs(idq2), iflav + 1);
2697 qnumber2 = -qnumber2;
2699 net_qnumber[iflav] += qnumber2;
2703 std::vector<int> pdgid_possible;
2705 std::vector<double> mass_diff;
2707 if (!ptype.is_hadron() || ptype.is_stable() ||
2708 ptype.pdgcode().baryon_number() != baryon) {
2712 const int pdgid = ptype.pdgcode().get_decimal();
2713 const double mass_min = ptype.min_mass_spectral();
2714 if (mass < mass_min) {
2719 if (ptype.pdgcode().isospin3() != net_qnumber[1] - net_qnumber[0]) {
2723 if (ptype.pdgcode().strangeness() != -net_qnumber[2]) {
2727 if (ptype.pdgcode().charmness() != net_qnumber[3]) {
2731 if (ptype.pdgcode().bottomness() != -net_qnumber[4]) {
2736 const double mass_pole = ptype.mass();
2738 pdgid_possible.push_back(pdgid);
2739 mass_diff.push_back(mass - mass_pole);
2742 const int n_res = pdgid_possible.size();
2748 int ires_closest = 0;
2749 double mass_diff_min = std::fabs(mass_diff[0]);
2752 for (
int ires = 1; ires < n_res; ires++) {
2753 if (std::fabs(mass_diff[ires]) < mass_diff_min) {
2754 ires_closest = ires;
2755 mass_diff_min = mass_diff[ires];
2758 logg[
LPythia].debug(
"Quark constituents ", idq1,
" and ", idq2,
" with mass ",
2759 mass,
" (GeV) turned into a resonance ",
2760 pdgid_possible[ires_closest]);
2761 return pdgid_possible[ires_closest];
2765 bool separate_fragment_hadron,
double ppos_string,
double pneg_string,
2766 double mTrn_had_forward,
double mTrn_had_backward,
double &ppos_had_forward,
2767 double &ppos_had_backward,
double &pneg_had_forward,
2768 double &pneg_had_backward) {
2769 const double mTsqr_string = 2. * ppos_string * pneg_string;
2770 if (mTsqr_string < 0.) {
2773 const double mTrn_string = std::sqrt(mTsqr_string);
2774 if (mTrn_string < mTrn_had_forward + mTrn_had_backward) {
2779 const double mTsqr_had_forward = mTrn_had_forward * mTrn_had_forward;
2781 const double mTsqr_had_backward = mTrn_had_backward * mTrn_had_backward;
2795 const double xm_diff =
2796 (mTsqr_had_forward - mTsqr_had_backward) / mTsqr_string;
2797 const double xe_pos = 0.5 * (1. + xm_diff);
2798 const double xe_neg = 0.5 * (1. - xm_diff);
2801 const double lambda_sqr =
2802 pow_int(mTsqr_string - mTsqr_had_forward - mTsqr_had_backward, 2) -
2803 4. * mTsqr_had_forward * mTsqr_had_backward;
2804 if (lambda_sqr <= 0.) {
2807 const double lambda = std::sqrt(lambda_sqr);
2808 const double b_lund =
2813 const double prob_reverse =
2814 std::exp(-b_lund * lambda) / (1. + std::exp(-b_lund * lambda));
2815 double xpz_pos = 0.5 * lambda / mTsqr_string;
2820 ppos_had_forward = (xe_pos + xpz_pos) * ppos_string;
2821 ppos_had_backward = (xe_neg - xpz_pos) * ppos_string;
2823 pneg_had_forward = 0.5 * mTsqr_had_forward / ppos_had_forward;
2824 pneg_had_backward = 0.5 * mTsqr_had_backward / ppos_had_backward;
2832 bool xfrac_accepted =
false;
2840 while (!xfrac_accepted) {
2841 const double fac_env = b * mTrn * mTrn;
2845 const double xfrac_inv = 1. - std::log(u_aux) / fac_env;
2846 assert(xfrac_inv >= 1.);
2849 const double xf_ratio = std::pow(1. - 1. / xfrac_inv, a) / xfrac_inv;
2854 xfrac = 1. / xfrac_inv;
2855 xfrac_accepted =
true;
2862 Pythia8::Event &event_fragments, std::array<ThreeVector, 3> &evec_basis,
2863 double ppos_string,
double pneg_string,
double QTrx_string,
2864 double QTry_string,
double QTrx_add_pos,
double QTry_add_pos,
2865 double QTrx_add_neg,
double QTry_add_neg) {
2866 logg[
LPythia].debug(
"Correcting the kinematics of fragmented hadrons...");
2868 if (ppos_string < 0. || pneg_string < 0.) {
2870 " wrong lightcone momenta of string : ppos_string (GeV) = ",
2871 ppos_string,
" pneg_string (GeV) = ", pneg_string);
2875 const double yrapid_string = 0.5 * std::log(ppos_string / pneg_string);
2876 logg[
LOutput].debug(
"Momentum-space rapidity of the string should be ",
2880 const double mTrn_string = std::sqrt(2. * ppos_string * pneg_string);
2881 logg[
LOutput].debug(
"Transvere mass (GeV) of the string should be ",
2884 const double QTrn_string =
2885 std::sqrt(QTrx_string * QTrx_string + QTry_string * QTry_string);
2886 if (mTrn_string < QTrn_string) {
2888 " wrong transverse mass of string : mTrn_string (GeV) = ", mTrn_string,
2889 " QTrn_string (GeV) = ", QTrn_string);
2892 const double msqr_string =
2893 mTrn_string * mTrn_string - QTrn_string * QTrn_string;
2895 const double mass_string = std::sqrt(msqr_string);
2896 logg[
LOutput].debug(
"The string mass (GeV) should be ", mass_string);
2900 if (std::fabs(QTrx_add_pos) <
small_number * mass_string &&
2901 std::fabs(QTry_add_pos) <
small_number * mass_string &&
2902 std::fabs(QTrx_add_neg) <
small_number * mass_string &&
2903 std::fabs(QTry_add_neg) <
small_number * mass_string) {
2904 logg[
LOutput].debug(
" no need to add transverse momenta - skipping.");
2910 for (
int ipyth = 1; ipyth < event_fragments.size(); ipyth++) {
2911 if (!event_fragments[ipyth].isFinal()) {
2916 FourVector(event_fragments[ipyth].e(), event_fragments[ipyth].px(),
2917 event_fragments[ipyth].py(), event_fragments[ipyth].pz());
2918 ptot_string_ini += p_frag;
2920 const double E_string_ini = ptot_string_ini.
x0();
2921 const double pz_string_ini = ptot_string_ini.
threevec() * evec_basis[0];
2922 const double ppos_string_ini = (E_string_ini + pz_string_ini) * M_SQRT1_2;
2923 const double pneg_string_ini = (E_string_ini - pz_string_ini) * M_SQRT1_2;
2925 const double yrapid_string_ini =
2926 0.5 * std::log(ppos_string_ini / pneg_string_ini);
2932 int ip_backward = 0;
2933 double y_forward = 0.;
2934 double y_backward = 0.;
2935 ptot_string_ini =
FourVector(0., 0., 0., 0.);
2937 for (
int ipyth = 1; ipyth < event_fragments.size(); ipyth++) {
2938 if (!event_fragments[ipyth].isFinal()) {
2943 FourVector(event_fragments[ipyth].e(), event_fragments[ipyth].px(),
2944 event_fragments[ipyth].py(), event_fragments[ipyth].pz());
2945 ptot_string_ini += p_frag;
2947 const double E_frag = p_frag.
x0();
2948 const double pl_frag = p_frag.
threevec() * evec_basis[0];
2949 double y_current = 0.5 * std::log((E_frag + pl_frag) / (E_frag - pl_frag));
2950 if (y_current > y_forward) {
2952 y_forward = y_current;
2954 if (y_current < y_backward) {
2955 ip_backward = ipyth;
2956 y_backward = y_current;
2959 logg[
LOutput].debug(
" The most forward hadron is ip_forward = ", ip_forward,
2960 " with rapidity ", y_forward);
2961 logg[
LOutput].debug(
" The most backward hadron is ip_backward = ",
2962 ip_backward,
" with rapidity ", y_backward);
2964 const double px_string_ini = ptot_string_ini.
threevec() * evec_basis[1];
2965 const double py_string_ini = ptot_string_ini.
threevec() * evec_basis[2];
2969 bool correct_px = std::fabs(px_string_ini + QTrx_add_pos + QTrx_add_neg -
2973 " input transverse momenta in x-axis are not consistent.");
2978 bool correct_py = std::fabs(py_string_ini + QTry_add_pos + QTry_add_neg -
2982 " input transverse momenta in y-axis are not consistent.");
2986 Pythia8::Vec4 pvec_string_now =
2990 " Adding transverse momentum to the most forward hadron.");
2991 pvec_string_now -= event_fragments[ip_forward].p();
2992 const double mass_frag_pos = event_fragments[ip_forward].p().mCalc();
2995 event_fragments[ip_forward].e(), event_fragments[ip_forward].px(),
2996 event_fragments[ip_forward].py(), event_fragments[ip_forward].pz());
2999 QTrx_add_pos * evec_basis[1] +
3000 QTry_add_pos * evec_basis[2];
3002 double E_new_frag_pos =
3003 std::sqrt(mom_new_frag_pos.
sqr() + mass_frag_pos * mass_frag_pos);
3004 Pythia8::Vec4 pvec_new_frag_pos =
set_Vec4(E_new_frag_pos, mom_new_frag_pos);
3005 pvec_string_now += pvec_new_frag_pos;
3007 event_fragments[ip_forward].p(pvec_new_frag_pos);
3010 " Adding transverse momentum to the most backward hadron.");
3011 pvec_string_now -= event_fragments[ip_backward].p();
3012 const double mass_frag_neg = event_fragments[ip_backward].p().mCalc();
3015 event_fragments[ip_backward].e(), event_fragments[ip_backward].px(),
3016 event_fragments[ip_backward].py(), event_fragments[ip_backward].pz());
3019 QTrx_add_neg * evec_basis[1] +
3020 QTry_add_neg * evec_basis[2];
3022 double E_new_frag_neg =
3023 std::sqrt(mom_new_frag_neg.
sqr() + mass_frag_neg * mass_frag_neg);
3024 Pythia8::Vec4 pvec_new_frag_neg =
set_Vec4(E_new_frag_neg, mom_new_frag_neg);
3025 pvec_string_now += pvec_new_frag_neg;
3027 event_fragments[ip_backward].p(pvec_new_frag_neg);
3030 event_fragments[0].p(pvec_string_now);
3031 event_fragments[0].m(pvec_string_now.mCalc());
3035 double mTrn_frag_all = 0.;
3036 for (
int ipyth = 1; ipyth < event_fragments.size(); ipyth++) {
3037 if (!event_fragments[ipyth].isFinal()) {
3043 FourVector(event_fragments[ipyth].e(), event_fragments[ipyth].px(),
3044 event_fragments[ipyth].py(), event_fragments[ipyth].pz());
3045 ptot_string_ini += p_frag;
3047 const double E_frag = p_frag.
x0();
3048 const double pl_frag = p_frag.
threevec() * evec_basis[0];
3049 const double ppos_frag = (E_frag + pl_frag) * M_SQRT1_2;
3050 const double pneg_frag = (E_frag - pl_frag) * M_SQRT1_2;
3051 const double mTrn_frag = std::sqrt(2. * ppos_frag * pneg_frag);
3052 mTrn_frag_all += mTrn_frag;
3055 "Sum of transverse masses (GeV) of all fragmented hadrons : ",
3059 if (mTrn_string < mTrn_frag_all) {
3060 logg[
LOutput].debug(
" which is larger than mT of the actual string ",
3065 double mass_string_now = pvec_string_now.mCalc();
3066 double msqr_string_now = mass_string_now * mass_string_now;
3069 FourVector(pvec_string_now.e(), pvec_string_now.px(),
3070 pvec_string_now.py(), pvec_string_now.pz());
3071 double E_string_now = p_string_now.
x0();
3072 double pz_string_now = p_string_now.
threevec() * evec_basis[0];
3073 logg[
LOutput].debug(
"The string mass (GeV) at this point : ",
3075 double ppos_string_now = (E_string_now + pz_string_now) * M_SQRT1_2;
3076 double pneg_string_now = (E_string_now - pz_string_now) * M_SQRT1_2;
3078 double yrapid_string_now = 0.5 * std::log(ppos_string_now / pneg_string_now);
3079 logg[
LOutput].debug(
"The momentum-space rapidity of string at this point : ",
3082 "The momentum-space rapidities of hadrons will be changed.");
3083 const int niter_max = 10000;
3084 bool accepted =
false;
3085 double fac_all_yrapid = 1.;
3090 for (
int iiter = 0; iiter < niter_max; iiter++) {
3091 if (std::fabs(mass_string_now - mass_string) <
really_small * mass_string) {
3095 double E_deriv = 0.;
3096 double pz_deriv = 0.;
3100 for (
int ipyth = 1; ipyth < event_fragments.size(); ipyth++) {
3101 if (!event_fragments[ipyth].isFinal()) {
3106 FourVector(event_fragments[ipyth].e(), event_fragments[ipyth].px(),
3107 event_fragments[ipyth].py(), event_fragments[ipyth].pz());
3108 const double E_frag = p_frag.
x0();
3109 const double pl_frag = p_frag.
threevec() * evec_basis[0];
3110 const double ppos_frag = (E_frag + pl_frag) * M_SQRT1_2;
3111 const double pneg_frag = (E_frag - pl_frag) * M_SQRT1_2;
3112 const double mTrn_frag = std::sqrt(2. * ppos_frag * pneg_frag);
3113 const double y_frag = 0.5 * std::log(ppos_frag / pneg_frag);
3115 E_deriv += mTrn_frag * (y_frag - yrapid_string_now) * std::sinh(y_frag);
3116 pz_deriv += mTrn_frag * (y_frag - yrapid_string_now) * std::cosh(y_frag);
3118 double slope = 2. * (E_string_now * E_deriv - pz_string_now * pz_deriv);
3119 double fac_yrapid = 1. + std::tanh((msqr_string - msqr_string_now) / slope);
3120 fac_all_yrapid *= fac_yrapid;
3124 (1. - fac_yrapid) * yrapid_string_now);
3126 pvec_string_now = event_fragments[0].p();
3127 mass_string_now = pvec_string_now.mCalc();
3128 msqr_string_now = mass_string_now * mass_string_now;
3129 p_string_now =
FourVector(pvec_string_now.e(), pvec_string_now.px(),
3130 pvec_string_now.py(), pvec_string_now.pz());
3131 E_string_now = p_string_now.
x0();
3132 pz_string_now = p_string_now.
threevec() * evec_basis[0];
3133 ppos_string_now = (E_string_now + pz_string_now) * M_SQRT1_2;
3134 pneg_string_now = (E_string_now - pz_string_now) * M_SQRT1_2;
3135 yrapid_string_now = 0.5 * std::log(ppos_string_now / pneg_string_now);
3136 logg[
LOutput].debug(
" step ", iiter + 1,
" : fac_yrapid = ", fac_yrapid,
3137 " , string mass (GeV) = ", mass_string_now,
3138 " , string rapidity = ", yrapid_string_now);
3142 logg[
LOutput].debug(
" Too many iterations in rapidity rescaling.");
3146 "The overall factor multiplied to the rapidities of hadrons = ",
3148 logg[
LOutput].debug(
"The momentum-space rapidity of string at this point : ",
3150 const double y_diff = yrapid_string - yrapid_string_now;
3151 logg[
LOutput].debug(
"The hadrons will be boosted by rapidity ", y_diff,
3152 " for the longitudinal momentum conservation.");
3161 double suppression_factor) {
3176 ParticleList &list) {
3177 assert(list.size() >= 2);
3178 int end = list.size() - 1;
3181 i1 <= end && !list[i1].pdgcode().contains_enough_valence_quarks(nq1);
3185 i2 >= 0 && !list[i2].pdgcode().contains_enough_valence_quarks(nq2);
3188 std::pair<int, int> indices(i1, i2);
3193 ParticleList &outgoing_particles,
3195 double suppression_factor) {
3198 data.set_cross_section_scaling_factor(0.0);
3201 std::sort(outgoing_particles.begin(), outgoing_particles.end(),
3204 j.momentum().velocity() * evecLong;
3207 switch (baryon_string) {
3221 throw std::runtime_error(
"string is neither mesonic nor baryonic");
3226 std::pair<int, int> i =
find_leading(nq1, nq2, outgoing_particles);
3227 std::pair<int, int> j =
find_leading(nq2, nq1, outgoing_particles);
3228 if (baryon_string == 0 && i.second - i.first < j.second - j.first) {
3231 suppression_factor);
3235 suppression_factor);
3255 throw std::runtime_error(
"StringProcess::pdg_map_for_pythia failed.");