9 #include "Pythia8/FragmentationFlavZpT.h"
21 double LundFFRaw(
double z,
double a,
double b,
double c,
double mT2) {
22 if (z <= 0. || z >= 1.)
return 0.;
23 return pow(1. - z, a) / pow(z, c) * exp(-b * mT2 / z);
30 double LundFFAvg(
double a,
double b,
double c,
31 double mT2,
double tol = 1.e-6) {
38 auto lundFF = [=, &c](
double z) {
return LundFFRaw(z, a, b, c, mT2); };
41 double denominator = 1.;
42 check = integrateGauss(denominator, lundFF, 0, 1, tol);
43 if (!check || denominator <= 0.)
return -1.;
47 double numerator = 0.;
48 check = integrateGauss(numerator, lundFF, 0., 1., tol);
49 if (!check || numerator <= 0.)
return -1.;
52 return numerator / denominator;
65 const int StringFlav::mesonMultipletCode[6]
66 = { 1, 3, 10003, 10001, 20003, 5};
71 const double StringFlav::baryonCGOct[6]
72 = { 0.75, 0.5, 0., 0.1667, 0.0833, 0.1667};
73 const double StringFlav::baryonCGDec[6]
74 = { 0., 0., 1., 0.3333, 0.6667, 0.3333};
80 void StringFlav::init() {
84 probQQtoQ = parm(
"StringFlav:probQQtoQ");
85 probStoUD = parm(
"StringFlav:probStoUD");
86 probSQtoQQ = parm(
"StringFlav:probSQtoQQ");
87 probQQ1toQQ0 = parm(
"StringFlav:probQQ1toQQ0");
90 probQandQQ = 1. + probQQtoQ;
91 probQandS = 2. + probStoUD;
92 probQandSinQQ = 2. + probSQtoQQ * probStoUD;
93 probQQ1corr = 3. * probQQ1toQQ0;
94 probQQ1corrInv = 1. / probQQ1corr;
95 probQQ1norm = probQQ1corr / (1. + probQQ1corr);
98 vector<double> pQQ1tmp = settingsPtr->pvec(
"StringFlav:probQQ1toQQ0join");
99 for (
int i = 0; i < 4; ++i)
100 probQQ1join[i] = 3. * pQQ1tmp[i] / (1. + 3. * pQQ1tmp[i]);
103 for (
int i = 0; i < 4; ++i) mesonRate[i][0] = 1.;
104 mesonRate[0][1] = parm(
"StringFlav:mesonUDvector");
105 mesonRate[1][1] = parm(
"StringFlav:mesonSvector");
106 mesonRate[2][1] = parm(
"StringFlav:mesonCvector");
107 mesonRate[3][1] = parm(
"StringFlav:mesonBvector");
110 mesonRate[0][2] = parm(
"StringFlav:mesonUDL1S0J1");
111 mesonRate[1][2] = parm(
"StringFlav:mesonSL1S0J1");
112 mesonRate[2][2] = parm(
"StringFlav:mesonCL1S0J1");
113 mesonRate[3][2] = parm(
"StringFlav:mesonBL1S0J1");
114 mesonRate[0][3] = parm(
"StringFlav:mesonUDL1S1J0");
115 mesonRate[1][3] = parm(
"StringFlav:mesonSL1S1J0");
116 mesonRate[2][3] = parm(
"StringFlav:mesonCL1S1J0");
117 mesonRate[3][3] = parm(
"StringFlav:mesonBL1S1J0");
118 mesonRate[0][4] = parm(
"StringFlav:mesonUDL1S1J1");
119 mesonRate[1][4] = parm(
"StringFlav:mesonSL1S1J1");
120 mesonRate[2][4] = parm(
"StringFlav:mesonCL1S1J1");
121 mesonRate[3][4] = parm(
"StringFlav:mesonBL1S1J1");
122 mesonRate[0][5] = parm(
"StringFlav:mesonUDL1S1J2");
123 mesonRate[1][5] = parm(
"StringFlav:mesonSL1S1J2");
124 mesonRate[2][5] = parm(
"StringFlav:mesonCL1S1J2");
125 mesonRate[3][5] = parm(
"StringFlav:mesonBL1S1J2");
128 for (
int i = 0; i < 4; ++i) mesonRateSum[i]
129 = mesonRate[i][0] + mesonRate[i][1] + mesonRate[i][2]
130 + mesonRate[i][3] + mesonRate[i][4] + mesonRate[i][5];
135 if (
spin == 0) theta = parm(
"StringFlav:thetaPS");
136 else if (
spin == 1) theta = parm(
"StringFlav:thetaV");
137 else if (
spin == 2) theta = parm(
"StringFlav:thetaL1S0J1");
138 else if (
spin == 3) theta = parm(
"StringFlav:thetaL1S1J0");
139 else if (
spin == 4) theta = parm(
"StringFlav:thetaL1S1J1");
140 else theta = parm(
"StringFlav:thetaL1S1J2");
141 double alpha = (
spin == 0) ? 90. - (theta + 54.7) : theta + 54.7;
142 alpha *= M_PI / 180.;
145 mesonMix1[0][
spin] = 0.5;
146 mesonMix2[0][
spin] = 0.5 * (1. + pow2(sin(alpha)));
147 mesonMix1[1][
spin] = 0.;
148 mesonMix2[1][
spin] = pow2(cos(alpha));
150 mesMixRate1[0][
spin] = mesonMix1[0][
spin];
151 mesMixRate2[0][
spin] = mesonMix2[0][
spin] - mesonMix1[0][
spin];
152 mesMixRate3[0][
spin] = 1.0 - mesMixRate1[0][
spin] - mesMixRate2[0][
spin];
153 mesMixRate1[1][
spin] = mesonMix1[1][
spin];
154 mesMixRate2[1][
spin] = mesonMix2[1][
spin] - mesonMix1[1][
spin];
155 mesMixRate3[1][
spin] = 1.0 - mesMixRate1[1][
spin] - mesMixRate2[1][
spin];
159 etaSup = parm(
"StringFlav:etaSup");
160 etaPrimeSup = parm(
"StringFlav:etaPrimeSup");
163 decupletSup = parm(
"StringFlav:decupletSup");
164 for (
int i = 0; i < 6; ++i) baryonCGSum[i]
165 = baryonCGOct[i] + decupletSup * baryonCGDec[i];
168 baryonCGMax[0] = max( baryonCGSum[0], baryonCGSum[1]);
169 baryonCGMax[1] = baryonCGMax[0];
170 baryonCGMax[2] = max( baryonCGSum[2], baryonCGSum[3]);
171 baryonCGMax[3] = baryonCGMax[2];
172 baryonCGMax[4] = max( baryonCGSum[4], baryonCGSum[5]);
173 baryonCGMax[5] = baryonCGMax[4];
176 popcornRate = parm(
"StringFlav:popcornRate");
177 popcornSpair = parm(
"StringFlav:popcornSpair");
178 popcornSmeson = parm(
"StringFlav:popcornSmeson");
181 suppressLeadingB = flag(
"StringFlav:suppressLeadingB");
182 lightLeadingBSup = parm(
"StringFlav:lightLeadingBSup");
183 heavyLeadingBSup = parm(
"StringFlav:heavyLeadingBSup");
186 mT2suppression = flag(
"StringPT:mT2suppression");
187 sigmaHad = (sqrt(2.0)*parm(
"StringPT:sigma"));
188 widthPreStrange = parm(
"StringPT:widthPreStrange");
189 widthPreDiquark = parm(
"StringPT:widthPreDiquark");
190 useWidthPre = (widthPreStrange > 1.0) || (widthPreDiquark > 1.0);
193 closePacking = flag(
"StringPT:closePacking");
194 exponentMPI = parm(
"StringPT:expMPI");
195 exponentNSP = parm(
"StringPT:expNSP");
200 enum Diquark {ud0, ud1, uu1, us0, su0, us1, su1, ss1};
204 barCGMax[ud0] = baryonCGMax[0];
205 barCGMax[ud1] = baryonCGMax[4];
206 barCGMax[uu1] = baryonCGMax[2];
207 barCGMax[us0] = baryonCGMax[0];
208 barCGMax[su0] = baryonCGMax[0];
209 barCGMax[us1] = baryonCGMax[4];
210 barCGMax[su1] = baryonCGMax[4];
211 barCGMax[ss1] = baryonCGMax[2];
215 dMB[ud0] = 2. * baryonCGSum[0] + probStoUD * baryonCGSum[1];
216 dMB[ud1] = 2. * baryonCGSum[4] + probStoUD * baryonCGSum[5];
217 dMB[uu1] = baryonCGSum[2] + (1. + probStoUD) * baryonCGSum[3];
218 dMB[us0] = (1. + probStoUD) * baryonCGSum[0] + baryonCGSum[1];
220 dMB[us1] = (1. + probStoUD) * baryonCGSum[4] + baryonCGSum[5];
222 dMB[ss1] = probStoUD * baryonCGSum[2] + 2. * baryonCGSum[3];
223 for (
int i = 1; i < 8; ++i) dMB[i] = dMB[i] / dMB[0];
226 double probStoUDroot = sqrt(probStoUD);
227 double probSQtoQQroot = sqrt(probSQtoQQ);
228 double probQQ1toQQ0root = sqrt(probQQ1toQQ0);
230 qBB[ud1] = probQQ1toQQ0root;
231 qBB[uu1] = probQQ1toQQ0root;
232 qBB[us0] = probSQtoQQroot;
233 qBB[su0] = probStoUDroot * probSQtoQQroot;
234 qBB[us1] = probQQ1toQQ0root * qBB[us0];
235 qBB[su1] = probQQ1toQQ0root * qBB[su0];
236 qBB[ss1] = probStoUDroot * pow2(probSQtoQQroot) * probQQ1toQQ0root;
240 qBM[ud1] = 3. * qBB[ud1];
241 qBM[uu1] = 6. * qBB[uu1];
242 qBM[us0] = probStoUD * qBB[us0];
244 qBM[us1] = probStoUD * 3. * qBB[us1];
245 qBM[su1] = 3. * qBB[su1];
246 qBM[ss1] = probStoUD * 6. * qBB[ss1];
249 for (
int i = 1; i < 8; ++i) qBB[i] = qBB[i] * qBM[i];
252 qBM[us0] *= popcornSmeson;
253 qBM[us1] *= popcornSmeson;
254 qBM[ss1] *= popcornSmeson;
259 double uNorm = 1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1];
260 scbBM[0] = (2. * (qBM[su0] + qBM[su1]) + qBM[ss1]) / uNorm;
261 scbBM[1] = scbBM[0] * popcornSpair * qBM[su0] / qBM[us0];
262 scbBM[2] = (1. + qBM[ud1]) * (2. + qBM[us0]) / uNorm;
265 for (
int i = 1; i < 8; ++i) dMB[i] *= qBM[i];
266 for (
int i = 1; i < 8; ++i) qBM[i] *= barCGMax[i] / barCGMax[0];
267 for (
int i = 1; i < 8; ++i) qBB[i] *= barCGMax[i] / barCGMax[0];
270 double qNorm = uNorm * popcornRate / 3.;
271 double sNorm = scbBM[0] * popcornSpair;
272 popFrac = qNorm * (1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1]
273 + sNorm * (qBM[su0] + qBM[su1] + 0.5 * qBM[ss1])) / (1. + qBB[ud1]
274 + qBB[uu1] + 2. * (qBB[us0] + qBB[us1]) + 0.5 * qBB[ss1]);
277 popS[0] = qNorm * qBM[ud1] / qBB[ud1];
278 popS[1] = qNorm * 0.5 * (qBM[us1] / qBB[us1]
279 + sNorm * qBM[su1] / qBB[su1]);
280 popS[2] = qNorm * sNorm * qBM[ss1] / qBB[ss1];
289 dWT[0][0] = (2. * (qBB[su0] + qBB[su1]) + qBB[ss1])
290 / (1. + qBB[ud1] + qBB[uu1] + qBB[us0] + qBB[us1]);
291 dWT[0][1] = 2. * (qBB[us0] + qBB[us1]) / (1. + qBB[ud1] + qBB[uu1]);
292 dWT[0][2] = qBB[ss1] / (qBB[su0] + qBB[su1]);
293 dWT[0][3] = qBB[uu1] / (1. + qBB[ud1] + qBB[uu1]);
294 dWT[0][4] = qBB[su1] / qBB[su0];
295 dWT[0][5] = qBB[us1] / qBB[us0];
296 dWT[0][6] = qBB[ud1];
299 dWT[1][0] = (2. * (qBM[su0] + qBM[su1]) + qBM[ss1])
300 / (1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1]);
301 dWT[1][1] = 2. * (qBM[us0] + qBM[us1]) / (1. + qBM[ud1] + qBM[uu1]);
302 dWT[1][2] = qBM[ss1] / (qBM[su0] + qBM[su1]);
303 dWT[1][3] = qBM[uu1] / (1. + qBM[ud1] + qBM[uu1]);
304 dWT[1][4] = qBM[su1] / qBM[su0];
305 dWT[1][5] = qBM[us1] / qBM[us0];
306 dWT[1][6] = qBM[ud1];
309 dWT[2][0] = (2. * (dMB[su0] + dMB[su1]) + dMB[ss1])
310 / (1. + dMB[ud1] + dMB[uu1] + dMB[us0] + dMB[us1]);
311 dWT[2][1] = 2. * (dMB[us0] + dMB[us1]) / (1. + dMB[ud1] + dMB[uu1]);
312 dWT[2][2] = dMB[ss1] / (dMB[su0] + dMB[su1]);
313 dWT[2][3] = dMB[uu1] / (1. + dMB[ud1] + dMB[uu1]);
314 dWT[2][4] = dMB[su1] / dMB[su0];
315 dWT[2][5] = dMB[us1] / dMB[us0];
316 dWT[2][6] = dMB[ud1];
319 thermalModel = flag(
"StringPT:thermalModel");
320 if (thermalModel || mT2suppression) {
323 temperature = parm(
"StringPT:temperature");
324 tempPreFactor = parm(
"StringPT:tempPreFactor");
327 mesonNonetL1 = flag(
"StringFlav:mesonNonetL1");
328 nNewQuark = mode(
"StringFlav:nQuark");
333 vector<int> hadIDsProd, hadIDsHvyC, hadIDsHvyB;
336 int baryonLight[18] = { 2112, 2212, 3112, 3122, 3212, 3222, 3312, 3322,
337 1114, 2114, 2214, 2224, 3114, 3214, 3224, 3314,
339 int baryonHvyC[22] = { 4112, 4122, 4132, 4212, 4222, 4232, 4312, 4322,
340 4332, 4412, 4422, 4432,
341 4114, 4214, 4224, 4314, 4324, 4334, 4414, 4424,
343 int baryonHvyB[35] = { 5112, 5122, 5132, 5142, 5212, 5222, 5232, 5242,
344 5312, 5322, 5332, 5342, 5412, 5422, 5432, 5442,
345 5512, 5522, 5532, 5542,
346 5114, 5214, 5224, 5314, 5324, 5334, 5414, 5424,
347 5434, 5444, 5514, 5524, 5534, 5544, 5554 };
348 for (
int i = 0; i < 18; i++) hadIDsProd.push_back( baryonLight[i] );
351 for (
int i = 0; i < 35; i++) hadIDsProd.push_back( baryonHvyB[i] );
354 int bBar[9] = { 5112, 5122, 5132, 5212, 5222, 5232, 5312, 5322, 5332 };
355 for (
int i = 0; i < 9; i++) {
356 hadIDsHvyB.push_back( bBar[i] );
357 hadIDsHvyB.push_back( -bBar[i] );
361 for (
int i = 0; i < 22; i++) hadIDsProd.push_back( baryonHvyC[i] );
364 int cBar[9] = { 4112, 4122, 4132, 4212, 4222, 4232, 4312, 4322, 4332 };
365 for (
int i = 0; i < 9; i++) {
366 hadIDsHvyC.push_back( cBar[i] );
367 hadIDsHvyC.push_back( -cBar[i] );
371 int sizeNow = int(hadIDsProd.size());
372 for (
int i = 0; i < sizeNow; i++) hadIDsProd.push_back( -hadIDsProd[i] );
375 int mesonPSLight[9] = { 311, 321, 211, -311, -321, -211, 111, 221, 331 };
376 int mesonPSHvyC[7] = { 411, 421, 431, -411, -421, -431, 441 };
377 int mesonPSHvyB[9] = { 511, 521, 531, 541, -511, -521, -531, -541, 551 };
379 for (
int i = 0; i < 9; i++) mesonPS.push_back( mesonPSLight[i] );
383 for (
int i = 0; i < 9; i++) mesonPS.push_back( mesonPSHvyB[i] );
387 int bMes[10] = { 511, 521, 531, 541, -511, -521, -531, -541, 551 };
388 for (
int i = 0; i < 10; i++) hadIDsHvyB.push_back( bMes[i] );
391 for (
int i = 0; i < 7; i++) mesonPS.push_back( mesonPSHvyC[i] );
395 int cMes[8] = { 411, 421, 431, -411, -421, -431, 441 };
396 for (
int i = 0; i < 8; i++) hadIDsHvyC.push_back( cMes[i] );
398 int nMeson = int(mesonPS.size());
400 for (
int i = 0; i < nMeson; i++)
401 hadIDsProd.push_back( mesonPS[i] );
403 for (
int i = 0; i < nMeson; i++)
404 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 2 : -2) );
408 for (
int i = 0; i < nMeson; i++)
409 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 10002 : -10002) );
411 for (
int i = 0; i < nMeson; i++)
412 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 10000 : -10000) );
414 for (
int i = 0; i < nMeson; i++)
415 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 20002 : -20002) );
417 for (
int i = 0; i < nMeson; i++)
418 hadIDsProd.push_back( mesonPS[i] + (mesonPS[i] > 0 ? 4 : -4) );
422 vector<int> hadIDsAll;
423 for (
int i = 0; i < int(hadIDsProd.size()); i++)
424 hadIDsAll.push_back( hadIDsProd[i] );
425 for (
int i = 0; i < int(hadIDsHvyC.size()); i++)
426 hadIDsAll.push_back( hadIDsHvyC[i] );
427 for (
int i = 0; i < int(hadIDsHvyB.size()); i++)
428 hadIDsAll.push_back( hadIDsHvyB[i] );
431 for (
int i = 0; i < int(hadIDsAll.size()); i++) {
432 int id = hadIDsAll[i];
434 vector< pair<int,int> > quarkCombis;
436 if (particleDataPtr->isBaryon(
id)) {
437 bool isOctet = ( (idAbs % 10) == 2 );
438 int q3 = (idAbs/10) % 10;
439 int q2 = (idAbs/100) % 10;
440 int q1 = (idAbs/1000) % 10;
441 bool threeFlav = q1 != q2 && q1 != q3 && q2 != q3;
447 int j = (q2 < q3) ? 1 : 3;
448 int qn[2] = { min( q3, q2), max( q3, q2) };
449 addQuarkDiquark(quarkCombis, q1,
450 1000 * qn[1] + 100 * qn[0] + j,
id);
452 for (j = 1; j < 4; j += 2) {
454 addQuarkDiquark(quarkCombis, q2, 1000 * q1 + 100 * q3 + j,
id);
456 addQuarkDiquark(quarkCombis, q3, 1000 * q1 + 100 * q2 + j,
id);
461 for (
int j = 1; j < 4; j += 2) {
463 if ( j == 3 || q1 != q2 )
464 addQuarkDiquark(quarkCombis, q3, 1000 * q1 + 100 * q2 + j,
id);
466 if ( j == 3 || q1 != q3 )
467 addQuarkDiquark(quarkCombis, q2, 1000 * q1 + 100 * q3 + j,
id);
469 if ( j == 3 || q2 != q3 )
470 addQuarkDiquark(quarkCombis, q1, 1000 * q2 + 100 * q3 + j,
id);
478 addQuarkDiquark(quarkCombis, q3, 1000 * q1 + 100 * q2 + 3,
id);
480 addQuarkDiquark(quarkCombis, q2, 1000 * q1 + 100 * q3 + 3,
id);
482 addQuarkDiquark(quarkCombis, q1, 1000 * q2 + 100 * q3 + 3,
id);
487 int q1 = (idAbs/100) % 10;
488 bool uptype1 = (q1 % 2 == 0);
489 int q2 = (idAbs/10) % 10;
490 bool uptype2 = (q2 % 2 == 0);
495 if ( uptype2 && !uptype1 ) swap( quark, antiQuark);
496 if ( (q1 > q2 && !uptype1 && !uptype2)
497 || (q2 > q1 && uptype2 && uptype1) ) swap( quark, antiQuark);
498 if (
id < 0) swap( quark, antiQuark);
499 quarkCombis.push_back( make_pair( quark, -antiQuark) );
501 hadronConstIDs[id] = quarkCombis;
506 map< int, vector< pair<int,int> > > hadConstIDsC, hadConstIDsB,
508 for (
int i=0; i<int(hadIDsAll.size()); i++) {
509 int id = hadIDsAll[i];
510 if (find(hadIDsProd.begin(), hadIDsProd.end(), id) != hadIDsProd.end())
511 hadConstIDsProd[
id] = hadronConstIDs[
id];
512 if (find(hadIDsHvyC.begin(), hadIDsHvyC.end(), id) != hadIDsHvyC.end())
513 hadConstIDsC[
id] = hadronConstIDs[
id];
514 if (find(hadIDsHvyB.begin(), hadIDsHvyB.end(), id) != hadIDsHvyB.end())
515 hadConstIDsB[
id] = hadronConstIDs[
id];
517 map< int, map< int, vector< pair<int,int> > > > hadConstIDsHvy;
518 hadConstIDsHvy[4] = hadConstIDsC;
519 hadConstIDsHvy[5] = hadConstIDsB;
522 int inIDs[26] = { 1, 2, 3, 4, 5, 1103, 2203, 3303, 2101, 2103, 3101,
523 3103, 3201, 3203, 4101, 4103, 4201, 4203, 4301,
524 4303, 5101, 5103, 5201, 5203, 5301, 5303 };
525 int inIDsHvyC[2] = { 4403, -4403 };
526 int inIDsHvyB[6] = { 5503, -5503, 5401, -5401, 5403, -5403 };
527 vector<int> incomingIDs;
528 for (
int i = 0; i < 26; i++) {
529 incomingIDs.push_back( inIDs[i]);
530 incomingIDs.push_back(-inIDs[i]);
535 for (
int i = 0; i < 2; i++) incomingIDs.push_back(inIDsHvyC[i]);
537 for (
int i = 0; i < 6; i++) incomingIDs.push_back( inIDsHvyB[i]);
540 int nIncome = int(incomingIDs.size());
546 for (
int iIDin = 0; iIDin < nIncome; iIDin++) {
547 int idIn = incomingIDs[iIDin];
548 int idInAbs = abs(idIn);
549 map< int, vector< pair<int,int> > > hadConstIDsNow = hadConstIDsProd;
551 for (
int iHvy = nNewQuark+1; iHvy <= 5; iHvy++) {
552 if (particleDataPtr->nQuarksInCode(idInAbs, iHvy) > 0)
553 for (map<
int, vector< pair<int,int> > >::iterator
554 it = hadConstIDsHvy[iHvy].begin();
555 it != hadConstIDsHvy[iHvy].end(); ++it)
556 hadConstIDsNow[it->first] = it->second;
560 vector< pair<int,int> > possibleHadronIDs;
563 for (map<
int, vector< pair<int,int> > >::iterator
564 it = hadConstIDsNow.begin(); it != hadConstIDsNow.end(); ++it) {
565 vector< pair<int,int> > constituentIDs = it->second;
566 int nConst = int(constituentIDs.size());
567 int hadronID = it->first;
569 for (
int iConst = 0; iConst < nConst; iConst++) {
570 int ID1 = constituentIDs[iConst].first;
571 int ID2 = constituentIDs[iConst].second;
572 if ( (ID1 == idIn) || (ID2 == idIn) ) {
573 possibleHadronIDs.push_back( make_pair(hadronID,iConst) );
575 if ( (idInAbs < 4) && (ID1 == -ID2) ) {
577 possibleHadronIDs.push_back( make_pair(hadronID+110,iConst) );
578 possibleHadronIDs.push_back( make_pair(hadronID+220,iConst) );
579 }
else if (idInAbs == 2) {
580 possibleHadronIDs.push_back( make_pair(hadronID-110,iConst) );
581 possibleHadronIDs.push_back( make_pair(hadronID+110,iConst) );
582 }
else if (idInAbs == 3) {
583 possibleHadronIDs.push_back( make_pair(hadronID-220,iConst) );
584 possibleHadronIDs.push_back( make_pair(hadronID-110,iConst) );
590 if (
int(possibleHadronIDs.size()) < 1)
591 infoPtr->errorMsg(
"Error in StringFlav::init: no possible "
593 possibleHadrons[idIn] = possibleHadronIDs;
600 for (
int q1 = 0; q1 < 6; q1++) {
601 for (
int q2 = 0; q2 < 6; q2++) {
602 baryonOctWeight[q1][q1][q2][0] = 0.0;
603 baryonDecWeight[q1][q1][q2][0] = 0.0;
605 baryonOctWeight[ 0][q1][q2][
spin] = 0.0;
606 baryonOctWeight[q1][ 0][q2][
spin] = 0.0;
607 baryonOctWeight[q1][q2][ 0][
spin] = 0.0;
608 baryonDecWeight[ 0][q1][q2][
spin] = 0.0;
609 baryonDecWeight[q1][ 0][q2][
spin] = 0.0;
610 baryonDecWeight[q1][q2][ 0][
spin] = 0.0;
615 for (
int q1 = 1; q1 < 6; q1++) {
616 baryonOctWeight[q1][q1][q1][1] = 0.0;
617 baryonDecWeight[q1][q1][q1][1] = 1.0;
618 for (
int q2 = 1; q2 < 6; q2++)
if (q1!=q2) {
619 baryonOctWeight[q1][q1][q2][1] = 0.1667;
620 baryonDecWeight[q1][q1][q2][1] = 0.3333;
621 baryonOctWeight[q1][q2][q1][0] = 0.75;
622 baryonDecWeight[q1][q2][q1][0] = 0.0;
623 baryonOctWeight[q2][q1][q1][0] = 0.75;
624 baryonDecWeight[q2][q1][q1][0] = 0.0;
625 baryonOctWeight[q1][q2][q1][1] = 0.0833;
626 baryonDecWeight[q1][q2][q1][1] = 0.6667;
627 baryonOctWeight[q2][q1][q1][1] = 0.0833;
628 baryonDecWeight[q2][q1][q1][1] = 0.6667;
629 for (
int q3 = 0; q3 < 6; q3++)
if ((q1 != q3) && (q2 != q3)) {
630 baryonOctWeight[q1][q2][q3][0] = 0.5;
631 baryonDecWeight[q1][q2][q3][0] = 0.0;
632 baryonOctWeight[q1][q2][q3][1] = 0.1667;
633 baryonDecWeight[q1][q2][q3][1] = 0.3333;
639 double BtoMratio = parm(
"StringFlav:BtoMratio");
640 for (
int q1 = 0; q1 < 6; q1++) {
641 for (
int q2 = 0; q2 < 6; q2++) {
642 for (
int q3 = 0; q3 < 6; q3++) {
644 baryonOctWeight[q1][q2][q3][
spin] *= BtoMratio;
645 baryonDecWeight[q1][q2][q3][
spin] *= BtoMratio;
647 baryonOctWeight[q1][q2][q3][1] *= 3.0;
648 baryonDecWeight[q1][q2][q3][1] *= 3.0;
657 double strSup = parm(
"StringFlav:StrangeSuppression");
658 for (
int iIDin = 0; iIDin < nIncome; iIDin++) {
659 int idIn = incomingIDs[iIDin];
660 int idInAbs = abs(idIn);
661 vector< pair<int,int> > possibleHadronsNow = possibleHadrons[idIn];
662 vector<double> prefactors;
663 for (
int iHad = 0; iHad < int(possibleHadronsNow.size()); iHad++) {
664 double prefacNow = 1.0;
666 int hadronID = possibleHadronsNow[iHad].first;
667 int hadronIDabs = abs(hadronID);
668 int iConst = possibleHadronsNow[iHad].second;
669 int ID1 = hadronConstIDs[hadronID][iConst].first;
670 int ID2 = hadronConstIDs[hadronID][iConst].second;
673 for (
int i = 3; i <= 5; i++) {
674 nHeavy += particleDataPtr->nQuarksInCode( ID1, i);
675 nHeavy += particleDataPtr->nQuarksInCode( ID2, i);
677 prefacNow *= pow(strSup, nHeavy);
678 if (particleDataPtr->isMeson(hadronID)) {
680 prefacNow *= (abs(hadronID) % 10);
682 if ( (idInAbs < 4) && (ID1 == -ID2) ) {
683 int flav = ( (idInAbs < 3) ? 0 : 1 );
685 int spin = getMesonSpinCounter(hadronID);
686 double mesonMix[3] = { mesMixRate1[flav][
spin],
687 mesMixRate2[flav][
spin],
688 mesMixRate3[flav][
spin] };
689 prefacNow *= mesonMix[abs(ID1)-1];
693 bool isOct = ((hadronIDabs % 10) == 2);
695 if (abs(ID2) < abs(ID1)) swap(ID1,ID2);
697 int Q1 = ( (abs(ID2)/1000) % 10 );
698 int Q2 = ( (abs(ID2)/100) % 10 );
699 if (Q1 > 5 || Q2 > 5) {
700 infoPtr->errorMsg(
"Error in StringFlav::init: invalid quark "
701 "content flavours for diquark");
704 int diqSpin = ( ((abs(ID2) % 10) == 1) ? 0 : 1 );
708 if (isOct) prefacNow *= baryonOctWeight[Q1][Q2][Q3][diqSpin];
709 else prefacNow *= baryonDecWeight[Q1][Q2][Q3][diqSpin];
711 if ( isOct && (Q1!=Q2) && (Q1!=Q3) && (Q2!=Q3) ) {
713 int Qhad1 = ( (hadronIDabs/10) % 10 );
714 int Qhad2 = ( (hadronIDabs/100) % 10 );
715 int QhadMin = min(Qhad1,Qhad2);
716 int QhadMax = max(Qhad1,Qhad2);
718 int QdiqMin = min(Q1,Q2);
719 int QdiqMax = max(Q1,Q2);
721 if ( !((QdiqMin == QhadMin) && (QdiqMax == QhadMax)) ) {
723 if (Qhad2 > Qhad1) prefacNow *= ( (diqSpin == 0) ? 0.75 : 0.25 );
725 else prefacNow *= ( (diqSpin == 0) ? 0.25 : 0.27 );
730 prefactors.push_back(prefacNow);
732 possibleRatePrefacs[idIn] = prefactors;
736 for (
int iIDin1 = 0; iIDin1 < nIncome; iIDin1++) {
737 int idIn1 = incomingIDs[iIDin1];
738 int idIn1Abs = abs(idIn1);
740 for (
int iIDin2 = iIDin1+1; iIDin2 < nIncome; iIDin2++) {
741 int idIn2 = incomingIDs[iIDin2];
742 int idIn2Abs = abs(idIn2);
743 int idInNow[2] = { min(idIn1,idIn2), max(idIn1,idIn2) };
744 pair<int,int> inPair = pair<int,int>(idInNow[0], idInNow[1]);
746 if ( (idIn1Abs > 1000) && (idIn2Abs > 1000) )
continue;
748 if ( ( ((idIn1 > 0) && (idIn2 > 0)) || ((idIn1 < 0) && (idIn2 < 0)) )
749 && (idIn1Abs < 10) && (idIn2Abs < 10) )
continue;
752 if ( ((idIn2 > 1000) && (idIn1Abs < 10) && (idIn1 < 0)) ||
753 ((idIn2 < -1000) && (idIn1Abs < 10) && (idIn1 > 0)) )
continue;
756 if ((idIn1Abs < 10) && (idIn2Abs > 1000)) {
757 vector< pair<int,int> > hvyCombs;
759 hvyCombs.push_back(make_pair(4,4));
761 hvyCombs.push_back(make_pair(5,4));
762 hvyCombs.push_back(make_pair(4,5));
763 hvyCombs.push_back(make_pair(5,5));
767 for (
int iComb = 0; iComb < int(hvyCombs.size()); iComb++) {
768 int idNow[2] = { hvyCombs[iComb].first, hvyCombs[iComb].second };
769 if ( (particleDataPtr->nQuarksInCode(idIn2Abs,idNow[0]) > 0) &&
770 (idIn1Abs == idNow[1]) ) skip =
true;
779 if ( (idIn1Abs < 10) && (idIn2Abs < 10) ) {
780 idUse = ( (idIn1Abs > idIn2Abs) ? idIn1 : idIn2 );
783 bool useDiquark =
false;
784 for (
int plus = 1; plus < 5; plus++)
785 if (particleDataPtr->nQuarksInCode(idIn2Abs, idIn1Abs + plus) > 0)
787 idUse = ( useDiquark ? idIn2 : idIn1 );
789 vector<double> possibleRatePrefacsNow = possibleRatePrefacs[idUse];
790 vector< pair<int,int> > possibleHadronsNow = possibleHadrons[idUse];
792 vector< pair<int,int> > possibleHadronsNew;
793 vector<double> possibleRatePrefacsNew;
796 for (
int iHad = 0; iHad < int(possibleHadronsNow.size()); iHad++) {
798 int hadronID = possibleHadronsNow[iHad].first;
799 int iConst = possibleHadronsNow[iHad].second;
800 int ID1 = hadronConstIDs[hadronID][iConst].first;
801 int ID2 = hadronConstIDs[hadronID][iConst].second;
802 if ( ((ID1 == idIn1) && (ID2 == idIn2)) ||
803 ((ID1 == idIn2) && (ID2 == idIn1)) ) {
805 possibleHadronsNew.push_back(possibleHadronsNow[iHad]);
806 possibleRatePrefacsNew.push_back(possibleRatePrefacsNow[iHad]);
809 if (
int(possibleHadronsNew.size()) < 1)
810 infoPtr->errorMsg(
"Error in StringFlav::init: no possible "
811 "hadrons found for last two");
813 possibleRatePrefacsLast[inPair] = possibleRatePrefacsNew;
814 possibleHadronsLast[inPair] = possibleHadronsNew;
822 hadronMassWin = -1.0;
831 FlavContainer StringFlav::pickGauss(FlavContainer& flavOld,
bool allowPop) {
834 FlavContainer flavNew;
835 flavNew.rank = flavOld.rank + 1;
838 int idOld = abs(flavOld.id);
839 if (flavOld.rank == 0 && idOld > 1000 && allowPop) assignPopQ(flavOld);
842 bool doOldBaryon = (idOld > 1000 && flavOld.nPop == 0);
844 bool doPopcornMeson = flavOld.nPop > 0;
846 bool doNewBaryon =
false;
849 if (!doOldBaryon && !doPopcornMeson && probQandQQ * rndmPtr->flat() > 1.) {
851 if ((1. + popFrac) * rndmPtr->flat() > 1.) flavNew.nPop = 1;
855 if (flavOld.rank == 0 && doNewBaryon && suppressLeadingB) {
856 double leadingBSup = (idOld < 4) ? lightLeadingBSup : heavyLeadingBSup;
857 if (rndmPtr->flat() > leadingBSup) {
864 if (!doPopcornMeson && !doNewBaryon) {
865 flavNew.id = pickLightQ();
866 if ( (flavOld.id > 0 && flavOld.id < 9) || flavOld.id < -1000 )
867 flavNew.id = -flavNew.id;
874 int iCase = flavNew.nPop;
875 if (flavOld.nPop == 1) iCase = 2;
879 double sPopWT = dWT[iCase][0];
880 if (iCase == 1) sPopWT *= scbBM[0] * popcornSpair;
881 double rndmFlav = (2. + sPopWT) * rndmPtr->flat();
883 if (rndmFlav > 1.) flavNew.idPop = 2;
884 if (rndmFlav > 2.) flavNew.idPop = 3;
885 }
else flavNew.idPop = flavOld.idPop;
888 double sVtxWT = dWT[iCase][1];
889 if (flavNew.idPop >= 3) sVtxWT = dWT[iCase][2];
890 if (flavNew.idPop > 3) sVtxWT *= 0.5 * (1. + 1./dWT[iCase][4]);
891 double rndmFlav = (2. + sVtxWT) * rndmPtr->flat();
893 if (rndmFlav > 1.) flavNew.idVtx = 2;
894 if (rndmFlav > 2.) flavNew.idVtx = 3;
897 if (flavNew.idPop < 3 && flavNew.idVtx < 3) {
898 flavNew.idVtx = flavNew.idPop;
899 if (rndmPtr->flat() > dWT[iCase][3]) flavNew.idVtx = 3 - flavNew.idPop;
904 if (flavNew.idVtx != flavNew.idPop) {
905 double spinWT = dWT[iCase][6];
906 if (flavNew.idVtx == 3) spinWT = dWT[iCase][5];
907 if (flavNew.idPop >= 3) spinWT = dWT[iCase][4];
908 if ((1. + spinWT) * rndmPtr->flat() < 1.) spin = 1;
912 flavNew.id = 1000 * max(flavNew.idVtx, flavNew.idPop)
913 + 100 * min(flavNew.idVtx, flavNew.idPop) +
spin;
914 if ( (flavOld.id < 0 && flavOld.id > -9) || flavOld.id > 1000 )
915 flavNew.id = -flavNew.id;
928 FlavContainer StringFlav::pickThermal(FlavContainer& flavOld,
929 double pT,
double nNSP) {
932 FlavContainer flavNew;
933 flavNew.rank = flavOld.rank + 1;
935 int idIn = flavOld.id;
936 int idInAbs = abs(idIn);
937 double temprNow = temperature;
940 if (idInAbs > 2) temprNow *= tempPreFactor;
943 temprNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
944 temprNow *= pow(max(1.0,nNSP), exponentNSP);
947 double sigmaNow = sigmaHad;
951 if (abs(idIn) > 10) sigmaNow *= widthPreDiquark;
952 sigmaNow *= pow(widthPreStrange,
953 particleDataPtr->nQuarksInCode(idIn,3) );
958 sigmaNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
959 sigmaNow *= pow(max(1.0,nNSP), exponentNSP);
965 vector<double> possibleRatePrefacsNow = possibleRatePrefacs[idIn];
966 vector< pair<int,int> > possibleHadronsNow = possibleHadrons[idIn];
967 int nPossHads = int(possibleHadronsNow.size());
969 infoPtr->errorMsg(
"Error in StringFlav::pickThermal: no possible "
976 vector<double> possibleHadronMasses;
979 vector<double> rates;
980 double rateSum = 0.0;
981 for (
int iHad = 0; iHad < nPossHads; iHad++) {
982 int hadronID = possibleHadronsNow[iHad].first;
984 double mass = particleDataPtr->mSel(hadronID);
985 possibleHadronMasses.push_back(mass);
986 double rate = exp( -sqrt(pow2(pT)+pow2(mass))/temprNow );
988 if (mT2suppression) rate = exp( -(pow2(pT)+pow2(mass))/pow2(sigmaNow) );
990 rate *= possibleRatePrefacsNow[iHad];
992 rates.push_back(rate);
996 for (
int iHad = 0; iHad < nPossHads; iHad++) rates[iHad] /= rateSum;
999 vector<double> accumRates;
1000 for (
int iHad = 0; iHad < nPossHads; iHad++) accumRates.push_back(0);
1001 for (
int iHad1 = 0; iHad1 < nPossHads; iHad1++)
1002 for (
int iHad2 = 0; iHad2 <= iHad1; iHad2++)
1003 accumRates[iHad1] += rates[iHad2];
1006 double rand = rndmPtr->flat();
1009 double hadronMass = -1.0;
1010 for (
int iHad = 0; iHad < nPossHads; iHad++) {
1011 if (rand <= accumRates[iHad]) {
1012 hadronID = possibleHadronsNow[iHad].first;
1013 iConst = possibleHadronsNow[iHad].second;
1014 hadronMass = possibleHadronMasses[iHad];
1021 vector< pair<int,int> > constituentIDs = hadronConstIDs[hadronID];
1023 if (particleDataPtr->isMeson(hadronID)) {
1024 int ID1 = constituentIDs[0].first;
1025 int ID2 = constituentIDs[0].second;
1027 if (ID1 == -ID2) idNext = idIn;
1028 else idNext = (idIn == ID1 ? -ID2 : -ID1);
1032 int ID1 = constituentIDs[iConst].first;
1033 int ID2 = constituentIDs[iConst].second;
1034 if (ID1 == idIn) idNext = -ID2;
1035 if (ID2 == idIn) idNext = -ID1;
1039 flavNew.id = -idNext;
1040 hadronIDwin = hadronID;
1042 hadronMassWin = hadronMass;
1054 int StringFlav::combine(FlavContainer& flav1, FlavContainer& flav2) {
1057 int id1Abs = abs(flav1.id);
1058 int id2Abs = abs(flav2.id);
1059 int idMax = max(id1Abs, id2Abs);
1060 int idMin = min(id1Abs, id2Abs);
1063 if (idMax < 9 || idMin > 1000) {
1067 id1Abs = flav1.idVtx;
1068 id2Abs = flav2.idVtx;
1069 idMax = max(id1Abs, id2Abs);
1070 idMin = min(id1Abs, id2Abs);
1071 if (idMin == 0)
return 0;
1075 int flav = (idMax < 3) ? 0 : idMax - 2;
1076 double rndmSpin = mesonRateSum[flav] * rndmPtr->flat();
1078 do rndmSpin -= mesonRate[flav][++
spin];
1079 while (rndmSpin > 0.);
1080 int idMeson = 100 * idMax + 10 * idMin + mesonMultipletCode[
spin];
1083 if (idMax != idMin) {
1084 int sign = (idMax%2 == 0) ? 1 : -1;
1085 if ( (idMax == id1Abs && flav1.id < 0)
1086 || (idMax == id2Abs && flav2.id < 0) ) sign = -sign;
1090 }
else if (flav < 2) {
1091 double rMix = rndmPtr->flat();
1092 if (rMix < mesonMix1[flav][spin]) idMeson = 110;
1093 else if (rMix < mesonMix2[flav][spin]) idMeson = 220;
1095 idMeson += mesonMultipletCode[
spin];
1098 if (idMeson == 221 && etaSup < rndmPtr->flat())
return 0;
1099 if (idMeson == 331 && etaPrimeSup < rndmPtr->flat())
return 0;
1107 int idQQ1 = idMax / 1000;
1108 int idQQ2 = (idMax / 100) % 10;
1109 int spinQQ = idMax % 10;
1110 int spinFlav = spinQQ - 1;
1111 if (spinFlav == 2 && idQQ1 != idQQ2) spinFlav = 4;
1112 if (idMin != idQQ1 && idMin != idQQ2) spinFlav++;
1113 if (spinFlav < 0 || spinFlav > 5)
return 0;
1114 if (baryonCGSum[spinFlav] < rndmPtr->flat() * baryonCGMax[spinFlav])
1118 int idOrd1 = max( idMin, max( idQQ1, idQQ2) );
1119 int idOrd3 = min( idMin, min( idQQ1, idQQ2) );
1120 int idOrd2 = idMin + idQQ1 + idQQ2 - idOrd1 - idOrd3;
1121 int spinBar = (baryonCGSum[spinFlav] * rndmPtr->flat()
1122 < baryonCGOct[spinFlav]) ? 2 : 4;
1125 bool LambdaLike =
false;
1126 if (spinBar == 2 && idOrd1 > idOrd2 && idOrd2 > idOrd3) {
1127 LambdaLike = (spinQQ == 1);
1128 if (idOrd1 != idMin && spinQQ == 1) LambdaLike = (rndmPtr->flat() < 0.25);
1129 else if (idOrd1 != idMin) LambdaLike = (rndmPtr->flat() < 0.75);
1133 int idBaryon = (LambdaLike)
1134 ? 1000 * idOrd1 + 100 * idOrd3 + 10 * idOrd2 + spinBar
1135 : 1000 * idOrd1 + 100 * idOrd2 + 10 * idOrd3 + spinBar;
1136 return (flav1.id > 0) ? idBaryon : -idBaryon;
1145 int StringFlav::combineToLightest(
int id1,
int id2) {
1148 int id1Abs = abs(id1);
1149 int id2Abs = abs(id2);
1150 int idMax = max(id1Abs, id2Abs);
1151 int idMin = min(id1Abs, id2Abs);
1155 int idMeson = 100 * idMax + 10 * idMin + 1;
1158 if (idMax != idMin) {
1159 int sign = (idMax%2 == 0) ? 1 : -1;
1160 if ( (idMax == id1Abs && id1 < 0)
1161 || (idMax == id2Abs && id2 < 0) ) sign = -sign;
1166 else if (idMax < 3) idMeson = 111;
1167 else if (idMax == 3) idMeson = 221;
1174 int idQQ1 = idMax / 1000;
1175 int idQQ2 = (idMax / 100) % 10;
1176 int idOrd1 = max( idMin, max( idQQ1, idQQ2) );
1177 int idOrd3 = min( idMin, min( idQQ1, idQQ2) );
1178 int idOrd2 = idMin + idQQ1 + idQQ2 - idOrd1 - idOrd3;
1181 int idBaryon = 1000 * idOrd1 + 100 * idOrd2 + 10 * idOrd3 + 2;
1182 if (idOrd3 == idOrd1) idBaryon += 2;
1183 else if (idOrd2 != idOrd1 && idOrd3 != idOrd2)
1184 idBaryon = 1000 * idOrd1 + 100 * idOrd3 + 10 * idOrd2 + 2;
1187 return (id1 > 0) ? idBaryon : -idBaryon;
1196 int StringFlav::combineLastThermal(FlavContainer& flav1, FlavContainer& flav2,
1197 double pT,
double nNSP) {
1200 int idIn[2] = { flav1.id, flav2.id };
1201 if (rndmPtr->flat() < 0.5) swap(idIn[0], idIn[1]);
1202 int idInNow[2] = { min(idIn[0],idIn[1]), max(idIn[0],idIn[1]) };
1204 int idInAbs = abs(idIn[0]);
1205 double temprNow = temperature;
1208 if (idInAbs > 2) temprNow *= tempPreFactor;
1212 temprNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1213 temprNow *= pow(max(1.0,nNSP), exponentNSP);
1217 double sigmaNow = sigmaHad;
1220 if (abs(idInAbs) > 10) sigmaNow *= widthPreDiquark;
1221 sigmaNow *= pow(widthPreStrange,
1222 particleDataPtr->nQuarksInCode(idInAbs,3) );
1227 sigmaNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1228 sigmaNow *= pow(max(1.0,nNSP), exponentNSP);
1234 pair<int,int> inPr = pair<int,int>(idInNow[0], idInNow[1]);
1235 vector<double> possibleRatePrefacsNow = possibleRatePrefacsLast[inPr];
1236 vector< pair<int,int> > possibleHadronsNow = possibleHadronsLast[inPr];
1237 int nPossHads = int(possibleHadronsNow.size());
1238 if (nPossHads < 1) {
1239 infoPtr->errorMsg(
"Error in StringFlav::combineLastThermal: no "
1240 "possible hadrons found for last two");
1246 vector<double> possibleHadronMasses;
1249 vector<double> rates;
1250 double rateSum = 0.0;
1251 for (
int iHad = 0; iHad < nPossHads; iHad++) {
1252 int hadronID = possibleHadronsNow[iHad].first;
1254 double mass = particleDataPtr->mSel(hadronID);
1255 possibleHadronMasses.push_back(mass);
1256 double rate = exp( -sqrt(pow2(pT)+pow2(mass))/temprNow );
1258 if (mT2suppression) rate = exp( -(pow2(pT)+pow2(mass))/pow2(sigmaNow) );
1260 rate *= possibleRatePrefacsNow[iHad];
1262 rates.push_back(rate);
1266 for (
int iHad = 0; iHad < nPossHads; iHad++) rates[iHad] /= rateSum;
1269 vector<double> accumRates;
1270 for (
int iHad = 0; iHad < nPossHads; iHad++) accumRates.push_back(0);
1271 for (
int iHad1 = 0; iHad1 < nPossHads; iHad1++)
1272 for (
int iHad2 = 0; iHad2 <= iHad1; iHad2++)
1273 accumRates[iHad1] += rates[iHad2];
1276 double rand = rndmPtr->flat();
1278 double hadronMass = -1.0;
1279 for (
int iHad = 0; iHad < nPossHads; iHad++) {
1280 if (rand <= accumRates[iHad]) {
1281 hadronID = possibleHadronsNow[iHad].first;
1282 hadronMass = possibleHadronMasses[iHad];
1288 hadronIDwin = hadronID;
1289 hadronMassWin = hadronMass;
1299 void StringFlav::assignPopQ(FlavContainer& flav) {
1302 int idAbs = abs(flav.id);
1303 if (flav.rank > 0 || idAbs < 1000)
return;
1306 int id1 = (idAbs/1000)%10;
1307 int id2 = (idAbs/100)%10;
1309 if (id1 == 3) pop2WT = scbBM[1];
1310 else if (id1 > 3) pop2WT = scbBM[2];
1311 if (id2 == 3) pop2WT /= scbBM[1];
1312 else if (id2 > 3) pop2WT /= scbBM[2];
1314 flav.idPop = ((1. + pop2WT) * rndmPtr->flat() > 1.) ? id2 : id1;
1315 flav.idVtx = id1 + id2 - flav.idPop;
1319 double popWT = popS[0];
1320 if (id1 == 3) popWT = popS[1];
1321 if (id2 == 3) popWT = popS[2];
1322 if (idAbs%10 == 1) popWT *= sqrt(probQQ1toQQ0);
1323 if ((1. + popWT) * rndmPtr->flat() > 1.) flav.nPop = 1;
1333 int StringFlav::makeDiquark(
int id1,
int id2,
int idHad) {
1336 int idMin = min( abs(id1), abs(id2));
1337 int idMax = max( abs(id1), abs(id2));
1342 if (abs(idHad) == 2212 || abs(idHad) == 2112) {
1343 if (idMin == 1 && idMax == 2 && rndmPtr->flat() < 0.75) spin = 0;
1346 }
else if (idMin != idMax) {
1347 if (rndmPtr->flat() > probQQ1join[min(idMax,5) - 2]) spin = 0;
1351 int idNewAbs = 1000 * idMax + 100 * idMin + 2 * spin + 1;
1352 return (id1 > 0) ? idNewAbs : -idNewAbs;
1366 const double StringZ::CFROMUNITY = 0.01;
1367 const double StringZ::AFROMZERO = 0.02;
1368 const double StringZ::AFROMC = 0.01;
1371 const double StringZ::EXPMAX = 50.;
1377 void StringZ::init() {
1380 mc2 = pow2( particleDataPtr->m0(4));
1381 mb2 = pow2( particleDataPtr->m0(5));
1384 aLund = parm(
"StringZ:aLund");
1385 bLund = parm(
"StringZ:bLund");
1386 aExtraSQuark = parm(
"StringZ:aExtraSQuark");
1387 aExtraDiquark = parm(
"StringZ:aExtraDiquark");
1388 rFactC = parm(
"StringZ:rFactC");
1389 rFactB = parm(
"StringZ:rFactB");
1390 rFactH = parm(
"StringZ:rFactH");
1393 if (flag(
"StringZ:deriveBLund")) {
1394 if (!deriveBLund()) {
1395 infoPtr->errorMsg(
"Error in StringZ::init: Derivation of b parameter "
1396 " failed. Reverting to default.");
1397 settingsPtr->resetParm(
"StringZ:bLund");
1402 useNonStandC = flag(
"StringZ:useNonstandardC");
1403 useNonStandB = flag(
"StringZ:useNonstandardB");
1404 useNonStandH = flag(
"StringZ:useNonstandardH");
1405 aNonC = parm(
"StringZ:aNonstandardC");
1406 aNonB = parm(
"StringZ:aNonstandardB");
1407 aNonH = parm(
"StringZ:aNonstandardH");
1408 bNonC = parm(
"StringZ:bNonstandardC");
1409 bNonB = parm(
"StringZ:bNonstandardB");
1410 bNonH = parm(
"StringZ:bNonstandardH");
1413 usePetersonC = flag(
"StringZ:usePetersonC");
1414 usePetersonB = flag(
"StringZ:usePetersonB");
1415 usePetersonH = flag(
"StringZ:usePetersonH");
1416 epsilonC = parm(
"StringZ:epsilonC");
1417 epsilonB = parm(
"StringZ:epsilonB");
1418 epsilonH = parm(
"StringZ:epsilonH");
1421 stopM = parm(
"StringFragmentation:stopMass");
1422 stopNF = parm(
"StringFragmentation:stopNewFlav");
1423 stopS = parm(
"StringFragmentation:stopSmear");
1432 bool StringZ::deriveBLund() {
1435 double mRef = particleDataPtr->m0(113);
1436 double mT2ref = pow2(mRef) + 2.*pow2(parm(
"stringPT:sigma"));
1437 double avgZ = parm(
"StringZ:avgZLund");
1438 double a = parm(
"StringZ:aLund");
1441 auto lundFF = [=](
double b) {
return LundFFAvg(a, b, 1., mT2ref, 1.e-6); };
1445 bool check = brent(bNow, lundFF, avgZ, 0.01, 20.0, 1.e-6);
1449 settingsPtr->parm(
"StringZ:bLund", bNow,
false);
1453 msg << fixed << setprecision(2) <<
"\n <z(rho)> = " << setw(5)
1454 << avgZ <<
" for aLund = "<< a <<
" & mT2ref = " << setw(5) << mT2ref
1455 <<
" GeV^2 gave bLund = " << setw(5) << bNow <<
" GeV^-2:";
1456 if ( bNow == parm(
"StringZ:bLund") ) {
1457 if (!settingsPtr->parm(
"Print:quiet"))
1458 cout << msg.str() <<
" accepted" << endl;
1462 msg <<
" accepted (forced)";
1463 infoPtr->errorMsg(
"Warning in StringZ::deriveBLund", msg.str());
1464 settingsPtr->parm(
"StringZ:bLund", bNow,
true);
1468 settingsPtr->flag(
"StringZ:deriveBLund",
false);
1479 double StringZ::zFrag(
int idOld,
int idNew,
double mT2) {
1482 int idOldAbs = abs(idOld);
1483 int idNewAbs = abs(idNew);
1484 bool isOldSQuark = (idOldAbs == 3);
1485 bool isNewSQuark = (idNewAbs == 3);
1486 bool isOldDiquark = (idOldAbs > 1000 && idOldAbs < 10000);
1487 bool isNewDiquark = (idNewAbs > 1000 && idNewAbs < 10000);
1490 int idFrag = idOldAbs;
1491 if (isOldDiquark) idFrag = max( idOldAbs / 1000, (idOldAbs / 100) % 10);
1494 if (idFrag == 4 && usePetersonC)
return zPeterson( epsilonC);
1495 if (idFrag == 5 && usePetersonB)
return zPeterson( epsilonB);
1496 if (idFrag > 5 && usePetersonH) {
1497 double epsilon = epsilonH * mb2 / mT2;
1498 return zPeterson( epsilon);
1502 double aNow = aLund;
1503 double bNow = bLund;
1504 if (idFrag == 4 && useNonStandC) {
1507 }
else if (idFrag == 5 && useNonStandB) {
1510 }
else if (idFrag > 5 && useNonStandH) {
1516 double aShape = aNow;
1517 if (isOldSQuark) aShape += aExtraSQuark;
1518 if (isOldDiquark) aShape += aExtraDiquark;
1519 double bShape = bNow * mT2;
1521 if (isOldSQuark) cShape -= aExtraSQuark;
1522 if (isNewSQuark) cShape += aExtraSQuark;
1523 if (isOldDiquark) cShape -= aExtraDiquark;
1524 if (isNewDiquark) cShape += aExtraDiquark;
1525 if (idFrag == 4) cShape += rFactC * bNow * mc2;
1526 if (idFrag == 5) cShape += rFactB * bNow * mb2;
1527 if (idFrag > 5) cShape += rFactH * bNow * mT2;
1528 return zLund( aShape, bShape, cShape);
1540 double StringZ::zLund(
double a,
double b,
double c) {
1543 bool cIsUnity = (abs( c - 1.) < CFROMUNITY);
1544 bool aIsZero = (a < AFROMZERO);
1545 bool aIsC = (abs(a - c) < AFROMC);
1549 if (aIsZero) zMax = (c > b) ? b / c : 1.;
1550 else if (aIsC) zMax = b / (b + c);
1551 else { zMax = 0.5 * (b + c - sqrt( pow2(b - c) + 4. * a * b)) / (c - a);
1552 if (zMax > 0.9999 && b > 100.) zMax = min(zMax, 1. - a / b); }
1555 bool peakedNearZero = (zMax < 0.1);
1556 bool peakedNearUnity = (zMax > 0.85 && b > 1.);
1560 double fIntLow = 1.;
1561 double fIntHigh = 1.;
1568 if (peakedNearZero) {
1571 if (cIsUnity) fIntHigh = -zDiv * log(zDiv);
1572 else { zDivC = pow( zDiv, 1. - c);
1573 fIntHigh = zDiv * (1. - 1./zDivC) / (c - 1.);}
1574 fInt = fIntLow + fIntHigh;
1579 }
else if (peakedNearUnity) {
1580 double rcb = sqrt(4. + pow2(c / b));
1581 zDiv = rcb - 1./zMax - (c / b) * log( zMax * 0.5 * (rcb + c / b) );
1582 if (!aIsZero) zDiv += (a/b) * log(1. - zMax);
1583 zDiv = min( zMax, max(0., zDiv));
1585 fIntHigh = 1. - zDiv;
1586 fInt = fIntLow + fIntHigh;
1596 z = rndmPtr->flat();
1599 if (peakedNearZero) {
1600 if (fInt * rndmPtr->flat() < fIntLow) z = zDiv * z;
1601 else if (cIsUnity) {z = pow( zDiv, z); fPrel = zDiv / z;}
1602 else { z = pow( zDivC + (1. - zDivC) * z, 1. / (1. - c) );
1603 fPrel = pow( zDiv / z, c); }
1606 }
else if (peakedNearUnity) {
1607 if (fInt * rndmPtr->flat() < fIntLow) {
1608 z = zDiv + log(z) / b;
1609 fPrel = exp( b * (z - zDiv) );
1610 }
else z = zDiv + (1. - zDiv) * z;
1614 if (z > 0 && z < 1) {
1615 double fExp = b * (1. / zMax - 1. / z)+ c * log(zMax / z);
1616 if (!aIsZero) fExp += a * log( (1. - z) / (1. - zMax) );
1617 fVal = exp( max( -EXPMAX, min( EXPMAX, fExp) ) ) ;
1619 }
while (fVal < rndmPtr->flat() * fPrel);
1632 double StringZ::zPeterson(
double epsilon) {
1638 if (epsilon > 0.01) {
1640 z = rndmPtr->flat();
1641 fVal = 4. * epsilon * z * pow2(1. - z)
1642 / pow2( pow2(1. - z) + epsilon * z);
1643 }
while (fVal < rndmPtr->flat());
1650 double epsRoot = sqrt(epsilon);
1651 double epsComb = 0.5 / epsRoot - 1.;
1652 double fIntLow = 4. * epsilon * epsComb;
1653 double fInt = fIntLow + 2. * epsRoot;
1655 if (rndmPtr->flat() * fInt < fIntLow) {
1656 z = 1. - 1. / (1. + rndmPtr->flat() * epsComb);
1657 fVal = z * pow2( pow2(1. - z) / (pow2(1. - z) + epsilon * z) );
1659 z = 1. - 2. * epsRoot * rndmPtr->flat();
1660 fVal = 4. * epsilon * z * pow2(1. - z)
1661 / pow2( pow2(1. - z) + epsilon * z);
1663 }
while (fVal < rndmPtr->flat());
1678 const double StringPT::SIGMAMIN = 0.2;
1684 void StringPT::init() {
1687 double sigma = parm(
"StringPT:sigma");
1688 sigmaQ = sigma / sqrt(2.);
1689 enhancedFraction = parm(
"StringPT:enhancedFraction");
1690 enhancedWidth = parm(
"StringPT:enhancedWidth");
1691 widthPreStrange = parm(
"StringPT:widthPreStrange");
1692 widthPreDiquark = parm(
"StringPT:widthPreDiquark");
1693 useWidthPre = (widthPreStrange > 1.0) || (widthPreDiquark > 1.0);
1696 thermalModel = flag(
"StringPT:thermalModel");
1697 temperature = parm(
"StringPT:temperature");
1698 tempPreFactor = parm(
"StringPT:tempPreFactor");
1701 fracSmallX = 0.6 / (0.6 + (1.2/0.9) * exp(-0.9));
1704 closePacking = flag(
"StringPT:closePacking");
1705 exponentMPI = parm(
"StringPT:expMPI");
1706 exponentNSP = parm(
"StringPT:expNSP");
1709 sigma2Had = 2. * pow2( max( SIGMAMIN, sigma) );
1718 pair<double, double> StringPT::pxyThermal(
int idIn,
double nNSP) {
1720 double temprNow = temperature;
1723 if (abs(idIn) > 2) temprNow *= tempPreFactor;
1727 temprNow *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1728 temprNow *= pow(max(1.0,nNSP), exponentNSP);
1732 double xrand, approx, wanted;
1734 xrand = (rndmPtr->flat() < fracSmallX) ? rndmPtr->flat()
1735 : 1. - log(rndmPtr->flat()) / 0.9;
1736 approx = (xrand < 1.) ? 0.6 : 1.2 * exp(-0.9 * xrand);
1737 wanted = BesselK14(xrand) * pow( xrand, 0.75);
1738 }
while (rndmPtr->flat() * approx > wanted);
1741 double pTquark = xrand * temprNow;
1742 double phi = 2.0 * M_PI * rndmPtr->flat();
1745 return pair<double, double>( pTquark * cos(phi), pTquark * sin(phi) );
1754 pair<double, double> StringPT::pxyGauss(
int idIn,
double nNSP) {
1757 double sigma = sigmaQ;
1758 if (rndmPtr->flat() < enhancedFraction) sigma *= enhancedWidth;
1762 if (abs(idIn) > 10) sigma *= widthPreDiquark;
1763 sigma *= pow(widthPreStrange, particleDataPtr->nQuarksInCode(idIn, 3) );
1768 sigma *= pow(max(1.0,
double(infoPtr->nMPI())), exponentMPI);
1769 sigma *= pow(max(1.0,nNSP), exponentNSP);
1773 pair<double, double> gauss2 = rndmPtr->gauss2();
1774 return pair<double, double>(sigma * gauss2.first, sigma * gauss2.second);
1785 double StringPT::BesselK14(
double x) {
1789 double xRat = 0.25 * x * x;
1790 double prodP = pow( 0.5 * x, -0.25) / 1.2254167024;
1791 double prodN = pow( 0.5 * x, 0.25) / 0.9064024771;
1792 double sum = prodP - prodN;
1795 for (
int k = 1; k < 6; ++k) {
1796 prodP *= xRat / (k * (k - 0.25));
1797 prodN *= xRat / (k * (k + 0.25));
1798 sum += prodP - prodN;
1800 sum *= M_PI * sqrt(0.5);
1805 double asym = sqrt(M_PI * 0.5 / x) * exp(-x);
1806 double term1 = - 0.75 / ( 8. * x);
1807 double term2 = -term1 * 8.75 / (16. * x);
1808 double term3 = -term2 * 24.75 / (24. * x);
1809 double term4 = -term3 * 48.75 / (32. * x);
1810 asym *= 1. + term1 + term2 + term3 + term4;