9 #include "Pythia8/DeuteronProduction.h"
23 const int DeuteronProduction::NTRYDECAY = 10;
27 const double DeuteronProduction::WTCORRECTION[11] = { 1., 1., 1.,
28 2., 5., 15., 60., 250., 1250., 7000., 50000. };
34 bool DeuteronProduction::init() {
37 valid =
true; ids.clear(); parms.clear(); masses.clear();
38 models = settingsPtr->mvec(
"DeuteronProduction:models");
40 for (
string channelTmp : settingsPtr->wvec(
"DeuteronProduction:channels"))
41 ids.push_back(parseIds(channelTmp));
43 for (
string parmTmp : settingsPtr->wvec(
"DeuteronProduction:parms"))
44 parms.push_back(parseParms(parmTmp));
47 bool verbose(flag(
"Init:showProcesses"));
48 mSafety = parm(
"ParticleDecays:mSafety");
49 kMin = parm(
"DeuteronProduction:kMin");
50 kMax = parm(
"DeuteronProduction:kMax");
51 kTol = parm(
"DeuteronProduction:kTol");
52 kSteps = mode(
"DeuteronProduction:kSteps");
55 string pre(
"Error in DeuteronProduction::init: ");
56 if (parms.size() != ids.size() || parms.size() != models.size()) {
58 vals <<
" " << ids.size() <<
", " << models.size() <<
", " << parms.size();
59 infoPtr->errorMsg(pre +
"channels, models, and parms are size",
65 for (
int chn = 0; chn < int(parms.size()); ++chn) {
68 if (ids[chn].size() < 3) {
69 infoPtr->errorMsg(pre +
"ids must have 3 or more IDs");
71 }
else if (ids[chn][2] != 0) {
72 infoPtr->errorMsg(pre +
"ids initial state must be size 2");
77 if (models[chn] == 0 && parms[chn].size() != 2) {
78 infoPtr->errorMsg(pre +
"model 0 channels must have",
81 }
else if (models[chn] == 1 && parms[chn].size() != 15) {
82 infoPtr->errorMsg(pre +
"model 1 channels must have",
85 }
else if (models[chn] == 2 && parms[chn].size() != 5) {
86 infoPtr->errorMsg(pre +
"model 2 channels must have",
89 }
else if (models[chn] == 3 && parms[chn].size()%5 != 0) {
90 infoPtr->errorMsg(pre +
"model 3 channels must have",
91 "a multiple of 5 coefficients");
95 if (!valid)
return valid;
96 mPion = particleDataPtr->m0(211);
100 cout <<
"\n *---------- PYTHIA Deuteron Production "
101 <<
"Initialization -----------*\n"
102 <<
" |" << setw(68) <<
"| | |\n"
103 <<
" | Subprocess" << setw(57) <<
"| k (GeV) | Max (mb) |\n"
104 <<
" |" << setw(68) <<
"| | |\n"
105 <<
" |--------------------------------------------------------------"
107 <<
" |" << setw(68) <<
"| | |\n";
109 for (
int chn = 0; chn < int(ids.size()); ++chn) {
112 if (ids[chn][1] == 2212) swap(ids[chn][1], ids[chn][0]);
113 ids[chn].push_back(1000010020);
116 vector<double> mass(ids[chn].size(), 0);
117 for (
int id = 0;
id < int(ids[chn].size()); ++id)
118 mass[
id] = particleDataPtr->m0(ids[chn][
id]);
119 masses.push_back(mass);
125 for (
int id = 0;
id < 2; ++id)
126 proc +=
" " + particleDataPtr->name(ids[chn][
id]);
128 for (
int id = 3;
id < int(ids[chn].size()); ++id)
129 proc +=
" " + particleDataPtr->name(ids[chn][
id]);
130 cout << left << setw(43) << proc;
131 cout <<
" | " << scientific << setprecision(3) << k
132 <<
" | " << scientific << setprecision(3) << s <<
" |\n";
134 if (s > max) max = s;
138 norm = parm(
"DeuteronProduction:norm");
139 if (norm < 1) norm = max;
142 cout <<
" |" << right << setw(68) <<
" |\n"
143 <<
" | Using a maximum of " << norm <<
" mb" << setw(36) <<
"|\n"
144 <<
" |" << right << setw(68) <<
" |\n"
145 <<
" *---------- End PYTHIA Deuteron Production "
146 <<
"Initializaiton -------*\n";
157 bool DeuteronProduction::combine(
Event& event) {
160 if (!valid)
return false;
161 vector<int> nucs, anucs;
162 for (
int idx = 0; idx <
event.size(); ++idx) {
163 Particle &prt =
event[idx];
164 if (prt.statusAbs() > 80 && (prt.idAbs() == 2212 || prt.idAbs() == 2112)
165 && prt.iBotCopy() == idx) {
166 if (prt.id() > 0) nucs.push_back(idx);
167 else anucs.push_back(idx);
182 void DeuteronProduction::bind(
Event& event, vector<int>& prts) {
185 vector<pair<int, int> > cmbs;
186 combos(event, prts, cmbs);
187 vector<double> sigmas(ids.size(), 0);
190 for (
int cmb = 0; cmb < int(cmbs.size()); ++ cmb) {
193 Particle &prt0 =
event[cmbs[cmb].first];
194 Particle &prt1 =
event[cmbs[cmb].second];
195 if (prt0.status() < 0 || prt1.status() < 0)
continue;
198 Vec4 p0(prt0.p()), p1(prt1.p()), p(p0 + p1);
201 double k((p0 - p1).pAbs());
205 for (
int chn = 0; chn < int(ids.size()); ++chn) {
206 if (prt0.idAbs() == ids[chn][0] && prt1.idAbs() == ids[chn][1])
207 sigmas[chn] = sigma(k, chn);
208 else {sigmas[chn] = 0;
continue;}
209 if (sigmas[chn] > norm)
210 infoPtr->errorMsg(
"Warning in DeuteronProduction::bind:",
211 "maximum weight exceeded");
212 if (rndmPtr->flat() >= sigmas[chn]/norm) sigmas[chn] = 0;
217 if (sum == 0)
continue;
218 double rndm(sum*rndmPtr->flat());
int chn(-1);
219 do rndm -= sigmas[++chn];
220 while (rndm > 0. && chn <
int(sigmas.size()));
223 decay(event, prt0.index(), prt1.index(), chn);
232 void DeuteronProduction::combos(
Event& event, vector<int>& prts,
233 vector<pair<int, int> >& cmbs) {
236 for (
int idx0 = 0; idx0 < int(prts.size()); ++idx0) {
237 int prt0(prts[idx0]), id(event[prt0].idAbs() == 2112);
238 for (
int idx1 = idx0 + 1; idx1 < int(prts.size()); ++idx1) {
239 int prt1(prts[idx1]);
240 cmbs.push_back(make_pair(
id ? prt1 : prt0,
id ? prt0 : prt1));
245 for (
int idx =
int(cmbs.size()) - 1; idx > 0; --idx)
246 swap(cmbs[idx], cmbs[rndmPtr->flat()*(idx + 1)]);
253 double DeuteronProduction::fit(
double k, vector<double>& c,
int i) {
255 return c[i] * pow(k, c[i + 1])
256 / (pow((c[i + 2] - exp(c[i + 3]*k)),2) + c[i + 4]);
264 double DeuteronProduction::sigma(
double k,
int chn) {
267 int model(models[chn]);
268 vector<double> &c = parms[chn];
269 vector<double> &m = masses[chn];
272 double ecm(sqrt(m[0]*m[0] + k*k/4) + sqrt(m[1]*m[1] + k*k/4)), mtot(0);
273 for (
int dtr = 3; dtr < int(m.size()); ++dtr) mtot += m[dtr];
278 }
else if (model == 0) {
279 sum = k < c[0] ? c[1] : 0;
282 }
else if (model == 1) {
283 if (k < c[0]) {
for (
int i = 1; i < 13; ++i) sum += c[i]*pow(k, i - 2);}
284 else sum = exp(-c[13]*k - c[14]*k*k);
287 }
else if (model == 2) {
288 double s(ecm*ecm), q(sqrtpos(pow(s + m[3]*m[3] - m.back()*m.back(), 2)
289 /(4*s) - m[3]*m[3]));
290 sum = fit(q/mPion, c, 0);
293 }
else if (model == 3) {
294 for (
int i = 0; i < int(c.size()); i += 5) sum += fit(k, c, i);
306 bool DeuteronProduction::decay(
Event& event,
int idx0,
int idx1,
int chn) {
309 if (idx0 < idx1) swap(idx0, idx1);
310 int mult(ids[chn].size() - 3);
311 vector<double> mProd(mult + 1), mInv(mult + 1, 0);
312 Vec4 pMom(event[idx0].p() + event[idx1].p());
313 mProd[0] = pMom.mCalc();
317 for (
int tries = 0; tries < NTRYDECAY && mDiff < mSafety; ++tries) {
319 for (
int i = 1; i <= mult; ++i) {
320 mProd[i] = particleDataPtr->mSel(ids[chn][i + 2]);
324 if (mDiff < mSafety) {
325 infoPtr->errorMsg(
"Warning in DeuteronProduction::decay:",
326 "no valid decay found");
331 vector<int> iProd(mult + 1);
332 for (
int i = 1; i <= mult; ++i) {
333 int id(ids[chn][i + 2]);
334 if (event[idx0].
id() < 0 && particleDataPtr->hasAnti(
id))
id *= -1;
335 iProd[i] =
event.append(
id, 121, idx0, idx1, 0, 0, 0, 0,
336 Vec4(0., 0., 0., 0.), mProd[i], 0);
338 for (
int i = 0; i <= mult; ++i) mInv[i] = mProd[i];
339 vector<double> rndmOrd(mult, 0);
340 vector<Vec4> pInv(mult + 1, 0);
343 double wtPS, wtME, wtMEmax;
344 double wtPSmax = 1. / WTCORRECTION[mult];
345 double mMax = mDiff + mProd[mult];
347 for (
int i = mult - 1; i > 0; --i) {
350 double mNow = mProd[i];
351 wtPSmax *= 0.5 * sqrtpos( (mMax - mMin - mNow) * (mMax + mMin + mNow)
352 * (mMax + mMin - mNow) * (mMax - mMin + mNow) ) / mMax;
366 for (
int i = 1; i < mult - 1; ++i) {
367 double rndm = rndmPtr->flat();
369 for (
int j = i - 1; j > 0; --j) {
370 if (rndm > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
374 rndmOrd[mult -1] = 0.;
377 for (
int i = mult - 1; i > 0; --i) {
378 mInv[i] = mInv[i+1] + mProd[i] + (rndmOrd[i-1] - rndmOrd[i]) * mDiff;
379 wtPS *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
380 * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
381 * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
385 }
while ( wtPS < rndmPtr->flat() * wtPSmax );
388 for (
int i = 1; i < mult; ++i) {
390 pair<Vec4, Vec4> ps = rndmPtr->phaseSpace2(mInv[i], mInv[i+1], mProd[i]);
391 pInv[i+1].p(ps.first);
392 event[iProd[i]].p(ps.second);
396 event[iProd[mult]].p( pInv[mult] );
397 for (
int iFrame = mult - 1; iFrame > 1; --iFrame)
398 for (
int i = iFrame; i <= mult; ++i)
399 event[iProd[i]].bst( pInv[iFrame], mInv[iFrame]);
402 }
while ( wtME < rndmPtr->flat() * wtMEmax );
405 for (
int i = 1; i <= mult; ++i) event[iProd[i]].bst( pMom, mInv[1] );
406 event[idx0].statusNeg();
407 event[idx1].statusNeg();
408 event[idx0].daughter1(iProd[1]);
event[idx0].daughter2(iProd.back());
409 event[idx1].daughter1(iProd[1]);
event[idx1].daughter2(iProd.back());
418 void DeuteronProduction::maximum(
double& k,
double& s,
int chn) {
421 double y, xa(kMin), xb(kMax), xstep((xb - xa)/(kSteps + 1)), xm(xa), ym(0);
422 for (
double x = xa; x <= xb; x += xstep) {
424 if (y > ym) {xm = x; ym = y;}
428 vector<double> xs(5, xm);
int im(2);
429 xs[0] = xm == xa ? xa : xm - xstep;
430 xs[4] = xm == xb ? xb : xm + xstep;
431 for (
int itr = 0; itr < 1000 && abs((xs[0] - xs[4])/xs[2]) > kTol; ++itr) {
432 xs[2] = (xs[0] + xs[4])/2;
433 xs[1] = (xs[0] + xs[2])/2;
434 xs[3] = (xs[2] + xs[4])/2;
436 for (
int i = 0; i < int(xs.size()); ++i) {
437 y = sigma(xs[i], chn);
438 if (y > ym) {im = i; ym = y;}
440 if (im < 2) xs[4] = xs[2];
441 else if (im > 2) xs[0] = xs[2];
442 else {xs[0] = xs[1]; xs[4] = xs[3];}
452 vector<int> DeuteronProduction::parseIds(
string line) {
455 if (line ==
"")
return vals;
458 while (pos != string::npos) {
459 pos = line.find(
" ");
460 if (pos == 0) {line = line.substr(pos + 1);
continue;}
461 istringstream stream(line.substr(0, pos));
462 line = line.substr(pos + 1);
474 vector<double> DeuteronProduction::parseParms(
string line) {
477 if (line ==
"")
return vals;
480 while (pos != string::npos) {
481 pos = line.find(
" ");
482 if (pos == 0) {line = line.substr(pos + 1);
continue;}
483 istringstream stream(line.substr(0, pos));
484 line = line.substr(pos + 1);