9 #include "Pythia8/StringFragmentation.h"
22 const double StringEnd::TINY = 1e-6;
25 const double StringEnd::PT2SAME = 0.01;
29 const double StringEnd::MEANMMIN = 0.2;
30 const double StringEnd::MEANM = 0.8;
31 const double StringEnd::MEANPT = 0.4;
37 void StringEnd::setUp(
bool fromPosIn,
int iEndIn,
int idOldIn,
int iMaxIn,
38 double pxIn,
double pyIn,
double GammaIn,
double xPosIn,
double xNegIn) {
44 flavOld = FlavContainer(idOldIn);
48 iPosOld = (fromPos) ? 0 : iMax;
49 iNegOld = (fromPos) ? iMax : 0;
59 void StringEnd::newHadron(
double nNSP) {
63 if (thermalModel || mT2suppression) {
66 pair<double, double> pxy = pTSelPtr->pxy(flavNew.id, nNSP);
69 pxHad = pxOld + pxNew;
70 pyHad = pyOld + pyNew;
71 double pT2Had = pow2(pxHad) + pow2(pyHad);
75 flavNew = flavSelPtr->pick( flavOld, sqrt(pT2Had), nNSP);
76 idHad = flavSelPtr->getHadronID( flavOld, flavNew);
80 mHad = flavSelPtr->getHadronMassWin(idHad);
81 mT2Had = pow2(mHad) + pow2(pxHad) + pow2(pyHad);
90 flavNew = flavSelPtr->pick( flavOld);
91 idHad = flavSelPtr->combine( flavOld, flavNew);
95 pair<double, double> pxy = pTSelPtr->pxy(flavNew.id, nNSP);
98 pxHad = pxOld + pxNew;
99 pyHad = pyOld + pyNew;
102 mHad = particleDataPtr->mSel(idHad);
103 mT2Had = pow2(mHad) + pow2(pxHad) + pow2(pyHad);
113 Vec4 StringEnd::kinematicsHadron( StringSystem& system,
114 vector<StringVertex>& stringVertices,
bool useInputZ,
double zHadIn) {
117 if (useInputZ) zHad = zHadIn;
118 else zHad = zSelPtr->zFrag( flavOld.id, flavNew.id, mT2Had);
119 GammaNew = (1. - zHad) * (GammaOld + mT2Had / zHad);
123 int& iDirOld = (fromPos) ? iPosOld : iNegOld;
124 int& iInvOld = (fromPos) ? iNegOld : iPosOld;
125 int& iDirNew = (fromPos) ? iPosNew : iNegNew;
126 int& iInvNew = (fromPos) ? iNegNew : iPosNew;
127 double& xDirOld = (fromPos) ? xPosOld : xNegOld;
128 double& xInvOld = (fromPos) ? xNegOld : xPosOld;
129 double& xDirNew = (fromPos) ? xPosNew : xNegNew;
130 double& xInvNew = (fromPos) ? xNegNew : xPosNew;
131 double& xDirHad = (fromPos) ? xPosHad : xNegHad;
132 double& xInvHad = (fromPos) ? xNegHad : xPosHad;
140 for (
int iStep = 0; ; ++iStep) {
143 StringRegion& region = system.region( iPosNew, iNegNew);
146 if (iStep == 0 && iPosOld + iNegOld == iMax) {
149 if (mT2Had < zHad * xDirOld * (1. - xInvOld) * region.w2) {
152 xDirHad = zHad * xDirOld;
153 xInvHad = mT2Had / (xDirHad * region.w2);
154 xDirNew = xDirOld - xDirHad;
155 xInvNew = xInvOld + xInvHad;
158 stringVertices.push_back( StringVertex( fromPos, iPosNew, iNegNew,
162 return region.pHad( xPosHad, xNegHad, pxHad, pyHad);
168 if (iInvNew < 0)
return Vec4(0., 0., 0., -1.);
171 xInvHad = 1. - xInvOld;
173 pSoFar = region.pHad( xPosHad, xNegHad, pxOld, pyOld);
178 }
else if (iStep == 0) {
179 pSoFar = region.pHad( 0., 0., pxOld, pyOld);
180 pTNew = region.pHad( 0., 0., pxNew, pyNew);
186 if (!region.isSetUp) region.setUp(
187 system.regionLowPos(iPosNew).pPos,
188 system.regionLowNeg(iNegNew).pNeg,
true);
192 if (region.isEmpty) {
193 xDirHad = (iDirNew == iDirOld) ? xDirOld : 1.;
195 pSoFar += region.pHad( xPosHad, xNegHad, 0., 0.);
197 if (iDirNew + iInvNew > iMax)
return Vec4(0., 0., 0., -1.);
203 double pxNewTemp = -pTNew * region.eX;
204 double pyNewTemp = -pTNew * region.eY;
205 if (abs( pxNewTemp * pxNewTemp + pyNewTemp * pyNewTemp
206 - pxNew * pxNew - pyNew * pyNew) < PT2SAME) {
212 Vec4 pTemp = pSoFar + region.pHad( 0., 0., pxNew, pyNew);
216 double cM1 = pTemp.m2Calc();
217 double cM2 = 2. * (pTemp * region.pPos);
218 double cM3 = 2. * (pTemp * region.pNeg);
219 double cM4 = region.w2;
220 if (!fromPos) swap( cM2, cM3);
228 for (
int iInv = iInvNew; iInv <= iMax - iDirNew; ++iInv) {
230 if (iInv == iInvNew) xInv = (iInvNew == iInvOld) ? xInvOld : 0.;
231 for (
int iDir = iDirNew; iDir <= iMax - iInv; ++iDir) {
232 double xDir = (iDir == iDirOld) ? xDirOld : 1.;
233 int iPos = (fromPos) ? iDir : iInv;
234 int iNeg = (fromPos) ? iInv : iDir;
235 StringRegion& regionGam = system.region( iPos, iNeg);
236 if (!regionGam.isSetUp) regionGam.setUp(
237 system.regionLowPos(iPos).pPos,
238 system.regionLowNeg(iNeg).pNeg,
true);
239 double w2 = regionGam.w2;
240 cGam1 += xDir * xInv * w2;
241 if (iDir == iDirNew) cGam2 -= xInv * w2;
242 if (iInv == iInvNew) cGam3 += xDir * w2;
243 if (iDir == iDirNew && iInv == iInvNew) cGam4 -= w2;
248 double cM0 = pow2(mHad) - cM1;
249 double cGam0 = GammaNew - cGam1;
250 double r2 = cM3 * cGam4 - cM4 * cGam3;
251 double r1 = cM4 * cGam0 - cM0 * cGam4 + cM3 * cGam2 - cM2 * cGam3;
252 double r0 = cM2 * cGam0 - cM0 * cGam2;
253 double root = sqrtpos( r1*r1 - 4. * r2 * r0 );
254 if (abs(r2) < TINY || root < TINY)
return Vec4(0., 0., 0., -1.);
255 xInvHad = 0.5 * (root / abs(r2) - r1 / r2);
256 if (abs(cM2 + cM4 * xInvHad) < TINY)
return Vec4(0., 0., 0., -1.);
257 xDirHad = (cM0 - cM3 * xInvHad) / (cM2 + cM4 * xInvHad);
260 xDirNew = (iDirNew == iDirOld) ? xDirOld - xDirHad : 1. - xDirHad;
261 xInvNew = (iInvNew == iInvOld) ? xInvOld + xInvHad : xInvHad;
265 xInvHad = (iInvNew == iInvOld) ? 1. - xInvOld : 1.;
267 pSoFar += region.pHad( xPosHad, xNegHad, 0., 0.);
269 if (iInvNew < 0)
return Vec4(0., 0., 0., -1.);
273 }
else if (xDirNew < 0.) {
274 xDirHad = (iDirNew == iDirOld) ? xDirOld : 1.;
276 pSoFar += region.pHad( xPosHad, xNegHad, 0., 0.);
278 if (iDirNew + iInvNew > iMax)
return Vec4(0., 0., 0., -1.);
283 stringVertices.push_back( StringVertex( fromPos, iPosNew, iNegNew,
287 if (useInputZ)
return Vec4( 0., 0., 0., 0.);
288 else return pSoFar + region.pHad( xPosHad, xNegHad, pxNew, pyNew);
300 Vec4 StringEnd::kinematicsHadronTmp( StringSystem system, Vec4 pRem,
301 double phi,
double mult) {
304 double mRem = pRem.mCalc();
305 double meanM = (mRem > 0.0) ? max( MEANMMIN, min( MEANM, mRem) ) : MEANM;
306 double meanMT2 = pow2(meanM) + pow2(MEANPT);
307 double GammaNow = (1.0 + aLund) / bLund;
309 if (mult > 0.0) GammaNow *= mult;
310 double tmp = ( GammaNow + meanMT2 - GammaOld ) / GammaOld;
311 double zPlus = (-0.5 * tmp + sqrt(0.25 * pow2(tmp) + meanMT2 / GammaOld));
312 double zMinus = (-0.5 * tmp - sqrt(0.25 * pow2(tmp) + meanMT2 / GammaOld));
314 if (GammaOld < 1e-10) {
315 zPlus = pow(1.0 + meanMT2 / GammaNow, -1.0);
318 bool zPlusOk = (zPlus < 1.0) && (zPlus > 0.0);
319 bool zMinusOk = (zMinus < 1.0) && (zMinus > 0.0);
321 if ( (!zPlusOk) && (!zMinusOk) )
return Vec4(0., 0., 0., -1.);
322 double zHadTmp = (zPlusOk ? zPlus : zMinus);
324 double pxHadTmp = cos(phi) * MEANPT;
325 double pyHadTmp = sin(phi) * MEANPT;
328 int iPosOldTmp = iPosOld, iNegOldTmp = iNegOld;
329 int iPosNewTmp = iPosNew, iNegNewTmp = iNegNew;
330 double xPosOldTmp = xPosOld, xNegOldTmp = xNegOld;
331 double xPosNewTmp = xPosNew, xNegNewTmp = xNegNew;
332 double xPosHadTmp = xPosHad, xNegHadTmp = xNegHad;
333 double pxNewTmp = pxNew, pxOldTmp = pxOld;
334 double pyNewTmp = pyNew, pyOldTmp = pyOld;
336 Vec4 pSoFarTmp = pSoFar;
340 int& iDirOld = (fromPos) ? iPosOldTmp : iNegOldTmp;
341 int& iInvOld = (fromPos) ? iNegOldTmp : iPosOldTmp;
342 int& iDirNew = (fromPos) ? iPosNewTmp : iNegNewTmp;
343 int& iInvNew = (fromPos) ? iNegNewTmp : iPosNewTmp;
344 double& xDirOld = (fromPos) ? xPosOldTmp : xNegOldTmp;
345 double& xInvOld = (fromPos) ? xNegOldTmp : xPosOldTmp;
346 double& xDirNew = (fromPos) ? xPosNewTmp : xNegNewTmp;
347 double& xInvNew = (fromPos) ? xNegNewTmp : xPosNewTmp;
348 double& xDirHad = (fromPos) ? xPosHadTmp : xNegHadTmp;
349 double& xInvHad = (fromPos) ? xNegHadTmp : xPosHadTmp;
357 for (
int iStep = 0; ; ++iStep) {
360 StringRegion region = system.region( iPosNewTmp, iNegNewTmp);
363 if (iStep == 0 && iPosOldTmp + iNegOldTmp == iMax) {
367 if ( (meanMT2 < zHadTmp * xDirOld * (1. - xInvOld) * region.w2)
368 || (iInvNew - 1 < 0) ) {
371 zHadTmp = meanMT2 / xDirOld / (1. - xInvOld) / region.w2;
374 xDirHad = zHad * xDirOld;
375 xInvHad = meanMT2 / (xDirHad * region.w2);
376 xDirNew = xDirOld - xDirHad;
377 xInvNew = xInvOld + xInvHad;
380 return region.pHad( xPosHadTmp, xNegHadTmp, pxHadTmp, pyHadTmp);
387 if (iInvNew < 0)
return Vec4(0., 0., 0., -1.);
390 xInvHad = 1. - xInvOld;
392 pSoFarTmp = region.pHad( xPosHadTmp, xNegHadTmp, pxOldTmp, pyOldTmp);
397 }
else if (iStep == 0) {
398 pSoFarTmp = region.pHad( 0., 0., pxOldTmp, pyOldTmp);
399 pTNew = region.pHad( 0., 0., pxNewTmp, pyNewTmp);
404 if (!region.isSetUp) region.setUp(
405 system.regionLowPos(iPosNewTmp).pPos,
406 system.regionLowNeg(iNegNewTmp).pNeg,
true);
410 if (region.isEmpty) {
411 xDirHad = (iDirNew == iDirOld) ? xDirOld : 1.;
413 pSoFarTmp += region.pHad( xPosHadTmp, xNegHadTmp, 0., 0.);
415 if (iDirNew + iInvNew > iMax)
return Vec4(0., 0., 0., -1.);
421 double pxNewRegNow = -pTNew * region.eX;
422 double pyNewRegNow = -pTNew * region.eY;
423 if (abs( pxNewRegNow * pxNewRegNow + pyNewRegNow * pyNewRegNow
424 - pxNewTmp * pxNewTmp - pyNewTmp * pyNewTmp) < PT2SAME) {
425 pxNewTmp = pxNewRegNow;
426 pyNewTmp = pyNewRegNow;
430 Vec4 pTemp = pSoFarTmp + region.pHad( 0., 0., pxNewTmp, pyNewTmp);
434 double cM1 = pTemp.m2Calc();
435 double cM2 = 2. * (pTemp * region.pPos);
436 double cM3 = 2. * (pTemp * region.pNeg);
437 double cM4 = region.w2;
438 if (!fromPos) swap( cM2, cM3);
446 for (
int iInv = iInvNew; iInv <= iMax - iDirNew; ++iInv) {
448 if (iInv == iInvNew) xInv = (iInvNew == iInvOld) ? xInvOld : 0.;
449 for (
int iDir = iDirNew; iDir <= iMax - iInv; ++iDir) {
450 double xDir = (iDir == iDirOld) ? xDirOld : 1.;
451 int iPos = (fromPos) ? iDir : iInv;
452 int iNeg = (fromPos) ? iInv : iDir;
453 StringRegion regionGam = system.region( iPos, iNeg);
454 if (!regionGam.isSetUp) regionGam.setUp(
455 system.regionLowPos(iPos).pPos,
456 system.regionLowNeg(iNeg).pNeg,
true);
457 double w2 = regionGam.w2;
458 cGam1 += xDir * xInv * w2;
459 if (iDir == iDirNew) cGam2 -= xInv * w2;
460 if (iInv == iInvNew) cGam3 += xDir * w2;
461 if (iDir == iDirNew && iInv == iInvNew) cGam4 -= w2;
466 double cM0 = pow2(meanM) - cM1;
467 double cGam0 = GammaNow - cGam1;
468 double r2 = cM3 * cGam4 - cM4 * cGam3;
469 double r1 = cM4 * cGam0 - cM0 * cGam4 + cM3 * cGam2 - cM2 * cGam3;
470 double r0 = cM2 * cGam0 - cM0 * cGam2;
471 double root = sqrtpos( r1*r1 - 4. * r2 * r0 );
472 if (abs(r2) < TINY || root < TINY)
return Vec4(0., 0., 0., -1.);
473 xInvHad = 0.5 * (root / abs(r2) - r1 / r2);
474 xDirHad = (cM0 - cM3 * xInvHad) / (cM2 + cM4 * xInvHad);
477 xDirNew = (iDirNew == iDirOld) ? xDirOld - xDirHad : 1. - xDirHad;
478 xInvNew = (iInvNew == iInvOld) ? xInvOld + xInvHad : xInvHad;
482 xInvHad = (iInvNew == iInvOld) ? 1. - xInvOld : 1.;
484 pSoFarTmp += region.pHad( xPosHadTmp, xNegHadTmp, 0., 0.);
486 if (iInvNew < 0)
return Vec4(0., 0., 0., -1.);
490 }
else if (xDirNew < 0.) {
491 xDirHad = (iDirNew == iDirOld) ? xDirOld : 1.;
493 pSoFarTmp += region.pHad( xPosHadTmp, xNegHadTmp, 0., 0.);
495 if (iDirNew + iInvNew > iMax)
return Vec4(0., 0., 0., -1.);
500 return pSoFarTmp + region.pHad( xPosHadTmp, xNegHadTmp, pxNewTmp,
512 void StringEnd::update() {
514 flavOld.anti(flavNew);
535 const int StringFragmentation::NTRYFLAV = 10;
536 const int StringFragmentation::NTRYJOIN = 30;
539 const int StringFragmentation::NSTOPMASS = 15;
540 const double StringFragmentation::FACSTOPMASS = 1.05;
543 const double StringFragmentation::CLOSEDM2MAX = 25.;
544 const double StringFragmentation::CLOSEDM2FRAC = 0.1;
547 const double StringFragmentation::EXPMAX = 50.;
550 const double StringFragmentation::MATCHPOSNEG = 1e-4;
553 const double StringFragmentation::EJNWEIGHTMAX = 10.;
556 const double StringFragmentation::CONVJNREST = 1e-5;
557 const int StringFragmentation::NTRYJNREST = 20;
560 const int StringFragmentation::NTRYJNMATCH = 20;
561 const double StringFragmentation::EEXTRAJNMATCH = 0.5;
562 const double StringFragmentation::MDIQUARKMIN = -2.0;
565 const double StringFragmentation::M2MAXJRF = 1e-4;
568 const double StringFragmentation::M2MINJRF = 1e-4;
571 const double StringFragmentation::CONVJRFEQ = 1e-12;
572 const int StringFragmentation::NTRYJRFEQ = 40;
575 const double StringFragmentation::CHECKPOS = 1e-10;
581 void StringFragmentation::init(Info* infoPtrIn, Settings& settings,
582 ParticleData* particleDataPtrIn, Rndm* rndmPtrIn, StringFlav* flavSelPtrIn,
583 StringPT* pTSelPtrIn, StringZ* zSelPtrIn, FlavourRope* flavRopePtrIn,
584 UserHooks* userHooksPtrIn) {
588 particleDataPtr = particleDataPtrIn;
590 flavSelPtr = flavSelPtrIn;
591 pTSelPtr = pTSelPtrIn;
593 flavRopePtr = flavRopePtrIn;
594 userHooksPtr = userHooksPtrIn;
597 stopMass = zSelPtr->stopMass();
598 stopNewFlav = zSelPtr->stopNewFlav();
599 stopSmear = zSelPtr->stopSmear();
600 eNormJunction = settings.parm(
"StringFragmentation:eNormJunction");
602 = settings.parm(
"StringFragmentation:eBothLeftJunction");
604 = settings.parm(
"StringFragmentation:eMaxLeftJunction");
606 = settings.parm(
"StringFragmentation:eMinLeftJunction");
609 hadronVertex = settings.mode(
"HadronVertex:mode");
610 setVertices = settings.flag(
"Fragmentation:setVertices");
611 kappaVtx = settings.parm(
"HadronVertex:kappa");
612 smearOn = settings.flag(
"HadronVertex:smearOn");
613 xySmear = settings.parm(
"HadronVertex:xySmear");
614 constantTau = settings.flag(
"HadronVertex:constantTau");
617 doFlavRope = settings.flag(
"Ropewalk:RopeHadronization")
618 && settings.flag(
"Ropewalk:doFlavour");
624 if (!settings.flag(
"PartonVertex:setVertex") &&
625 (!settings.flag(
"Ropewalk:setFixedKappa") &&
626 !settings.flag(
"Ropewalk:doBuffon")) ) {
627 infoPtr->errorMsg(
"Error in StringFragmentation::init: "
628 "failed initialization of flavour ropes");
633 mJoin = settings.parm(
"FragmentationSystems:mJoin");
636 bLund = zSelPtr->bAreaLund();
639 mc = particleDataPtr->m0(4);
640 mb = particleDataPtr->m0(5);
643 pT20 = pow2(settings.parm(
"MultipartonInteractions:pT0Ref"));
646 hadrons.init(
"(string fragmentation)", particleDataPtr);
649 posEnd.init( particleDataPtr, flavSelPtr, pTSelPtr, zSelPtr, settings);
650 negEnd.init( particleDataPtr, flavSelPtr, pTSelPtr, zSelPtr, settings);
653 closePacking = settings.flag(
"StringPT:closePacking");
661 bool StringFragmentation::fragment(
int iSub, ColConfig& colConfig,
665 iParton = colConfig[iSub].iParton;
667 if (iPos < 0) iPos = iParton[1];
668 int idPos =
event[iPos].id();
669 iNeg = iParton.back();
670 int idNeg =
event[iNeg].id();
671 pSum = colConfig[iSub].pSum;
674 vector< vector< pair<double,double> > > rapPairs = colConfig.rapPairs;
678 stringVertices.clear();
679 legMinVertices.clear();
680 legMidVertices.clear();
685 isClosed = colConfig[iSub].isClosed;
686 if (isClosed) iParton = findFirstRegion(iSub, colConfig, event);
690 pJunctionHadrons = 0.;
691 hasJunction = colConfig[iSub].hasJunction;
692 if (hasJunction && !fragmentToJunction(event))
return false;
693 int junctionHadrons = hadrons.size();
695 idPos =
event[ iParton[0] ].id();
696 idNeg =
event.back().id();
697 pSum -= pJunctionHadrons;
701 if (doFlavRope) flavRopePtr->setEventPtr(event);
704 system.setUp(iParton, event);
705 stopMassNow = stopMass;
709 for (
int iTry = 0; ; ++iTry) {
710 if (iTry > NTRYJOIN) {
711 infoPtr->errorMsg(
"Error in StringFragmentation::fragment: "
713 if (hasJunction) ++nExtraJoin;
714 if (nExtraJoin > 0)
event.popBack(nExtraJoin);
719 if (iTry == NTRYJOIN / 3) nExtraJoin = extraJoin( 2., event);
720 if (iTry == 2 * NTRYJOIN / 3) nExtraJoin += extraJoin( 4., event);
723 if (iTry > NTRYJOIN - NSTOPMASS) stopMassNow *= FACSTOPMASS;
726 setStartEnds(idPos, idNeg, system);
733 bool usedPosJun =
false, usedNegJun =
false;
736 Vec4 hadMomPos, hadMomNeg;
741 fromPos = (rndmPtr->flat() < 0.5);
742 StringEnd& nowEnd = (fromPos) ? posEnd : negEnd;
745 double nNSP = (closePacking) ? nearStringPieces(nowEnd, rapPairs) : 0.;
749 if (!flavRopePtr->doChangeFragPar(flavSelPtr, zSelPtr, pTSelPtr,
750 (fromPos ? hadMomPos.m2Calc() : hadMomNeg.m2Calc()), iParton,
751 (fromPos ? idPos : idNeg)) )
752 infoPtr->errorMsg(
"Error in StringFragmentation::fragment: "
753 "FlavourRope failed to change fragmentation parameters.");
757 if ( (userHooksPtr != 0) && userHooksPtr->canChangeFragPar() ) {
758 if ( !userHooksPtr->doChangeFragPar( flavSelPtr, zSelPtr, pTSelPtr,
759 (fromPos ? idPos : idNeg),
760 (fromPos ? hadMomPos.m2Calc() : hadMomNeg.m2Calc()), iParton) )
761 infoPtr->errorMsg(
"Error in StringFragmentation::fragment: "
762 "failed to change hadronisation parameters.");
766 nowEnd.newHadron(nNSP);
768 if ( energyUsedUp(fromPos) )
break;
771 Vec4 pHad = nowEnd.kinematicsHadron(system, stringVertices);
772 int statusHad = (fromPos) ? 83 : 84;
773 nowEnd.hadSoFar += 1;
776 if (abs(nowEnd.idHad) > 1000 && abs(nowEnd.idHad) < 10000) {
777 if (fromPos && event[iPos].statusAbs() == 74 && !usedPosJun) {
781 if (!fromPos && event[iNeg].statusAbs() == 74 && !usedNegJun) {
785 if (!fromPos && hasJunction && !usedNegJun) {
792 if ( (userHooksPtr != 0) && userHooksPtr->canChangeFragPar() ) {
794 if ( userHooksPtr->doVetoFragmentation( Particle( nowEnd.idHad,
795 statusHad, iPos, iNeg, 0, 0, 0, 0, pHad, nowEnd.mHad) ) )
800 if (fromPos) hadMomPos += pHad;
801 else hadMomNeg += pHad;
804 hadrons.append( nowEnd.idHad, statusHad, iPos, iNeg,
805 0, 0, 0, 0, pHad, nowEnd.mHad);
806 if (pHad.e() < 0.)
break;
816 double nNSP = (closePacking) ? nearStringPieces(
817 ((rndmPtr->flat() < 0.5) ? posEnd : negEnd), rapPairs) : 0.;
820 if ( finalTwo(fromPos, event, usedPosJun, usedNegJun, nNSP) )
break;
824 int newHadrons = hadrons.size() - junctionHadrons;
825 hadrons.popBack(newHadrons);
826 stringVertices.clear();
832 if (hasJunction) ++nExtraJoin;
833 if (nExtraJoin > 0) {
834 event.popBack(nExtraJoin);
835 iParton = colConfig[iSub].iParton;
842 if (setVertices) setHadronVertices( event);
853 vector<int> StringFragmentation::findFirstRegion(
int iSub,
854 ColConfig& colConfig,
Event& event) {
857 vector<int> iPartonIn = colConfig[iSub].iParton;
860 vector<double> m2Pair;
862 int size = iPartonIn.size();
863 for (
int i = 0; i < size; ++i) {
864 double m2Now = 0.5 *
event[ iPartonIn[i] ].p()
865 *
event[ iPartonIn[(i + 1)%size] ].p();
866 m2Pair.push_back(m2Now);
871 double m2Reg = m2Sum * rndmPtr->flat();
873 do m2Reg -= m2Pair[++iReg];
874 while (m2Reg > 0. && iReg < size - 1);
877 vector<int> iPartonOut;
878 for (
int i = 0; i < size + 2; ++i)
879 iPartonOut.push_back( iPartonIn[(i + iReg)%size] );
890 void StringFragmentation::setStartEnds(
int idPos,
int idNeg,
891 StringSystem systemNow,
int legNow) {
897 double xPosFromPos = 1.;
898 double xNegFromPos = 0.;
899 double xPosFromNeg = 0.;
900 double xNegFromNeg = 1.;
905 int idTry = flavSelPtr->pickLightQ();
906 FlavContainer flavTry(idTry, 1);
907 flavTry = flavSelPtr->pick( flavTry);
908 flavTry = flavSelPtr->pick( flavTry);
911 }
while (idPos == 0);
914 pair<double, double> pxy = pTSelPtr->pxy(idPos);
917 double m2Region = systemNow.regionLowPos(0).w2;
918 double m2Temp = min( CLOSEDM2MAX, CLOSEDM2FRAC * m2Region);
920 double zTemp = zSelPtr->zFrag( idPos, idNeg, m2Temp);
921 xPosFromPos = 1. - zTemp;
922 xNegFromPos = m2Temp / (zTemp * m2Region);
923 }
while (xNegFromPos > 1.);
924 Gamma = xPosFromPos * xNegFromPos * m2Region;
925 xPosFromNeg = xPosFromPos;
926 xNegFromNeg = xNegFromPos;
930 posEnd.setUp(
true, iPos, idPos, systemNow.iMax, px, py,
931 Gamma, xPosFromPos, xNegFromPos);
932 negEnd.setUp(
false, iNeg, idNeg, systemNow.iMax, -px, -py,
933 Gamma, xPosFromNeg, xNegFromNeg);
937 if (legNow == legMin) legMinVertices.push_back(
938 StringVertex(
true, 0, systemNow.iMax, xPosFromPos, xNegFromPos) );
939 else if (legNow == legMid) legMidVertices.push_back(
940 StringVertex(
true, 0, systemNow.iMax, xPosFromPos, xNegFromPos) );
942 stringVertices.push_back(
943 StringVertex (
true, 0, systemNow.iMax, xPosFromPos, xNegFromPos) );
944 stringVertices.push_back(
945 StringVertex(
false, systemNow.iMax, 0, xPosFromNeg, xNegFromNeg) );
950 flavSelPtr->assignPopQ(posEnd.flavOld);
951 flavSelPtr->assignPopQ(negEnd.flavOld);
952 if (rndmPtr->flat() < 0.5) posEnd.flavOld.nPop = 0;
953 else negEnd.flavOld.nPop = 0;
954 posEnd.flavOld.rank = 1;
955 negEnd.flavOld.rank = 1;
966 bool StringFragmentation::energyUsedUp(
bool fromPos) {
969 if (pRem.e() < 0.)
return true;
972 double wMin = stopMassNow
973 + particleDataPtr->constituentMass(posEnd.flavOld.id)
974 + particleDataPtr->constituentMass(negEnd.flavOld.id);
975 if (fromPos) wMin += stopNewFlav
976 * particleDataPtr->constituentMass(posEnd.flavNew.id);
977 else wMin += stopNewFlav
978 * particleDataPtr->constituentMass(negEnd.flavNew.id);
979 wMin *= 1. + (2. * rndmPtr->flat() - 1.) * stopSmear;
980 w2Rem = pRem.m2Calc();
981 if (w2Rem < pow2(wMin))
return true;
993 void StringFragmentation::setHadronVertices(
Event& event) {
996 int vertexSize = stringVertices.size();
997 vector<StringVertex> orderedVertices;
998 for (
int i = 0; i < vertexSize; ++i)
if (stringVertices[i].fromPos)
999 orderedVertices.push_back( stringVertices[i] );
1000 for (
int i = vertexSize - 1; i >= 0; --i)
if (!stringVertices[i].fromPos)
1001 orderedVertices.push_back( stringVertices[i] );
1004 vector<Vec4> longitudinal;
1005 int finalSpacePos = 0;
1006 int finalVertexPos = 0;
1007 vector<int> iPartonIn = (hasJunction) ? iPartonMax : iParton;
1008 int id1 =
event[ iPartonIn.front() ].idAbs();
1009 int id2 = (hasJunction) ? idDiquark : event[ iPartonIn.back() ].idAbs();
1010 int iHadJunc = (hasJunction)
1011 ? legMinVertices.size() + legMidVertices.size() - 2 : 0;
1014 for (
int i = 0; i < vertexSize; ++i) {
1015 int iPosIn = orderedVertices[i].iRegPos;
1016 int iNegIn = orderedVertices[i].iRegNeg;
1017 double xPosIn = orderedVertices[i].xRegPos;
1018 double xNegIn = orderedVertices[i].xRegNeg;
1021 if (iPosIn == -1 && iNegIn == -1) {
1022 longitudinal.push_back( Vec4( 0., 0., 0., 0.) );
1023 finalSpacePos = i + 1;
1028 StringRegion currentRegion = system.region( iPosIn, iNegIn);
1029 Vec4 gluonOffset = currentRegion.gluonOffset( iPartonIn, event, iPosIn,
1031 Vec4 noOffset = (xPosIn * currentRegion.pPos +
1032 xNegIn * currentRegion.pNeg) / kappaVtx;
1033 Vec4 pRegion = (currentRegion.pPos + currentRegion.pNeg) / kappaVtx;
1037 if (noOffset.m2Calc() < 0.) {
1038 double cPlus = (-pRegion * noOffset + sqrt( pow2(pRegion*noOffset)
1039 - pRegion.m2Calc() * noOffset.m2Calc())) / pRegion.m2Calc();
1040 Vec4 pCorrection = noOffset + cPlus * pRegion;
1041 Vec4 fracCorrection;
1042 bool betterFrac =
false;
1043 if (xPosIn < 0. || xPosIn > 1. || xNegIn < 0. || xNegIn > 1.) {
1044 xPosIn = max( 0., min( 1., xPosIn) );
1045 xNegIn = max( 0., min( 1., xNegIn) );
1046 fracCorrection = (xPosIn * currentRegion.pPos
1047 + xNegIn * currentRegion.pNeg) / kappaVtx;
1048 betterFrac = abs(noOffset.e() - pCorrection.e())
1049 > abs(noOffset.e() - fracCorrection.e());
1051 noOffset = (betterFrac) ? fracCorrection : pCorrection;
1054 Vec4 fromBreaks = noOffset + gluonOffset;
1055 longitudinal.push_back(fromBreaks);
1056 if (fromBreaks.m2Calc() < -CHECKPOS * max(1., pow2(fromBreaks.e())))
1057 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices: "
1058 "negative tau^2 from breaks");
1063 if (finalSpacePos != 0) {
1064 double xPosIn = orderedVertices[finalVertexPos].xRegPos;
1065 double xNegIn = orderedVertices[finalVertexPos].xRegNeg;
1066 Vec4 v1 = longitudinal[finalSpacePos - 1];
1067 Vec4 v2 = longitudinal[finalSpacePos + 1];
1069 Vec4 vk = pPosFinalReg + pNegFinalReg;
1071 if (vl.m2Calc() > 0.) {
1072 Vec4 va = ( 0.5 * (v1 + v2) + xPosIn * pPosFinalReg +
1073 xNegIn * pNegFinalReg ) / kappaVtx;
1074 r = (va * vk - sqrt(pow2(va * vk) - vk.m2Calc() * va.m2Calc()) )
1076 }
else r = 0.5 * sqrt(-vl.m2Calc() / vk.m2Calc());
1077 longitudinal[finalSpacePos] = ( 0.5 * (v1 + v2) + (xPosIn - r)
1078 * pPosFinalReg + (xNegIn - r) * pNegFinalReg ) / kappaVtx;
1082 for (
int i = 0; i < vertexSize; ++i) {
1083 int iPosIn = orderedVertices[i].iRegPos;
1084 int iNegIn = orderedVertices[i].iRegNeg;
1086 StringRegion currentRegion = system.region( iPosIn, iNegIn);
1087 if ( currentRegion.massiveOffset( iPosIn, iNegIn, system.iMax,
1088 id1, id2, mc, mb) ) {
1092 if (i == 0 && (id1 == 4 || id1 == 5)) {
1093 int iPosIn2 = orderedVertices[i + 1].iRegPos;
1094 int iNegIn2 = orderedVertices[i + 1].iRegNeg;
1095 v2 = longitudinal[i + 1];
1096 double mHad =
event[
event.size() + iHadJunc - hadrons.size()].m();
1097 double pPosMass = particleDataPtr->m0(id1);
1098 if (iPosIn == iPosIn2 && iNegIn == iNegIn2) {
1099 v1 = longitudinal[i];
1100 longitudinal[i] = v1 + (pPosMass / mHad) * (v2 - v1);
1101 if (longitudinal[i].m2Calc()
1102 < -CHECKPOS * max(1., pow2(longitudinal[i].e())))
1103 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices: "
1104 "negative tau^2 for endpoint massive correction");
1106 StringRegion region2 = system.region( iPosIn2, iNegIn2);
1107 Vec4 gluonOffset = currentRegion.gluonOffset( iPartonIn, event,
1109 v1 = (region2.pPos + gluonOffset) / kappaVtx;
1110 longitudinal[i] = v1 + (pPosMass / mHad) * (v2 - v1);
1111 if (longitudinal[i].m2Calc()
1112 < -CHECKPOS * max(1., pow2(longitudinal[i].e())))
1113 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices: "
1114 "negative tau^2 for endpoint massive correction");
1120 if (i == vertexSize - 1 && (id2 == 4 || id2 == 5) && !hasJunction) {
1121 int iPosIn2 = orderedVertices[i - 1].iRegPos;
1122 int iNegIn2 = orderedVertices[i - 1].iRegNeg;
1123 double mHad =
event[i - 1 +
event.size() + iHadJunc
1124 - hadrons.size()].m();
1125 double pNegMass = particleDataPtr->m0(id2);
1126 if (iPosIn == iPosIn2 && iNegIn == iNegIn2) {
1127 v1 = longitudinal[i];
1128 v2 = longitudinal[i - 1] + currentRegion.massOffset / kappaVtx;
1129 longitudinal[i] = v1 + (pNegMass / mHad) * (v2 - v1);
1130 if (longitudinal[i].m2Calc()
1131 < -CHECKPOS * max(1., pow2(longitudinal[i].e())))
1132 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices: "
1133 "negative tau^2 for endpoint massive correction");
1136 StringRegion region2 = system.region( iPosIn2, iNegIn2);
1137 Vec4 gluonOffset = currentRegion.gluonOffset( iPartonIn, event,
1139 v1 = (region2.pNeg + gluonOffset) / kappaVtx;
1140 v2 = longitudinal[i - 1];
1141 longitudinal[i] = v1 + (pNegMass / mHad) * (v2 - v1);
1142 if (longitudinal[i].m2Calc()
1143 < -CHECKPOS * max(1., pow2(longitudinal[i].e())))
1144 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices: "
1145 "negative tau^2 for endpoint massive correction");
1151 Vec4 massOffset = currentRegion.massOffset / kappaVtx;
1152 Vec4 position = longitudinal[i] - massOffset;
1153 if (position.m2Calc() < 0.) {
1155 if (position.m2Calc() > -CHECKPOS * max(1., pow2(position.e())))
1156 position.e( position.pAbs() );
1158 if (massOffset.m2Calc() > 1e-6)
1159 cMinus = (longitudinal[i] * massOffset
1160 - sqrt(pow2(longitudinal[i] * massOffset)
1161 - longitudinal[i].m2Calc() * massOffset.m2Calc()))
1162 / massOffset.m2Calc();
1163 else cMinus = 0.5 * longitudinal[i].m2Calc()
1164 / (longitudinal[i] * massOffset);
1165 position = longitudinal[i] - cMinus * massOffset;
1168 longitudinal[i] = position;
1174 vector<Vec4> spaceTime;
1175 for (
int i = 0; i < vertexSize; ++i) {
1176 Vec4 positionTot = longitudinal[i];
1179 if (!isClosed && (i == 0 || i == vertexSize -1)) {
1180 spaceTime.push_back(positionTot);
1184 int iPosIn = orderedVertices[i].iRegPos;
1185 int iNegIn = orderedVertices[i].iRegNeg;
1188 if (iPosIn == -1 && iNegIn == -1) {
1192 StringRegion currentRegion = system.region(iPosIn, iNegIn);
1193 eX = currentRegion.eX;
1194 eY = currentRegion.eY;
1198 for (
int iTry = 0; ; ++iTry) {
1199 double transX = rndmPtr -> gauss();
1200 double transY = rndmPtr -> gauss();
1201 Vec4 transversePos = xySmear * (transX * eX + transY * eY) / sqrt(2.);
1202 positionTot = transversePos + longitudinal[i];
1206 double newtime = sqrt(longitudinal[i].m2Calc()
1207 + positionTot.pAbs2());
1208 positionTot.e(newtime);
1211 if (positionTot.m2Calc() >= 0.)
break;
1213 positionTot = longitudinal[i];
1219 spaceTime.push_back(positionTot);
1223 vector<Vec4> legMinSpaceTime, legMidSpaceTime;
1227 for (
int legLoop = 0; legLoop < 2; ++legLoop) {
1228 vector<StringVertex> legVertices = (legLoop == 0) ? legMinVertices
1230 StringSystem& systemNow = (legLoop == 0) ? systemMin : systemMid;
1231 vector<int> iPartonNow = (legLoop == 0) ? iPartonMinLeg : iPartonMidLeg;
1232 vector<Vec4> longitudinalPos;
1233 if (
int(legVertices.size()) < 2)
continue;
1236 for (
int i = 0; i < int(legVertices.size()); i++) {
1239 int iPosIn = legVertices[i].iRegPos;
1240 int iNegIn = legVertices[i].iRegNeg;
1241 double xPosIn = legVertices[i].xRegPos;
1242 double xNegIn = legVertices[i].xRegNeg;
1243 StringRegion currentRegion = systemNow.region( iPosIn, iNegIn);
1244 Vec4 gluonOffset = currentRegion.gluonOffsetJRF( iPartonNow, event,
1245 iPosIn, iNegIn, MtoJRF) / kappaVtx;
1246 Vec4 pRegion = (currentRegion.pPos + currentRegion.pNeg) / kappaVtx;
1247 Vec4 noOffset = (xPosIn * currentRegion.pPos
1248 + xNegIn * currentRegion.pNeg) / kappaVtx;
1252 if (noOffset.m2Calc() < 0.) {
1253 double cPlus = (-pRegion * noOffset + sqrt( pow2(pRegion * noOffset)
1254 - pRegion.m2Calc() * noOffset.m2Calc())) / pRegion.m2Calc();
1255 Vec4 pCorrection = noOffset + cPlus * pRegion;
1256 Vec4 fracCorrection;
1257 bool betterFrac =
false;
1258 if (xPosIn < 0. || xPosIn > 1. || xNegIn < 0. || xNegIn > 1.) {
1259 xPosIn = max( 0., min( 1., xPosIn) );
1260 xNegIn = max( 0., min( 1., xNegIn) );
1261 fracCorrection = (xPosIn * currentRegion.pPos
1262 + xNegIn * currentRegion.pNeg) / kappaVtx;
1263 betterFrac = abs(noOffset.e() - pCorrection.e())
1264 > abs(noOffset.e() - fracCorrection.e());
1266 noOffset = (betterFrac) ? fracCorrection : pCorrection;
1269 Vec4 fromBreaks = noOffset + gluonOffset;
1270 longitudinalPos.push_back(fromBreaks);
1271 if (fromBreaks.m2Calc() < -CHECKPOS * max(1., pow2(fromBreaks.e())))
1272 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices: "
1273 "negative tau^2 from breaks");
1277 for (
int i = 0; i < int(legVertices.size()); ++i) {
1278 int iPosIn = legVertices[i].iRegPos;
1279 int iNegIn = legVertices[i].iRegNeg;
1280 StringRegion currentRegion = systemNow.region( iPosIn, iNegIn);
1281 int id =
event[ iPartonNow.front() ].idAbs();
1283 if ( currentRegion.massiveOffset( iPosIn, iNegIn, systemNow.iMax,
1287 if (i == 0 && (
id == 4 ||
id == 5)) {
1288 int iPosIn2 = legVertices[i + 1].iRegPos;
1289 int iNegIn2 = legVertices[i + 1].iRegNeg;
1290 v2 = longitudinalPos[i + 1];
1291 double mHad =
event[hadSoFar +
event.size() - hadrons.size()].m();
1292 double pPosMass = particleDataPtr->m0(
id);
1293 if (iPosIn == iPosIn2 && iNegIn == iNegIn2) {
1294 v1 = longitudinalPos[i];
1295 longitudinalPos[i] = v1 + (pPosMass / mHad) * (v2 - v1);
1296 if (longitudinalPos[i].m2Calc()
1297 < -CHECKPOS * max(1., pow2(longitudinalPos[i].e())))
1298 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices"
1299 ": negative tau^2 for endpoint massive correction");
1301 StringRegion region2 = systemNow.region( iPosIn2, iNegIn2);
1302 Vec4 gluonOffset = currentRegion.gluonOffsetJRF( iPartonNow,
1303 event, iPosIn2, iNegIn2, MtoJRF);
1304 v1 = (region2.pPos + gluonOffset) / kappaVtx;
1305 longitudinalPos[i] = v1 + (pPosMass / mHad) * (v2 - v1);
1306 if (longitudinalPos[i].m2Calc()
1307 < -CHECKPOS * max(1., pow2(longitudinalPos[i].e())))
1308 infoPtr->errorMsg(
"Warning in StringFragmentation::setVertices"
1309 ": negative tau^2 for endpoint massive correction");
1315 Vec4 massOffset = currentRegion.massOffset / kappaVtx;
1316 Vec4 position = longitudinalPos[i] - massOffset;
1319 if (position.m2Calc() < 0.) {
1321 if (position.m2Calc() > -CHECKPOS * max(1., pow2(position.e())))
1322 position.e( position.pAbs() );
1324 if (massOffset.m2Calc() > 1e-6)
1325 cMinus = (longitudinalPos[i] * massOffset
1326 - sqrt(pow2(longitudinalPos[i] * massOffset)
1327 - longitudinalPos[i].m2Calc() * massOffset.m2Calc()))
1328 / massOffset.m2Calc();
1329 else cMinus = 0.5 * longitudinalPos[i].m2Calc()
1330 / (longitudinalPos[i] * massOffset);
1331 position = longitudinalPos[i] - cMinus * massOffset;
1334 longitudinalPos[i] = position;
1338 for (
int i = 0; i < int(legVertices.size()); ++i) {
1339 Vec4 positionTot = longitudinalPos[i];
1343 int iPosIn = legVertices[i].iRegPos;
1344 int iNegIn = legVertices[i].iRegNeg;
1345 StringRegion currentRegion = systemNow.region( iPosIn, iNegIn);
1346 Vec4 eX = currentRegion.eX;
1347 Vec4 eY = currentRegion.eY;
1348 for (
int iTry = 0; ; ++iTry) {
1349 double transX = rndmPtr->gauss();
1350 double transY = rndmPtr->gauss();
1351 Vec4 transversePos = xySmear * (transX * eX + transY * eY)
1353 positionTot = transversePos + longitudinalPos[i];
1357 double newtime = sqrt( longitudinalPos[i].m2Calc()
1358 + positionTot.pAbs2());
1359 positionTot.e(newtime);
1362 if (positionTot.m2Calc() >= 0.)
break;
1364 positionTot = longitudinalPos[i];
1372 positionTot.rotbst(MfromJRF);
1376 if (positionTot.m2Calc() < 0.)
1377 positionTot.e( positionTot.pAbs() );
1378 if (legLoop == 0) legMinSpaceTime.push_back(positionTot);
1379 else legMidSpaceTime.push_back(positionTot);
1383 hadSoFar = hadSoFar + legVertices.size() - 1;
1392 for (
int legLoop = 0; legLoop < 2; legLoop++) {
1393 vector<Vec4>& finalLocation = (legLoop == 0) ? legMinSpaceTime
1395 vector<int> iPartonNow = (legLoop == 0) ? iPartonMinLeg : iPartonMidLeg;
1396 int id =
event[iPartonNow.front()].idAbs();
1400 for (
int i = 0; i < int(finalLocation.size()) - 1; ++i) {
1401 Vec4 middlePoint = 0.5 * (finalLocation[i] + finalLocation[i + 1]);
1402 int iHad = i + hadSoFar +
event.size() - hadrons.size();
1403 Vec4 pHad =
event[iHad].p();
1404 Vec4 prodPoints = Vec4( 0., 0., 0., 0.);
1407 double mHad =
event[iHad].m();
1408 double redOsc = (i == 0 && (
id == 4 ||
id == 5))
1409 ? 1. - pow2(particleDataPtr->m0(
id) / mHad) : 1.;
1412 if (hadronVertex == 0) prodPoints = middlePoint;
1413 else if (hadronVertex == 1)
1414 prodPoints = middlePoint + 0.5 * redOsc * pHad / kappaVtx;
1416 prodPoints = middlePoint - 0.5 * redOsc * pHad / kappaVtx;
1417 if (prodPoints.m2Calc() < 0.) {
1418 double midpProd = redOsc * middlePoint * pHad;
1419 double tau0fac = 2. * (midpProd - sqrt( pow2(midpProd)
1420 - middlePoint.m2Calc() * pow2(redOsc * mHad)))
1421 / pow2(redOsc * mHad);
1422 prodPoints = middlePoint - 0.5 * tau0fac * redOsc * pHad
1426 event[iHad].vProd( event[iHad].vProd() + prodPoints * FM2MM );
1429 hadSoFar = hadSoFar + finalLocation.size() - 1;
1435 for (
int i = 0; i < int(spaceTime.size()) - 1; ++i) {
1436 Vec4 middlePoint = 0.5 * (spaceTime[i] + spaceTime[i + 1]);
1437 int iHad = i + iHadJunc +
event.size() - hadrons.size();
1438 Vec4 pHad =
event[iHad].p();
1439 Vec4 prodPoints = Vec4( 0., 0., 0., 0.);
1443 double mHad =
event[iHad].m();
1444 if (i == 0 && (id1 == 4 || id1 == 5))
1445 redOsc = 1. - pow2( particleDataPtr->m0(id1) / mHad);
1446 if (i ==
int(spaceTime.size()) - 1 && (id2 == 4 || id2 == 5))
1447 redOsc = 1. - pow2( particleDataPtr->m0(id2) / mHad);
1450 if (hadronVertex == 0) prodPoints = middlePoint;
1451 else if (hadronVertex == 1)
1452 prodPoints = middlePoint + 0.5 * redOsc * pHad / kappaVtx;
1454 prodPoints = middlePoint - 0.5 * redOsc * pHad / kappaVtx;
1455 if (prodPoints.m2Calc() < 0.) {
1456 double midpProd = redOsc * middlePoint * pHad;
1457 double tau0fac = 2. * ( midpProd - sqrt( pow2(midpProd)
1458 - middlePoint.m2Calc() * pow2(redOsc * mHad))) / pow2(redOsc * mHad);
1459 prodPoints = middlePoint - 0.5 * tau0fac * redOsc * pHad / kappaVtx;
1462 event[iHad].vProd( event[iHad].vProd() + prodPoints * FM2MM );
1471 bool StringFragmentation::finalTwo(
bool fromPos,
Event& event,
1472 bool usedPosJun,
bool usedNegJun,
double nNSP) {
1475 if (pRem.e() < 0. || w2Rem < 0. || (hadrons.size() > 0
1476 && hadrons.back().e() < 0.) )
return false;
1477 if ( posEnd.iPosOld > negEnd.iPosOld || negEnd.iNegOld > posEnd.iNegOld)
1479 if ( posEnd.iPosOld == negEnd.iPosOld && posEnd.xPosOld < negEnd.xPosOld)
1481 if ( posEnd.iNegOld == negEnd.iNegOld && posEnd.xNegOld > negEnd.xNegOld)
1485 FlavContainer flav1 = (fromPos) ? posEnd.flavNew.anti() : posEnd.flavOld;
1486 FlavContainer flav2 = (fromPos) ? negEnd.flavOld : negEnd.flavNew.anti();
1487 if (flav1.isDiquark() && flav2.isDiquark())
return false;
1490 double pHadPrelim[2] = { 0.0, 0.0 };
1492 pHadPrelim[0] = negEnd.pxOld-posEnd.pxNew;
1493 pHadPrelim[1] = negEnd.pyOld-posEnd.pyNew;
1495 pHadPrelim[0] = posEnd.pxOld-negEnd.pxNew;
1496 pHadPrelim[1] = posEnd.pyOld-negEnd.pyNew;
1498 double pThadPrelim = sqrt( pow2(pHadPrelim[0]) + pow2(pHadPrelim[1]) );
1502 for (
int iTry = 0; iTry < NTRYFLAV; ++iTry) {
1503 idHad = flavSelPtr->getHadronID( flav1, flav2, pThadPrelim, nNSP,
true);
1504 if (idHad != 0)
break;
1506 if (idHad == 0)
return false;
1510 negEnd.idHad = idHad;
1511 negEnd.pxNew = -posEnd.pxNew;
1512 negEnd.pyNew = -posEnd.pyNew;
1513 negEnd.mHad = flavSelPtr->getHadronMassWin(idHad);
1515 posEnd.idHad = idHad;
1516 posEnd.pxNew = -negEnd.pxNew;
1517 posEnd.pyNew = -negEnd.pyNew;
1518 posEnd.mHad = flavSelPtr->getHadronMassWin(idHad);
1522 StringRegion region = finalRegion();
1523 if (region.isEmpty)
return false;
1526 region.project( pRem);
1527 double pxRem = region.px() - posEnd.pxOld - negEnd.pxOld;
1528 double pyRem = region.py() - posEnd.pyOld - negEnd.pyOld;
1529 double xPosRem = region.xPos();
1530 double xNegRem = region.xNeg();
1533 posEnd.pxOld += 0.5 * pxRem;
1534 posEnd.pyOld += 0.5 * pyRem;
1535 negEnd.pxOld += 0.5 * pxRem;
1536 negEnd.pyOld += 0.5 * pyRem;
1539 posEnd.pxHad = posEnd.pxOld + posEnd.pxNew;
1540 posEnd.pyHad = posEnd.pyOld + posEnd.pyNew;
1541 posEnd.mT2Had = pow2(posEnd.mHad) + pow2(posEnd.pxHad)
1542 + pow2(posEnd.pyHad);
1543 negEnd.pxHad = negEnd.pxOld + negEnd.pxNew;
1544 negEnd.pyHad = negEnd.pyOld + negEnd.pyNew;
1545 negEnd.mT2Had = pow2(negEnd.mHad) + pow2(negEnd.pxHad)
1546 + pow2(negEnd.pyHad);
1549 double wT2Rem = w2Rem + pow2( posEnd.pxHad + negEnd.pxHad)
1550 + pow2( posEnd.pyHad + negEnd.pyHad);
1553 if ( sqrt(wT2Rem) < sqrt(posEnd.mT2Had) + sqrt(negEnd.mT2Had) )
1555 double lambda2 = pow2( wT2Rem - posEnd.mT2Had - negEnd.mT2Had)
1556 - 4. * posEnd.mT2Had * negEnd.mT2Had;
1557 if (lambda2 <= 0.)
return false;
1560 double lambda = sqrt(lambda2);
1561 double probReverse = 1. / (1. + exp( min( EXPMAX, bLund * lambda) ) );
1562 double xpzPos = 0.5 * lambda/ wT2Rem;
1563 if (probReverse > rndmPtr->flat()) xpzPos = -xpzPos;
1564 double xmDiff = (posEnd.mT2Had - negEnd.mT2Had) / wT2Rem;
1565 double xePos = 0.5 * (1. + xmDiff);
1566 double xeNeg = 0.5 * (1. - xmDiff );
1569 Vec4 pHadPos = region.pHad( (xePos + xpzPos) * xPosRem,
1570 (xePos - xpzPos) * xNegRem, posEnd.pxHad, posEnd.pyHad);
1571 Vec4 pHadNeg = region.pHad( (xeNeg - xpzPos) * xPosRem,
1572 (xeNeg + xpzPos) * xNegRem, negEnd.pxHad, negEnd.pyHad);
1577 StringRegion posRegion = system.region( posEnd.iPosOld, posEnd.iNegOld);
1578 posRegion.project(pHadPos);
1579 double xFromPosPos = posEnd.xPosOld - posRegion.xPos();
1580 double xFromPosNeg = posEnd.xNegOld + posRegion.xNeg();
1583 StringRegion negRegion = system.region( negEnd.iPosOld, negEnd.iNegOld);
1584 negRegion.project(pHadNeg);
1585 double xFromNegPos = negEnd.xPosOld + negRegion.xPos();
1586 double xFromNegNeg = negEnd.xNegOld - negRegion.xNeg();
1590 if (xFromPosPos > 0. && xFromPosPos < 1. && xFromPosNeg > 0.
1591 && xFromPosNeg < 1.) stringVertices.push_back( StringVertex(
1592 fromPos, posEnd.iPosOld, posEnd.iNegOld, xFromPosPos, xFromPosNeg) );
1593 else if (xFromNegPos > 0. && xFromNegPos < 1. && xFromNegNeg > 0.
1594 && xFromNegNeg < 1.) stringVertices.push_back( StringVertex(
1595 fromPos, negEnd.iPosOld, negEnd.iNegOld, xFromNegPos, xFromNegNeg) );
1600 double gammaPosOld = posEnd.GammaOld;
1601 double gammaNegOld = negEnd.GammaOld;
1602 double zNewReg = 0.;
1603 if (posEnd.hadSoFar == 0) zNewReg = wT2Rem / (wT2Rem + gammaNegOld);
1604 else zNewReg = 0.5 * ( sqrt( pow2(wT2Rem + gammaNegOld - gammaPosOld)
1605 + 4. * wT2Rem * gammaPosOld) - (wT2Rem + gammaNegOld - gammaPosOld) )
1607 double zHad = (xePos + xpzPos) * zNewReg;
1608 Vec4 proof = posEnd.kinematicsHadron(system, stringVertices,
true, zHad);
1611 if (proof.e() < -1e-8) {
1612 if (negEnd.hadSoFar == 0) zNewReg = wT2Rem / (wT2Rem + gammaPosOld);
1613 else zNewReg = 0.5 * ( sqrt( pow2(wT2Rem + gammaPosOld - gammaNegOld)
1614 + 4. * wT2Rem * gammaNegOld) - (wT2Rem + gammaPosOld - gammaNegOld) )
1616 zHad = (xeNeg + xpzPos) * zNewReg;
1617 proof = negEnd.kinematicsHadron( system, stringVertices,
true, zHad);
1620 if (proof.e() < -1.) {
1621 pPosFinalReg = region.pPos;
1622 pNegFinalReg = region.pNeg;
1623 eXFinalReg = region.eX;
1624 eYFinalReg = region.eY;
1625 stringVertices.push_back( StringVertex(
true, -1, -1,
1626 1. - (xePos + xpzPos) * xPosRem, (xePos - xpzPos) * xNegRem) );
1633 int statusHadPos = 83;
1634 int statusHadNeg = 84;
1636 if (abs(posEnd.idHad) > 1000 && abs(posEnd.idHad) < 10000) {
1637 if (event[iPos].statusAbs() == 74 && !usedPosJun) {
1642 if (abs(idHad) > 1000 && abs(idHad) < 10000) {
1643 if ((!usedNegJun && (event[iNeg].statusAbs() == 74 || hasJunction))
1644 || (!usedPosJun && event[iPos].statusAbs() == 74)) {
1649 if (abs(negEnd.idHad) > 1000 && abs(negEnd.idHad) < 10000) {
1650 if (!usedNegJun && (event[iNeg].statusAbs() == 74 || hasJunction)) {
1655 if (abs(idHad) > 1000 && abs(idHad) < 10000) {
1656 if ((!usedNegJun && (event[iNeg].statusAbs() == 74 || hasJunction))
1657 || (!usedPosJun && event[iPos].statusAbs() == 74)) {
1664 hadrons.append( posEnd.idHad, statusHadPos, posEnd.iEnd, negEnd.iEnd,
1665 0, 0, 0, 0, pHadPos, posEnd.mHad);
1666 hadrons.append( negEnd.idHad, statusHadNeg, posEnd.iEnd, negEnd.iEnd,
1667 0, 0, 0, 0, pHadNeg, negEnd.mHad);
1678 StringRegion StringFragmentation::finalRegion() {
1681 if (posEnd.iPosOld == negEnd.iPosOld && posEnd.iNegOld == negEnd.iNegOld)
1682 return system.region( posEnd.iPosOld, posEnd.iNegOld);
1685 StringRegion region;
1689 if ( posEnd.iPosOld == negEnd.iPosOld) {
1690 double xPosJoin = posEnd.xPosOld - negEnd.xPosOld;
1691 if (xPosJoin < 0.)
return region;
1692 pPosJoin = system.regionLowPos(posEnd.iPosOld).pHad( xPosJoin, 0., 0., 0.);
1694 for (
int iPosNow = posEnd.iPosOld; iPosNow <= negEnd.iPosOld; ++iPosNow) {
1695 if (iPosNow == posEnd.iPosOld) pPosJoin
1696 += system.regionLowPos(iPosNow).pHad( posEnd.xPosOld, 0., 0., 0.);
1697 else if (iPosNow == negEnd.iPosOld) pPosJoin
1698 += system.regionLowPos(iPosNow).pHad( 1. - negEnd.xPosOld, 0., 0., 0.);
1699 else pPosJoin += system.regionLowPos(iPosNow).pHad( 1., 0., 0., 0.);
1705 if ( negEnd.iNegOld == posEnd.iNegOld) {
1706 double xNegJoin = negEnd.xNegOld - posEnd.xNegOld;
1707 if (xNegJoin < 0.)
return region;
1708 pNegJoin = system.regionLowNeg(negEnd.iNegOld).pHad( 0., xNegJoin, 0., 0.);
1710 for (
int iNegNow = negEnd.iNegOld; iNegNow <= posEnd.iNegOld; ++iNegNow) {
1711 if (iNegNow == negEnd.iNegOld) pNegJoin
1712 += system.regionLowNeg(iNegNow).pHad( 0., negEnd.xNegOld, 0., 0.);
1713 else if (iNegNow == posEnd.iNegOld) pNegJoin
1714 += system.regionLowNeg(iNegNow).pHad( 0., 1. - posEnd.xNegOld, 0., 0.);
1715 else pNegJoin += system.regionLowNeg(iNegNow).pHad( 0., 1., 0., 0.);
1721 Vec4 pTest = pPosJoin - pNegJoin;
1722 if ( abs(pTest.px()) + abs(pTest.py()) + abs(pTest.pz()) + abs(pTest.e())
1723 < MATCHPOSNEG * (pPosJoin.e() + pNegJoin.e()) ) {
1725 = system.regionLowPos(posEnd.iPosOld + 1).pHad( 1., 0., 0., 0.)
1726 - system.regionLowNeg(negEnd.iNegOld + 1).pHad( 0., 1., 0., 0.);
1729 if ( abs(delta.px()) + abs(delta.py()) + abs(delta.pz()) + abs(delta.e())
1730 < MATCHPOSNEG * (pPosJoin.e() + pNegJoin.e()) ) {
1731 double cthe = 2. * rndmPtr->flat() - 1.;
1732 double sthe = sqrtpos(1. - cthe * cthe);
1733 double phi = 2. * M_PI * rndmPtr->flat();
1734 delta = 0.5 * min( pPosJoin.e(), pNegJoin.e())
1735 * Vec4( sthe * sin(phi), sthe * cos(phi), cthe, 0.);
1736 infoPtr->errorMsg(
"Warning in StringFragmentation::finalRegion: "
1737 "random axis needed to break tie");
1744 region.setUp( pPosJoin, pNegJoin);
1745 if (region.isEmpty)
return region;
1748 Vec4 pTposOld = system.region( posEnd.iPosOld, posEnd.iNegOld).pHad(
1749 0., 0., posEnd.pxOld, posEnd.pyOld);
1750 region.project( pTposOld);
1751 posEnd.pxOld = region.px();
1752 posEnd.pyOld = region.py();
1753 Vec4 pTnegOld = system.region( negEnd.iPosOld, negEnd.iNegOld).pHad(
1754 0., 0., negEnd.pxOld, negEnd.pyOld);
1755 region.project( pTnegOld);
1756 negEnd.pxOld = region.px();
1757 negEnd.pyOld = region.py();
1768 void StringFragmentation::store(
Event& event) {
1771 int iFirst =
event.size();
1775 for (
int i = 0; i < hadrons.size(); ++i)
1776 if (hadrons[i].status() == 85 || hadrons[i].status() == 86)
1777 event.append( hadrons[i] );
1781 for (
int i = 0; i < hadrons.size(); ++i)
1782 if (hadrons[i].status() == 83 || hadrons[i].status() == 87)
1783 event.append( hadrons[i] );
1786 for (
int i = hadrons.size() - 1; i >= 0 ; --i)
1787 if (hadrons[i].status() == 84 || hadrons[i].status() == 88)
1788 event.append( hadrons[i] );
1790 int iLast =
event.size() - 1;
1793 if (event[posEnd.iEnd].hasVertex()) {
1794 Vec4 vDec =
event[posEnd.iEnd].vDec();
1795 for (
int i = iFirst; i <= iLast; ++i) event[i].vProd( vDec );
1799 for (
int i = iFirst; i <= iLast; ++i)
1800 event[i].tau( event[i].tau0() * rndmPtr->exp() );
1803 for (
int i = 0; i < int(iParton.size()); ++i)
1804 if (iParton[i] >= 0) {
1805 event[ iParton[i] ].statusNeg();
1806 event[ iParton[i] ].daughters(iFirst, iLast);
1815 bool StringFragmentation::fragmentToJunction(
Event& event) {
1820 int legBeg[3] = { 0, 0, 0};
1821 int legEnd[3] = { 0, 0, 0};
1824 if (iParton[0] > 0) {
1825 infoPtr->errorMsg(
"Error in StringFragmentation::fragment"
1826 "ToJunction: iParton[0] not a valid junctionNumber");
1829 for (
int i = 0; i < int(iParton.size()); ++i) {
1830 if (iParton[i] < 0) {
1832 infoPtr->errorMsg(
"Error in StringFragmentation::fragment"
1833 "ToJunction: unprocessed multi-junction system");
1836 legBeg[++leg] = i + 1;
1838 else legEnd[leg] = i;
1844 MtoJRF.bstback(pSum);
1847 double errInCM = 0.;
1852 for (leg = 0; leg < 3; ++ leg) {
1854 double eWeight = 0.;
1855 for (
int i = legBeg[leg]; i <= legEnd[leg]; ++i) {
1856 Vec4 pTemp =
event[ iParton[i] ].p();
1857 pTemp.rotbst(MtoJRF);
1858 pWTinJRF[leg] += pTemp * exp(-eWeight);
1859 eWeight += pTemp.e() / eNormJunction;
1860 if (eWeight > EJNWEIGHTMAX)
break;
1865 if (iter == 1) errInCM = pow2(costheta(pWTinJRF[0], pWTinJRF[1]) + 0.5)
1866 + pow2(costheta(pWTinJRF[0], pWTinJRF[2]) + 0.5)
1867 + pow2(costheta(pWTinJRF[1], pWTinJRF[2]) + 0.5);
1870 if ( (pWTinJRF[0] + pWTinJRF[1]).m2Calc() < M2MINJRF
1871 || (pWTinJRF[0] + pWTinJRF[2]).m2Calc() < M2MINJRF
1872 || (pWTinJRF[1] + pWTinJRF[2]).m2Calc() < M2MINJRF ) {
1873 infoPtr->errorMsg(
"Warning in StringFragmentation::fragmentTo"
1874 "Junction: Negative invariant masses in junction rest frame");
1876 MtoJRF.bstback(pSum);
1880 Mstep = junctionRestFrame( pWTinJRF[0], pWTinJRF[1], pWTinJRF[2]);
1883 MtoJRF.rotbst( Mstep );
1884 }
while (iter < 3 || (Mstep.deviation() > CONVJNREST && iter < NTRYJNREST) );
1887 double errInJRF = pow2(costheta(pWTinJRF[0], pWTinJRF[1]) + 0.5)
1888 + pow2(costheta(pWTinJRF[0], pWTinJRF[2]) + 0.5)
1889 + pow2(costheta(pWTinJRF[1], pWTinJRF[2]) + 0.5);
1890 if (errInJRF > errInCM + CONVJNREST) {
1891 infoPtr->errorMsg(
"Warning in StringFragmentation::fragmentTo"
1892 "Junction: bad convergence junction rest frame");
1894 MtoJRF.bstback(pSum);
1902 Vec4 pInLeg[3], pInJRF[3];
1903 for (leg = 0; leg < 3; ++leg) {
1905 for (
int i = legBeg[leg]; i <= legEnd[leg]; ++i)
1906 pInLeg[leg] += event[ iParton[i] ].p();
1907 pInJRF[leg] = pInLeg[leg];
1908 pInJRF[leg].rotbst(MtoJRF);
1912 legMin = (pInJRF[0].e() < pInJRF[1].e()) ? 0 : 1;
1913 int legMax = 1 - legMin;
1914 if (pInJRF[2].e() < min(pInJRF[0].e(), pInJRF[1].e()) ) legMin = 2;
1915 else if (pInJRF[2].e() > max(pInJRF[0].e(), pInJRF[1].e()) ) legMax = 2;
1916 legMid = 3 - legMin - legMax;
1919 int iJunction = (-iParton[0]) / 10 - 1;
1920 event.statusJunction( iJunction, legMin, 85);
1921 event.statusJunction( iJunction, legMid, 86);
1922 event.statusJunction( iJunction, legMax, 83);
1926 vector<int> iPartonMin;
1927 iPartonMinLeg.clear();
1928 for (
int i = legEnd[legMin]; i >= legBeg[legMin]; --i) {
1929 if (setVertices) iPartonMinLeg.push_back( iParton[i] );
1930 int iNew =
event.append( event[ iParton[i] ] );
1931 event[iNew].rotbst(MtoJRF);
1932 iPartonMin.push_back( iNew );
1934 vector<int> iPartonMid;
1935 iPartonMidLeg.clear();
1936 for (
int i = legEnd[legMid]; i >= legBeg[legMid]; --i) {
1937 if (setVertices) iPartonMidLeg.push_back( iParton[i] );
1938 int iNew =
event.append( event[ iParton[i] ] );
1939 event[iNew].rotbst(MtoJRF);
1940 iPartonMid.push_back( iNew );
1944 double eWeight = 0.;
1945 pWTinJRF[legMin] = 0.;
1946 for (
int i = iPartonMin.size() - 1; i >= 0; --i) {
1947 pWTinJRF[legMin] +=
event[ iPartonMin[i] ].p() * exp(-eWeight);
1948 eWeight +=
event[ iPartonMin[i] ].e() / eNormJunction;
1949 if (eWeight > EJNWEIGHTMAX)
break;
1952 pWTinJRF[legMid] = 0.;
1953 for (
int i = iPartonMid.size() - 1; i >= 0; --i) {
1954 pWTinJRF[legMid] +=
event[ iPartonMid[i] ].p() * exp(-eWeight);
1955 eWeight +=
event[ iPartonMid[i] ].e() / eNormJunction;
1956 if (eWeight > EJNWEIGHTMAX)
break;
1960 Vec4 pOppose = pWTinJRF[legMin];
1962 int idOppose = (rndmPtr->flat() > 0.5) ? 2 : 1;
1963 if (event[ iPartonMin[0] ].col() > 0) idOppose = -idOppose;
1964 int iOppose =
event.append( idOppose, 77, 0, 0, 0, 0, 0, 0,
1966 iPartonMin.push_back( iOppose);
1967 pOppose = pWTinJRF[legMid];
1969 idOppose = (rndmPtr->flat() > 0.5) ? 2 : 1;
1970 if (event[ iPartonMid[0] ].col() > 0) idOppose = -idOppose;
1971 iOppose =
event.append( idOppose, 77, 0, 0, 0, 0, 0, 0,
1973 iPartonMid.push_back( iOppose);
1976 systemMin.setUp(iPartonMin, event);
1977 systemMid.setUp(iPartonMid, event);
1983 for (
int iTryOuter = 0; ; ++iTryOuter) {
1986 double eLeftMin = 0.;
1987 double eLeftMid = 0.;
1988 for (
int iTryMiddle = 0; ; ++iTryMiddle) {
1991 for (
int legLoop = 0; legLoop < 2; ++ legLoop) {
1992 int legNow = (legLoop == 0) ? legMin : legMid;
1995 StringSystem& systemNow = (legLoop == 0) ? systemMin : systemMid;
1996 int idPos = (legLoop == 0) ? event[ iPartonMin[0] ].
id()
1997 :
event[ iPartonMid[0] ].id();
1998 idOppose = (legLoop == 0) ? event[ iPartonMin.back() ].id()
1999 :
event[ iPartonMid.back() ].id();
2000 double eInJRF = pInJRF[legNow].e();
2001 int statusHad = (legLoop == 0) ? 85 : 86;
2005 vector<StringVertex> junctionVertices;
2006 for (
int iTryInner = 0; ; ++iTryInner) {
2008 if (iTryInner > 2 * NTRYJNMATCH) {
2009 infoPtr->errorMsg(
"Error in StringFragmentation::fragment"
2010 "ToJunction: caught in junction flavour loop");
2011 event.popBack( iPartonMin.size() + iPartonMid.size() );
2015 bool needBaryon = (abs(idPos) > 10 && iTryInner > NTRYJNMATCH);
2016 double eExtra = (iTryInner > NTRYJNMATCH) ? EEXTRAJNMATCH : 0.;
2019 setStartEnds(idPos, idOppose, systemNow, legNow);
2026 for ( ; ; ++nHadrons) {
2030 if (!flavRopePtr->doChangeFragPar(flavSelPtr, zSelPtr, pTSelPtr,
2031 hadMom.m2Calc(), (legLoop == 0 ? iPartonMin : iPartonMid ),
2032 idPos )) infoPtr->errorMsg(
"Error in StringFragmentation::"
2033 "fragmentToJunction: FlavourRope failed to change "
2034 "fragmentation parameters.");
2038 if ( (userHooksPtr != 0) && userHooksPtr->canChangeFragPar() ) {
2039 if ( !userHooksPtr->doChangeFragPar( flavSelPtr, zSelPtr,
2040 pTSelPtr, idPos, hadMom.m2Calc(),
2041 (legLoop == 0 ? iPartonMin : iPartonMid )) )
2042 infoPtr->errorMsg(
"Error in StringFragmentation::fragment"
2043 "ToJunction: failed to change hadronisation parameters.");
2048 Vec4 pHad = posEnd.kinematicsHadron(systemNow, junctionVertices);
2051 if (pHad.e() < 0. ) { noNegE =
false;
break; }
2055 bool delayedBreak =
false;
2056 if (eUsed + pHad.e() + eExtra > eInJRF) {
2057 if (nHadrons > 0 || !needBaryon) {
2058 junctionVertices.pop_back();
2061 delayedBreak =
true;
2065 hadrons.append( posEnd.idHad, statusHad, iPos, iNeg,
2066 0, 0, 0, 0, pHad, posEnd.mHad);
2081 if (iTryInner > NTRYJNMATCH && !noNegE && nHadrons == 0 &&
2082 abs(idPos) < 10)
break;
2085 if ( noNegE && abs(posEnd.flavOld.id) < 10 )
break;
2086 hadrons.popBack(nHadrons);
2087 junctionVertices.clear();
2088 if (legNow == legMin) legMinVertices.clear();
2089 else legMidVertices.clear();
2093 if (legNow == legMin) {
2094 idMin = posEnd.flavOld.id;
2095 eLeftMin = eInJRF - eUsed;
2097 idMid = posEnd.flavOld.id;
2098 eLeftMid = eInJRF - eUsed;
2103 for (
int i = 0; i < int(junctionVertices.size()); ++i) {
2104 if (legNow == legMin)
2105 legMinVertices.push_back( junctionVertices[i]);
2106 else legMidVertices.push_back( junctionVertices[i]);
2113 double eTrial = eBothLeftJunction + rndmPtr->flat() * eMaxLeftJunction;
2114 if (iTryMiddle > NTRYJNMATCH
2115 || ( min( eLeftMin, eLeftMid) < eBothLeftJunction
2116 && max( eLeftMin, eLeftMid) < eTrial ) )
break;
2118 legMinVertices.clear();
2119 legMidVertices.clear();
2123 for (
int i = 0; i < hadrons.size(); ++i) {
2124 hadrons[i].rotbst(MfromJRF);
2128 hadrons[i].e( hadrons[i].eCalc() );
2129 pJunctionHadrons += hadrons[i].p();
2134 pDiquark = pInLeg[legMin] + pInLeg[legMid] - pJunctionHadrons;
2135 double m2Left = m2( pInLeg[legMax], pDiquark);
2136 if (iTryOuter > NTRYJNMATCH || (pDiquark.mCalc() > MDIQUARKMIN
2137 && m2Left > eMinLeftJunction * pInLeg[legMax].e()) )
break;
2139 legMinVertices.clear();
2140 legMidVertices.clear();
2141 pJunctionHadrons = 0.;
2145 event.popBack( iPartonMin.size() + iPartonMid.size() );
2149 idDiquark = flavSelPtr->makeDiquark( idMin, idMid);
2150 int iDiquark =
event.append( idDiquark, 78, 0, 0, 0, 0, 0, 0,
2151 pDiquark, pDiquark.mCalc());
2155 for (
int i = legEnd[legMax]; i >= legBeg[legMax]; --i)
2156 iPartonMax.push_back( iParton[i] );
2157 iPartonMax.push_back( iDiquark );
2160 int iPsize = iPartonMax.size();
2161 double m0Diquark =
event[iDiquark].m0();
2162 while (iPsize > 2) {
2163 Vec4 pGluNear =
event[ iPartonMax[iPsize - 2] ].p();
2164 if ( (pDiquark + 0.5 * pGluNear).mCalc() > m0Diquark + mJoin )
break;
2165 pDiquark += pGluNear;
2166 event[iDiquark].p( pDiquark );
2167 event[iDiquark].m( pDiquark.mCalc() );
2168 iPartonMax.pop_back();
2170 iPartonMax[iPsize - 1] = iDiquark;
2174 iParton = iPartonMax;
2185 RotBstMatrix StringFragmentation::junctionRestFrame(Vec4& p0, Vec4& p1,
2189 Vec4 pSumJun = p0 + p1 + p2;
2190 double sHat = pSumJun.m2Calc();
2192 pp[0][0] = p0.m2Calc();
2193 pp[1][1] = p1.m2Calc();
2194 pp[2][2] = p2.m2Calc();
2195 pp[0][1] = pp[1][0] = p0 * p1;
2196 pp[0][2] = pp[2][0] = p0 * p2;
2197 pp[1][2] = pp[2][1] = p1 * p2;
2201 double eMax01 = pow2(pp[0][1]) * pp[2][2];
2202 double eMax02 = pow2(pp[0][2]) * pp[1][1];
2203 double eMax12 = pow2(pp[1][2]) * pp[0][0];
2206 int i = (pp[1][1] > pp[0][0]) ? 1 : 0;
2207 if (pp[2][2] > max(pp[0][0], pp[1][1])) i = 2;
2212 for (
int iTry = 0; iTry < 3; ++iTry) {
2215 if (i == 0) j = (eMax02 < eMax01) ? 2 : 1;
2216 else if (i == 1) j = (eMax12 < eMax01) ? 2 : 0;
2217 else j = (eMax12 < eMax02) ? 1 : 0;
2221 double m2i = pp[i][i];
2222 double m2j = pp[j][j];
2223 double m2k = pp[k][k];
2224 double pipj = pp[i][j];
2225 double pipk = pp[i][k];
2226 double pjpk = pp[j][k];
2229 if (m2i < M2MAXJRF) {
2230 ei = sqrt( 2. * pipk * pipj / (3. * pjpk) );
2231 ej = sqrt( 2. * pjpk * pipj / (3. * pipk) );
2232 ek = sqrt( 2. * pipk * pjpk / (3. * pipj) );
2238 double eiMin = sqrt(m2i);
2239 double ejMin = pipj / eiMin;
2240 double ekMin = pipk / eiMin;
2241 double pjMin = sqrtpos( ejMin*ejMin - m2j );
2242 double pkMin = sqrtpos( ekMin*ekMin - m2k );
2243 double fMin = ejMin * ekMin + 0.5 * pjMin * pkMin - pjpk;
2245 double eiMax = (pipj + pipk)
2246 / sqrt( max( M2MINJRF, m2j + m2k + 2. * pjpk) );
2247 if (m2j > M2MAXJRF) eiMax = min( eiMax, pipj / sqrt(m2j) );
2248 double piMax = sqrtpos( eiMax*eiMax - m2i );
2249 double temp = eiMax*eiMax - 0.25 *piMax*piMax;
2250 double pjMax = (eiMax * sqrtpos( pipj*pipj - m2j * temp )
2251 - 0.5 * piMax * pipj) / temp;
2252 double pkMax = (eiMax * sqrtpos( pipk*pipk - m2k * temp )
2253 - 0.5 * piMax * pipk) / temp;
2254 double ejMax = sqrt(pjMax*pjMax + m2j);
2255 double ekMax = sqrt(pkMax*pkMax + m2k);
2256 double fMax = ejMax * ekMax + 0.5 * pjMax * pkMax - pjpk;
2260 int iPrel = (i + 1)%3;
2261 if (pp[iPrel][iPrel] > M2MAXJRF) {i = iPrel;
continue;}
2264 if (iTry < 3 && pp[iPrel][iPrel] > M2MAXJRF) {i = iPrel;
continue;}
2270 double pi = 0.5 * (piMin + piMax);
2271 for (
int iter = 0; iter < NTRYJRFEQ; ++iter) {
2274 ei = sqrt(pi*pi + m2i);
2275 temp = ei*ei - 0.25 * pi*pi;
2276 double pj = (ei * sqrtpos( pipj*pipj - m2j * temp )
2277 - 0.5 * pi * pipj) / temp;
2278 double pk = (ei * sqrtpos( pipk*pipk - m2k * temp )
2279 - 0.5 * pi * pipk) / temp;
2280 ej = sqrt(pj*pj + m2j);
2281 ek = sqrt(pk*pk + m2k);
2282 double fNow = ej * ek + 0.5 * pj * pk - pjpk;
2285 if (fNow > 0.) { ++iterMin; piMin = pi; fMin = fNow;}
2286 else {++iterMax; piMax = pi; fMax = fNow;}
2289 if (2 * iter < NTRYJRFEQ
2290 && (iterMin < 2 || iterMax < 2 || 4 * iter < NTRYJRFEQ))
2291 { pi = 0.5 * (piMin + piMax);
continue;}
2292 if (fMin < 0. || fMax > 0. || abs(fNow) < CONVJRFEQ * sHat)
break;
2293 pi = piMin + (piMax - piMin) * fMin / (fMin - fMax);
2301 double eNew[3] = { 0., 0., 0.};
2311 Mmove.bstback(pSumJun);
2317 Vec4 pDir01 = p0cm / p0cm.e() - p1cm / p1cm.e();
2318 Vec4 pDir02 = p0cm / p0cm.e() - p2cm / p2cm.e();
2319 double pDiff01 = pDir01.pAbs2();
2320 double pDiff02 = pDir02.pAbs2();
2321 double pDiff0102 = dot3(pDir01, pDir02);
2322 double eDiff01 = eNew[0] / p0cm.e() - eNew[1] / p1cm.e();
2323 double eDiff02 = eNew[0] / p0cm.e() - eNew[2] / p2cm.e();
2324 double denom = pDiff01 * pDiff02 - pDiff0102*pDiff0102;
2325 double coef01 = (eDiff01 * pDiff02 - eDiff02 * pDiff0102) / denom;
2326 double coef02 = (eDiff02 * pDiff01 - eDiff01 * pDiff0102) / denom;
2327 Vec4 vJunction = coef01 * pDir01 + coef02 * pDir02;
2328 vJunction.e( sqrt(1. + vJunction.pAbs2()) );
2331 Mmove.bst(vJunction);
2341 int StringFragmentation::extraJoin(
double facExtra,
Event& event) {
2345 int iPsize = iParton.size();
2346 while (iPsize > 2) {
2351 double mJoinMin = 2. * facExtra * mJoin;
2352 for (
int i = 0; i < iPsize - 1; ++i) {
2353 Particle& parton1 =
event[ iParton[i] ];
2354 Particle& parton2 =
event[ iParton[i + 1] ];
2356 pSumNow += (parton2.isGluon()) ? 0.5 * parton1.p() : parton1.p();
2357 pSumNow += (parton2.isGluon()) ? 0.5 * parton2.p() : parton2.p();
2358 double mJoinNow = pSumNow.mCalc();
2359 if (!parton1.isGluon()) mJoinNow -= parton1.m0();
2360 if (!parton2.isGluon()) mJoinNow -= parton2.m0();
2361 if (mJoinNow < mJoinMin) { iJoinMin = i; mJoinMin = mJoinNow; }
2365 if (iJoinMin < 0 || mJoinMin > facExtra * mJoin)
return nJoin;
2369 int iJoin1 = iParton[iJoinMin];
2370 int iJoin2 = iParton[iJoinMin + 1];
2371 int idNew = (
event[iJoin1].isGluon()) ? event[iJoin2].
id()
2372 :
event[iJoin1].id();
2373 int colNew =
event[iJoin1].col();
2374 int acolNew =
event[iJoin2].acol();
2375 if (colNew == acolNew) {
2376 colNew =
event[iJoin2].col();
2377 acolNew =
event[iJoin1].acol();
2379 Vec4 pNew =
event[iJoin1].p() +
event[iJoin2].p();
2382 int iNew =
event.append( idNew, 73, min(iJoin1, iJoin2),
2383 max(iJoin1, iJoin2), 0, 0, colNew, acolNew, pNew, pNew.mCalc() );
2384 iParton[iJoinMin] = iNew;
2385 for (
int i = iJoinMin + 1; i < iPsize - 1; ++i)
2386 iParton[i] = iParton[i + 1];
2401 double StringFragmentation::nearStringPieces(StringEnd end,
2402 vector< vector< pair<double,double> > >& rapPairs) {
2405 if (hasJunction)
return 1;
2408 double phi = 2.0 * M_PI * rndmPtr->flat();
2411 double multStep = 5.0 / ((double)nTryMax/2);
2412 double multNow = 1.0 + multStep;
2413 Vec4 pHad = Vec4(0., 0., 0., -1.);
2414 for (
int i = 1; i <= nTryMax; i++) {
2415 pHad = end.kinematicsHadronTmp(system, pRem, phi, mult);
2417 if (pHad.e() > 0.0)
break;
2423 multNow += multStep;
2424 }
else mult /= multNow;
2428 if (pHad.e() < 0.0) pHad = pRem;
2432 Particle hadron = Particle();
2433 hadron.p(pHad); hadron.m(pHad.mCalc());
2434 double yHad = hadron.y();
2436 for (
int iSub = 0; iSub < int(rapPairs.size()); iSub++) {
2437 vector< pair<double,double> > pairNow = rapPairs[iSub];
2438 for (
int iPair = 0; iPair < int(pairNow.size()); iPair++) {
2439 double y1 = pairNow[iPair].first;
2440 double y2 = pairNow[iPair].second;
2441 if ( (y1 < yHad) && (yHad < y2) ) nString++;
2445 double pT2Had = pHad.pT2();
2446 double nStringEff = double(nString) / (1.0 + pT2Had / pT20);
2448 return nStringEff + 1.0;