9 #include "Pythia8/FragmentationFlavZpT.h"
23 const int StringFlav::mesonMultipletCode[6]
24 = { 1, 3, 10003, 10001, 20003, 5};
29 const double StringFlav::baryonCGOct[6]
30 = { 0.75, 0.5, 0., 0.1667, 0.0833, 0.1667};
31 const double StringFlav::baryonCGDec[6]
32 = { 0., 0., 1., 0.3333, 0.6667, 0.3333};
38 void StringFlav::init(Settings& settings, ParticleData* particleDataPtrIn,
39 Rndm* rndmPtrIn, Info* infoPtrIn) {
43 particleDataPtr = particleDataPtrIn;
47 probQQtoQ = settings.parm(
"StringFlav:probQQtoQ");
48 probStoUD = settings.parm(
"StringFlav:probStoUD");
49 probSQtoQQ = settings.parm(
"StringFlav:probSQtoQQ");
50 probQQ1toQQ0 = settings.parm(
"StringFlav:probQQ1toQQ0");
53 probQandQQ = 1. + probQQtoQ;
54 probQandS = 2. + probStoUD;
55 probQandSinQQ = 2. + probSQtoQQ * probStoUD;
56 probQQ1corr = 3. * probQQ1toQQ0;
57 probQQ1corrInv = 1. / probQQ1corr;
58 probQQ1norm = probQQ1corr / (1. + probQQ1corr);
61 vector<double> pQQ1tmp = settings.pvec(
"StringFlav:probQQ1toQQ0join");
62 for (
int i = 0; i < 4; ++i)
63 probQQ1join[i] = 3. * pQQ1tmp[i] / (1. + 3. * pQQ1tmp[i]);
66 for (
int i = 0; i < 4; ++i) mesonRate[i][0] = 1.;
67 mesonRate[0][1] = settings.parm(
"StringFlav:mesonUDvector");
68 mesonRate[1][1] = settings.parm(
"StringFlav:mesonSvector");
69 mesonRate[2][1] = settings.parm(
"StringFlav:mesonCvector");
70 mesonRate[3][1] = settings.parm(
"StringFlav:mesonBvector");
73 mesonRate[0][2] = settings.parm(
"StringFlav:mesonUDL1S0J1");
74 mesonRate[1][2] = settings.parm(
"StringFlav:mesonSL1S0J1");
75 mesonRate[2][2] = settings.parm(
"StringFlav:mesonCL1S0J1");
76 mesonRate[3][2] = settings.parm(
"StringFlav:mesonBL1S0J1");
77 mesonRate[0][3] = settings.parm(
"StringFlav:mesonUDL1S1J0");
78 mesonRate[1][3] = settings.parm(
"StringFlav:mesonSL1S1J0");
79 mesonRate[2][3] = settings.parm(
"StringFlav:mesonCL1S1J0");
80 mesonRate[3][3] = settings.parm(
"StringFlav:mesonBL1S1J0");
81 mesonRate[0][4] = settings.parm(
"StringFlav:mesonUDL1S1J1");
82 mesonRate[1][4] = settings.parm(
"StringFlav:mesonSL1S1J1");
83 mesonRate[2][4] = settings.parm(
"StringFlav:mesonCL1S1J1");
84 mesonRate[3][4] = settings.parm(
"StringFlav:mesonBL1S1J1");
85 mesonRate[0][5] = settings.parm(
"StringFlav:mesonUDL1S1J2");
86 mesonRate[1][5] = settings.parm(
"StringFlav:mesonSL1S1J2");
87 mesonRate[2][5] = settings.parm(
"StringFlav:mesonCL1S1J2");
88 mesonRate[3][5] = settings.parm(
"StringFlav:mesonBL1S1J2");
91 for (
int i = 0; i < 4; ++i) mesonRateSum[i]
92 = mesonRate[i][0] + mesonRate[i][1] + mesonRate[i][2]
93 + mesonRate[i][3] + mesonRate[i][4] + mesonRate[i][5];
98 if (
spin == 0) theta = settings.parm(
"StringFlav:thetaPS");
99 else if (
spin == 1) theta = settings.parm(
"StringFlav:thetaV");
100 else if (
spin == 2) theta = settings.parm(
"StringFlav:thetaL1S0J1");
101 else if (
spin == 3) theta = settings.parm(
"StringFlav:thetaL1S1J0");
102 else if (
spin == 4) theta = settings.parm(
"StringFlav:thetaL1S1J1");
103 else theta = settings.parm(
"StringFlav:thetaL1S1J2");
104 double alpha = (
spin == 0) ? 90. - (theta + 54.7) : theta + 54.7;
105 alpha *= M_PI / 180.;
108 mesonMix1[0][
spin] = 0.5;
109 mesonMix2[0][
spin] = 0.5 * (1. + pow2(sin(alpha)));
110 mesonMix1[1][
spin] = 0.;
111 mesonMix2[1][
spin] = pow2(cos(alpha));
113 mesMixRate1[0][
spin] = mesonMix1[0][
spin];
114 mesMixRate2[0][
spin] = mesonMix2[0][
spin] - mesonMix1[0][
spin];
115 mesMixRate3[0][
spin] = 1.0 - mesMixRate1[0][
spin] - mesMixRate2[0][
spin];
116 mesMixRate1[1][
spin] = mesonMix1[1][
spin];
117 mesMixRate2[1][
spin] = mesonMix2[1][
spin] - mesonMix1[1][
spin];
118 mesMixRate3[1][
spin] = 1.0 - mesMixRate1[1][
spin] - mesMixRate2[1][
spin];
122 etaSup = settings.parm(
"StringFlav:etaSup");
123 etaPrimeSup = settings.parm(
"StringFlav:etaPrimeSup");
126 decupletSup = settings.parm(
"StringFlav:decupletSup");
127 for (
int i = 0; i < 6; ++i) baryonCGSum[i]
128 = baryonCGOct[i] + decupletSup * baryonCGDec[i];
131 baryonCGMax[0] = max( baryonCGSum[0], baryonCGSum[1]);
132 baryonCGMax[1] = baryonCGMax[0];
133 baryonCGMax[2] = max( baryonCGSum[2], baryonCGSum[3]);
134 baryonCGMax[3] = baryonCGMax[2];
135 baryonCGMax[4] = max( baryonCGSum[4], baryonCGSum[5]);
136 baryonCGMax[5] = baryonCGMax[4];
139 popcornRate = settings.parm(
"StringFlav:popcornRate");
140 popcornSpair = settings.parm(
"StringFlav:popcornSpair");
141 popcornSmeson = settings.parm(
"StringFlav:popcornSmeson");
144 suppressLeadingB = settings.flag(
"StringFlav:suppressLeadingB");
145 lightLeadingBSup = settings.parm(
"StringFlav:lightLeadingBSup");
146 heavyLeadingBSup = settings.parm(
"StringFlav:heavyLeadingBSup");
149 mT2suppression = settings.flag(
"StringPT:mT2suppression");
150 sigmaHad = (sqrt(2.0)*settings.parm(
"StringPT:sigma"));
151 widthPreStrange = settings.parm(
"StringPT:widthPreStrange");
152 widthPreDiquark = settings.parm(
"StringPT:widthPreDiquark");
153 useWidthPre = (widthPreStrange > 1.0) || (widthPreDiquark > 1.0);
156 closePacking = settings.flag(
"StringPT:closePacking");
157 exponentMPI = settings.parm(
"StringPT:expMPI");
158 exponentNSP = settings.parm(
"StringPT:expNSP");
163 enum Diquark {ud0, ud1, uu1, us0, su0, us1, su1, ss1};
167 barCGMax[ud0] = baryonCGMax[0];
168 barCGMax[ud1] = baryonCGMax[4];
169 barCGMax[uu1] = baryonCGMax[2];
170 barCGMax[us0] = baryonCGMax[0];
171 barCGMax[su0] = baryonCGMax[0];
172 barCGMax[us1] = baryonCGMax[4];
173 barCGMax[su1] = baryonCGMax[4];
174 barCGMax[ss1] = baryonCGMax[2];
178 dMB[ud0] = 2. * baryonCGSum[0] + probStoUD * baryonCGSum[1];
179 dMB[ud1] = 2. * baryonCGSum[4] + probStoUD * baryonCGSum[5];
180 dMB[uu1] = baryonCGSum[2] + (1. + probStoUD) * baryonCGSum[3];
181 dMB[us0] = (1. + probStoUD) * baryonCGSum[0] + baryonCGSum[1];
183 dMB[us1] = (1. + probStoUD) * baryonCGSum[4] + baryonCGSum[5];
185 dMB[ss1] = probStoUD * baryonCGSum[2] + 2. * baryonCGSum[3];
186 for (
int i = 1; i < 8; ++i) dMB[i] = dMB[i] / dMB[0];
189 double probStoUDroot = sqrt(probStoUD);
190 double probSQtoQQroot = sqrt(probSQtoQQ);
191 double probQQ1toQQ0root = sqrt(probQQ1toQQ0);
193 qBB[ud1] = probQQ1toQQ0root;
194 qBB[uu1] = probQQ1toQQ0root;
195 qBB[us0] = probSQtoQQroot;
196 qBB[su0] = probStoUDroot * probSQtoQQroot;
197 qBB[us1] = probQQ1toQQ0root * qBB[us0];
198 qBB[su1] = probQQ1toQQ0root * qBB[su0];
199 qBB[ss1] = probStoUDroot * pow2(probSQtoQQroot) * probQQ1toQQ0root;
203 qBM[ud1] = 3. * qBB[ud1];
204 qBM[uu1] = 6. * qBB[uu1];
205 qBM[us0] = probStoUD * qBB[us0];
207 qBM[us1] = probStoUD * 3. * qBB[us1];
208 qBM[su1] = 3. * qBB[su1];
209 qBM[ss1] = probStoUD * 6. * qBB[ss1];
212 for (
int i = 1; i < 8; ++i) qBB[i] = qBB[i] * qBM[i];
215 qBM[us0] *= popcornSmeson;
216 qBM[us1] *= popcornSmeson;
217 qBM[ss1] *= popcornSmeson;
222 double uNorm = 1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1];
223 scbBM[0] = (2. * (qBM[su0] + qBM[su1]) + qBM[ss1]) / uNorm;
224 scbBM[1] = scbBM[0] * popcornSpair * qBM[su0] / qBM[us0];
225 scbBM[2] = (1. + qBM[ud1]) * (2. + qBM[us0]) / uNorm;
228 for (
int i = 1; i < 8; ++i) dMB[i] *= qBM[i];
229 for (
int i = 1; i < 8; ++i) qBM[i] *= barCGMax[i] / barCGMax[0];
230 for (
int i = 1; i < 8; ++i) qBB[i] *= barCGMax[i] / barCGMax[0];
233 double qNorm = uNorm * popcornRate / 3.;
234 double sNorm = scbBM[0] * popcornSpair;
235 popFrac = qNorm * (1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1]
236 + sNorm * (qBM[su0] + qBM[su1] + 0.5 * qBM[ss1])) / (1. + qBB[ud1]
237 + qBB[uu1] + 2. * (qBB[us0] + qBB[us1]) + 0.5 * qBB[ss1]);
240 popS[0] = qNorm * qBM[ud1] / qBB[ud1];
241 popS[1] = qNorm * 0.5 * (qBM[us1] / qBB[us1]
242 + sNorm * qBM[su1] / qBB[su1]);
243 popS[2] = qNorm * sNorm * qBM[ss1] / qBB[ss1];
252 dWT[0][0] = (2. * (qBB[su0] + qBB[su1]) + qBB[ss1])
253 / (1. + qBB[ud1] + qBB[uu1] + qBB[us0] + qBB[us1]);
254 dWT[0][1] = 2. * (qBB[us0] + qBB[us1]) / (1. + qBB[ud1] + qBB[uu1]);
255 dWT[0][2] = qBB[ss1] / (qBB[su0] + qBB[su1]);
256 dWT[0][3] = qBB[uu1] / (1. + qBB[ud1] + qBB[uu1]);
257 dWT[0][4] = qBB[su1] / qBB[su0];
258 dWT[0][5] = qBB[us1] / qBB[us0];
259 dWT[0][6] = qBB[ud1];
262 dWT[1][0] = (2. * (qBM[su0] + qBM[su1]) + qBM[ss1])
263 / (1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1]);
264 dWT[1][1] = 2. * (qBM[us0] + qBM[us1]) / (1. + qBM[ud1] + qBM[uu1]);
265 dWT[1][2] = qBM[ss1] / (qBM[su0] + qBM[su1]);
266 dWT[1][3] = qBM[uu1] / (1. + qBM[ud1] + qBM[uu1]);
267 dWT[1][4] = qBM[su1] / qBM[su0];
268 dWT[1][5] = qBM[us1] / qBM[us0];
269 dWT[1][6] = qBM[ud1];
272 dWT[2][0] = (2. * (dMB[su0] + dMB[su1]) + dMB[ss1])
273 / (1. + dMB[ud1] + dMB[uu1] + dMB[us0] + dMB[us1]);
274 dWT[2][1] = 2. * (dMB[us0] + dMB[us1]) / (1. + dMB[ud1] + dMB[uu1]);
275 dWT[2][2] = dMB[ss1] / (dMB[su0] + dMB[su1]);
276 dWT[2][3] = dMB[uu1] / (1. + dMB[ud1] + dMB[uu1]);
277 dWT[2][4] = dMB[su1] / dMB[su0];
278 dWT[2][5] = dMB[us1] / dMB[us0];
279 dWT[2][6] = dMB[ud1];
282 thermalModel = settings.flag(
"StringPT:thermalModel");
283 if (thermalModel || mT2suppression) {
286 temperature = settings.parm(
"StringPT:temperature");
287 tempPreFactor = settings.parm(
"StringPT:tempPreFactor");
290 mesonNonetL1 = settings.flag(
"StringFlav:mesonNonetL1");
291 nNewQuark = settings.mode(
"StringFlav:nQuark");
296 vector<int> hadIDsProd, hadIDsHvyC, hadIDsHvyB;
299 int baryonLight[18] = { 2112, 2212, 3112, 3122, 3212, 3222, 3312, 3322,
300 1114, 2114, 2214, 2224, 3114, 3214, 3224, 3314,
302 int baryonHvyC[22] = { 4112, 4122, 4132, 4212, 4222, 4232, 4312, 4322,
303 4332, 4412, 4422, 4432,
304 4114, 4214, 4224, 4314, 4324, 4334, 4414, 4424,
306 int baryonHvyB[35] = { 5112, 5122, 5132, 5142, 5212, 5222, 5232, 5242,
307 5312, 5322, 5332, 5342, 5412, 5422, 5432, 5442,
308 5512, 5522, 5532, 5542,
309 5114, 5214, 5224, 5314, 5324, 5334, 5414, 5424,
310 5434, 5444, 5514, 5524, 5534, 5544, 5554 };
311 for (
int i = 0; i < 18; i++) hadIDsProd.push_back( baryonLight[i] );
314 for (
int i = 0; i < 35; i++) hadIDsProd.push_back( baryonHvyB[i] );
317 int bBar[9] = { 5112, 5122, 5132, 5212, 5222, 5232, 5312, 5322, 5332 };
318 for (
int i = 0; i < 9; i++) {
319 hadIDsHvyB.push_back( bBar[i] );
320 hadIDsHvyB.push_back( -bBar[i] );
324 for (
int i = 0; i < 22; i++) hadIDsProd.push_back( baryonHvyC[i] );
327 int cBar[9] = { 4112, 4122, 4132, 4212, 4222, 4232, 4312, 4322, 4332 };
328 for (
int i = 0; i < 9; i++) {
329 hadIDsHvyC.push_back( cBar[i] );
330 hadIDsHvyC.push_back( -cBar[i] );
334 int sizeNow = int(hadIDsProd.size());
335 for (
int i = 0; i < sizeNow; i++) hadIDsProd.push_back( -hadIDsProd[i] );
338 int mesonPSLight[9] = { 311, 321, 211, -311, -321, -211, 111, 221, 331 };
339 int mesonPSHvyC[7] = { 411, 421, 431, -411, -421, -431, 441 };
340 int mesonPSHvyB[9] = { 511, 521, 531, 541, -511, -521, -531, -541, 551 };
342 for (
int i = 0; i < 9; i++) mesonPS.push_back( mesonPSLight[i] );
346 for (
int i = 0; i < 9; i++) mesonPS.push_back( mesonPSHvyB[i] );
350 int bMes[10] = { 511, 521, 531, 541, -511, -521, -531, -541, 551 };
351 for (
int i = 0; i < 10; i++) hadIDsHvyB.push_back( bMes[i] );
354 for (
int i = 0; i < 7; i++) mesonPS.push_back( mesonPSHvyC[i] );
358 int cMes[8] = { 411, 421, 431, -411, -421, -431, 441 };
359 for (
int i = 0; i < 8; i++) hadIDsHvyC.push_back( cMes[i] );
361 int nMeson = int(mesonPS.size());
363 for (
int i = 0; i < nMeson; i++)
364 hadIDsProd.push_back( mesonPS[i] );
366 for (
int i = 0; i < nMeson; i++)
367 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 2 : -2) );
371 for (
int i = 0; i < nMeson; i++)
372 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 10002 : -10002) );
374 for (
int i = 0; i < nMeson; i++)
375 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 10000 : -10000) );
377 for (
int i = 0; i < nMeson; i++)
378 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 20002 : -20002) );
380 for (
int i = 0; i < nMeson; i++)
381 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 4 : -4) );
385 vector<int> hadIDsAll;
386 for (
int i = 0; i < int(hadIDsProd.size()); i++)
387 hadIDsAll.push_back( hadIDsProd[i] );
388 for (
int i = 0; i < int(hadIDsHvyC.size()); i++)
389 hadIDsAll.push_back( hadIDsHvyC[i] );
390 for (
int i = 0; i < int(hadIDsHvyB.size()); i++)
391 hadIDsAll.push_back( hadIDsHvyB[i] );
394 for (
int i = 0; i < int(hadIDsAll.size()); i++) {
395 int id = hadIDsAll[i];
397 vector< pair<int,int> > quarkCombis;
399 if (particleDataPtr->isBaryon(
id)) {
400 bool isOctet = ( (idAbs % 10) == 2 );
401 int q3 = (idAbs/10) % 10;
402 int q2 = (idAbs/100) % 10;
403 int q1 = (idAbs/1000) % 10;
404 bool threeFlav = q1 != q2 && q1 != q3 && q2 != q3;
410 int j = (q2 < q3) ? 1 : 3;
411 int qn[2] = { min( q3, q2), max( q3, q2) };
412 addQuarkDiquark(quarkCombis, q1,
413 1000 * qn[1] + 100 * qn[0] + j,
id);
415 for (j = 1; j < 4; j += 2) {
417 addQuarkDiquark(quarkCombis, q2, 1000 * q1 + 100 * q3 + j,
id);
419 addQuarkDiquark(quarkCombis, q3, 1000 * q1 + 100 * q2 + j,
id);
424 for (
int j = 1; j < 4; j += 2) {
426 if ( j == 3 || q1 != q2 )
427 addQuarkDiquark(quarkCombis, q3, 1000 * q1 + 100 * q2 + j,
id);
429 if ( j == 3 || q1 != q3 )
430 addQuarkDiquark(quarkCombis, q2, 1000 * q1 + 100 * q3 + j,
id);
432 if ( j == 3 || q2 != q3 )
433 addQuarkDiquark(quarkCombis, q1, 1000 * q2 + 100 * q3 + j,
id);
441 addQuarkDiquark(quarkCombis, q3, 1000 * q1 + 100 * q2 + 3,
id);
443 addQuarkDiquark(quarkCombis, q2, 1000 * q1 + 100 * q3 + 3,
id);
445 addQuarkDiquark(quarkCombis, q1, 1000 * q2 + 100 * q3 + 3,
id);
450 int q1 = (idAbs/100) % 10;
451 bool uptype1 = (q1 % 2 == 0);
452 int q2 = (idAbs/10) % 10;
453 bool uptype2 = (q2 % 2 == 0);
458 if ( uptype2 && !uptype1 ) swap( quark, antiQuark);
459 if ( (q1 > q2 && !uptype1 && !uptype2)
460 || (q2 > q1 && uptype2 && uptype1) ) swap( quark, antiQuark);
461 if (
id < 0) swap( quark, antiQuark);
462 quarkCombis.push_back( make_pair( quark, -antiQuark) );
464 hadronConstIDs[id] = quarkCombis;
469 map< int, vector< pair<int,int> > > hadConstIDsC, hadConstIDsB,
471 for (
int i=0; i<int(hadIDsAll.size()); i++) {
472 int id = hadIDsAll[i];
473 if (find(hadIDsProd.begin(), hadIDsProd.end(), id) != hadIDsProd.end())
474 hadConstIDsProd[
id] = hadronConstIDs[
id];
475 if (find(hadIDsHvyC.begin(), hadIDsHvyC.end(), id) != hadIDsHvyC.end())
476 hadConstIDsC[
id] = hadronConstIDs[
id];
477 if (find(hadIDsHvyB.begin(), hadIDsHvyB.end(), id) != hadIDsHvyB.end())
478 hadConstIDsB[
id] = hadronConstIDs[
id];
480 map< int, map< int, vector< pair<int,int> > > > hadConstIDsHvy;
481 hadConstIDsHvy[4] = hadConstIDsC;
482 hadConstIDsHvy[5] = hadConstIDsB;
485 int inIDs[26] = { 1, 2, 3, 4, 5, 1103, 2203, 3303, 2101, 2103, 3101,
486 3103, 3201, 3203, 4101, 4103, 4201, 4203, 4301,
487 4303, 5101, 5103, 5201, 5203, 5301, 5303 };
488 int inIDsHvyC[2] = { 4403, -4403 };
489 int inIDsHvyB[6] = { 5503, -5503, 5401, -5401, 5403, -5403 };
490 vector<int> incomingIDs;
491 for (
int i = 0; i < 26; i++) {
492 incomingIDs.push_back( inIDs[i]);
493 incomingIDs.push_back(-inIDs[i]);
498 for (
int i = 0; i < 2; i++) incomingIDs.push_back(inIDsHvyC[i]);
500 for (
int i = 0; i < 6; i++) incomingIDs.push_back( inIDsHvyB[i]);
503 int nIncome = int(incomingIDs.size());
509 for (
int iIDin = 0; iIDin < nIncome; iIDin++) {
510 int idIn = incomingIDs[iIDin];
511 int idInAbs = abs(idIn);
512 map< int, vector< pair<int,int> > > hadConstIDsNow = hadConstIDsProd;
514 for (
int iHvy = nNewQuark+1; iHvy <= 5; iHvy++) {
515 if (particleDataPtr->nQuarksInCode(idInAbs, iHvy) > 0)
516 for (map<
int, vector< pair<int,int> > >::iterator
517 it = hadConstIDsHvy[iHvy].begin();
518 it != hadConstIDsHvy[iHvy].end(); ++it)
519 hadConstIDsNow[it->first] = it->second;
523 vector< pair<int,int> > possibleHadronIDs;
526 for (map<
int, vector< pair<int,int> > >::iterator
527 it = hadConstIDsNow.begin(); it != hadConstIDsNow.end(); ++it) {
528 vector< pair<int,int> > constituentIDs = it->second;
529 int nConst = int(constituentIDs.size());
530 int hadronID = it->first;
532 for (
int iConst = 0; iConst < nConst; iConst++) {
533 int ID1 = constituentIDs[iConst].first;
534 int ID2 = constituentIDs[iConst].second;
535 if ( (ID1 == idIn) || (ID2 == idIn) ) {
536 possibleHadronIDs.push_back( make_pair(hadronID,iConst) );
538 if ( (idInAbs < 4) && (ID1 == -ID2) ) {
540 possibleHadronIDs.push_back( make_pair(hadronID+110,iConst) );
541 possibleHadronIDs.push_back( make_pair(hadronID+220,iConst) );
542 }
else if (idInAbs == 2) {
543 possibleHadronIDs.push_back( make_pair(hadronID-110,iConst) );
544 possibleHadronIDs.push_back( make_pair(hadronID+110,iConst) );
545 }
else if (idInAbs == 3) {
546 possibleHadronIDs.push_back( make_pair(hadronID-220,iConst) );
547 possibleHadronIDs.push_back( make_pair(hadronID-110,iConst) );
553 if (
int(possibleHadronIDs.size()) < 1)
554 infoPtr->errorMsg(
"Error in StringFlav::init: no possible "
556 possibleHadrons[idIn] = possibleHadronIDs;
563 for (
int q1 = 0; q1 < 6; q1++) {
564 for (
int q2 = 0; q2 < 6; q2++) {
565 baryonOctWeight[q1][q1][q2][0] = 0.0;
566 baryonDecWeight[q1][q1][q2][0] = 0.0;
568 baryonOctWeight[ 0][q1][q2][
spin] = 0.0;
569 baryonOctWeight[q1][ 0][q2][
spin] = 0.0;
570 baryonOctWeight[q1][q2][ 0][
spin] = 0.0;
571 baryonDecWeight[ 0][q1][q2][
spin] = 0.0;
572 baryonDecWeight[q1][ 0][q2][
spin] = 0.0;
573 baryonDecWeight[q1][q2][ 0][
spin] = 0.0;
578 for (
int q1 = 1; q1 < 6; q1++) {
579 baryonOctWeight[q1][q1][q1][1] = 0.0;
580 baryonDecWeight[q1][q1][q1][1] = 1.0;
581 for (
int q2 = 1; q2 < 6; q2++)
if (q1!=q2) {
582 baryonOctWeight[q1][q1][q2][1] = 0.1667;
583 baryonDecWeight[q1][q1][q2][1] = 0.3333;
584 baryonOctWeight[q1][q2][q1][0] = 0.75;
585 baryonDecWeight[q1][q2][q1][0] = 0.0;
586 baryonOctWeight[q2][q1][q1][0] = 0.75;
587 baryonDecWeight[q2][q1][q1][0] = 0.0;
588 baryonOctWeight[q1][q2][q1][1] = 0.0833;
589 baryonDecWeight[q1][q2][q1][1] = 0.6667;
590 baryonOctWeight[q2][q1][q1][1] = 0.0833;
591 baryonDecWeight[q2][q1][q1][1] = 0.6667;
592 for (
int q3 = 0; q3 < 6; q3++)
if ((q1 != q3) && (q2 != q3)) {
593 baryonOctWeight[q1][q2][q3][0] = 0.5;
594 baryonDecWeight[q1][q2][q3][0] = 0.0;
595 baryonOctWeight[q1][q2][q3][1] = 0.1667;
596 baryonDecWeight[q1][q2][q3][1] = 0.3333;
602 double BtoMratio = settings.parm(
"StringFlav:BtoMratio");
603 for (
int q1 = 0; q1 < 6; q1++) {
604 for (
int q2 = 0; q2 < 6; q2++) {
605 for (
int q3 = 0; q3 < 6; q3++) {
607 baryonOctWeight[q1][q2][q3][
spin] *= BtoMratio;
608 baryonDecWeight[q1][q2][q3][
spin] *= BtoMratio;
610 baryonOctWeight[q1][q2][q3][1] *= 3.0;
611 baryonDecWeight[q1][q2][q3][1] *= 3.0;
620 double strSup = settings.parm(
"StringFlav:StrangeSuppression");
621 for (
int iIDin = 0; iIDin < nIncome; iIDin++) {
622 int idIn = incomingIDs[iIDin];
623 int idInAbs = abs(idIn);
624 vector< pair<int,int> > possibleHadronsNow = possibleHadrons[idIn];
625 vector<double> prefactors;
626 for (
int iHad = 0; iHad < int(possibleHadronsNow.size()); iHad++) {
627 double prefacNow = 1.0;
629 int hadronID = possibleHadronsNow[iHad].first;
630 int hadronIDabs = abs(hadronID);
631 int iConst = possibleHadronsNow[iHad].second;
632 int ID1 = hadronConstIDs[hadronID][iConst].first;
633 int ID2 = hadronConstIDs[hadronID][iConst].second;
636 for (
int i = 3; i <= 5; i++) {
637 nHeavy += particleDataPtr->nQuarksInCode( ID1, i);
638 nHeavy += particleDataPtr->nQuarksInCode( ID2, i);
640 prefacNow *= pow(strSup, nHeavy);
641 if (particleDataPtr->isMeson(hadronID)) {
643 prefacNow *= (abs(hadronID) % 10);
645 if ( (idInAbs < 4) && (ID1 == -ID2) ) {
646 int flav = ( (idInAbs < 3) ? 0 : 1 );
648 int spin = getMesonSpinCounter(hadronID);
649 double mesonMix[3] = { mesMixRate1[flav][
spin],
650 mesMixRate2[flav][
spin],
651 mesMixRate3[flav][
spin] };
652 prefacNow *= mesonMix[abs(ID1)-1];
656 bool isOct = ((hadronIDabs % 10) == 2);
658 if (abs(ID2) < abs(ID1)) swap(ID1,ID2);
660 int Q1 = ( (abs(ID2)/1000) % 10 );
661 int Q2 = ( (abs(ID2)/100) % 10 );
662 int diqSpin = ( ((abs(ID2) % 10) == 1) ? 0 : 1 );
666 if (isOct) prefacNow *= baryonOctWeight[Q1][Q2][Q3][diqSpin];
667 else prefacNow *= baryonDecWeight[Q1][Q2][Q3][diqSpin];
669 if ( isOct && (Q1!=Q2) && (Q1!=Q3) && (Q2!=Q3) ) {
671 int Qhad1 = ( (hadronIDabs/10) % 10 );
672 int Qhad2 = ( (hadronIDabs/100) % 10 );
673 int QhadMin = min(Qhad1,Qhad2);
674 int QhadMax = max(Qhad1,Qhad2);
676 int QdiqMin = min(Q1,Q2);
677 int QdiqMax = max(Q1,Q2);
679 if ( !((QdiqMin == QhadMin) && (QdiqMax == QhadMax)) ) {
681 if (Qhad2 > Qhad1) prefacNow *= ( (diqSpin == 0) ? 0.75 : 0.25 );
683 else prefacNow *= ( (diqSpin == 0) ? 0.25 : 0.27 );
688 prefactors.push_back(prefacNow);
690 possibleRatePrefacs[idIn] = prefactors;
694 for (
int iIDin1 = 0; iIDin1 < nIncome; iIDin1++) {
695 int idIn1 = incomingIDs[iIDin1];
696 int idIn1Abs = abs(idIn1);
698 for (
int iIDin2 = iIDin1+1; iIDin2 < nIncome; iIDin2++) {
699 int idIn2 = incomingIDs[iIDin2];
700 int idIn2Abs = abs(idIn2);
701 int idInNow[2] = { min(idIn1,idIn2), max(idIn1,idIn2) };
702 pair<int,int> inPair = pair<int,int>(idInNow[0], idInNow[1]);
704 if ( (idIn1Abs > 1000) && (idIn2Abs > 1000) )
continue;
706 if ( ( ((idIn1 > 0) && (idIn2 > 0)) || ((idIn1 < 0) && (idIn2 < 0)) )
707 && (idIn1Abs < 10) && (idIn2Abs < 10) )
continue;
710 if ( ((idIn2 > 1000) && (idIn1Abs < 10) && (idIn1 < 0)) ||
711 ((idIn2 < -1000) && (idIn1Abs < 10) && (idIn1 > 0)) )
continue;
714 if ((idIn1Abs < 10) && (idIn2Abs > 1000)) {
715 vector< pair<int,int> > hvyCombs;
717 hvyCombs.push_back(make_pair(4,4));
719 hvyCombs.push_back(make_pair(5,4));
720 hvyCombs.push_back(make_pair(4,5));
721 hvyCombs.push_back(make_pair(5,5));
725 for (
int iComb = 0; iComb < int(hvyCombs.size()); iComb++) {
726 int idNow[2] = { hvyCombs[iComb].first, hvyCombs[iComb].second };
727 if ( (particleDataPtr->nQuarksInCode(idIn2Abs,idNow[0]) > 0) &&
728 (idIn1Abs == idNow[1]) ) skip =
true;
737 if ( (idIn1Abs < 10) && (idIn2Abs < 10) ) {
738 idUse = ( (idIn1Abs > idIn2Abs) ? idIn1 : idIn2 );
741 bool useDiquark =
false;
742 for (
int plus = 1; plus < 5; plus++)
743 if (particleDataPtr->nQuarksInCode(idIn2Abs, idIn1Abs + plus) > 0)
745 idUse = ( useDiquark ? idIn2 : idIn1 );
747 vector<double> possibleRatePrefacsNow = possibleRatePrefacs[idUse];
748 vector< pair<int,int> > possibleHadronsNow = possibleHadrons[idUse];
750 vector< pair<int,int> > possibleHadronsNew;
751 vector<double> possibleRatePrefacsNew;
754 for (
int iHad = 0; iHad < int(possibleHadronsNow.size()); iHad++) {
756 int hadronID = possibleHadronsNow[iHad].first;
757 int iConst = possibleHadronsNow[iHad].second;
758 int ID1 = hadronConstIDs[hadronID][iConst].first;
759 int ID2 = hadronConstIDs[hadronID][iConst].second;
760 if ( ((ID1 == idIn1) && (ID2 == idIn2)) ||
761 ((ID1 == idIn2) && (ID2 == idIn1)) ) {
763 possibleHadronsNew.push_back(possibleHadronsNow[iHad]);
764 possibleRatePrefacsNew.push_back(possibleRatePrefacsNow[iHad]);
767 if (
int(possibleHadronsNew.size()) < 1)
768 infoPtr->errorMsg(
"Error in StringFlav::init: no possible "
769 "hadrons found for last two");
771 possibleRatePrefacsLast[inPair] = possibleRatePrefacsNew;
772 possibleHadronsLast[inPair] = possibleHadronsNew;
780 hadronMassWin = -1.0;
789 FlavContainer StringFlav::pickGauss(FlavContainer& flavOld) {
792 FlavContainer flavNew;
793 flavNew.rank = flavOld.rank + 1;
796 int idOld = abs(flavOld.id);
797 if (flavOld.rank == 0 && idOld > 1000) assignPopQ(flavOld);
800 bool doOldBaryon = (idOld > 1000 && flavOld.nPop == 0);
802 bool doPopcornMeson = flavOld.nPop > 0;
804 bool doNewBaryon =
false;
807 if (!doOldBaryon && !doPopcornMeson && probQandQQ * rndmPtr->flat() > 1.) {
809 if ((1. + popFrac) * rndmPtr->flat() > 1.) flavNew.nPop = 1;
813 if (flavOld.rank == 0 && doNewBaryon && suppressLeadingB) {
814 double leadingBSup = (idOld < 4) ? lightLeadingBSup : heavyLeadingBSup;
815 if (rndmPtr->flat() > leadingBSup) {
822 if (!doPopcornMeson && !doNewBaryon) {
823 flavNew.id = pickLightQ();
824 if ( (flavOld.id > 0 && flavOld.id < 9) || flavOld.id < -1000 )
825 flavNew.id = -flavNew.id;
832 int iCase = flavNew.nPop;
833 if (flavOld.nPop == 1) iCase = 2;
837 double sPopWT = dWT[iCase][0];
838 if (iCase == 1) sPopWT *= scbBM[0] * popcornSpair;
839 double rndmFlav = (2. + sPopWT) * rndmPtr->flat();
841 if (rndmFlav > 1.) flavNew.idPop = 2;
842 if (rndmFlav > 2.) flavNew.idPop = 3;
843 }
else flavNew.idPop = flavOld.idPop;
846 double sVtxWT = dWT[iCase][1];
847 if (flavNew.idPop >= 3) sVtxWT = dWT[iCase][2];
848 if (flavNew.idPop > 3) sVtxWT *= 0.5 * (1. + 1./dWT[iCase][4]);
849 double rndmFlav = (2. + sVtxWT) * rndmPtr->flat();
851 if (rndmFlav > 1.) flavNew.idVtx = 2;
852 if (rndmFlav > 2.) flavNew.idVtx = 3;
855 if (flavNew.idPop < 3 && flavNew.idVtx < 3) {
856 flavNew.idVtx = flavNew.idPop;
857 if (rndmPtr->flat() > dWT[iCase][3]) flavNew.idVtx = 3 - flavNew.idPop;
862 if (flavNew.idVtx != flavNew.idPop) {
863 double spinWT = dWT[iCase][6];
864 if (flavNew.idVtx == 3) spinWT = dWT[iCase][5];
865 if (flavNew.idPop >= 3) spinWT = dWT[iCase][4];
866 if ((1. + spinWT) * rndmPtr->flat() < 1.) spin = 1;
870 flavNew.id = 1000 * max(flavNew.idVtx, flavNew.idPop)
871 + 100 * min(flavNew.idVtx, flavNew.idPop) +
spin;
872 if ( (flavOld.id < 0 && flavOld.id > -9) || flavOld.id > 1000 )
873 flavNew.id = -flavNew.id;
886 FlavContainer StringFlav::pickThermal(FlavContainer& flavOld,
887 double pT,
double nNSP) {
890 FlavContainer flavNew;
891 flavNew.rank = flavOld.rank + 1;
893 int idIn = flavOld.id;
894 int idInAbs = abs(idIn);
895 double temprNow = temperature;
898 if (idInAbs > 2) temprNow *= tempPreFactor;
901 temprNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
902 temprNow *= pow(max(1.0,nNSP), exponentNSP);
905 double sigmaNow = sigmaHad;
909 if (abs(idIn) > 10) sigmaNow *= widthPreDiquark;
910 sigmaNow *= pow(widthPreStrange,
911 particleDataPtr->nQuarksInCode(idIn,3) );
916 sigmaNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
917 sigmaNow *= pow(max(1.0,nNSP), exponentNSP);
923 vector<double> possibleRatePrefacsNow = possibleRatePrefacs[idIn];
924 vector< pair<int,int> > possibleHadronsNow = possibleHadrons[idIn];
925 int nPossHads = int(possibleHadronsNow.size());
927 infoPtr->errorMsg(
"Error in StringFlav::pickThermal: no possible "
934 vector<double> possibleHadronMasses;
937 vector<double> rates;
938 double rateSum = 0.0;
939 for (
int iHad = 0; iHad < nPossHads; iHad++) {
940 int hadronID = possibleHadronsNow[iHad].first;
942 double mass = particleDataPtr->mSel(hadronID);
943 possibleHadronMasses.push_back(mass);
944 double rate = exp( -sqrt(pow2(pT)+pow2(mass))/temprNow );
946 if (mT2suppression) rate = exp( -(pow2(pT)+pow2(mass))/pow2(sigmaNow) );
948 rate *= possibleRatePrefacsNow[iHad];
950 rates.push_back(rate);
954 for (
int iHad = 0; iHad < nPossHads; iHad++) rates[iHad] /= rateSum;
957 vector<double> accumRates;
958 for (
int iHad = 0; iHad < nPossHads; iHad++) accumRates.push_back(0);
959 for (
int iHad1 = 0; iHad1 < nPossHads; iHad1++)
960 for (
int iHad2 = 0; iHad2 <= iHad1; iHad2++)
961 accumRates[iHad1] += rates[iHad2];
964 double rand = rndmPtr->flat();
967 double hadronMass = -1.0;
968 for (
int iHad = 0; iHad < nPossHads; iHad++) {
969 if (rand <= accumRates[iHad]) {
970 hadronID = possibleHadronsNow[iHad].first;
971 iConst = possibleHadronsNow[iHad].second;
972 hadronMass = possibleHadronMasses[iHad];
979 vector< pair<int,int> > constituentIDs = hadronConstIDs[hadronID];
981 if (particleDataPtr->isMeson(hadronID)) {
982 int ID1 = constituentIDs[0].first;
983 int ID2 = constituentIDs[0].second;
985 if (ID1 == -ID2) idNext = idIn;
986 else idNext = (idIn == ID1 ? -ID2 : -ID1);
990 int ID1 = constituentIDs[iConst].first;
991 int ID2 = constituentIDs[iConst].second;
992 if (ID1 == idIn) idNext = -ID2;
993 if (ID2 == idIn) idNext = -ID1;
997 flavNew.id = -idNext;
998 hadronIDwin = hadronID;
1000 hadronMassWin = hadronMass;
1012 int StringFlav::combine(FlavContainer& flav1, FlavContainer& flav2) {
1015 int id1Abs = abs(flav1.id);
1016 int id2Abs = abs(flav2.id);
1017 int idMax = max(id1Abs, id2Abs);
1018 int idMin = min(id1Abs, id2Abs);
1021 if (idMax < 9 || idMin > 1000) {
1025 id1Abs = flav1.idVtx;
1026 id2Abs = flav2.idVtx;
1027 idMax = max(id1Abs, id2Abs);
1028 idMin = min(id1Abs, id2Abs);
1029 if (idMin == 0)
return 0;
1033 int flav = (idMax < 3) ? 0 : idMax - 2;
1034 double rndmSpin = mesonRateSum[flav] * rndmPtr->flat();
1036 do rndmSpin -= mesonRate[flav][++
spin];
1037 while (rndmSpin > 0.);
1038 int idMeson = 100 * idMax + 10 * idMin + mesonMultipletCode[
spin];
1041 if (idMax != idMin) {
1042 int sign = (idMax%2 == 0) ? 1 : -1;
1043 if ( (idMax == id1Abs && flav1.id < 0)
1044 || (idMax == id2Abs && flav2.id < 0) ) sign = -sign;
1048 }
else if (flav < 2) {
1049 double rMix = rndmPtr->flat();
1050 if (rMix < mesonMix1[flav][spin]) idMeson = 110;
1051 else if (rMix < mesonMix2[flav][spin]) idMeson = 220;
1053 idMeson += mesonMultipletCode[
spin];
1056 if (idMeson == 221 && etaSup < rndmPtr->flat())
return 0;
1057 if (idMeson == 331 && etaPrimeSup < rndmPtr->flat())
return 0;
1065 int idQQ1 = idMax / 1000;
1066 int idQQ2 = (idMax / 100) % 10;
1067 int spinQQ = idMax % 10;
1068 int spinFlav = spinQQ - 1;
1069 if (spinFlav == 2 && idQQ1 != idQQ2) spinFlav = 4;
1070 if (idMin != idQQ1 && idMin != idQQ2) spinFlav++;
1071 if (baryonCGSum[spinFlav] < rndmPtr->flat() * baryonCGMax[spinFlav])
1075 int idOrd1 = max( idMin, max( idQQ1, idQQ2) );
1076 int idOrd3 = min( idMin, min( idQQ1, idQQ2) );
1077 int idOrd2 = idMin + idQQ1 + idQQ2 - idOrd1 - idOrd3;
1078 int spinBar = (baryonCGSum[spinFlav] * rndmPtr->flat()
1079 < baryonCGOct[spinFlav]) ? 2 : 4;
1082 bool LambdaLike =
false;
1083 if (spinBar == 2 && idOrd1 > idOrd2 && idOrd2 > idOrd3) {
1084 LambdaLike = (spinQQ == 1);
1085 if (idOrd1 != idMin && spinQQ == 1) LambdaLike = (rndmPtr->flat() < 0.25);
1086 else if (idOrd1 != idMin) LambdaLike = (rndmPtr->flat() < 0.75);
1090 int idBaryon = (LambdaLike)
1091 ? 1000 * idOrd1 + 100 * idOrd3 + 10 * idOrd2 + spinBar
1092 : 1000 * idOrd1 + 100 * idOrd2 + 10 * idOrd3 + spinBar;
1093 return (flav1.id > 0) ? idBaryon : -idBaryon;
1102 int StringFlav::combineLastThermal(FlavContainer& flav1, FlavContainer& flav2,
1103 double pT,
double nNSP) {
1106 int idIn[2] = { flav1.id, flav2.id };
1107 if (rndmPtr->flat() < 0.5) swap(idIn[0], idIn[1]);
1108 int idInNow[2] = { min(idIn[0],idIn[1]), max(idIn[0],idIn[1]) };
1110 int idInAbs = abs(idIn[0]);
1111 double temprNow = temperature;
1114 if (idInAbs > 2) temprNow *= tempPreFactor;
1118 temprNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1119 temprNow *= pow(max(1.0,nNSP), exponentNSP);
1123 double sigmaNow = sigmaHad;
1126 if (abs(idInAbs) > 10) sigmaNow *= widthPreDiquark;
1127 sigmaNow *= pow(widthPreStrange,
1128 particleDataPtr->nQuarksInCode(idInAbs,3) );
1133 sigmaNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1134 sigmaNow *= pow(max(1.0,nNSP), exponentNSP);
1140 pair<int,int> inPr = pair<int,int>(idInNow[0], idInNow[1]);
1141 vector<double> possibleRatePrefacsNow = possibleRatePrefacsLast[inPr];
1142 vector< pair<int,int> > possibleHadronsNow = possibleHadronsLast[inPr];
1143 int nPossHads = int(possibleHadronsNow.size());
1144 if (nPossHads < 1) {
1145 infoPtr->errorMsg(
"Error in StringFlav::combineLastThermal: no possible "
1146 "hadrons found for last two");
1152 vector<double> possibleHadronMasses;
1155 vector<double> rates;
1156 double rateSum = 0.0;
1157 for (
int iHad = 0; iHad < nPossHads; iHad++) {
1158 int hadronID = possibleHadronsNow[iHad].first;
1160 double mass = particleDataPtr->mSel(hadronID);
1161 possibleHadronMasses.push_back(mass);
1162 double rate = exp( -sqrt(pow2(pT)+pow2(mass))/temprNow );
1164 if (mT2suppression) rate = exp( -(pow2(pT)+pow2(mass))/pow2(sigmaNow) );
1166 rate *= possibleRatePrefacsNow[iHad];
1168 rates.push_back(rate);
1172 for (
int iHad = 0; iHad < nPossHads; iHad++) rates[iHad] /= rateSum;
1175 vector<double> accumRates;
1176 for (
int iHad = 0; iHad < nPossHads; iHad++) accumRates.push_back(0);
1177 for (
int iHad1 = 0; iHad1 < nPossHads; iHad1++)
1178 for (
int iHad2 = 0; iHad2 <= iHad1; iHad2++)
1179 accumRates[iHad1] += rates[iHad2];
1182 double rand = rndmPtr->flat();
1184 double hadronMass = -1.0;
1185 for (
int iHad = 0; iHad < nPossHads; iHad++) {
1186 if (rand <= accumRates[iHad]) {
1187 hadronID = possibleHadronsNow[iHad].first;
1188 hadronMass = possibleHadronMasses[iHad];
1194 hadronIDwin = hadronID;
1195 hadronMassWin = hadronMass;
1205 void StringFlav::assignPopQ(FlavContainer& flav) {
1208 int idAbs = abs(flav.id);
1209 if (flav.rank > 0 || idAbs < 1000)
return;
1212 int id1 = (idAbs/1000)%10;
1213 int id2 = (idAbs/100)%10;
1215 if (id1 == 3) pop2WT = scbBM[1];
1216 else if (id1 > 3) pop2WT = scbBM[2];
1217 if (id2 == 3) pop2WT /= scbBM[1];
1218 else if (id2 > 3) pop2WT /= scbBM[2];
1220 flav.idPop = ((1. + pop2WT) * rndmPtr->flat() > 1.) ? id2 : id1;
1221 flav.idVtx = id1 + id2 - flav.idPop;
1225 double popWT = popS[0];
1226 if (id1 == 3) popWT = popS[1];
1227 if (id2 == 3) popWT = popS[2];
1228 if (idAbs%10 == 1) popWT *= sqrt(probQQ1toQQ0);
1229 if ((1. + popWT) * rndmPtr->flat() > 1.) flav.nPop = 1;
1239 int StringFlav::makeDiquark(
int id1,
int id2,
int idHad) {
1242 int idMin = min( abs(id1), abs(id2));
1243 int idMax = max( abs(id1), abs(id2));
1248 if (abs(idHad) == 2212 || abs(idHad) == 2112) {
1249 if (idMin == 1 && idMax == 2 && rndmPtr->flat() < 0.75) spin = 0;
1252 }
else if (idMin != idMax) {
1253 if (rndmPtr->flat() > probQQ1join[min(idMax,5) - 2]) spin = 0;
1257 int idNewAbs = 1000 * idMax + 100 * idMin + 2 * spin + 1;
1258 return (id1 > 0) ? idNewAbs : -idNewAbs;
1272 const double StringZ::CFROMUNITY = 0.01;
1273 const double StringZ::AFROMZERO = 0.02;
1274 const double StringZ::AFROMC = 0.01;
1277 const double StringZ::EXPMAX = 50.;
1283 void StringZ::init(Settings& settings, ParticleData& particleData,
1284 Rndm* rndmPtrIn, Info* infoPtrIn) {
1287 rndmPtr = rndmPtrIn;
1288 infoPtr = infoPtrIn;
1291 mc2 = pow2( particleData.m0(4));
1292 mb2 = pow2( particleData.m0(5));
1295 aLund = settings.parm(
"StringZ:aLund");
1296 bLund = settings.parm(
"StringZ:bLund");
1297 aExtraSQuark = settings.parm(
"StringZ:aExtraSQuark");
1298 aExtraDiquark = settings.parm(
"StringZ:aExtraDiquark");
1299 rFactC = settings.parm(
"StringZ:rFactC");
1300 rFactB = settings.parm(
"StringZ:rFactB");
1301 rFactH = settings.parm(
"StringZ:rFactH");
1304 if (settings.flag(
"StringZ:deriveBLund")) {
1305 if (!deriveBLund(settings, particleData)) {
1306 infoPtr->errorMsg(
"Error in StringZ::init: Derivation of b parameter "
1307 " failed. Reverting to default.");
1308 settings.resetParm(
"StringZ:bLund");
1313 useNonStandC = settings.flag(
"StringZ:useNonstandardC");
1314 useNonStandB = settings.flag(
"StringZ:useNonstandardB");
1315 useNonStandH = settings.flag(
"StringZ:useNonstandardH");
1316 aNonC = settings.parm(
"StringZ:aNonstandardC");
1317 aNonB = settings.parm(
"StringZ:aNonstandardB");
1318 aNonH = settings.parm(
"StringZ:aNonstandardH");
1319 bNonC = settings.parm(
"StringZ:bNonstandardC");
1320 bNonB = settings.parm(
"StringZ:bNonstandardB");
1321 bNonH = settings.parm(
"StringZ:bNonstandardH");
1324 usePetersonC = settings.flag(
"StringZ:usePetersonC");
1325 usePetersonB = settings.flag(
"StringZ:usePetersonB");
1326 usePetersonH = settings.flag(
"StringZ:usePetersonH");
1327 epsilonC = settings.parm(
"StringZ:epsilonC");
1328 epsilonB = settings.parm(
"StringZ:epsilonB");
1329 epsilonH = settings.parm(
"StringZ:epsilonH");
1332 stopM = settings.parm(
"StringFragmentation:stopMass");
1333 stopNF = settings.parm(
"StringFragmentation:stopNewFlav");
1334 stopS = settings.parm(
"StringFragmentation:stopSmear");
1343 bool StringZ::deriveBLund(Settings& settings, ParticleData& particleData) {
1346 double mRef = particleData.m0(113);
1347 double mT2ref = pow2(mRef) + 2.*pow2(settings.parm(
"stringPT:sigma"));
1348 double avgZ = settings.parm(
"StringZ:avgZLund");
1349 double a = settings.parm(
"StringZ:aLund");
1352 LundFFAvg lundFFAvg;
1353 vector<double> args(4);
1361 bool check = lundFFAvg.brent(bNow, avgZ, 1, 0.01, 20.0, args, 1.e-6, 1000);
1363 settings.parm(
"StringZ:bLund", bNow,
false);
1366 cout << fixed << setprecision(2) <<
"\n <z(rho)> = " << setw(5)
1367 << avgZ <<
" for aLund = "<< a <<
" & mT2ref = " << setw(5) << mT2ref
1368 <<
" GeV^2 gave bLund = " << setw(5) << bNow <<
" GeV^-2:";
1369 if ( bNow == settings.parm(
"StringZ:bLund") ) cout <<
" accepted" << endl;
1372 cout <<
" accepted (forced)" << endl;
1373 settings.parm(
"StringZ:bLund", bNow,
true);
1377 settings.flag(
"StringZ:deriveBLund",
false);
1388 double StringZ::zFrag(
int idOld,
int idNew,
double mT2) {
1391 int idOldAbs = abs(idOld);
1392 int idNewAbs = abs(idNew);
1393 bool isOldSQuark = (idOldAbs == 3);
1394 bool isNewSQuark = (idNewAbs == 3);
1395 bool isOldDiquark = (idOldAbs > 1000 && idOldAbs < 10000);
1396 bool isNewDiquark = (idNewAbs > 1000 && idNewAbs < 10000);
1399 int idFrag = idOldAbs;
1400 if (isOldDiquark) idFrag = max( idOldAbs / 1000, (idOldAbs / 100) % 10);
1403 if (idFrag == 4 && usePetersonC)
return zPeterson( epsilonC);
1404 if (idFrag == 5 && usePetersonB)
return zPeterson( epsilonB);
1405 if (idFrag > 5 && usePetersonH) {
1406 double epsilon = epsilonH * mb2 / mT2;
1407 return zPeterson( epsilon);
1411 double aNow = aLund;
1412 double bNow = bLund;
1413 if (idFrag == 4 && useNonStandC) {
1416 }
else if (idFrag == 5 && useNonStandB) {
1419 }
else if (idFrag > 5 && useNonStandH) {
1425 double aShape = aNow;
1426 if (isOldSQuark) aShape += aExtraSQuark;
1427 if (isOldDiquark) aShape += aExtraDiquark;
1428 double bShape = bNow * mT2;
1430 if (isOldSQuark) cShape -= aExtraSQuark;
1431 if (isNewSQuark) cShape += aExtraSQuark;
1432 if (isOldDiquark) cShape -= aExtraDiquark;
1433 if (isNewDiquark) cShape += aExtraDiquark;
1434 if (idFrag == 4) cShape += rFactC * bNow * mc2;
1435 if (idFrag == 5) cShape += rFactB * bNow * mb2;
1436 if (idFrag > 5) cShape += rFactH * bNow * mT2;
1437 return zLund( aShape, bShape, cShape);
1449 double StringZ::zLund(
double a,
double b,
double c) {
1452 bool cIsUnity = (abs( c - 1.) < CFROMUNITY);
1453 bool aIsZero = (a < AFROMZERO);
1454 bool aIsC = (abs(a - c) < AFROMC);
1458 if (aIsZero) zMax = (c > b) ? b / c : 1.;
1459 else if (aIsC) zMax = b / (b + c);
1460 else { zMax = 0.5 * (b + c - sqrt( pow2(b - c) + 4. * a * b)) / (c - a);
1461 if (zMax > 0.9999 && b > 100.) zMax = min(zMax, 1. - a / b); }
1464 bool peakedNearZero = (zMax < 0.1);
1465 bool peakedNearUnity = (zMax > 0.85 && b > 1.);
1469 double fIntLow = 1.;
1470 double fIntHigh = 1.;
1477 if (peakedNearZero) {
1480 if (cIsUnity) fIntHigh = -zDiv * log(zDiv);
1481 else { zDivC = pow( zDiv, 1. - c);
1482 fIntHigh = zDiv * (1. - 1./zDivC) / (c - 1.);}
1483 fInt = fIntLow + fIntHigh;
1488 }
else if (peakedNearUnity) {
1489 double rcb = sqrt(4. + pow2(c / b));
1490 zDiv = rcb - 1./zMax - (c / b) * log( zMax * 0.5 * (rcb + c / b) );
1491 if (!aIsZero) zDiv += (a/b) * log(1. - zMax);
1492 zDiv = min( zMax, max(0., zDiv));
1494 fIntHigh = 1. - zDiv;
1495 fInt = fIntLow + fIntHigh;
1505 z = rndmPtr->flat();
1508 if (peakedNearZero) {
1509 if (fInt * rndmPtr->flat() < fIntLow) z = zDiv * z;
1510 else if (cIsUnity) {z = pow( zDiv, z); fPrel = zDiv / z;}
1511 else { z = pow( zDivC + (1. - zDivC) * z, 1. / (1. - c) );
1512 fPrel = pow( zDiv / z, c); }
1515 }
else if (peakedNearUnity) {
1516 if (fInt * rndmPtr->flat() < fIntLow) {
1517 z = zDiv + log(z) / b;
1518 fPrel = exp( b * (z - zDiv) );
1519 }
else z = zDiv + (1. - zDiv) * z;
1523 if (z > 0 && z < 1) {
1524 double fExp = b * (1. / zMax - 1. / z)+ c * log(zMax / z);
1525 if (!aIsZero) fExp += a * log( (1. - z) / (1. - zMax) );
1526 fVal = exp( max( -EXPMAX, min( EXPMAX, fExp) ) ) ;
1528 }
while (fVal < rndmPtr->flat() * fPrel);
1541 double StringZ::zPeterson(
double epsilon) {
1547 if (epsilon > 0.01) {
1549 z = rndmPtr->flat();
1550 fVal = 4. * epsilon * z * pow2(1. - z)
1551 / pow2( pow2(1. - z) + epsilon * z);
1552 }
while (fVal < rndmPtr->flat());
1559 double epsRoot = sqrt(epsilon);
1560 double epsComb = 0.5 / epsRoot - 1.;
1561 double fIntLow = 4. * epsilon * epsComb;
1562 double fInt = fIntLow + 2. * epsRoot;
1564 if (rndmPtr->flat() * fInt < fIntLow) {
1565 z = 1. - 1. / (1. + rndmPtr->flat() * epsComb);
1566 fVal = z * pow2( pow2(1. - z) / (pow2(1. - z) + epsilon * z) );
1568 z = 1. - 2. * epsRoot * rndmPtr->flat();
1569 fVal = 4. * epsilon * z * pow2(1. - z)
1570 / pow2( pow2(1. - z) + epsilon * z);
1572 }
while (fVal < rndmPtr->flat());
1587 const double StringPT::SIGMAMIN = 0.2;
1593 void StringPT::init(Settings& settings, ParticleData* particleDataPtrIn,
1594 Rndm* rndmPtrIn, Info* infoPtrIn) {
1597 particleDataPtr = particleDataPtrIn;
1598 rndmPtr = rndmPtrIn;
1599 infoPtr = infoPtrIn;
1602 double sigma = settings.parm(
"StringPT:sigma");
1603 sigmaQ = sigma / sqrt(2.);
1604 enhancedFraction = settings.parm(
"StringPT:enhancedFraction");
1605 enhancedWidth = settings.parm(
"StringPT:enhancedWidth");
1606 widthPreStrange = settings.parm(
"StringPT:widthPreStrange");
1607 widthPreDiquark = settings.parm(
"StringPT:widthPreDiquark");
1608 useWidthPre = (widthPreStrange > 1.0) || (widthPreDiquark > 1.0);
1611 thermalModel = settings.flag(
"StringPT:thermalModel");
1612 temperature = settings.parm(
"StringPT:temperature");
1613 tempPreFactor = settings.parm(
"StringPT:tempPreFactor");
1616 fracSmallX = 0.6 / (0.6 + (1.2/0.9) * exp(-0.9));
1619 closePacking = settings.flag(
"StringPT:closePacking");
1620 exponentMPI = settings.parm(
"StringPT:expMPI");
1621 exponentNSP = settings.parm(
"StringPT:expNSP");
1624 sigma2Had = 2. * pow2( max( SIGMAMIN, sigma) );
1633 pair<double, double> StringPT::pxyThermal(
int idIn,
double nNSP) {
1635 double temprNow = temperature;
1638 if (abs(idIn) > 2) temprNow *= tempPreFactor;
1642 temprNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1643 temprNow *= pow(max(1.0,nNSP), exponentNSP);
1647 double xrand, approx, wanted;
1649 xrand = (rndmPtr->flat() < fracSmallX) ? rndmPtr->flat()
1650 : 1. - log(rndmPtr->flat()) / 0.9;
1651 approx = (xrand < 1.) ? 0.6 : 1.2 * exp(-0.9 * xrand);
1652 wanted = BesselK14(xrand) * pow( xrand, 0.75);
1653 }
while (rndmPtr->flat() * approx > wanted);
1656 double pTquark = xrand * temprNow;
1657 double phi = 2.0 * M_PI * rndmPtr->flat();
1660 return pair<double, double>( pTquark * cos(phi), pTquark * sin(phi) );
1669 pair<double, double> StringPT::pxyGauss(
int idIn,
double nNSP) {
1672 double sigma = sigmaQ;
1673 if (rndmPtr->flat() < enhancedFraction) sigma *= enhancedWidth;
1677 if (abs(idIn) > 10) sigma *= widthPreDiquark;
1678 sigma *= pow(widthPreStrange, particleDataPtr->nQuarksInCode(idIn, 3) );
1683 sigma *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1684 sigma *= pow(max(1.0,nNSP), exponentNSP);
1688 pair<double, double> gauss2 = rndmPtr->gauss2();
1689 return pair<double, double>(sigma * gauss2.first, sigma * gauss2.second);
1700 double StringPT::BesselK14(
double x) {
1704 double xRat = 0.25 * x * x;
1705 double prodP = pow( 0.5 * x, -0.25) / 1.2254167024;
1706 double prodN = pow( 0.5 * x, 0.25) / 0.9064024771;
1707 double sum = prodP - prodN;
1710 for (
int k = 1; k < 6; ++k) {
1711 prodP *= xRat / (k * (k - 0.25));
1712 prodN *= xRat / (k * (k + 0.25));
1713 sum += prodP - prodN;
1715 sum *= M_PI * sqrt(0.5);
1720 double asym = sqrt(M_PI * 0.5 / x) * exp(-x);
1721 double term1 = - 0.75 / ( 8. * x);
1722 double term2 = -term1 * 8.75 / (16. * x);
1723 double term3 = -term2 * 24.75 / (24. * x);
1724 double term4 = -term3 * 48.75 / (32. * x);
1725 asym *= 1. + term1 + term2 + term3 + term4;