9 #include "BeamRemnants.h"
22 BeamDipole(
int colIn = 0,
int iColIn = 0,
int iAcolIn = 0)
23 : col(colIn), iCol(iColIn), iAcol(iAcolIn) {}
41 const bool BeamRemnants::ALLOWCOLOURTWICE =
true;
44 const int BeamRemnants::NTRYCOLMATCH = 10;
45 const int BeamRemnants::NTRYKINMATCH = 10;
50 const bool BeamRemnants::CORRECTMISMATCH =
false;
56 bool BeamRemnants::init(
Info* infoPtrIn,
Settings& settings,
Rndm* rndmPtrIn,
63 beamAPtr = beamAPtrIn;
64 beamBPtr = beamBPtrIn;
65 partonSystemsPtr = partonSystemsPtrIn;
68 doPrimordialKT = settings.flag(
"BeamRemnants:primordialKT");
69 primordialKTsoft = settings.parm(
"BeamRemnants:primordialKTsoft");
70 primordialKThard = settings.parm(
"BeamRemnants:primordialKThard");
71 primordialKTremnant = settings.parm(
"BeamRemnants:primordialKTremnant");
72 halfScaleForKT = settings.parm(
"BeamRemnants:halfScaleForKT");
73 halfMassForKT = settings.parm(
"BeamRemnants:halfMassForKT");
76 allowRescatter = settings.flag(
"MultipartonInteractions:allowRescatter");
77 doRescatterRestoreY = settings.flag(
"BeamRemnants:rescatterRestoreY");
81 doReconnect = settings.flag(
"BeamRemnants:reconnectColours");
82 reconnectRange = settings.parm(
"BeamRemnants:reconnectRange");
83 pT0Ref = settings.parm(
"MultipartonInteractions:pT0Ref");
84 ecmRef = settings.parm(
"MultipartonInteractions:ecmRef");
85 ecmPow = settings.parm(
"MultipartonInteractions:ecmPow");
92 pT0 = pT0Ref * pow(eCM / ecmRef, ecmPow);
93 pT20Rec = pow2(reconnectRange * pT0);
106 bool BeamRemnants::add(
Event& event) {
109 eCM = infoPtr->eCM();
113 for (
int i = 0; i < beamAPtr->size(); ++i) {
114 int j = (*beamAPtr)[i].iPos();
115 if ((*beamAPtr)[i].
id() != event[j].
id()) {
116 infoPtr->errorMsg(
"Error in BeamRemnants::add: "
117 "event and beam flavours do not match");
121 for (
int i = 0; i < beamBPtr->size(); ++i) {
122 int j = (*beamBPtr)[i].iPos();
123 if ((*beamBPtr)[i].
id() != event[j].
id()) {
124 infoPtr->errorMsg(
"Error in BeamRemnants::add: "
125 "event and beam flavours do not match");
131 nSys = partonSystemsPtr->sizeSys();
132 oldSize =
event.size();
136 if ( !beamAPtr->remnantFlavours(event)
137 || !beamBPtr->remnantFlavours(event) ) {
138 infoPtr->errorMsg(
"Error in BeamRemnants::add:"
139 " remnant flavour setup failed");
144 if (!setKinematics(event))
return false;
147 if (doReconnect) reconnectColours(event);
151 vector<int> acolSave;
152 for (
int i = oldSize; i <
event.size(); ++i) {
153 colSave.push_back( event[i].col() );
154 acolSave.push_back( event[i].acol() );
156 event.saveJunctionSize();
161 bool physical =
true;
162 for (
int iTry = 0; iTry < NTRYCOLMATCH; ++iTry) {
170 if (!beamAPtr->remnantColours(event, colFrom, colTo))
172 if (!beamBPtr->remnantColours(event, colFrom, colTo))
176 if ( physical && !checkColours(event) ) physical =
false;
180 for (
int i = oldSize; i <
event.size(); ++i)
181 event[i].cols( colSave[i - oldSize], acolSave[i - oldSize] );
182 event.restoreJunctionSize();
183 infoPtr->errorMsg(
"Warning in BeamRemnants::add:"
184 " colour tracing failed; will try again");
189 infoPtr->errorMsg(
"Error in BeamRemnants::add:"
190 " colour tracing failed after several attempts");
204 bool BeamRemnants::setKinematics(
Event& event) {
207 BeamParticle& beamA = *beamAPtr;
208 BeamParticle& beamB = *beamBPtr;
211 if ( beamA.isUnresolvedLepton() && beamB.isUnresolvedLepton() )
215 if ( (!beamA.isLepton() && beamA.xMax(-1) <= 0.)
216 || (!beamB.isLepton() && beamB.xMax(-1) <= 0.) ) {
217 infoPtr->errorMsg(
"Error in BeamRemnants::setKinematics:"
218 " no momentum left for beam remnants");
224 for (
int i = 3; i <
event.size(); ++i)
225 if (event[i].statusAbs() < 20) nBeams = i + 1;
226 int nOffset = nBeams - 3;
229 int nMaxBeam = max( beamA.size(), beamB.size() );
230 vector<double> sHatSys(nMaxBeam);
231 vector<double> kTwidth(nMaxBeam);
232 vector<double> kTcomp(nMaxBeam);
233 vector<RotBstMatrix> Msys(nSys);
236 double kTcompSumA = 0.;
237 double kTcompSumB = 0.;
238 for (
int iSys = 0; iSys < nSys; ++iSys) {
239 double kTwidthNow = 0.;
240 double mHatDamp = 1.;
241 int iInA = partonSystemsPtr->getInA(iSys);
242 int iInB = partonSystemsPtr->getInB(iSys);
243 double sHatNow = (
event[iInA].p() +
event[iInB].p()).m2Calc();
247 if (doPrimordialKT) {
248 double mHat = sqrt(sHatNow);
249 mHatDamp = mHat / (mHat + halfMassForKT);
250 double scale = (iSys == 0) ? infoPtr->QRen() : infoPtr->pTMPI(iSys);
251 kTwidthNow = ( (halfScaleForKT * primordialKTsoft
252 + scale * primordialKThard) / (halfScaleForKT + scale) ) * mHatDamp;
257 sHatSys[iSys] = sHatNow;
258 kTwidth[iSys] = kTwidthNow ;
259 kTcomp[iSys] = mHatDamp;
260 if (beamA[iSys].isFromBeam()) kTcompSumA += mHatDamp;
261 else beamA[iSys].m( event[iInA].m() );
262 if (beamB[iSys].isFromBeam()) kTcompSumB += mHatDamp;
263 else beamB[iSys].m( event[iInB].m() );
267 double kTwidthNow = (doPrimordialKT) ? primordialKTremnant : 0.;
268 for (
int iRem = nSys; iRem < nMaxBeam; ++iRem) {
270 kTwidth[iRem] = kTwidthNow ;
273 kTcompSumA += beamA.size() - nSys;
274 kTcompSumB += beamB.size() - nSys;
278 double xSum[2], xInvM[2], w2Beam[2], wPosRem, wNegRem, w2Rem;
279 for (
int iTry = 0; iTry < NTRYKINMATCH; ++iTry) {
283 for (
int iBeam = 0; iBeam < 2; ++iBeam) {
284 BeamParticle&
beam = (iBeam == 0) ? beamA : beamB;
285 int nPar = beam.size();
289 if (beam.isHadron() && doPrimordialKT) {
292 for (
int iPar = 0; iPar < nPar; ++iPar) {
293 if ( beam[iPar].isFromBeam() ) {
294 pair<double, double> gauss2 = rndmPtr->gauss2();
295 double px = kTwidth[iPar] * gauss2.first;
296 double py = kTwidth[iPar] * gauss2.second;
302 int iInAB = (iBeam == 0) ? partonSystemsPtr->getInA(iPar)
303 : partonSystemsPtr->getInB(iPar);
304 beam[iPar].p( event[iInAB].p() );
309 double kTcompSum = (iBeam == 0) ? kTcompSumA : kTcompSumB;
310 for (
int iPar = 0; iPar < nPar; ++iPar)
311 if (beam[iPar].isFromBeam() ) {
312 beam[iPar].px( beam[iPar].px() - pxSum * kTcomp[iPar] / kTcompSum );
313 beam[iPar].py( beam[iPar].py() - pySum * kTcomp[iPar] / kTcompSum );
317 }
else if (beam.isHadron()) {
318 for (
int iPar = 0; iPar < nPar; ++iPar)
319 if ( !beam[iPar].isFromBeam() ) {
320 int iInAB = (iBeam == 0) ? partonSystemsPtr->getInA(iPar)
321 : partonSystemsPtr->getInB(iPar);
322 beam[iPar].p( event[iInAB].p() );
329 for (
int iRem = nSys; iRem < nPar; ++iRem) {
330 double xPrel = beam.xRemnant( iRem);
332 xSum[iBeam] += xPrel;
333 xInvM[iBeam] += beam[iRem].mT2()/xPrel;
337 w2Beam[iBeam] = xSum[iBeam] * xInvM[iBeam];
345 for (
int iSys = 0; iSys < nSys; ++iSys) {
346 int iA = beamA[iSys].iPos();
347 int iB = beamB[iSys].iPos();
348 double sHat = sHatSys[iSys];
351 bool normalA = beamA[iSys].isFromBeam();
352 bool normalB = beamB[iSys].isFromBeam();
353 bool normalSys = normalA && normalB;
354 bool doubleRes = !normalA && !normalB;
357 if (allowRescatter && CORRECTMISMATCH) {
358 Vec4 pInitial =
event[iA].p() +
event[iB].p();
360 for (
int iMem = 0; iMem < partonSystemsPtr->sizeOut(iSys); ++iMem) {
361 int iAB = partonSystemsPtr->getOut(iSys, iMem);
362 if (event[iAB].isFinal()) pFinal +=
event[iAB].p();
366 if (normalA && pFinal.pPos() > pInitial.pPos())
367 beamA[iSys].scalePT( pInitial.pPos() / pFinal.pPos() );
370 if (normalB && pFinal.pNeg() > pInitial.pNeg())
371 beamB[iSys].scalePT( pInitial.pNeg() / pFinal.pNeg() );
378 && (event[iA].pPos() / beamA[iSys].pPos() < 0
379 || event[iB].pNeg() / beamB[iSys].pNeg() < 0) ) {
380 infoPtr->errorMsg(
"Warning in BeamRemnants::setKinematics:"
381 " change in lightcone momentum sign; retrying kinematics");
387 double sHatTAft = sHat + pow2( beamA[iSys].px() + beamB[iSys].px())
388 + pow2( beamA[iSys].py() + beamB[iSys].py());
389 double w2A = beamA[iSys].mT2();
390 double w2B = beamB[iSys].mT2();
391 double w2Diff = sHatTAft - w2A - w2B;
392 double lambda = pow2(w2Diff) - 4. * w2A * w2B;
399 double lamRoot = sqrtpos( lambda );
402 if (allowRescatter && doubleRes && (event[iA].pPos() * event[iB].pNeg()
403 < event[iA].pNeg() * event[iB].pPos()) ) lamRoot = -lamRoot;
408 if (normalSys || doRescatterRestoreY || doubleRes) {
412 double sHatTBef = sHat;
413 double wPosBef, wNegBef, wPosBefRes, wNegBefRes;
416 wPosBef = beamA[iSys].x() * eCM;
417 wNegBef = beamB[iSys].x() * eCM;
421 }
else if (normalB) {
422 sHatTBef +=
event[iA].pT2();
423 wPosBef =
event[iA].pPos();
424 wNegBef =
event[iA].pNeg() + beamB[iSys].x() * eCM;
425 wPosBefRes = beamA[iSys].pPos();
426 wNegBefRes = beamA[iSys].pNeg();
428 }
else if (normalA) {
429 sHatTBef +=
event[iB].pT2();
430 wPosBef = beamA[iSys].x() * eCM +
event[iB].pPos();
431 wNegBef =
event[iB].pNeg();
432 wPosBefRes = beamB[iSys].pPos();
433 wNegBefRes = beamB[iSys].pNeg();
436 sHatTBef += pow2( event[iA].px() + event[iB].px())
437 + pow2( event[iA].py() + event[iB].py());
438 wPosBef =
event[iA].pPos() +
event[iB].pPos();
439 wNegBef =
event[iA].pNeg() +
event[iB].pNeg();
440 wPosBefRes = beamA[iSys].pPos() + beamB[iSys].pPos();
441 wNegBefRes = beamA[iSys].pNeg() + beamB[iSys].pNeg();
446 double rescale = sqrt(sHatTAft / sHatTBef);
447 double wPosAft = rescale * wPosBef;
448 double wNegAft = rescale * wNegBef;
449 wPosRem -= wPosAft - wPosBefRes;
450 wNegRem -= wNegAft - wNegBefRes;
451 double wPosA = 0.5 * (sHatTAft + w2A - w2B + lamRoot) / wNegAft;
452 double wNegB = 0.5 * (sHatTAft + w2B - w2A + lamRoot) / wPosAft;
455 beamA[iSys].e( 0.5 * (wPosA + w2A / wPosA) );
456 beamA[iSys].pz( 0.5 * (wPosA - w2A / wPosA) );
457 beamB[iSys].e( 0.5 * (w2B / wNegB + wNegB) );
458 beamB[iSys].pz( 0.5 * (w2B / wNegB - wNegB) );
466 double wPosA = beamA[iSys].pPos();
467 double wNegB = 0.5 * (w2Diff + lamRoot) / wPosA;
468 beamB[iSys].e( 0.5 * (w2B / wNegB + wNegB) );
469 beamB[iSys].pz( 0.5 * (w2B / wNegB - wNegB) );
470 wPosRem -= w2B / wNegB;
475 }
else if (normalA) {
476 double wNegB = beamB[iSys].pNeg();
477 double wPosA = 0.5 * (w2Diff + lamRoot) / wNegB;
478 beamA[iSys].e( 0.5 * (wPosA + w2A / wPosA) );
479 beamA[iSys].pz( 0.5 * (wPosA - w2A / wPosA) );
481 wNegRem -= w2A / wPosA;
493 Msys[iSys].toCMframe( event[iA].p(), event[iB].p() );
494 Msys[iSys].fromCMframe( beamA[iSys].p(), beamB[iSys].p() );
497 for (
int iSys2 = iSys + 1; iSys2 < nSys; ++iSys2) {
498 if (!beamA[iSys2].isFromBeam()) {
499 int iBefResc =
event[ beamA[iSys2].iPos() ].mother1();
500 for (
int iMem = 0; iMem < partonSystemsPtr->sizeOut(iSys); ++iMem)
501 if (partonSystemsPtr->getOut(iSys, iMem) == iBefResc) {
502 Vec4 pTemp =
event[iBefResc].p();
503 pTemp.rotbst( Msys[iSys] );
504 beamA[iSys2].p( pTemp );
509 if (!beamB[iSys2].isFromBeam()) {
510 int iBefResc =
event[ beamB[iSys2].iPos() ].mother1();
511 for (
int iMem = 0; iMem < partonSystemsPtr->sizeOut(iSys); ++iMem)
512 if (partonSystemsPtr->getOut(iSys, iMem) == iBefResc) {
513 Vec4 pTemp =
event[iBefResc].p();
514 pTemp.rotbst( Msys[iSys] );
515 beamB[iSys2].p( pTemp );
522 if (wPosRem < 0. || wNegRem < 0.) physical =
false;
523 w2Rem = wPosRem * wNegRem;
524 if (sqrtpos(w2Rem) < sqrt(w2Beam[0]) + sqrt(w2Beam[1]))
533 infoPtr->errorMsg(
"Error in BeamRemnants::setKinematics:"
534 " kinematics construction failed");
540 for (
int iSys = 0; iSys < nSys; ++iSys) {
545 if (beamA[iSys].isFromBeam()) {
546 int iA = beamA[iSys].iPos();
547 int iAcopy =
event.copy(iA, -61);
548 event[iAcopy].rotbst(Msys[iSys]);
549 partonSystemsPtr->setInA(iSys, iAcopy);
550 beamA[iSys].iPos( iAcopy);
552 int mother =
event[iAcopy].mother1();
553 event[mother].daughter1(iAcopy);
556 if (beamB[iSys].isFromBeam()) {
557 int iB = beamB[iSys].iPos();
558 int iBcopy =
event.copy(iB, -61);
559 event[iBcopy].rotbst(Msys[iSys]);
560 partonSystemsPtr->setInB(iSys, iBcopy);
561 beamB[iSys].iPos( iBcopy);
563 int mother =
event[iBcopy].mother1();
564 event[mother].daughter1(iBcopy);
568 for (
int iMem = 0; iMem < partonSystemsPtr->sizeOut(iSys); ++iMem) {
569 int iAB = partonSystemsPtr->getOut(iSys, iMem);
570 if (event[iAB].isFinal()) {
571 int iABcopy =
event.copy(iAB, 62);
572 event[iABcopy].rotbst(Msys[iSys]);
573 partonSystemsPtr->setOut(iSys, iMem, iABcopy);
574 pSumOut +=
event[iABcopy].p();
582 if (allowRescatter && CORRECTMISMATCH) {
587 for (
int iRem = nSys; iRem < beamA.size(); ++iRem) {
588 pxBeams += beamA[iRem].px();
589 pyBeams += beamA[iRem].py();
591 for (
int iRem = nSys; iRem < beamB.size(); ++iRem) {
592 pxBeams += beamB[iRem].px();
593 pyBeams += beamB[iRem].py();
597 Vec4 pSumTo( -pxBeams, -pyBeams, pSumOut.pz(), sqrt( pow2(pxBeams)
598 + pow2(pyBeams) + pow2(pSumOut.pz()) + pSumOut.m2Calc() ) );
599 RotBstMatrix Mmismatch;
600 Mmismatch.bst( pSumOut, pSumTo);
601 for (
int iSys = 0; iSys < nSys; ++iSys)
602 for (
int iMem = 0; iMem < partonSystemsPtr->sizeOut(iSys); ++iMem) {
603 int iAB = partonSystemsPtr->getOut(iSys, iMem);
604 if (event[iAB].isFinal())
event[iAB].rotbst(Mmismatch);
606 pSumOut.rotbst(Mmismatch);
609 wPosRem = eCM - (pSumOut.e() + pSumOut.pz());
610 wNegRem = eCM - (pSumOut.e() - pSumOut.pz());
611 w2Rem = wPosRem * wNegRem;
612 if ( wPosRem < 0. || wNegRem < 0.
613 || sqrtpos(w2Rem) < sqrt(w2Beam[0]) + sqrt(w2Beam[1])) {
614 infoPtr->errorMsg(
"Error in BeamRemnants::setKinematics:"
615 " kinematics construction failed owing to recoil mismatch");
621 double lambdaRoot = sqrtpos( pow2(w2Rem - w2Beam[0] - w2Beam[1])
622 - 4. * w2Beam[0] * w2Beam[1] );
623 double rescaleA = (w2Rem + w2Beam[0] - w2Beam[1] + lambdaRoot)
624 / (2. * w2Rem * xSum[0]) ;
625 double rescaleB = (w2Rem + w2Beam[1] - w2Beam[0] + lambdaRoot)
626 / (2. * w2Rem * xSum[1]) ;
629 for (
int iRem = nSys; iRem < beamA.size(); ++iRem) {
630 double pPos = rescaleA * beamA[iRem].x() * wPosRem;
631 double pNeg = beamA[iRem].mT2() / pPos;
632 beamA[iRem].e( 0.5 * (pPos + pNeg) );
633 beamA[iRem].pz( 0.5 * (pPos - pNeg) );
636 int iNew =
event.append( beamA[iRem].
id(), 63, 1 + nOffset, 0, 0, 0,
637 beamA[iRem].col(), beamA[iRem].acol(), beamA[iRem].p(),
639 beamA[iRem].iPos( iNew);
643 for (
int iRem = nSys; iRem < beamB.size(); ++iRem) {
644 double pNeg = rescaleB * beamB[iRem].x() * wNegRem;
645 double pPos = beamB[iRem].mT2() / pNeg;
646 beamB[iRem].e( 0.5 * (pPos + pNeg) );
647 beamB[iRem].pz( 0.5 * (pPos - pNeg) );
650 int iNew =
event.append( beamB[iRem].
id(), 63, 2 + nOffset, 0, 0, 0,
651 beamB[iRem].col(), beamB[iRem].acol(), beamB[iRem].p(),
653 beamB[iRem].iPos( iNew);
670 bool BeamRemnants::reconnectColours(
Event& event) {
673 BeamParticle& beamA = *beamAPtr;
674 BeamParticle& beamB = *beamBPtr;
678 vector<int> iMerge(nSys);
679 vector<bool> hasColour(nSys);
680 for (
int iSys = 0; iSys < nSys; ++iSys) {
683 for (
int iMem = 0; iMem < partonSystemsPtr->sizeOut(iSys); ++iMem) {
684 int iNow = partonSystemsPtr->getOut( iSys, iMem);
685 if (event[iNow].isFinal() && (event[iNow].col() > 0
686 || event[iNow].acol() > 0) ) {
691 hasColour[iSys] = hasCol;
695 for (
int iRec = nSys - 1; iRec > 0; --iRec) {
698 double pT2Rec = pow2( infoPtr->pTMPI(iRec) );
699 double probRec = pT20Rec / (pT20Rec + pT2Rec);
703 for (
int iSys = iRec - 1; iSys >= 0; --iSys)
704 if (hasColour[iSys] && probRec > rndmPtr->flat()) {
708 for (
int iRec2 = iRec + 1; iRec2 < nSys; ++iRec2)
709 if (iMerge[iRec2] == iRec) iMerge[iRec2] = iSys;
717 for (
int iSys = 0; iSys < nSys; ++iSys) {
719 for (
int iRec = iSys + 1; iRec < nSys; ++iRec)
720 if (iMerge[iRec] == iSys) ++nMerge;
721 if (nMerge == 0)
continue;
724 int iInASys = partonSystemsPtr->getInA(iSys);
725 bool hasInA = (beamA[iSys].isFromBeam());
726 int iInBSys = partonSystemsPtr->getInB(iSys);
727 bool hasInB = (beamB[iSys].isFromBeam());
730 vector<BeamDipole> dipoles;
731 int sizeOut = partonSystemsPtr->sizeOut(iSys);
732 for (
int iMem = 0; iMem < sizeOut; ++iMem) {
735 int iNow = partonSystemsPtr->getOut( iSys, iMem);
736 if (!event[iNow].isFinal())
continue;
737 int col =
event[iNow].col();
739 if (hasInA && event[iInASys].col() == col)
740 dipoles.push_back( BeamDipole( col, iNow, iInASys ) );
741 else if (hasInB && event[iInBSys].col() == col)
742 dipoles.push_back( BeamDipole( col, iNow, iInBSys ) );
745 else for (
int iMem2 = 0; iMem2 < sizeOut; ++iMem2)
747 int iNow2 = partonSystemsPtr->getOut( iSys, iMem2);
748 if (!event[iNow2].isFinal())
continue;
749 if (event[iNow2].acol() == col) {
750 dipoles.push_back( BeamDipole( col, iNow, iNow2) );
757 int acol =
event[iNow].acol();
759 if (hasInA && event[iInASys].acol() == acol)
760 dipoles.push_back( BeamDipole( acol, iInASys, iNow ) );
761 else if (hasInB && event[iInBSys].acol() == acol)
762 dipoles.push_back( BeamDipole( acol, iInBSys, iNow ) );
767 if (dipoles.size() == 0)
continue;
770 for (
int iDip = 0; iDip < int(dipoles.size()); ++iDip)
771 dipoles[iDip].p1p2 = event[dipoles[iDip].iCol].p()
772 *
event[dipoles[iDip].iAcol].p();
775 for (
int iRec = iSys + 1; iRec < nSys; ++iRec) {
776 if (iMerge[iRec] != iSys)
continue;
779 int sizeRec = partonSystemsPtr->sizeOut(iRec);
780 int iInARec = partonSystemsPtr->getInA(iRec);
781 int iInBRec = partonSystemsPtr->getInB(iRec);
784 vector<double> pT2GluRec;
787 vector<bool> freeAnyRec;
790 for (
int iMem = 0; iMem < sizeRec; ++iMem) {
791 int iNow = partonSystemsPtr->getOut( iRec, iMem);
792 if (!event[iNow].isFinal())
continue;
793 if (event[iNow].isGluon()) {
795 iGluRec.push_back( iNow );
796 pT2GluRec.push_back( event[iNow].pT2() );
797 for (
int i = nGluRec - 1; i > 1; --i) {
798 if (pT2GluRec[i - 1] > pT2GluRec[i])
break;
799 swap( iGluRec[i - 1], iGluRec[i] );
800 swap( pT2GluRec[i - 1], pT2GluRec[i] );
805 iAnyRec.push_back( iNow );
806 freeAnyRec.push_back(
true );
812 for (
int iGRec = 0; iGRec < nGluRec; ++iGRec) {
813 int iGlu = iGluRec[iGRec];
814 Vec4 pGlu =
event[iGlu].p();
816 double pT2DipMin = sCM;
817 for (
int iDip = 0; iDip < int(dipoles.size()); ++iDip) {
818 double pT2Dip = (pGlu *
event[dipoles[iDip].iCol].p())
819 * (pGlu * event[dipoles[iDip].iAcol].p()) / dipoles[iDip].p1p2;
820 if (pT2Dip < pT2DipMin) {
827 int colGlu =
event[iGlu].col();
828 int acolGlu =
event[iGlu].acol();
829 int colDip = dipoles[iDipMin].col;
830 int iColDip = dipoles[iDipMin].iCol;
831 int iAcolDip = dipoles[iDipMin].iAcol;
832 event[iGlu].acol( colDip );
833 if (event[iAcolDip].acol() == colDip)
834 event[iAcolDip].acol( colGlu );
835 else event[iAcolDip].col( colGlu );
836 dipoles[iDipMin].iAcol = iGlu;
837 dipoles[iDipMin].p1p2 =
event[iColDip].p() * pGlu;
838 dipoles.push_back( BeamDipole( colGlu, iGlu, iAcolDip ) );
839 dipoles.back().p1p2 = pGlu *
event[iAcolDip].p();
842 for (
int i = oldSize; i <
event.size(); ++i)
843 if (i != iGlu && i != iAcolDip) {
844 if (event[i].isFinal()) {
845 if (event[i].acol() == colGlu) event[i].acol( acolGlu );
847 if (event[i].col() == colGlu) event[i].col( acolGlu );
852 for (
int iJun = 0; iJun <
event.sizeJunction(); ++iJun) {
855 if (event.kindJunction(iJun) % 2 == 0)
continue;
856 for (
int leg = 0; leg < 3; ++leg) {
857 int col =
event.colJunction(iJun, leg);
859 event.colJunction(iJun, leg, colGlu);
866 for (
int iQRec = 0; iQRec < nAnyRec; ++iQRec) {
867 int iQ = iAnyRec[iQRec];
868 int idQ =
event[iQ].id();
869 if (freeAnyRec[iQRec] && idQ > 0 && idQ < 6)
870 for (
int iQbarRec = 0; iQbarRec < nAnyRec; ++iQbarRec) {
871 int iQbar = iAnyRec[iQbarRec];
872 if (freeAnyRec[iQbarRec] && event[iQbar].
id() == -idQ) {
876 int iTopQ =
event.iTopCopyId(iQ);
877 int iTopQbar =
event.iTopCopyId(iQbar);
878 int iMother =
event[iTopQ].mother1();
879 if (event[iTopQbar].mother1() == iMother
880 && event[iMother].isGluon() && event[iMother].status() != -34
881 && event[iMother + 1].status() != -34 ) {
885 Vec4 pGlu =
event[iQ].p() +
event[iQbar].p();
887 double pT2DipMin = sCM;
888 for (
int iDip = 0; iDip < int(dipoles.size()); ++iDip) {
889 double pT2Dip = (pGlu *
event[dipoles[iDip].iCol].p())
890 * (pGlu * event[dipoles[iDip].iAcol].p())
891 / dipoles[iDip].p1p2;
892 if (pT2Dip < pT2DipMin) {
899 int colGlu =
event[iQ].col();
900 int acolGlu =
event[iQbar].acol();
901 int colDip = dipoles[iDipMin].col;
902 int iColDip = dipoles[iDipMin].iCol;
903 int iAcolDip = dipoles[iDipMin].iAcol;
904 event[iQbar].acol( colDip );
905 if (event[iAcolDip].acol() == colDip)
906 event[iAcolDip].acol( colGlu );
907 else event[iAcolDip].col( colGlu );
908 dipoles[iDipMin].iAcol = iQbar;
909 dipoles[iDipMin].p1p2 =
event[iColDip].p() *
event[iQbar].p();
910 dipoles.push_back( BeamDipole( colGlu, iQ, iAcolDip ) );
911 dipoles.back().p1p2 =
event[iQ].p() *
event[iAcolDip].p();
914 freeAnyRec[iQRec] =
false;
915 freeAnyRec[iQbarRec] =
false;
916 for (
int i = oldSize; i <
event.size(); ++i)
917 if (i != iQRec && i != iQbarRec && i != iColDip
919 if (event[i].isFinal()) {
920 if (event[i].acol() == colGlu) event[i].acol( acolGlu );
922 if (event[i].col() == colGlu) event[i].col( acolGlu );
927 for (
int iJun = 0; iJun <
event.sizeJunction(); ++iJun) {
930 if (event.kindJunction(iJun) % 2 == 0)
continue;
931 for (
int leg = 0; leg < 3; ++leg) {
932 int col =
event.colJunction(iJun, leg);
934 event.colJunction(iJun, leg, colGlu);
946 if ( event[iInARec].isGluon() && !event[iInARec].isRescatteredIncoming()
947 && event[iInBRec].isGluon() && !event[iInBRec].isRescatteredIncoming()
948 && event[iInARec].col() == event[iInBRec].acol()
949 && event[iInARec].acol() == event[iInBRec].col() ) {
950 event[iInARec].acol( event[iInARec].col() );
951 event[iInBRec].acol( event[iInBRec].col() );
967 bool BeamRemnants::checkColours(
Event& event) {
970 if (beamAPtr->isLepton() && beamBPtr->isLepton())
return true;
974 for (
int iCol = 1; iCol < int(colFrom.size()); ++iCol)
975 for (
int iColRef = 0; iColRef < iCol; ++iColRef) {
976 if (colFrom[iCol] == colFrom[iColRef]) {
977 colFrom[iCol] = colTo[iCol];
978 colTo[iCol] = colTo[iColRef];
980 if (colTo[iCol] == colFrom[iColRef]) colTo[iCol] = colTo[iColRef];
984 for (
int i = oldSize; i <
event.size(); ++i) {
985 int col =
event[i].col();
986 int acol =
event[i].acol();
987 for (
int iCol = 0; iCol < int(colFrom.size()); ++iCol) {
988 if (col == colFrom[iCol]) {col = colTo[iCol];
event[i].col(col);}
989 if (acol == colFrom[iCol]) {acol = colTo[iCol];
event[i].acol(acol);}
994 for (
int iJun = 0; iJun <
event.sizeJunction(); ++iJun)
995 for (
int leg = 0; leg < 3; ++leg) {
996 int col =
event.colJunction(iJun, leg);
997 for (
int iCol = 0; iCol < int(colFrom.size()); ++iCol) {
998 if (col == colFrom[iCol]) {
1000 event.colJunction(iJun, leg, col);
1006 vector<int> colList;
1007 vector<int> acolList;
1008 vector<int> iSingletGluon;
1011 for (
int i = oldSize; i <
event.size(); ++i)
1012 if (event[i].isFinal()) {
1013 int id =
event[i].id();
1014 int col =
event[i].col();
1015 int acol =
event[i].acol();
1016 int colType =
event[i].colType();
1019 if ( (
id > 0 &&
id < 9 && (col <= 0 || acol != 0) )
1020 || (id < 0 && id > -9 && (col != 0 || acol <= 0) )
1021 || (
id == 21 && (col <= 0 || acol <= 0) ) ) {
1022 infoPtr->errorMsg(
"Error in BeamRemnants::checkColours: "
1023 "q/qbar/g has wrong colour slots set");
1028 if ( (colType == 3 && (col <= 0 || acol >= 0))
1029 || (colType == -3 && (col >= 0 || acol <= 0)) ) {
1030 infoPtr->errorMsg(
"Error in BeamRemnants::checkColours: "
1031 "sextet has wrong colours");
1035 if ( col > 0) colList.push_back( col );
1036 if (acol > 0) acolList.push_back( acol );
1037 if (col > 0 && acol == col) iSingletGluon.push_back(i);
1039 if ( col < 0) acolList.push_back( -col );
1040 if (acol < 0) colList.push_back( -acol );
1045 for (
int iS = 0; iS < int(iSingletGluon.size()); ++iS) {
1046 int iGlu = iSingletGluon[iS];
1048 double pT2DipMin = sCM;
1049 for (
int iC = oldSize; iC <
event.size(); ++iC)
1050 if (iC != iGlu && event[iC].isFinal()) {
1051 int colDip =
event[iC].col();
1052 if (colDip > 0 && event[iC].acol() !=colDip)
1053 for (
int iA = oldSize; iA <
event.size(); ++iA)
1054 if (iA != iGlu && iA != iC && event[iA].isFinal()
1055 &&
event[iA].acol() == colDip &&
event[iA].col() !=colDip) {
1056 double pT2Dip = (
event[iGlu].p() *
event[iC].p())
1057 * (event[iGlu].p() *
event[iA].p())
1058 / (event[iC].p() *
event[iA].p());
1059 if (pT2Dip < pT2DipMin) {
1067 if (iAcolDip == -1)
return false;
1068 event[iGlu].acol( event[iAcolDip].acol() );
1069 event[iAcolDip].acol( event[iGlu].col() );
1072 for (
int iJun = 0; iJun <
event.sizeJunction(); ++iJun) {
1075 if (event.kindJunction(iJun) % 2 == 0)
continue;
1076 for (
int leg = 0; leg < 3; ++leg) {
1077 int col =
event.colJunction(iJun, leg);
1078 if (col == event[iGlu].acol())
1079 event.colJunction(iJun, leg, event[iGlu].col());
1086 for (
int iCol = 0; iCol < int(colList.size()) - 1; ++iCol) {
1087 int col = colList[iCol];
1088 for (
int iCol2 = iCol + 1; iCol2 < int(colList.size()); ++iCol2)
1089 if (colList[iCol2] == col) {
1090 infoPtr->errorMsg(
"Warning in BeamRemnants::checkColours:"
1091 " colour appears twice");
1092 if (!ALLOWCOLOURTWICE)
return false;
1095 for (
int iAcol = 0; iAcol < int(acolList.size()) - 1; ++iAcol) {
1096 int acol = acolList[iAcol];
1097 for (
int iAcol2 = iAcol + 1; iAcol2 < int(acolList.size()); ++iAcol2)
1098 if (acolList[iAcol2] == acol) {
1099 infoPtr->errorMsg(
"Warning in BeamRemnants::checkColours:"
1100 " anticolour appears twice");
1101 if (!ALLOWCOLOURTWICE)
return false;
1106 bool foundPair =
true;
1107 while (foundPair && colList.size() > 0 && acolList.size() > 0) {
1109 for (
int iCol = 0; iCol < int(colList.size()); ++iCol) {
1110 for (
int iAcol = 0; iAcol < int(acolList.size()); ++iAcol) {
1111 if (acolList[iAcol] == colList[iCol]) {
1112 colList[iCol] = colList.back(); colList.pop_back();
1113 acolList[iAcol] = acolList.back(); acolList.pop_back();
1118 if (foundPair)
break;
1123 for (
int iJun = 0; iJun <
event.sizeJunction(); ++iJun) {
1124 int kindJun =
event.kindJunction(iJun);
1125 for (
int leg = 0; leg < 3; ++leg) {
1126 int colEnd =
event.colJunction(iJun, leg);
1130 for (
int iCol = 0; iCol < int(colList.size()); ++iCol)
1131 if (colList[iCol] == colEnd) {
1133 colList[iCol] = colList.back();
1140 else if (kindJun == 2) {
1141 for (
int iAcol = 0; iAcol < int(acolList.size()); ++iAcol)
1142 if (acolList[iAcol] == colEnd) {
1144 acolList[iAcol] = acolList.back();
1145 acolList.pop_back();
1151 else if ( kindJun == 3 || kindJun == 5) {
1152 for (
int iCol = 0; iCol < int(colList.size()); ++iCol)
1153 if (colList[iCol] == colEnd) {
1155 colList[iCol] = colList.back();
1162 else if ( kindJun == 4 || kindJun == 6) {
1163 for (
int iAcol = 0; iAcol < int(acolList.size()); ++iAcol)
1164 if (acolList[iAcol] == colEnd) {
1166 acolList[iAcol] = acolList.back();
1167 acolList.pop_back();
1178 if (colList.size() > 0 || acolList.size() > 0) {
1179 infoPtr->errorMsg(
"Warning in BeamRemnants::checkColours:"
1180 " need to repair unmatched colours");
1182 while (colList.size() > 0 && acolList.size() > 0) {
1185 int colMatch = colList.back();
1186 int acolMatch = acolList.back();
1187 int colNew =
event.nextColTag();
1189 acolList.pop_back();
1190 for (
int i = oldSize; i <
event.size(); ++i)
1191 if (event[i].isFinal() &&
event[i].col() == colMatch) {
1192 event[i].col( colNew);
1195 for (
int i = oldSize; i <
event.size(); ++i)
1196 if (event[i].isFinal() &&
event[i].acol() == acolMatch) {
1197 event[i].acol( colNew);
1203 return (colList.size() == 0 && acolList.size() == 0);