9 #include "Pythia8/BeamParticle.h"
23 const double BeamParticle::XMINUNRESOLVED = 1. - 1e-10;
29 void BeamParticle::init(
int idIn,
double pzIn,
double eIn,
double mIn,
30 Info* infoPtrIn, Settings& settings, ParticleData* particleDataPtrIn,
31 Rndm* rndmPtrIn,PDF* pdfInPtr, PDF* pdfHardInPtr,
bool isUnresolvedIn,
32 StringFlav* flavSelPtrIn) {
36 particleDataPtr = particleDataPtrIn;
38 pdfBeamPtr = pdfInPtr;
39 pdfHardBeamPtr = pdfHardInPtr;
40 isUnresolvedBeam = isUnresolvedIn;
41 flavSelPtr = flavSelPtrIn;
44 maxValQuark = settings.mode(
"BeamRemnants:maxValQuark");
47 valencePowerMeson = settings.parm(
"BeamRemnants:valencePowerMeson");
48 valencePowerUinP = settings.parm(
"BeamRemnants:valencePowerUinP");
49 valencePowerDinP = settings.parm(
"BeamRemnants:valencePowerDinP");
52 valenceDiqEnhance = settings.parm(
"BeamRemnants:valenceDiqEnhance");
55 companionPower = settings.mode(
"BeamRemnants:companionPower");
58 companionPower = settings.mode(
"BeamRemnants:companionPower");
61 allowJunction = settings.flag(
"BeamRemnants:allowJunction");
64 pickQuarkNorm = settings.parm(
"Diffraction:pickQuarkNorm");
65 pickQuarkPower = settings.parm(
"Diffraction:pickQuarkPower");
68 diffPrimKTwidth = settings.parm(
"Diffraction:primKTwidth");
71 diffLargeMassSuppress = settings.parm(
"Diffraction:largeMassSuppress");
76 pBeam = Vec4( 0., 0., pzIn, eIn);
87 void BeamParticle::initBeamKind() {
90 idBeamAbs = abs(idBeam);
98 if (idBeamAbs > 10 && idBeamAbs < 17) {
106 if (idBeamAbs < 101 || idBeamAbs > 9999)
return;
109 if (idBeamAbs == 990) {
117 }
else if (idBeamAbs < 1000) {
118 int id1 = idBeamAbs/100;
119 int id2 = (idBeamAbs/10)%10;
120 if ( id1 < 1 || id1 > maxValQuark
121 || id2 < 1 || id2 > maxValQuark )
return;
139 int id1 = idBeamAbs/1000;
140 int id2 = (idBeamAbs/100)%10;
141 int id3 = (idBeamAbs/10)%10;
142 if ( id1 < 1 || id1 > maxValQuark || id2 < 1 || id2 > maxValQuark
143 || id3 < 1 || id3 > maxValQuark)
return;
144 if (id2 > id1 || id3 > id1)
return;
148 nValKinds = 1; idVal[0] = id1; nVal[0] = 1;
149 if (id2 == id1) ++nVal[0];
155 if (id3 == id1) ++nVal[0];
156 else if (id3 == id2) ++nVal[1];
158 idVal[nValKinds] = id3;
165 if (idBeam < 0)
for (
int i = 0; i < nValKinds; ++i) idVal[i] = -idVal[i];
176 void BeamParticle::newValenceContent() {
180 idVal[0] = (rndmPtr->flat() < 0.5) ? 1 : 2;
181 idVal[1] = -idVal[0];
184 }
else if (idBeam == 130 || idBeam == 310) {
185 idVal[0] = (rndmPtr->flat() < 0.5) ? 1 : 3;
186 idVal[1] = (idVal[0] == 1) ? -3 : -1;
189 }
else if (idBeam == 990) {
190 idVal[0] = (rndmPtr->flat() < 0.5) ? 1 : 2;
191 idVal[1] = -idVal[0];
197 pdfBeamPtr->newValenceContent( idVal[0], idVal[1]);
198 if (pdfHardBeamPtr != pdfBeamPtr && pdfHardBeamPtr != 0)
199 pdfHardBeamPtr->newValenceContent( idVal[0], idVal[1]);
205 double BeamParticle::xMax(
int iSkip) {
209 if (isHadron()) xLeft -= m() / e();
210 if (size() == 0)
return xLeft;
213 for (
int i = 0; i < size(); ++i)
214 if (i != iSkip && resolved[i].isFromBeam()) xLeft -= resolved[i].x();
225 double BeamParticle::xfModified(
int iSkip,
int idIn,
double x,
double Q2) {
236 if (x >= 1.)
return 0.;
237 bool canBeVal =
false;
238 for (
int i = 0; i < nValKinds; ++i)
239 if (idIn == idVal[i]) canBeVal =
true;
241 xqVal = xfVal( idIn, x, Q2);
242 xqgSea = xfSea( idIn, x, Q2);
244 else xqgSea = xf( idIn, x, Q2);
251 for (
int i = 0; i < size(); ++i)
252 if (i != iSkip) xUsed += resolved[i].x();
253 double xLeft = 1. - xUsed;
254 if (x >= xLeft)
return 0.;
255 double xRescaled = x / xLeft;
259 double xValLeft = 0.;
260 for (
int i = 0; i < nValKinds; ++i) {
261 nValLeft[i] = nVal[i];
262 for (
int j = 0; j < size(); ++j)
263 if (j != iSkip && resolved[j].isValence()
264 && resolved[j].id() == idVal[i]) --nValLeft[i];
265 double xValNow = xValFrac(i, Q2);
266 xValTot += nVal[i] * xValNow;
267 xValLeft += nValLeft[i] * xValNow;
271 double xCompAdded = 0.;
272 for (
int i = 0; i < size(); ++i)
273 if (i != iSkip && resolved[i].isUnmatched()) xCompAdded
274 += xCompFrac( resolved[i].x() / (xLeft + resolved[i].x()) )
278 * (1. + resolved[i].x() / xLeft);
281 double rescaleGS = max( 0., (1. - xValLeft - xCompAdded)
283 xqgSea = rescaleGS * xfSea( idIn, xRescaled, Q2);
286 for (
int i = 0; i < nValKinds; ++i)
287 if (idIn == idVal[i] && nValLeft[i] > 0)
288 xqVal = xfVal( idIn, xRescaled, Q2)
289 * double(nValLeft[i]) / double(nVal[i]);
292 for (
int i = 0; i < size(); ++i)
293 if (i != iSkip && resolved[i].
id() == -idIn
294 && resolved[i].isUnmatched()) {
295 double xsRescaled = resolved[i].x() / (xLeft + resolved[i].x());
296 double xcRescaled = x / (xLeft + resolved[i].x());
297 double xqCompNow = xCompDist( xcRescaled, xsRescaled);
298 resolved[i].xqCompanion( xqCompNow);
299 xqCompSum += xqCompNow;
305 xqgTot = xqVal + xqgSea + xqCompSum;
307 if (resolved[iSkip].isValence())
return xqVal;
308 if (resolved[iSkip].isUnmatched())
return xqgSea + xqCompSum;
320 int BeamParticle::pickValSeaComp() {
323 int oldCompanion = resolved[iSkipSave].companion();
324 if (oldCompanion >= 0) resolved[oldCompanion].companion(-2);
330 if (idSave == 21 || idSave == 22) vsc = -1;
333 else if (isLeptonBeam && idSave == idBeam) vsc = -3;
337 double xqRndm = xqgTot * rndmPtr->flat();
338 if (xqRndm < xqVal) vsc = -3;
339 else if (xqRndm < xqVal + xqgSea) vsc = -2;
343 xqRndm -= xqVal + xqgSea;
344 for (
int i = 0; i < size(); ++i)
345 if (i != iSkipSave && resolved[i].
id() == -idSave
346 && resolved[i].isUnmatched()) {
347 xqRndm -= resolved[i].xqCompanion();
348 if (xqRndm < 0.) vsc = i;
355 resolved[iSkipSave].companion(vsc);
356 if (vsc >= 0) resolved[vsc].companion(iSkipSave);
368 double BeamParticle::xValFrac(
int j,
double Q2) {
371 if (Q2 != Q2ValFracSav) {
375 double llQ2 = log( log( max( 1., Q2) / 0.04 ));
378 uValInt = 0.48 / (1. + 1.56 * llQ2);
379 dValInt = 0.385 / (1. + 1.60 * llQ2);
383 if (isBaryonBeam && nValKinds == 3)
return (2. * uValInt + dValInt) / 3.;
386 if (isBaryonBeam && nVal[j] == 1)
return dValInt;
387 if (isBaryonBeam && nVal[j] == 2)
return uValInt;
390 return 0.5 * (2. * uValInt + dValInt);
400 double BeamParticle::xCompFrac(
double xs) {
403 switch (companionPower) {
406 return xs * ( 5. + xs * (-9. - 2. * xs * (-3. + xs)) + 3. * log(xs) )
407 / ( (-1. + xs) * (2. + xs * (-1. + 2. * xs)) );
410 return -1. -3. * xs + ( 2. * pow2(-1. + xs) * (1. + xs + xs*xs))
411 / ( 2. + xs*xs * (xs - 3.) + 3. * xs * log(xs) );
414 return xs * ( (1. - xs) * (19. + xs * (43. + 4. * xs))
415 + 6. * log(xs) * (1. + 6. * xs + 4.*xs*xs) ) /
416 ( 4. * ( (xs - 1.) * (1. + xs * (4. + xs) )
417 - 3. * xs * log(xs) * (1 + xs) ) );
420 return 3. * xs * ( (xs - 1.) * (7. + xs * (28. + 13. * xs))
421 - 2. * log(xs) * (1. + xs * (9. + 2. * xs * (6. + xs))) )
422 / ( 4. + 27. * xs - 31. * pow3(xs)
423 + 6. * xs * log(xs) * (3. + 2. * xs * (3.+xs)) );
426 return ( -9. * xs * (xs*xs - 1.) * (5. + xs * (24. + xs)) + 12. * xs
427 * log(xs) * (1. + 2. * xs) * (1. + 2. * xs * (5. + 2. * xs)) )
428 / ( 8. * (1. + 2. * xs) * ((xs - 1.) * (1. + xs * (10. + xs))
429 - 6. * xs * log(xs) * (1. + xs)) );
440 double BeamParticle::xCompDist(
double xc,
double xs) {
444 if (xg > 1.)
return 0.;
448 double fac = 3. * xc * xs * (xc*xc + xs*xs) / pow4(xg);
451 switch (companionPower) {
454 return fac / ( 2. - xs * (3. - xs * (3. - 2. * xs)) );
457 return fac * (1. - xg) / ( 2. + xs*xs * (-3. + xs) + 3. * xs * log(xs) );
460 return fac * pow2(1. - xg) / ( 2. * ((1. - xs) * (1. + xs * (4. + xs))
461 + 3. * xs * (1. + xs) * log(xs)) );
464 return fac * pow3(1. - xg) * 2. / ( 4. + 27. * xs - 31. * pow3(xs)
465 + 6. * xs * log(xs) * (3. + 2. * xs * (3. + xs)) );
468 return fac * pow4(1. - xg) / ( 2. * (1. + 2. * xs) * ((1. - xs)
469 * (1. + xs * (10. + xs)) + 6. * xs * log(xs) * (1. + xs)) );
478 bool BeamParticle::remnantFlavours(
Event& event) {
481 hasJunctionBeam = (isBaryon());
487 for (
int i = 0; i < nValKinds; ++i) {
488 nValLeft[i] = nVal[i];
489 for (
int j = 0; j < nInit; ++j)
if (resolved[j].isValence()
490 && resolved[j].
id() == idVal[i]) --nValLeft[i];
492 for (
int k = 0; k < nValLeft[i]; ++k) append(0, idVal[i], 0., -3);
496 int nInitPlusVal = size();
497 if (isBaryon() && nInitPlusVal - nInit >= 2) {
502 if (nInitPlusVal - nInit == 3) {
503 double pickDq = 3. * rndmPtr->flat();
504 if (pickDq > 1.) iQ2 = nInit + 2;
505 if (pickDq > 2.) iQ1 = nInit + 1;
509 int idDq = flavSelPtr->makeDiquark( resolved[iQ1].
id(),
510 resolved[iQ2].
id(), idBeam);
513 resolved[iQ1].id(idDq);
514 if (nInitPlusVal - nInit == 3 && iQ2 == nInit + 1)
515 resolved[nInit + 1].id( resolved[nInit + 2].
id() );
517 hasJunctionBeam =
false;
521 for (
int i = 0; i < nInit; ++i)
522 if (resolved[i].isUnmatched()) {
525 append(0, -resolved[i].
id(), 0., i);
526 resolved[i].companion(size() - 1);
530 if (size() == nInit) {
531 int idRemnant = (isHadronBeam) ? 21 : 22;
532 append(0, idRemnant, 0., -1);
536 for (
int i = 0; i < size(); ++i) {
537 if (i < nInit) resolved[i].m(0.);
538 else resolved[i].m( particleDataPtr->m0( resolved[i].id() ) );
542 if (hasJunctionBeam && !allowJunction)
return false;
545 for (
int i = nInit; i < size(); ++i) {
546 int colType = particleDataPtr->colType( resolved[i].
id() );
547 int col = (colType == 1 || colType == 2) ? event.nextColTag() : 0;
548 int acol = (colType == -1 || colType == 2) ? event.nextColTag() : 0;
549 resolved[i].cols( col, acol);
561 bool BeamParticle::remnantColours(
Event& event, vector<int>& colFrom,
562 vector<int>& colTo) {
565 if (isLeptonBeam)
return true;
568 for (
int i = 0; i < size(); ++i) {
569 int j = resolved[i].iPos();
570 resolved[i].cols( event[j].col(), event[j].acol());
578 for (
int i = 0; i < size(); ++i)
579 if (resolved[i].isFromBeam()) {
580 if ( resolved[i].isValence() ) iVal.push_back(i);
581 else if ( resolved[i].isCompanion() && resolved[i].companion() > i )
583 else if ( resolved[i].
id() == 21
584 && resolved[i].col() != resolved[i].acol() ) iGlu.push_back(i);
589 int iValSel= iVal[0];
590 if (iVal.size() == 2) {
591 if ( abs(resolved[iValSel].
id()) > 10 ) iValSel = iVal[1];
593 double rndmValSel = 3. * rndmPtr->flat();
594 if (rndmValSel > 1.) iValSel= iVal[1];
595 if (rndmValSel > 2.) iValSel= iVal[2];
600 bool hasCol = (resolved[iBeg].col() > 0);
601 int begCol = (hasCol) ? resolved[iBeg].col() : resolved[iBeg].acol();
604 vector<int> iGluRndm;
605 for (
int i = 0; i < int(iGlu.size()); ++i)
606 iGluRndm.push_back( iGlu[i] );
607 for (
int iOrder = 0; iOrder < int(iGlu.size()); ++iOrder) {
608 int iRndm = int(
double(iGluRndm.size()) * rndmPtr->flat());
609 int iGluSel = iGluRndm[iRndm];
610 iGluRndm[iRndm] = iGluRndm[iGluRndm.size() - 1];
615 int endCol = (hasCol) ? resolved[iEnd].acol() : resolved[iEnd].col();
618 iEnd = resolved[iEnd].companion();
619 endCol = (hasCol) ? resolved[iEnd].acol() : resolved[iEnd].col();
623 if (begCol < endCol) {
624 if (hasCol) resolved[iEnd].acol(begCol);
625 else resolved[iEnd].col(begCol);
626 colFrom.push_back(endCol);
627 colTo.push_back(begCol);
629 if (hasCol) resolved[iBeg].col(endCol);
630 else resolved[iBeg].acol(endCol);
631 colFrom.push_back(begCol);
632 colTo.push_back(endCol);
637 begCol = (hasCol) ? resolved[iBeg].col() : resolved[iBeg].acol();
640 iBeg = resolved[iBeg].companion();
641 begCol = (hasCol) ? resolved[iBeg].col() : resolved[iBeg].acol();
650 vector<int> acolList;
651 for (
int i = 0; i < size(); ++i)
652 if ( resolved[i].isFromBeam() )
653 if ( resolved[i].col() != resolved[i].acol() ) {
654 if (resolved[i].col() > 0) colList.push_back( resolved[i].col() );
655 if (resolved[i].acol() > 0) acolList.push_back( resolved[i].acol() );
659 bool foundPair =
true;
660 while (foundPair && colList.size() > 0 && acolList.size() > 0) {
662 for (
int iCol = 0; iCol < int(colList.size()); ++iCol) {
663 for (
int iAcol = 0; iAcol < int(acolList.size()); ++iAcol) {
664 if (acolList[iAcol] == colList[iCol]) {
665 colList[iCol] = colList.back();
667 acolList[iAcol] = acolList.back();
672 }
if (foundPair)
break;
677 if (colList.size() == 1 && acolList.size() == 1) {
678 int finalFrom = max( colList[0], acolList[0]);
679 int finalTo = min( colList[0], acolList[0]);
680 for (
int i = 0; i < size(); ++i)
681 if ( resolved[i].isFromBeam() ) {
682 if (resolved[i].col() == finalFrom) resolved[i].col(finalTo);
683 if (resolved[i].acol() == finalFrom) resolved[i].acol(finalTo);
685 colFrom.push_back(finalFrom);
686 colTo.push_back(finalTo);
689 }
else if (hasJunctionBeam && colList.size() == 3
690 && acolList.size() == 0) {
691 event.appendJunction( 1, colList[0], colList[1], colList[2]);
692 junCol[0] = colList[0];
693 junCol[1] = colList[1];
694 junCol[2] = colList[2];
695 }
else if (hasJunctionBeam && acolList.size() == 3
696 && colList.size() == 0) {
697 event.appendJunction( 2, acolList[0], acolList[1], acolList[2]);
698 junCol[0] = acolList[0];
699 junCol[1] = acolList[1];
700 junCol[2] = acolList[2];
703 }
else if (colList.size() > 0 || acolList.size() > 0) {
704 infoPtr->errorMsg(
"Error in BeamParticle::remnantColours: "
705 "leftover unmatched colours");
710 for (
int i = nInit; i < size(); ++i)
711 event[resolved[i].iPos()].cols( resolved[i].col(), resolved[i].acol() );
722 double BeamParticle::xRemnant(
int i) {
727 if (resolved[i].isValence()) {
730 int id1 = resolved[i].id();
733 id2 = (id1 > 0) ? (id1/100)%10 : -(((-id1)/100)%10);
734 id1 = (id1 > 0) ? id1/1000 : -((-id1)/1000);
738 for (
int iId = 0; iId < 2; ++iId) {
739 int idNow = (iId == 0) ? id1 : id2;
740 if (idNow == 0)
break;
744 double xPow = valencePowerMeson;
746 if (nValKinds == 3 || nValKinds == 1)
747 xPow = (3. * rndmPtr->flat() < 2.)
748 ? valencePowerUinP : valencePowerDinP ;
749 else if (nValence(idNow) == 2) xPow = valencePowerUinP;
750 else xPow = valencePowerDinP;
752 do xPart = pow2( rndmPtr->flat() );
753 while ( pow(1. - xPart, xPow) < rndmPtr->flat() );
758 if (id2 != 0) x *= valenceDiqEnhance;
761 }
else if (resolved[i].isCompanion()) {
765 for (
int iInit = 0; iInit < nInit; ++iInit)
766 if (resolved[iInit].isFromBeam()) xLeft -= resolved[iInit].x();
767 double xCompanion = resolved[ resolved[i].companion() ].x();
768 xCompanion /= (xLeft + xCompanion);
771 do x = pow( xCompanion, rndmPtr->flat()) - xCompanion;
772 while ( pow( (1. - x - xCompanion) / (1. - xCompanion), companionPower)
773 * (pow2(x) + pow2(xCompanion)) / pow2(x + xCompanion)
786 void BeamParticle::list(ostream& os)
const {
789 os <<
"\n -------- PYTHIA Partons resolved in beam -----------------"
790 <<
"-------------------------------------------------------------\n"
791 <<
"\n i iPos id x comp xqcomp pTfact "
792 <<
"colours p_x p_y p_z e m \n";
797 for (
int i = 0; i < size(); ++i) {
798 ResolvedParton res = resolved[i];
799 os << fixed << setprecision(6) << setw(5) << i << setw(6) << res.iPos()
800 << setw(8) << res.id() << setw(10) << res.x() << setw(6)
801 << res.companion() << setw(10) << res.xqCompanion() << setw(10)
802 << res.pTfactor() << setprecision(3) << setw(6) << res.col()
803 << setw(6) << res.acol() << setw(11) << res.px() << setw(11)
804 << res.py() << setw(11) << res.pz() << setw(11) << res.e()
805 << setw(11) << res.m() <<
"\n";
808 if (res.companion() != -10) {
815 os << setprecision(6) <<
" x sum:" << setw(10) << xSum
816 << setprecision(3) <<
" p sum:"
817 << setw(11) << pSum.px() << setw(11) << pSum.py() << setw(11)
818 << pSum.pz() << setw(11) << pSum.e()
819 <<
"\n\n -------- End PYTHIA Partons resolved in beam -----------"
820 <<
"---------------------------------------------------------------"
828 bool BeamParticle::isUnresolvedLepton() {
831 if (!isLeptonBeam || resolved.size() > 2 || resolved[1].id() != 22
832 || resolved[0].x() < XMINUNRESOLVED)
return false;
841 bool BeamParticle::pickGluon(
double mDiff) {
844 double probPickQuark = pickQuarkNorm / pow( mDiff, pickQuarkPower);
845 return ( (1. + probPickQuark) * rndmPtr->flat() < 1. );
853 int BeamParticle::pickValence() {
856 int nTotVal = (isBaryonBeam) ? 3 : 2;
857 double rnVal = rndmPtr->flat() * nTotVal;
858 int iVal = (rnVal < 1.) ? 1 : ( (rnVal < 2.) ? 2 : 3 );
865 for (
int i = 0; i < nValKinds; ++i)
866 for (
int j = 0; j < nVal[i]; ++j) {
868 if (iNow == iVal) idVal1 = idVal[i];
869 else if ( idVal2 == 0) idVal2 = idVal[i];
870 else idVal3 = idVal[i];
874 if (idVal3 != 0) idVal2 = flavSelPtr->makeDiquark( idVal2, idVal3, idBeam);
885 double BeamParticle::zShare(
double mDiff,
double m1,
double m2) {
888 append(0, idVal1, 0., -3);
889 append(0, idVal2, 0., -3);
890 double m2Diff = mDiff*mDiff;
895 double x1 = xRemnant(0);
896 double x2 = xRemnant(0);
897 zRel = x1 / (x1 + x2);
898 pair<double, double> gauss2 = rndmPtr->gauss2();
899 pxRel = diffPrimKTwidth * gauss2.first;
900 pyRel = diffPrimKTwidth * gauss2.second;
903 double mTS1 = m1*m1 + pxRel*pxRel + pyRel*pyRel;
904 double mTS2 = m2*m2 + pxRel*pxRel + pyRel*pyRel;
905 double m2Sys = mTS1 / zRel + mTS2 / (1. - zRel);
906 wtAcc = (m2Sys < m2Diff)
907 ? pow( 1. - m2Sys / m2Diff, diffLargeMassSuppress) : 0.;
908 }
while (wtAcc < rndmPtr->flat());