9 #include "StringFragmentation.h"
22 const double StringEnd::TINY = 1e-6;
25 const double StringEnd::PT2SAME = 0.01;
31 void StringEnd::setUp(
bool fromPosIn,
int iEndIn,
int idOldIn,
int iMaxIn,
32 double pxIn,
double pyIn,
double GammaIn,
double xPosIn,
double xNegIn) {
38 flavOld = FlavContainer(idOldIn);
42 iPosOld = (fromPos) ? 0 : iMax;
43 iNegOld = (fromPos) ? iMax : 0;
53 void StringEnd::newHadron() {
57 flavNew = flavSelPtr->pick( flavOld);
58 idHad = flavSelPtr->combine( flavOld, flavNew);
62 pair<double, double> pxy = pTSelPtr->pxy();
65 pxHad = pxOld + pxNew;
66 pyHad = pyOld + pyNew;
69 mHad = particleDataPtr->mass(idHad);
70 mT2Had = pow2(mHad) + pow2(pxHad) + pow2(pyHad);
79 Vec4 StringEnd::kinematicsHadron( StringSystem& system) {
82 zHad = zSelPtr->zFrag( flavOld.id, flavNew.id, mT2Had);
83 GammaNew = (1. - zHad) * (GammaOld + mT2Had / zHad);
87 int& iDirOld = (fromPos) ? iPosOld : iNegOld;
88 int& iInvOld = (fromPos) ? iNegOld : iPosOld;
89 int& iDirNew = (fromPos) ? iPosNew : iNegNew;
90 int& iInvNew = (fromPos) ? iNegNew : iPosNew;
91 double& xDirOld = (fromPos) ? xPosOld : xNegOld;
92 double& xInvOld = (fromPos) ? xNegOld : xPosOld;
93 double& xDirNew = (fromPos) ? xPosNew : xNegNew;
94 double& xInvNew = (fromPos) ? xNegNew : xPosNew;
95 double& xDirHad = (fromPos) ? xPosHad : xNegHad;
96 double& xInvHad = (fromPos) ? xNegHad : xPosHad;
104 for (
int iStep = 0; ; ++iStep) {
107 StringRegion& region = system.region( iPosNew, iNegNew);
110 if (iStep == 0 && iPosOld + iNegOld == iMax) {
113 if (mT2Had < zHad * xDirOld * (1. - xInvOld) * region.w2) {
116 xDirHad = zHad * xDirOld;
117 xInvHad = mT2Had / (xDirHad * region.w2);
118 xDirNew = xDirOld - xDirHad;
119 xInvNew = xInvOld + xInvHad;
122 return region.pHad( xPosHad, xNegHad, pxHad, pyHad);
128 if (iInvNew < 0)
return Vec4(0., 0., 0., -1.);
131 xInvHad = 1. - xInvOld;
133 pSoFar = region.pHad( xPosHad, xNegHad, pxOld, pyOld);
138 }
else if (iStep == 0) {
139 pSoFar = region.pHad( 0., 0., pxOld, pyOld);
140 pTNew = region.pHad( 0., 0., pxNew, pyNew);
145 if (!region.isSetUp) region.setUp(
146 system.regionLowPos(iPosNew).pPos,
147 system.regionLowNeg(iNegNew).pNeg,
true);
151 if (region.isEmpty) {
152 xDirHad = (iDirNew == iDirOld) ? xDirOld : 1.;
154 pSoFar += region.pHad( xPosHad, xNegHad, 0., 0.);
156 if (iDirNew + iInvNew > iMax)
return Vec4(0., 0., 0., -1.);
162 double pxNewTemp = -pTNew * region.eX;
163 double pyNewTemp = -pTNew * region.eY;
164 if (abs( pxNewTemp * pxNewTemp + pyNewTemp * pyNewTemp
165 - pxNew * pxNew - pyNew * pyNew) < PT2SAME) {
171 Vec4 pTemp = pSoFar + region.pHad( 0., 0., pxNew, pyNew);
175 double cM1 = pTemp.m2Calc();
176 double cM2 = 2. * (pTemp * region.pPos);
177 double cM3 = 2. * (pTemp * region.pNeg);
178 double cM4 = region.w2;
179 if (!fromPos) swap( cM2, cM3);
187 for (
int iInv = iInvNew; iInv <= iMax - iDirNew; ++iInv) {
189 if (iInv == iInvNew) xInv = (iInvNew == iInvOld) ? xInvOld : 0.;
190 for (
int iDir = iDirNew; iDir <= iMax - iInv; ++iDir) {
191 double xDir = (iDir == iDirOld) ? xDirOld : 1.;
192 int iPos = (fromPos) ? iDir : iInv;
193 int iNeg = (fromPos) ? iInv : iDir;
194 StringRegion& regionGam = system.region( iPos, iNeg);
195 if (!regionGam.isSetUp) regionGam.setUp(
196 system.regionLowPos(iPos).pPos,
197 system.regionLowNeg(iNeg).pNeg,
true);
198 double w2 = regionGam.w2;
199 cGam1 += xDir * xInv * w2;
200 if (iDir == iDirNew) cGam2 -= xInv * w2;
201 if (iInv == iInvNew) cGam3 += xDir * w2;
202 if (iDir == iDirNew && iInv == iInvNew) cGam4 -= w2;
207 double cM0 = pow2(mHad) - cM1;
208 double cGam0 = GammaNew - cGam1;
209 double r2 = cM3 * cGam4 - cM4 * cGam3;
210 double r1 = cM4 * cGam0 - cM0 * cGam4 + cM3 * cGam2 - cM2 * cGam3;
211 double r0 = cM2 * cGam0 - cM0 * cGam2;
212 double root = sqrtpos( r1*r1 - 4. * r2 * r0 );
213 if (abs(r2) < TINY || root < TINY)
return Vec4(0., 0., 0., -1.);
214 xInvHad = 0.5 * (root / abs(r2) - r1 / r2);
215 xDirHad = (cM0 - cM3 * xInvHad) / (cM2 + cM4 * xInvHad);
218 xDirNew = (iDirNew == iDirOld) ? xDirOld - xDirHad : 1. - xDirHad;
219 xInvNew = (iInvNew == iInvOld) ? xInvOld + xInvHad : xInvHad;
223 xInvHad = (iInvNew == iInvOld) ? 1. - xInvOld : 1.;
225 pSoFar += region.pHad( xPosHad, xNegHad, 0., 0.);
227 if (iInvNew < 0)
return Vec4(0., 0., 0., -1.);
231 }
else if (xDirNew < 0.) {
232 xDirHad = (iDirNew == iDirOld) ? xDirOld : 1.;
234 pSoFar += region.pHad( xPosHad, xNegHad, 0., 0.);
236 if (iDirNew + iInvNew > iMax)
return Vec4(0., 0., 0., -1.);
241 return pSoFar + region.pHad( xPosHad, xNegHad, pxNew, pyNew);
252 void StringEnd::update() {
254 flavOld.anti(flavNew);
275 const int StringFragmentation::NTRYFLAV = 10;
276 const int StringFragmentation::NTRYJOIN = 25;
279 const int StringFragmentation::NSTOPMASS = 10;
280 const double StringFragmentation::FACSTOPMASS = 1.05;
283 const double StringFragmentation::CLOSEDM2MAX = 25.;
284 const double StringFragmentation::CLOSEDM2FRAC = 0.1;
287 const double StringFragmentation::EXPMAX = 50.;
290 const double StringFragmentation::MATCHPOSNEG = 1e-6;
293 const double StringFragmentation::EJNWEIGHTMAX = 10.;
296 const double StringFragmentation::CONVJNREST = 1e-5;
297 const int StringFragmentation::NTRYJNREST = 20;
300 const int StringFragmentation::NTRYJNMATCH = 20;
303 const double StringFragmentation::M2MAXJRF = 1e-4;
306 const double StringFragmentation::CONVJRFEQ = 1e-12;
307 const int StringFragmentation::NTRYJRFEQ = 40;
313 void StringFragmentation::init(Info* infoPtrIn, Settings& settings,
314 ParticleData* particleDataPtrIn, Rndm* rndmPtrIn, StringFlav* flavSelPtrIn,
315 StringPT* pTSelPtrIn, StringZ* zSelPtrIn) {
319 particleDataPtr = particleDataPtrIn;
321 flavSelPtr = flavSelPtrIn;
322 pTSelPtr = pTSelPtrIn;
326 stopMass = zSelPtr->stopMass();
327 stopNewFlav = zSelPtr->stopNewFlav();
328 stopSmear = zSelPtr->stopSmear();
329 eNormJunction = settings.parm(
"StringFragmentation:eNormJunction");
331 = settings.parm(
"StringFragmentation:eBothLeftJunction");
333 = settings.parm(
"StringFragmentation:eMaxLeftJunction");
335 = settings.parm(
"StringFragmentation:eMinLeftJunction");
338 bLund = zSelPtr->bAreaLund();
341 hadrons.init(
"(string fragmentation)", particleDataPtr);
344 posEnd.init( particleDataPtr, flavSelPtr, pTSelPtr, zSelPtr);
345 negEnd.init( particleDataPtr, flavSelPtr, pTSelPtr, zSelPtr);
353 bool StringFragmentation::fragment(
int iSub, ColConfig& colConfig,
357 iParton = colConfig[iSub].iParton;
359 if (iPos < 0) iPos = iParton[1];
360 int idPos =
event[iPos].id();
361 iNeg = iParton.back();
362 int idNeg =
event[iNeg].id();
363 pSum = colConfig[iSub].pSum;
369 isClosed = colConfig[iSub].isClosed;
370 if (isClosed) iParton = findFirstRegion(iParton, event);
374 pJunctionHadrons = 0.;
375 hasJunction = colConfig[iSub].hasJunction;
376 if (hasJunction && !fragmentToJunction(event))
return false;
377 int junctionHadrons = hadrons.size();
379 idPos =
event[ iParton[0] ].id();
380 idNeg =
event.back().id();
381 pSum -= pJunctionHadrons;
385 system.setUp(iParton, event);
386 stopMassNow = stopMass;
389 for (
int iTry = 0; ; ++iTry) {
390 if (iTry > NTRYJOIN) {
391 infoPtr->errorMsg(
"Error in StringFragmentation::fragment: "
393 if (hasJunction)
event.popBack(1);
398 if (iTry > NTRYJOIN - NSTOPMASS) stopMassNow *= FACSTOPMASS;
401 setStartEnds(idPos, idNeg, system);
409 fromPos = (rndmPtr->flat() < 0.5);
410 StringEnd& nowEnd = (fromPos) ? posEnd : negEnd;
414 if ( energyUsedUp(fromPos) )
break;
417 Vec4 pHad = nowEnd.kinematicsHadron(system);
418 int statusHad = (fromPos) ? 83 : 84;
419 hadrons.append( nowEnd.idHad, statusHad, iPos, iNeg,
420 0, 0, 0, 0, pHad, nowEnd.mHad);
421 if (pHad.e() < 0.)
break;
431 if ( finalTwo(fromPos) )
break;
435 int newHadrons = hadrons.size() - junctionHadrons;
436 hadrons.popBack(newHadrons);
442 iParton = colConfig[iSub].iParton;
457 vector<int> StringFragmentation::findFirstRegion(vector<int>& iPartonIn,
461 vector<double> m2Pair;
463 int size = iPartonIn.size();
464 for (
int i = 0; i < size; ++i) {
465 double m2Now = 0.5 *
event[ iPartonIn[i] ].p()
466 *
event[ iPartonIn[(i + 1)%size] ].p();
467 m2Pair.push_back(m2Now);
472 double m2Reg = m2Sum * rndmPtr->flat();
474 do m2Reg -= m2Pair[++iReg];
475 while (m2Reg > 0. && iReg < size - 1);
478 vector<int> iPartonOut;
479 for (
int i = 0; i < size + 2; ++i)
480 iPartonOut.push_back( iPartonIn[(i + iReg)%size] );
491 void StringFragmentation::setStartEnds(
int idPos,
int idNeg,
492 StringSystem systemNow) {
498 double xPosFromPos = 1.;
499 double xNegFromPos = 0.;
500 double xPosFromNeg = 0.;
501 double xNegFromNeg = 1.;
506 int idTry = flavSelPtr->pickLightQ();
507 FlavContainer flavTry(idTry, 1);
508 flavTry = flavSelPtr->pick( flavTry);
509 flavTry = flavSelPtr->pick( flavTry);
512 }
while (idPos == 0);
515 pair<double, double> pxy = pTSelPtr->pxy();
518 double m2Region = systemNow.regionLowPos(0).w2;
519 double m2Temp = min( CLOSEDM2MAX, CLOSEDM2FRAC * m2Region);
521 double zTemp = zSelPtr->zFrag( idPos, idNeg, m2Temp);
522 xPosFromPos = 1. - zTemp;
523 xNegFromPos = m2Temp / (zTemp * m2Region);
524 }
while (xNegFromPos > 1.);
525 Gamma = xPosFromPos * xNegFromPos * m2Region;
526 xPosFromNeg = xPosFromPos;
527 xNegFromNeg = xNegFromPos;
531 posEnd.setUp(
true, iPos, idPos, systemNow.iMax, px, py,
532 Gamma, xPosFromPos, xNegFromPos);
533 negEnd.setUp(
false, iNeg, idNeg, systemNow.iMax, -px, -py,
534 Gamma, xPosFromNeg, xNegFromNeg);
538 flavSelPtr->assignPopQ(posEnd.flavOld);
539 flavSelPtr->assignPopQ(negEnd.flavOld);
540 if (rndmPtr->flat() < 0.5) posEnd.flavOld.nPop = 0;
541 else negEnd.flavOld.nPop = 0;
542 posEnd.flavOld.rank = 1;
543 negEnd.flavOld.rank = 1;
554 bool StringFragmentation::energyUsedUp(
bool fromPos) {
557 if (pRem.e() < 0.)
return true;
560 double wMin = stopMassNow
561 + particleDataPtr->constituentMass(posEnd.flavOld.id)
562 + particleDataPtr->constituentMass(negEnd.flavOld.id);
563 if (fromPos) wMin += stopNewFlav
564 * particleDataPtr->constituentMass(posEnd.flavNew.id);
565 else wMin += stopNewFlav
566 * particleDataPtr->constituentMass(negEnd.flavNew.id);
567 wMin *= 1. + (2. * rndmPtr->flat() - 1.) * stopSmear;
568 w2Rem = pRem.m2Calc();
569 if (w2Rem < pow2(wMin))
return true;
580 bool StringFragmentation::finalTwo(
bool fromPos) {
583 if (pRem.e() < 0. || w2Rem < 0. || (hadrons.size() > 0
584 && hadrons.back().e() < 0.) )
return false;
585 if ( posEnd.iPosOld > negEnd.iPosOld || negEnd.iNegOld > posEnd.iNegOld)
587 if ( posEnd.iPosOld == negEnd.iPosOld && posEnd.xPosOld < negEnd.xPosOld)
589 if ( posEnd.iNegOld == negEnd.iNegOld && posEnd.xNegOld > negEnd.xNegOld)
594 FlavContainer flav1 = (fromPos) ? posEnd.flavNew.anti() : posEnd.flavOld;
595 FlavContainer flav2 = (fromPos) ? negEnd.flavOld : negEnd.flavNew.anti();
596 if (flav1.isDiquark() && flav2.isDiquark())
return false;
598 for (
int iTry = 0; iTry < NTRYFLAV; ++iTry) {
599 idHad = flavSelPtr->combine( flav1, flav2);
600 if (idHad != 0)
break;
602 if (idHad == 0)
return false;
606 negEnd.idHad = idHad;
607 negEnd.pxNew = -posEnd.pxNew;
608 negEnd.pyNew = -posEnd.pyNew;
609 negEnd.mHad = particleDataPtr->mass(idHad);
611 posEnd.idHad = idHad;
612 posEnd.pxNew = -negEnd.pxNew;
613 posEnd.pyNew = -negEnd.pyNew;
614 posEnd.mHad = particleDataPtr->mass(idHad);
618 StringRegion region = finalRegion();
619 if (region.isEmpty)
return false;
622 region.project( pRem);
623 double pxRem = region.px() - posEnd.pxOld - negEnd.pxOld;
624 double pyRem = region.py() - posEnd.pyOld - negEnd.pyOld;
625 double xPosRem = region.xPos();
626 double xNegRem = region.xNeg();
629 posEnd.pxOld += 0.5 * pxRem;
630 posEnd.pyOld += 0.5 * pyRem;
631 negEnd.pxOld += 0.5 * pxRem;
632 negEnd.pyOld += 0.5 * pyRem;
635 posEnd.pxHad = posEnd.pxOld + posEnd.pxNew;
636 posEnd.pyHad = posEnd.pyOld + posEnd.pyNew;
637 posEnd.mT2Had = pow2(posEnd.mHad) + pow2(posEnd.pxHad)
638 + pow2(posEnd.pyHad);
639 negEnd.pxHad = negEnd.pxOld + negEnd.pxNew;
640 negEnd.pyHad = negEnd.pyOld + negEnd.pyNew;
641 negEnd.mT2Had = pow2(negEnd.mHad) + pow2(negEnd.pxHad)
642 + pow2(negEnd.pyHad);
645 double wT2Rem = w2Rem + pow2( posEnd.pxHad + negEnd.pxHad)
646 + pow2( posEnd.pyHad + negEnd.pyHad);
649 if ( sqrt(wT2Rem) < sqrt(posEnd.mT2Had) + sqrt(negEnd.mT2Had) )
651 double lambda2 = pow2( wT2Rem - posEnd.mT2Had - negEnd.mT2Had)
652 - 4. * posEnd.mT2Had * negEnd.mT2Had;
653 if (lambda2 <= 0.)
return false;
656 double lambda = sqrt(lambda2);
657 double probReverse = 1. / (1. + exp( min( EXPMAX, bLund * lambda) ) );
658 double xpzPos = 0.5 * lambda/ wT2Rem;
659 if (probReverse > rndmPtr->flat()) xpzPos = -xpzPos;
660 double xmDiff = (posEnd.mT2Had - negEnd.mT2Had) / wT2Rem;
661 double xePos = 0.5 * (1. + xmDiff);
662 double xeNeg = 0.5 * (1. - xmDiff );
665 Vec4 pHadPos = region.pHad( (xePos + xpzPos) * xPosRem,
666 (xePos - xpzPos) * xNegRem, posEnd.pxHad, posEnd.pyHad);
667 Vec4 pHadNeg = region.pHad( (xeNeg - xpzPos) * xPosRem,
668 (xeNeg + xpzPos) * xNegRem, negEnd.pxHad, negEnd.pyHad);
671 hadrons.append( posEnd.idHad, 83, posEnd.iEnd, negEnd.iEnd,
672 0, 0, 0, 0, pHadPos, posEnd.mHad);
673 hadrons.append( negEnd.idHad, 84, posEnd.iEnd, negEnd.iEnd,
674 0, 0, 0, 0, pHadNeg, negEnd.mHad);
685 StringRegion StringFragmentation::finalRegion() {
688 if (posEnd.iPosOld == negEnd.iPosOld && posEnd.iNegOld == negEnd.iNegOld)
689 return system.region( posEnd.iPosOld, posEnd.iNegOld);
696 if ( posEnd.iPosOld == negEnd.iPosOld) {
697 double xPosJoin = posEnd.xPosOld - negEnd.xPosOld;
698 if (xPosJoin < 0.)
return region;
699 pPosJoin = system.regionLowPos(posEnd.iPosOld).pHad( xPosJoin, 0., 0., 0.);
701 for (
int iPosNow = posEnd.iPosOld; iPosNow <= negEnd.iPosOld; ++iPosNow) {
702 if (iPosNow == posEnd.iPosOld) pPosJoin
703 += system.regionLowPos(iPosNow).pHad( posEnd.xPosOld, 0., 0., 0.);
704 else if (iPosNow == negEnd.iPosOld) pPosJoin
705 += system.regionLowPos(iPosNow).pHad( 1. - negEnd.xPosOld, 0., 0., 0.);
706 else pPosJoin += system.regionLowPos(iPosNow).pHad( 1., 0., 0., 0.);
712 if ( negEnd.iNegOld == posEnd.iNegOld) {
713 double xNegJoin = negEnd.xNegOld - posEnd.xNegOld;
714 if (xNegJoin < 0.)
return region;
715 pNegJoin = system.regionLowNeg(negEnd.iNegOld).pHad( 0., xNegJoin, 0., 0.);
717 for (
int iNegNow = negEnd.iNegOld; iNegNow <= posEnd.iNegOld; ++iNegNow) {
718 if (iNegNow == negEnd.iNegOld) pNegJoin
719 += system.regionLowNeg(iNegNow).pHad( 0., negEnd.xNegOld, 0., 0.);
720 else if (iNegNow == posEnd.iNegOld) pNegJoin
721 += system.regionLowNeg(iNegNow).pHad( 0., 1. - posEnd.xNegOld, 0., 0.);
722 else pNegJoin += system.regionLowNeg(iNegNow).pHad( 0., 1., 0., 0.);
728 Vec4 pTest = pPosJoin - pNegJoin;
729 if ( abs(pTest.px()) + abs(pTest.py()) + abs(pTest.pz()) + abs(pTest.e())
730 < MATCHPOSNEG * (pPosJoin.e() + pNegJoin.e()) ) {
732 = system.regionLowPos(posEnd.iPosOld + 1).pHad( 1., 0., 0., 0.)
733 - system.regionLowNeg(negEnd.iNegOld + 1).pHad( 0., 1., 0., 0.);
739 region.setUp( pPosJoin, pNegJoin);
740 if (region.isEmpty)
return region;
743 Vec4 pTposOld = system.region( posEnd.iPosOld, posEnd.iNegOld).pHad(
744 0., 0., posEnd.pxOld, posEnd.pyOld);
745 region.project( pTposOld);
746 posEnd.pxOld = region.px();
747 posEnd.pyOld = region.py();
748 Vec4 pTnegOld = system.region( negEnd.iPosOld, negEnd.iNegOld).pHad(
749 0., 0., negEnd.pxOld, negEnd.pyOld);
750 region.project( pTnegOld);
751 negEnd.pxOld = region.px();
752 negEnd.pyOld = region.py();
763 void StringFragmentation::store(
Event& event) {
766 int iFirst =
event.size();
770 for (
int i = 0; i < hadrons.size(); ++i)
771 if (hadrons[i].status() == 85 || hadrons[i].status() == 86)
772 event.append( hadrons[i] );
776 for (
int i = 0; i < hadrons.size(); ++i)
777 if (hadrons[i].status() == 83) event.append( hadrons[i] );
780 for (
int i = hadrons.size() - 1; i >= 0 ; --i)
781 if (hadrons[i].status() == 84) event.append( hadrons[i] );
782 int iLast =
event.size() - 1;
785 if (event[posEnd.iEnd].hasVertex()) {
786 Vec4 vDec =
event[posEnd.iEnd].vDec();
787 for (
int i = iFirst; i <= iLast; ++i) event[i].vProd( vDec );
791 for (
int i = iFirst; i <= iLast; ++i)
792 event[i].tau( event[i].tau0() * rndmPtr->exp() );
795 for (
int i = 0; i < int(iParton.size()); ++i)
796 if (iParton[i] >= 0) {
797 event[ iParton[i] ].statusNeg();
798 event[ iParton[i] ].daughters(iFirst, iLast);
807 bool StringFragmentation::fragmentToJunction(
Event& event) {
812 int legBeg[3] = { 0, 0, 0};
813 int legEnd[3] = { 0, 0, 0};
816 if (iParton[0] > 0) {
817 infoPtr->errorMsg(
"Error in StringFragmentation::fragment"
818 "ToJunction: iParton[0] not a valid junctionNumber");
821 for (
int i = 0; i < int(iParton.size()); ++i) {
822 if (iParton[i] < 0) {
824 infoPtr->errorMsg(
"Error in StringFragmentation::fragment"
825 "ToJunction: unprocessed multi-junction system");
828 legBeg[++leg] = i + 1;
830 else legEnd[leg] = i;
834 RotBstMatrix MtoJRF, Mstep;
835 MtoJRF.bstback(pSum);
843 for (leg = 0; leg < 3; ++ leg) {
846 for (
int i = legBeg[leg]; i <= legEnd[leg]; ++i) {
847 Vec4 pTemp =
event[ iParton[i] ].p();
848 pTemp.rotbst(MtoJRF);
849 pWTinJRF[leg] += pTemp * exp(-eWeight);
850 eWeight += pTemp.e() / eNormJunction;
851 if (eWeight > EJNWEIGHTMAX)
break;
856 if (iter == 1) errInCM = pow2(costheta(pWTinJRF[0], pWTinJRF[1]) + 0.5)
857 + pow2(costheta(pWTinJRF[0], pWTinJRF[2]) + 0.5)
858 + pow2(costheta(pWTinJRF[1], pWTinJRF[2]) + 0.5);
861 Mstep = junctionRestFrame( pWTinJRF[0], pWTinJRF[1], pWTinJRF[2]);
864 MtoJRF.rotbst( Mstep );
865 }
while (iter < 3 || (Mstep.deviation() > CONVJNREST && iter < NTRYJNREST) );
868 double errInJRF = pow2(costheta(pWTinJRF[0], pWTinJRF[1]) + 0.5)
869 + pow2(costheta(pWTinJRF[0], pWTinJRF[2]) + 0.5)
870 + pow2(costheta(pWTinJRF[1], pWTinJRF[2]) + 0.5);
871 if (errInJRF > errInCM) {
872 infoPtr->errorMsg(
"Warning in StringFragmentation::fragmentTo"
873 "Junction: bad convergence junction rest frame");
875 MtoJRF.bstback(pSum);
879 RotBstMatrix MfromJRF = MtoJRF;
883 Vec4 pInLeg[3], pInJRF[3];
884 for (leg = 0; leg < 3; ++leg) {
886 for (
int i = legBeg[leg]; i <= legEnd[leg]; ++i)
887 pInLeg[leg] += event[ iParton[i] ].p();
888 pInJRF[leg] = pInLeg[leg];
889 pInJRF[leg].rotbst(MtoJRF);
893 int legMin = (pInJRF[0].e() < pInJRF[1].e()) ? 0 : 1;
894 int legMax = 1 - legMin;
895 if (pInJRF[2].e() < min(pInJRF[0].e(), pInJRF[1].e()) ) legMin = 2;
896 else if (pInJRF[2].e() > max(pInJRF[0].e(), pInJRF[1].e()) ) legMax = 2;
897 int legMid = 3 - legMin - legMax;
900 int iJunction = (-iParton[0]) / 10 - 1;
901 event.statusJunction( iJunction, legMin, 85);
902 event.statusJunction( iJunction, legMid, 86);
903 event.statusJunction( iJunction, legMax, 83);
907 vector<int> iPartonMin;
908 for (
int i = legEnd[legMin]; i >= legBeg[legMin]; --i) {
909 int iNew =
event.append( event[ iParton[i] ] );
910 event[iNew].rotbst(MtoJRF);
911 iPartonMin.push_back( iNew );
913 vector<int> iPartonMid;
914 for (
int i = legEnd[legMid]; i >= legBeg[legMid]; --i) {
915 int iNew =
event.append( event[ iParton[i] ] );
916 event[iNew].rotbst(MtoJRF);
917 iPartonMid.push_back( iNew );
922 pWTinJRF[legMin] = 0.;
923 for (
int i = iPartonMin.size() - 1; i >= 0; --i) {
924 pWTinJRF[legMin] +=
event[ iPartonMin[i] ].p() * exp(-eWeight);
925 eWeight +=
event[ iPartonMin[i] ].e() / eNormJunction;
926 if (eWeight > EJNWEIGHTMAX)
break;
929 pWTinJRF[legMid] = 0.;
930 for (
int i = iPartonMid.size() - 1; i >= 0; --i) {
931 pWTinJRF[legMid] +=
event[ iPartonMid[i] ].p() * exp(-eWeight);
932 eWeight +=
event[ iPartonMid[i] ].e() / eNormJunction;
933 if (eWeight > EJNWEIGHTMAX)
break;
937 Vec4 pOppose = pWTinJRF[legMin];
939 int idOppose = (rndmPtr->flat() > 0.5) ? 2 : 1;
940 if (event[ iPartonMin[0] ].col() > 0) idOppose = -idOppose;
941 int iOppose =
event.append( idOppose, 77, 0, 0, 0, 0, 0, 0,
943 iPartonMin.push_back( iOppose);
944 pOppose = pWTinJRF[legMid];
946 idOppose = (rndmPtr->flat() > 0.5) ? 2 : 1;
947 if (event[ iPartonMid[0] ].col() > 0) idOppose = -idOppose;
948 iOppose =
event.append( idOppose, 77, 0, 0, 0, 0, 0, 0,
950 iPartonMid.push_back( iOppose);
953 systemMin.setUp(iPartonMin, event);
954 systemMid.setUp(iPartonMid, event);
960 for (
int iTryOuter = 0; ; ++iTryOuter) {
963 double eLeftMin = 0.;
964 double eLeftMid = 0.;
965 for (
int iTryMiddle = 0; ; ++iTryMiddle) {
968 for (
int legLoop = 0; legLoop < 2; ++ legLoop) {
969 int legNow = (legLoop == 0) ? legMin : legMid;
972 StringSystem& systemNow = (legLoop == 0) ? systemMin : systemMid;
973 int idPos = (legLoop == 0) ? event[ iPartonMin[0] ].
id()
974 :
event[ iPartonMid[0] ].id();
975 idOppose = (legLoop == 0) ? event[ iPartonMin.back() ].id()
976 :
event[ iPartonMid.back() ].id();
977 double eInJRF = pInJRF[legNow].e();
978 int statusHad = (legLoop == 0) ? 85 : 86;
982 for (
int iTryInner = 0; ; ++iTryInner) {
983 if (iTryInner > NTRYJNMATCH) {
984 infoPtr->errorMsg(
"Error in StringFragmentation::fragment"
985 "ToJunction: caught in junction flavour loop");
986 event.popBack( iPartonMin.size() + iPartonMid.size() );
991 setStartEnds(idPos, idOppose, systemNow);
995 for ( ; ; ++nHadrons) {
999 Vec4 pHad = posEnd.kinematicsHadron(systemNow);
1002 if (pHad.e() < 0. ) { noNegE =
false;
break; }
1005 if (eUsed + pHad.e() > eInJRF)
break;
1008 hadrons.append( posEnd.idHad, statusHad, iPos, iNeg,
1009 0, 0, 0, 0, pHad, posEnd.mHad);
1017 if ( noNegE && abs(posEnd.flavOld.id) < 10 )
break;
1018 hadrons.popBack(nHadrons);
1022 if (legNow == legMin) {
1023 idMin = posEnd.flavOld.id;
1024 eLeftMin = eInJRF - eUsed;
1026 idMid = posEnd.flavOld.id;
1027 eLeftMid = eInJRF - eUsed;
1033 double eTrial = eBothLeftJunction + rndmPtr->flat() * eMaxLeftJunction;
1034 if (iTryMiddle > NTRYJNMATCH
1035 || ( min( eLeftMin, eLeftMid) < eBothLeftJunction
1036 && max( eLeftMin, eLeftMid) < eTrial ) )
break;
1041 for (
int i = 0; i < hadrons.size(); ++i) {
1042 hadrons[i].rotbst(MfromJRF);
1045 hadrons[i].e( hadrons[i].eCalc() );
1046 pJunctionHadrons += hadrons[i].p();
1050 pDiquark = pInLeg[legMin] + pInLeg[legMid] - pJunctionHadrons;
1051 double m2Left = m2( pInLeg[legMax], pDiquark);
1052 if (iTryOuter > NTRYJNMATCH
1053 || m2Left > eMinLeftJunction * pInLeg[legMax].e() )
break;
1055 pJunctionHadrons = 0.;
1059 event.popBack( iPartonMin.size() + iPartonMid.size() );
1063 int idDiquark = flavSelPtr->makeDiquark( idMin, idMid);
1064 double mDiquark = pDiquark.mCalc();
1065 int iDiquark =
event.append( idDiquark, 78, 0, 0, 0, 0, 0, 0,
1066 pDiquark, mDiquark);
1069 vector<int> iPartonMax;
1070 for (
int i = legEnd[legMax]; i >= legBeg[legMax]; --i)
1071 iPartonMax.push_back( iParton[i] );
1072 iPartonMax.push_back( iDiquark );
1075 iParton = iPartonMax;
1086 RotBstMatrix StringFragmentation::junctionRestFrame(Vec4& p0, Vec4& p1,
1090 Vec4 pSumJun = p0 + p1 + p2;
1091 double sHat = pSumJun.m2Calc();
1093 pp[0][0] = p0.m2Calc();
1094 pp[1][1] = p1.m2Calc();
1095 pp[2][2] = p2.m2Calc();
1096 pp[0][1] = pp[1][0] = p0 * p1;
1097 pp[0][2] = pp[2][0] = p0 * p2;
1098 pp[1][2] = pp[2][1] = p1 * p2;
1102 double eMax01 = pow2(pp[0][1]) * pp[2][2];
1103 double eMax02 = pow2(pp[0][2]) * pp[1][1];
1104 double eMax12 = pow2(pp[1][2]) * pp[0][0];
1107 int i = (pp[1][1] > pp[0][0]) ? 1 : 0;
1108 if (pp[2][2] > max(pp[0][0], pp[1][1])) i = 2;
1113 for (
int iTry = 0; iTry < 3; ++iTry) {
1116 if (i == 0) j = (eMax02 < eMax01) ? 2 : 1;
1117 else if (i == 1) j = (eMax12 < eMax01) ? 2 : 0;
1118 else j = (eMax12 < eMax02) ? 1 : 0;
1122 double m2i = pp[i][i];
1123 double m2j = pp[j][j];
1124 double m2k = pp[k][k];
1125 double pipj = pp[i][j];
1126 double pipk = pp[i][k];
1127 double pjpk = pp[j][k];
1130 if (m2i < M2MAXJRF) {
1131 ei = sqrt( 2. * pipk * pipj / (3. * pjpk) );
1132 ej = sqrt( 2. * pjpk * pipj / (3. * pipk) );
1133 ek = sqrt( 2. * pipk * pjpk / (3. * pipj) );
1139 double eiMin = sqrt(m2i);
1140 double ejMin = pipj / eiMin;
1141 double ekMin = pipk / eiMin;
1142 double pjMin = sqrtpos( ejMin*ejMin - m2j );
1143 double pkMin = sqrtpos( ekMin*ekMin - m2k );
1144 double fMin = ejMin * ekMin + 0.5 * pjMin * pkMin - pjpk;
1146 double eiMax = (pipj + pipk) / sqrt(m2j + m2k + 2. * pjpk);
1147 if (m2j > M2MAXJRF) eiMax = min( eiMax, pipj / sqrt(m2j) );
1148 double piMax = sqrtpos( eiMax*eiMax - m2i );
1149 double temp = eiMax*eiMax - 0.25 *piMax*piMax;
1150 double pjMax = (eiMax * sqrtpos( pipj*pipj - m2j * temp )
1151 - 0.5 * piMax * pipj) / temp;
1152 double pkMax = (eiMax * sqrtpos( pipk*pipk - m2k * temp )
1153 - 0.5 * piMax * pipk) / temp;
1154 double ejMax = sqrt(pjMax*pjMax + m2j);
1155 double ekMax = sqrt(pkMax*pkMax + m2k);
1156 double fMax = ejMax * ekMax + 0.5 * pjMax * pkMax - pjpk;
1160 int iPrel = (i + 1)%3;
1161 if (pp[iPrel][iPrel] > M2MAXJRF) {i = iPrel;
continue;}
1164 if (iTry < 3 && pp[iPrel][iPrel] > M2MAXJRF) {i = iPrel;
continue;}
1170 double pi = 0.5 * (piMin + piMax);
1171 for (
int iter = 0; iter < NTRYJRFEQ; ++iter) {
1174 ei = sqrt(pi*pi + m2i);
1175 temp = ei*ei - 0.25 * pi*pi;
1176 double pj = (ei * sqrtpos( pipj*pipj - m2j * temp )
1177 - 0.5 * pi * pipj) / temp;
1178 double pk = (ei * sqrtpos( pipk*pipk - m2k * temp )
1179 - 0.5 * pi * pipk) / temp;
1180 ej = sqrt(pj*pj + m2j);
1181 ek = sqrt(pk*pk + m2k);
1182 double fNow = ej * ek + 0.5 * pj * pk - pjpk;
1185 if (fNow > 0.) { ++iterMin; piMin = pi; fMin = fNow;}
1186 else {++iterMax; piMax = pi; fMax = fNow;}
1189 if (2 * iter < NTRYJRFEQ
1190 && (iterMin < 2 || iterMax < 2 || 4 * iter < NTRYJRFEQ))
1191 { pi = 0.5 * (piMin + piMax);
continue;}
1192 if (fMin < 0. || fMax > 0. || abs(fNow) < CONVJRFEQ * sHat)
break;
1193 pi = piMin + (piMax - piMin) * fMin / (fMin - fMax);
1201 double eNew[3] = { 0., 0., 0.};
1211 Mmove.bstback(pSumJun);
1217 Vec4 pDir01 = p0cm / p0cm.e() - p1cm / p1cm.e();
1218 Vec4 pDir02 = p0cm / p0cm.e() - p2cm / p2cm.e();
1219 double pDiff01 = pDir01.pAbs2();
1220 double pDiff02 = pDir02.pAbs2();
1221 double pDiff0102 = dot3(pDir01, pDir02);
1222 double eDiff01 = eNew[0] / p0cm.e() - eNew[1] / p1cm.e();
1223 double eDiff02 = eNew[0] / p0cm.e() - eNew[2] / p2cm.e();
1224 double denom = pDiff01 * pDiff02 - pDiff0102*pDiff0102;
1225 double coef01 = (eDiff01 * pDiff02 - eDiff02 * pDiff0102) / denom;
1226 double coef02 = (eDiff02 * pDiff01 - eDiff01 * pDiff0102) / denom;
1227 Vec4 vJunction = coef01 * pDir01 + coef02 * pDir02;
1228 vJunction.e( sqrt(1. + vJunction.pAbs2()) );
1231 Mmove.bst(vJunction);