9 #include "Pythia8/MiniStringFragmentation.h"
23 const int MiniStringFragmentation::NTRYDIFFRACTIVE = 200;
26 const int MiniStringFragmentation::NTRYLASTRESORT = 100;
29 const int MiniStringFragmentation::NTRYFLAV = 10;
35 void MiniStringFragmentation::init(Info* infoPtrIn, Settings& settings,
36 ParticleData* particleDataPtrIn, Rndm* rndmPtrIn,
37 StringFlav* flavSelPtrIn, StringPT* pTSelPtrIn, StringZ* zSelPtrIn) {
41 particleDataPtr = particleDataPtrIn;
43 flavSelPtr = flavSelPtrIn;
44 pTSelPtr = pTSelPtrIn;
48 nTryMass = settings.mode(
"MiniStringFragmentation:nTry");
51 bLund = zSelPtr->bAreaLund();
59 bool MiniStringFragmentation::fragment(
int iSub, ColConfig& colConfig,
60 Event& event,
bool isDiff) {
63 iParton = colConfig[iSub].iParton;
64 if (iParton.front() < 0) {
65 infoPtr->errorMsg(
"Error in MiniStringFragmentation::fragment: "
66 "very low-mass junction topologies not yet handled");
71 flav1 = FlavContainer( event[ iParton.front() ].id() );
72 flav2 = FlavContainer( event[ iParton.back() ].id() );
73 pSum = colConfig[iSub].pSum;
74 mSum = colConfig[iSub].mass;
76 isClosed = colConfig[iSub].isClosed;
79 int nTryFirst = (isDiff) ? NTRYDIFFRACTIVE : nTryMass;
82 if (ministring2two( nTryFirst, event))
return true;
85 if (ministring2one( iSub, colConfig, event))
return true;
88 if (ministring2two( NTRYLASTRESORT, event))
return true;
91 infoPtr->errorMsg(
"Error in MiniStringFragmentation::fragment: "
92 "no 1- or 2-body state found above mass threshold");
101 bool MiniStringFragmentation::ministring2two(
int nTry,
Event& event) {
111 for (
int iTry = 0; iTry < nTry; ++iTry) {
115 int idStart = flavSelPtr->pickLightQ();
116 FlavContainer flavStart(idStart, 1);
117 flavStart = flavSelPtr->pick( flavStart);
118 flav1 = flavSelPtr->pick( flavStart);
120 }
while (flav1.id == 0 || flav1.nPop > 0);
125 FlavContainer flav3 =
126 (flav1.isDiquark() || (!flav2.isDiquark() && rndmPtr->flat() < 0.5) )
127 ? flavSelPtr->pick( flav1) : flavSelPtr->pick( flav2).anti();
128 idHad1 = flavSelPtr->combine( flav1, flav3);
129 idHad2 = flavSelPtr->combine( flav2, flav3.anti());
130 }
while (idHad1 == 0 || idHad2 == 0);
133 mHad1 = particleDataPtr->mSel(idHad1);
134 mHad2 = particleDataPtr->mSel(idHad2);
135 mHadSum = mHad1 + mHad2;
136 if (mHadSum < mSum)
break;
138 if (mHadSum >= mSum)
return false;
142 Vec4 pSum1 =
event[ iParton.front() ].p();
143 Vec4 pSum2 =
event[ iParton.back() ].p();
144 if (iParton.size() > 2) {
147 Vec4 pEndSum = pEnd1 + pEnd2;
148 for (
int i = 1; i < int(iParton.size()) - 1 ; ++i) {
149 Vec4 pNow =
event[ iParton[i] ].p();
150 double ratio = (pEnd2 * pNow) / (pEndSum * pNow);
151 pSum1 += ratio * pNow;
152 pSum2 += (1. - ratio) * pNow;
158 region.setUp( pSum1, pSum2);
162 double pAbs2 = 0.25 * ( pow2(m2Sum - mHad1*mHad1 - mHad2*mHad2)
163 - pow2(2. * mHad1 * mHad2) ) / m2Sum;
166 double cosTheta = rndmPtr->flat();
167 pT2 = (1. - pow2(cosTheta)) * pAbs2;
168 }
while (pTSelPtr->suppressPT2(pT2) < rndmPtr->flat() );
171 double mT21 = mHad1*mHad1 + pT2;
172 double mT22 = mHad2*mHad2 + pT2;
173 double lambda = sqrtpos( pow2(m2Sum - mT21 - mT22) - 4. * mT21 * mT22 );
174 double probReverse = 1. / (1. + exp( min( 50., bLund * lambda) ) );
177 double xpz1 = 0.5 * lambda/ m2Sum;
178 if (probReverse > rndmPtr->flat()) xpz1 = -xpz1;
179 double xmDiff = (mT21 - mT22) / m2Sum;
180 double xe1 = 0.5 * (1. + xmDiff);
181 double xe2 = 0.5 * (1. - xmDiff );
184 double phi = 2. * M_PI * rndmPtr->flat();
185 double pT = sqrt(pT2);
186 double px = pT * cos(phi);
187 double py = pT * sin(phi);
190 Vec4 pHad1 = region.pHad( xe1 + xpz1, xe1 - xpz1, px, py);
191 Vec4 pHad2 = region.pHad( xe2 - xpz1, xe2 + xpz1, -px, -py);
194 int iFirst =
event.append( idHad1, 82, iParton.front(), iParton.back(),
195 0, 0, 0, 0, pHad1, mHad1);
196 int iLast =
event.append( idHad2, 82, iParton.front(), iParton.back(),
197 0, 0, 0, 0, pHad2, mHad2);
200 if (event[iParton.front()].hasVertex()) {
201 Vec4 vDec =
event[iParton.front()].vDec();
202 event[iFirst].vProd( vDec );
203 event[iLast].vProd( vDec );
207 event[iFirst].tau( event[iFirst].tau0() * rndmPtr->exp() );
208 event[iLast].tau( event[iLast].tau0() * rndmPtr->exp() );
211 for (
int i = 0; i < int(iParton.size()); ++i) {
212 event[ iParton[i] ].statusNeg();
213 event[ iParton[i] ].daughters(iFirst, iLast);
229 bool MiniStringFragmentation::ministring2one(
int iSub,
230 ColConfig& colConfig,
Event& event) {
233 if (abs(flav1.id) > 100 && abs(flav2.id) > 100)
return false;
237 int idStart = flavSelPtr->pickLightQ();
238 FlavContainer flavStart(idStart, 1);
239 flav1 = flavSelPtr->pick( flavStart);
240 flav2 = flav1.anti();
241 }
while (abs(flav1.id) > 100);
245 for (
int iTryFlav = 0; iTryFlav < NTRYFLAV; ++iTryFlav) {
246 idHad = flavSelPtr->combine( flav1, flav2);
247 if (idHad != 0)
break;
249 if (idHad == 0)
return false;
252 double mHad = particleDataPtr->mSel(idHad);
257 double deltaM2 = mHad*mHad - mSum*mSum;
258 double delta2Max = 0.;
259 for (
int iRec = iSub + 1; iRec < colConfig.size(); ++iRec) {
260 double delta2Rec = 2. * (pSum * colConfig[iRec].pSum) - deltaM2
261 - 2. * mHad * colConfig[iRec].mass;
262 if (delta2Rec > delta2Max) { iMax = iRec; delta2Max = delta2Rec;}
264 if (iMax == -1)
return false;
267 Vec4& pRec = colConfig[iMax].pSum;
268 double mRec = colConfig[iMax].mass;
269 double vecProd = pSum * pRec;
270 double coefOld = mSum*mSum + vecProd;
271 double coefNew = mHad*mHad + vecProd;
272 double coefRec = mRec*mRec + vecProd;
273 double coefSum = coefOld + coefNew;
274 double sHat = coefOld + coefRec;
275 double root = sqrtpos( (pow2(coefSum) - 4. * sHat * mHad*mHad)
276 / (pow2(vecProd) - pow2(mSum * mRec)) );
277 double k2 = 0.5 * (coefOld * root - coefSum) / sHat;
278 double k1 = (coefRec * k2 + 0.5 * deltaM2) / coefOld;
279 Vec4 pHad = (1. + k1) * pSum - k2 * pRec;
280 Vec4 pRecNew = (1. + k2) * pRec - k1 * pSum;
283 int iHad =
event.append( idHad, 81, iParton.front(), iParton.back(),
284 0, 0, 0, 0, pHad, mHad);
287 if (event[iParton.front()].hasVertex()) {
288 Vec4 vDec =
event[iParton.front()].vDec();
289 event[iHad].vProd( vDec );
293 event[iHad].tau( event[iHad].tau0() * rndmPtr->exp() );
296 for (
int i = 0; i < int(iParton.size()); ++i) {
297 event[ iParton[i] ].statusNeg();
298 event[ iParton[i] ].daughters(iHad, iHad);
303 M.bst(pRec, pRecNew);
304 for (
int i = 0; i < colConfig[iMax].size(); ++i) {
305 int iOld = colConfig[iMax].iParton[i];
308 int iNew =
event.copy(iOld, 72);
309 event[iNew].rotbst(M);
310 colConfig[iMax].iParton[i] = iNew;
313 colConfig[iMax].pSum = pRecNew;
314 colConfig[iMax].isCollected =
true;