File indexing completed on 2025-09-15 09:06:57
0001
0002
0003
0004
0005
0006
0007 #ifndef Pythia8_PythiaCascade_H
0008 #define Pythia8_PythiaCascade_H
0009
0010 #include "Pythia8/Pythia.h"
0011
0012 namespace Pythia8 {
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 class PythiaCascade {
0062
0063 public:
0064
0065
0066 PythiaCascade() = default;
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 bool init(double eMaxIn = 1e9, bool listFinalIn = false,
0096 bool rapidDecaysIn = false, double smallTau0In = 1e-10,
0097 int reuseMPI = 3, string initFile = "pythiaCascade.mpi") {
0098
0099
0100 eMax = eMaxIn;
0101 listFinal = listFinalIn;
0102 rapidDecays = rapidDecaysIn;
0103 smallTau0 = smallTau0In;
0104
0105
0106 mp = pythiaMain.particleData.m0(2212);
0107
0108
0109
0110 pythiaMain.readString("ProcessLevel:all = off");
0111 pythiaMain.readString("13:mayDecay = on");
0112 pythiaMain.readString("211:mayDecay = on");
0113 pythiaMain.readString("321:mayDecay = on");
0114 pythiaMain.readString("130:mayDecay = on");
0115 pythiaMain.settings.flag("ParticleDecays:limitTau0", rapidDecays);
0116 pythiaMain.settings.parm("ParticleDecays:tau0Max", smallTau0);
0117
0118
0119 pythiaMain.readString("Stat:showProcessLevel = off");
0120 pythiaMain.readString("Stat:showPartonLevel = off");
0121
0122
0123 if (!pythiaMain.init()) return false;
0124
0125 if ( reuseMPI < 0 ) {
0126 pythiaColl.readFile(initFile);
0127 initFile = "";
0128 }
0129
0130
0131
0132 pythiaColl.readString("Beams:allowVariableEnergy = on");
0133 pythiaColl.readString("Beams:allowIDAswitch = on");
0134
0135
0136 pythiaColl.readString("Beams:frameType = 3");
0137 pythiaColl.settings.parm("Beams:pzA", eMax);
0138 pythiaColl.readString("Beams:pzB = 0.");
0139
0140
0141 pythiaColl.readString("SoftQCD:all = on");
0142 pythiaColl.readString("LowEnergyQCD:all = on");
0143
0144
0145
0146 pythiaColl.readString("13:mayDecay = on");
0147 pythiaColl.readString("211:mayDecay = on");
0148 pythiaColl.readString("321:mayDecay = on");
0149 pythiaColl.readString("130:mayDecay = on");
0150
0151
0152 pythiaColl.readString("HadronLevel:Decay = off");
0153
0154
0155
0156 pythiaColl.readString("Print:quiet = on");
0157 pythiaColl.readString("Check:epTolErr = 0.01");
0158 pythiaColl.readString("Check:epTolWarn = 0.0001");
0159 pythiaColl.readString("Check:mTolErr = 0.01");
0160
0161
0162 pythiaColl.readString("Stat:showProcessLevel = off");
0163 pythiaColl.readString("Stat:showPartonLevel = off");
0164
0165
0166 if (reuseMPI > 0)
0167 pythiaColl.readString("MultipartonInteractions:reuseInit = 3");
0168 else if (reuseMPI == 0)
0169 pythiaColl.readString("MultipartonInteractions:reuseInit = 1");
0170 if (reuseMPI >= 0)
0171 pythiaColl.settings.word("MultipartonInteractions:initFile", initFile);
0172
0173
0174 if (!pythiaColl.init()) return false;
0175 return true;
0176
0177 }
0178
0179
0180
0181
0182
0183
0184
0185 double nCollAvg(int A) {
0186 for (int i = 0; i < nA; ++i) {
0187 if (A == tabA[i]) {
0188 return (sigmaNow < tabBorder) ? 1. + tabSlopeLo[i] * sigmaNow
0189 : 1. + tabOffset[i] + tabSlope[i] * sigmaNow;
0190 } else if (A < tabA[i]) {
0191 double nColl1 = (sigmaNow < tabBorder) ? tabSlopeLo[i - 1] * sigmaNow
0192 : tabOffset[i - 1] + tabSlope[i - 1] * sigmaNow;
0193 double nColl2 = (sigmaNow < tabBorder) ? tabSlopeLo[i] * sigmaNow
0194 : tabOffset[i] + tabSlope[i] * sigmaNow;
0195 double wt1 = (tabA[i] - A) / (tabA[i] - tabA[i - 1]);
0196 return 1. + wt1 * pow( A / tabA[i - 1], 2./3.) * nColl1
0197 + (1. - wt1) * pow( A / tabA[i], 2./3.) * nColl2;
0198 }
0199 }
0200
0201 return numeric_limits<double>::quiet_NaN();
0202 }
0203
0204
0205
0206
0207
0208
0209 bool sigmaSetuphN(int idNowIn, Vec4 pNowIn, double mNowIn) {
0210
0211
0212 if (pNowIn.e() - mNowIn < eKinMin) return false;
0213
0214
0215 if (pNowIn.e() > eMax) {
0216 logger.ERROR_MSG("too high energy");
0217 return false;
0218 }
0219
0220
0221 idNow = idNowIn;
0222 pNow = pNowIn;
0223 mNow = mNowIn;
0224
0225
0226
0227 eCMNow = (pNow + Vec4(0, 0, 0, mp)).mCalc();
0228 sigmaNow = pythiaColl.getSigmaTotal(idNow, 2212, eCMNow, mNow, mp);
0229 if (sigmaNow <= 0.) {
0230 if (eCMNow - mNow - mp > eKinMin)
0231 logger.ERROR_MSG("vanishing cross section");
0232 return false;
0233 }
0234
0235
0236 return true;
0237
0238 }
0239
0240
0241
0242
0243
0244
0245
0246 double sigmahA(int A) {
0247
0248
0249 if (A < 1 || A > 208) {
0250 logger.ERROR_MSG("A is outside of valid range (1 <= A <= 208)");
0251 return 0.;
0252 }
0253
0254
0255
0256 double sigmahA = A * sigmaNow / nCollAvg(A);
0257
0258
0259 return sigmahA;
0260
0261 }
0262
0263
0264
0265
0266
0267
0268 Event& nextColl(int Znow, int Anow, Vec4 vNow = Vec4() ) {
0269
0270
0271 Event& eventMain = pythiaMain.event;
0272 Event& eventColl = pythiaColl.event;
0273 eventMain.clear();
0274
0275
0276 if (Anow < 1 || Anow > 208) {
0277 logger.ERROR_MSG("A is outside of valid range (1 <= A <= 208)");
0278 return eventMain;
0279 }
0280
0281
0282 eventMain.append(90, -11, 0, 0, 1, 1, 0, 0, pNow, mNow);
0283 int iHad = eventMain.append(idNow, 12, 0, 0, 0, 0, 0, 0, pNow, mNow);
0284 eventMain[iHad].vProd(vNow);
0285
0286
0287 int np = Znow;
0288 int nn = Anow - Znow;
0289 int sizeOld = 0;
0290 int sizeNew = 0;
0291 Vec4 dirNow = pNow / pNow.pAbs();
0292 Rndm& rndm = pythiaMain.rndm;
0293
0294
0295 double probMore = 1. - 1. / nCollAvg(Anow);
0296
0297
0298 for (int iColl = 1; iColl <= Anow; ++iColl) {
0299 if (iColl > 1 && rndm.flat() > probMore) break;
0300
0301
0302 int iProj = iHad;
0303 int procType = 0;
0304
0305
0306 if (iColl > 1) {
0307 iProj = 0;
0308 double pMax = 0.;
0309 for (int i = sizeOld; i < sizeNew; ++i)
0310 if ( eventMain[i].isFinal() && eventMain[i].isHadron()) {
0311 double pp = dot3(dirNow, eventMain[i].p());
0312 if (pp > pMax) {
0313 iProj = i;
0314 pMax = pp;
0315 }
0316 }
0317
0318
0319 if ( iProj == 0 || eventMain[iProj].e() - eventMain[iProj].m()
0320 < eKinMin) break;
0321
0322
0323 double eCMSub = (eventMain[iProj].p() + Vec4(0, 0, 0, mp)).mCalc();
0324 if (eCMSub > 10.) procType = (rndm.flat() < probSD) ? 4 : 1;
0325 }
0326
0327
0328 int idProj = eventMain[iProj].id();
0329 bool doProton = rndm.flat() < (np / double(np + nn));
0330 if (doProton) np -= 1;
0331 else nn -= 1;
0332 int idNuc = (doProton) ? 2212 : 2112;
0333
0334
0335 pythiaColl.setBeamIDs(idProj, idNuc);
0336 pythiaColl.setKinematics(eventMain[iProj].p(), Vec4());
0337 if (!pythiaColl.next(procType)) {
0338 eventMain.clear();
0339 return eventMain;
0340 }
0341
0342
0343
0344 int statusNuc = (iColl == 1) ? -181 : -182;
0345 int iNuc = eventMain.append( idNuc, statusNuc, 0, iProj, 0, 0, 0, 0,
0346 0., 0., 0., mp, mp);
0347 eventMain[iNuc].vProdAdd(vNow);
0348
0349
0350 eventMain[0].e( eventMain[0].e() + mp);
0351 eventMain[0].m( eventMain[0].p().mCalc() );
0352
0353
0354
0355 sizeOld = eventMain.size();
0356 for (int iSub = 3; iSub < eventColl.size(); ++iSub) {
0357 if (!eventColl[iSub].isFinal()) continue;
0358 int iNew = eventMain.append(eventColl[iSub]);
0359 eventMain[iNew].mothers(iNuc, iProj);
0360 eventMain[iNew].vProdAdd(vNow);
0361 }
0362 sizeNew = eventMain.size();
0363
0364
0365 eventMain[iProj].daughters(sizeOld, sizeNew - 1);
0366 eventMain[iNuc].daughters(sizeOld, sizeNew - 1);
0367 eventMain[iProj].statusNeg();
0368 eventMain[iProj].tau(0.);
0369
0370
0371 }
0372
0373
0374 if (rapidDecays) pythiaMain.moreDecays();
0375
0376
0377 if (listFinal) compress();
0378
0379
0380 return eventMain;
0381
0382 }
0383
0384
0385
0386
0387
0388
0389 Event& nextDecay(int idNowIn, Vec4 pNowIn, double mNowIn,
0390 Vec4 vNow = Vec4() ) {
0391
0392
0393
0394 idNow = idNowIn;
0395 pNow = pNowIn;
0396 mNow = mNowIn;
0397
0398
0399 Event& eventMain = pythiaMain.event;
0400 Event& eventColl = pythiaColl.event;
0401 eventMain.clear();
0402 eventColl.clear();
0403
0404
0405 eventColl.append(90, -11, 0, 0, 1, 1, 0, 0, pNow, mNow);
0406 int iHad = eventColl.append(idNow, 12, 0, 0, 0, 0, 0, 0, pNow, mNow);
0407 eventColl[iHad].vProd(vNow);
0408
0409
0410 if (!pythiaColl.moreDecays(iHad)) return eventMain;
0411 eventMain = eventColl;
0412
0413
0414 if (rapidDecays) pythiaMain.moreDecays();
0415
0416
0417 if (listFinal) compress();
0418
0419
0420 return eventMain;
0421
0422 }
0423
0424
0425
0426
0427
0428
0429
0430 void compress() {
0431
0432
0433 Event& eventMain = pythiaMain.event;
0434 int sizeOld = eventMain.size();
0435 int sizeNew = 1;
0436
0437
0438
0439 for (int i = 1; i < sizeOld; ++i) if (eventMain[i].isFinal()) {
0440 eventMain[sizeNew] = eventMain[i];
0441 eventMain[sizeNew].mothers( 0, 0);
0442 eventMain[sizeNew].daughters( 0, 0);
0443 ++sizeNew;
0444 }
0445
0446
0447 eventMain.popBack( sizeOld - sizeNew);
0448
0449 }
0450
0451
0452
0453
0454
0455 void stat() {
0456 pythiaMain.stat();
0457 pythiaColl.stat();
0458 logger.errorStatistics();
0459 }
0460
0461
0462
0463
0464
0465
0466 ParticleData& particleData() {return pythiaMain.particleData;}
0467
0468 Rndm& rndm() {return pythiaMain.rndm;}
0469
0470
0471
0472 private:
0473
0474
0475
0476
0477 Pythia pythiaMain, pythiaColl;
0478
0479
0480 Logger logger;
0481
0482
0483 bool listFinal, rapidDecays;
0484 int idNow;
0485 double eMax, smallTau0, mp, mNow, eCMNow, sigmaNow;
0486 Vec4 pNow;
0487
0488
0489 static constexpr double probSD = 0.3;
0490
0491
0492
0493 static constexpr double eKinMin = 0.2;
0494
0495
0496
0497
0498 static constexpr int nA = 16;
0499 static constexpr double tabBorder = 20.;
0500 static const double tabA[nA];
0501 static const double tabOffset[nA];
0502 static const double tabSlope[nA];
0503 static const double tabSlopeLo[nA];
0504
0505 };
0506
0507
0508 const double PythiaCascade::tabA[] = {1, 2, 4, 9, 12, 14, 16, 27, 40, 56,
0509 63, 84, 107, 129, 197, 208};
0510 const double PythiaCascade::tabOffset[] = {0., 0.03, 0.08, 0.15, 0.20, 0.20,
0511 0.20, 0.26, 0.30, 0.34, 0.40, 0.40, 0.40, 0.50, 0.50, 0.60};
0512 const double PythiaCascade::tabSlope[] = {0., 0.0016, 0.0033, 0.0075, 0.0092,
0513 0.0105, 0.012, 0.017, 0.022, 0.027, 0.028, 0.034, 0.040, 0.044, 0.055,
0514 0.055};
0515 const double PythiaCascade::tabSlopeLo[] = {0., 0.0031, 0.0073, 0.015, 0.0192,
0516 0.0205, 0.022, 0.03, 0.037, 0.044, 0.048, 0.054, 0.06, 0.069, 0.08, 0.085};
0517
0518
0519
0520 }
0521
0522 #endif