File indexing completed on 2025-08-03 08:20:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include "Martini.h"
0017 #include "JetScapeLogger.h"
0018 #include "JetScapeXML.h"
0019 #include <string>
0020
0021 #include "tinyxml2.h"
0022 #include <iostream>
0023
0024 #include "FluidDynamics.h"
0025 #include "MartiniMutex.h"
0026 #define hbarc 0.197327053
0027
0028 #define MAGENTA "\033[35m"
0029
0030 using namespace Jetscape;
0031
0032
0033 RegisterJetScapeModule<Martini> Martini::reg("Martini");
0034
0035 using std::ofstream;
0036 using std::ifstream;
0037 using std::ostream;
0038 using std::ios;
0039
0040 int Martini::pLabelNew = 0;
0041
0042 Martini::Martini() {
0043 SetId("Martini");
0044 VERBOSE(8);
0045
0046
0047 dGamma_qq = new vector<double>;
0048 dGamma_qg = new vector<double>;
0049 dGamma_qq_q = new vector<double>;
0050 dGamma_qg_q = new vector<double>;
0051
0052
0053 auto martini_mutex = make_shared<MartiniMutex>();
0054 SetMutex(martini_mutex);
0055 }
0056
0057 Martini::~Martini() { VERBOSE(8); }
0058
0059 void Martini::Init() {
0060 JSINFO << "Initialize Martini ...";
0061
0062 double deltaT = 0.0;
0063 double Martini_deltaT_Max = 0.03 + rounding_error;
0064
0065 deltaT = GetXMLElementDouble({"Eloss", "deltaT"});
0066
0067 if (deltaT > Martini_deltaT_Max) {
0068 JSWARN << "Timestep for Martini ( deltaT = " << deltaT
0069 << " ) is too large. "
0070 << "Please choose a detaT smaller than or equal to 0.03 in the XML "
0071 "file.";
0072 throw std::runtime_error(
0073 "Martini not properly initialized in XML file ...");
0074 }
0075
0076 string s = GetXMLElementText({"Eloss", "Martini", "name"});
0077 JSDEBUG << s << " to be initialized ...";
0078
0079 tStart = GetXMLElementDouble({"Eloss", "tStart"});
0080 Q0 = GetXMLElementDouble({"Eloss", "Martini", "Q0"});
0081 alpha_s0 = GetXMLElementDouble({"Eloss", "Martini", "alpha_s"});
0082 pcut = GetXMLElementDouble({"Eloss", "Martini", "pcut"});
0083 hydro_Tc = GetXMLElementDouble({"Eloss", "Martini", "hydro_Tc"});
0084 recoil_on = GetXMLElementInt({"Eloss", "Martini", "recoil_on"});
0085 run_alphas = GetXMLElementInt({"Eloss", "Martini", "run_alphas"});
0086
0087 alpha_em = 1. / 137.;
0088
0089
0090 PathToTables = GetXMLElementText({"Eloss", "Martini", "path"});
0091
0092
0093 ZeroOneDistribution = uniform_real_distribution<double>{0.0, 1.0};
0094
0095 readRadiativeRate(&dat, &Gam);
0096 readElasticRateOmega();
0097 readElasticRateQ();
0098 }
0099
0100 void Martini::DoEnergyLoss(double deltaT, double Time, double Q2,
0101 vector<Parton> &pIn, vector<Parton> &pOut) {
0102 VERBOSESHOWER(5) << MAGENTA << "SentInPartons Signal received : " << deltaT
0103 << " " << Q2 << " " << pIn.size();
0104
0105
0106 int Id, newId;
0107 int pStat;
0108
0109
0110 int pLabel;
0111 double p0, px, py, pz;
0112 double pAbs;
0113 double velx, vely, velz;
0114 double pRest, pxRest;
0115 double pyRest, pzRest;
0116 double k, kRest;
0117 double pNew, pxNew;
0118 double pyNew, pzNew;
0119 double pNewRest;
0120 double omega, q;
0121 double pThermal, pxThermal;
0122 double pyThermal, pzThermal;
0123 double pRecoil, pxRecoil;
0124 double pyRecoil, pzRecoil;
0125 double pRecoilRest;
0126 double xx, yy, zz, tt;
0127 FourVector pVec, pVecNew;
0128 FourVector kVec;
0129 FourVector pVecRest;
0130 FourVector pVecNewRest;
0131 FourVector qVec;
0132 FourVector
0133 pVecThermalRest;
0134 FourVector pVecThermal;
0135 FourVector pVecRecoilRest;
0136 FourVector pVecRecoil;
0137 FourVector xVec;
0138 double velocity_jet[4];
0139 double eta;
0140 double SpatialRapidity;
0141 bool coherent;
0142
0143
0144 int sibling;
0145 FourVector pAtSplit;
0146 bool userInfo;
0147 bool active;
0148
0149
0150 double vx, vy, vz;
0151 double T;
0152 double beta, gamma;
0153 double cosPhi;
0154 double cosPhiRest;
0155 double boostBack;
0156 double cosPhiRestEl;
0157 double boostBackEl;
0158
0159 for (int i = 0; i < pIn.size(); i++) {
0160
0161 Id = pIn[i].pid();
0162 pStat = pIn[i].pstat();
0163
0164 if (pStat < 0)
0165 continue;
0166
0167 px = pIn[i].px();
0168 py = pIn[i].py();
0169 pz = pIn[i].pz();
0170 p0 = pIn[i].e();
0171
0172 pAbs = sqrt(px * px + py * py + pz * pz);
0173
0174
0175 pVec = FourVector(px, py, pz, pAbs);
0176
0177 velx = px / p0;
0178 vely = py / p0;
0179 velz = pz / p0;
0180 double velocityMod = std::sqrt(std::pow(velx, 2) + std::pow(vely, 2) +
0181 std::pow(velz, 2));
0182 tt = Time;
0183 xx = pIn[i].x_in().x() + (Time - pIn[i].x_in().t()) * velx / velocityMod;
0184 yy = pIn[i].x_in().y() + (Time - pIn[i].x_in().t()) * vely / velocityMod;
0185 zz = pIn[i].x_in().z() + (Time - pIn[i].x_in().t()) * velz / velocityMod;
0186
0187 eta = pIn[i].eta();
0188 SpatialRapidity = 0.5 * std::log((tt + zz) / (tt - zz));
0189 double boostedTStart = tStart * cosh(SpatialRapidity);
0190
0191
0192 std::unique_ptr<FluidCellInfo> check_fluid_info_ptr;
0193 GetHydroCellSignal(Time, xx, yy, zz, check_fluid_info_ptr);
0194 VERBOSE(8) << MAGENTA << "Temperature from Brick (Signal) = "
0195 << check_fluid_info_ptr->temperature;
0196
0197 vx = check_fluid_info_ptr->vx;
0198 vy = check_fluid_info_ptr->vy;
0199 vz = check_fluid_info_ptr->vz;
0200 T = check_fluid_info_ptr->temperature;
0201
0202 beta = sqrt(vx * vx + vy * vy + vz * vz);
0203
0204
0205 if (pIn[i].t() > Q0 * Q0 + rounding_error || Time <= boostedTStart ||
0206 T < hydro_Tc)
0207 continue;
0208 TakeResponsibilityFor(
0209 pIn[i]);
0210
0211 pLabel = pIn[i].plabel();
0212 if (pLabel == 0) {
0213 IncrementpLable();
0214 pIn[i].set_label(pLabelNew);
0215 pLabel = pLabelNew;
0216 }
0217
0218 userInfo = pIn[i].has_user_info<MARTINIUserInfo>();
0219
0220 if (!userInfo)
0221 pIn[i].set_user_info(new MARTINIUserInfo());
0222
0223 coherent = pIn[i].user_info<MARTINIUserInfo>().coherent();
0224 sibling = pIn[i].user_info<MARTINIUserInfo>().coherent_with();
0225 pAtSplit = pIn[i].user_info<MARTINIUserInfo>().p_at_split();
0226
0227
0228 if (beta < 1e-10) {
0229
0230 gamma = 1.;
0231 cosPhi = 1.;
0232 pRest = pAbs;
0233 pVecRest = pVec;
0234
0235 cosPhiRest = 1.;
0236 boostBack = 1.;
0237 } else {
0238
0239 gamma = 1. / sqrt(1. - beta * beta);
0240 cosPhi = (px * vx + py * vy + pz * vz) / (pAbs * beta);
0241
0242
0243 pRest = pAbs * gamma * (1. - beta * cosPhi);
0244
0245 pxRest = -vx * gamma * pAbs +
0246 (1. + (gamma - 1.) * vx * vx / (beta * beta)) * px +
0247 (gamma - 1.) * vx * vy / (beta * beta) * py +
0248 (gamma - 1.) * vx * vz / (beta * beta) * pz;
0249 pyRest = -vy * gamma * pAbs +
0250 (1. + (gamma - 1.) * vy * vy / (beta * beta)) * py +
0251 (gamma - 1.) * vx * vy / (beta * beta) * px +
0252 (gamma - 1.) * vy * vz / (beta * beta) * pz;
0253 pzRest = -vz * gamma * pAbs +
0254 (1. + (gamma - 1.) * vz * vz / (beta * beta)) * pz +
0255 (gamma - 1.) * vx * vz / (beta * beta) * px +
0256 (gamma - 1.) * vy * vz / (beta * beta) * py;
0257
0258 pVecRest = FourVector(pxRest, pyRest, pzRest, pRest);
0259
0260 cosPhiRest = (pxRest * vx + pyRest * vy + pzRest * vz) / (pRest * beta);
0261 boostBack = gamma * (1. + beta * cosPhiRest);
0262 }
0263
0264
0265 if (pRest < eLossCut) continue;
0266
0267 xVec = FourVector(xx + px / pAbs * deltaT, yy + py / pAbs * deltaT,
0268 zz + pz / pAbs * deltaT, Time + deltaT);
0269
0270 velocity_jet[0] = 1.0;
0271 velocity_jet[1] = pIn[i].jet_v().x();
0272 velocity_jet[2] = pIn[i].jet_v().y();
0273 velocity_jet[3] = pIn[i].jet_v().z();
0274
0275
0276 alpha_s = alpha_s0;
0277 if (run_alphas) {
0278 double mu = sqrt(2.*pAbs*T);
0279 alpha_s = RunningAlphaS(mu);
0280 }
0281 g = sqrt(4. * M_PI * alpha_s);
0282
0283 double deltaTRest = deltaT / gamma;
0284
0285 int process = DetermineProcess(pRest, T, deltaTRest, Id);
0286
0287
0288
0289 VERBOSE(8) << MAGENTA << "Time = " << Time << " Id = " << Id
0290 << " process = " << process << " T = " << setprecision(3) << T
0291 << " pAbs = " << pAbs << " " << px << " " << py << " " << pz
0292 << " | pRest = " << pRest << "/" << pcut
0293 << " | position = " << xx << " " << yy << " " << zz
0294 << " | stat = " << pStat << " " << pLabel << " " << coherent
0295 << " | " << pAtSplit.x();
0296
0297
0298 bool coherent_temp = coherent;
0299
0300
0301
0302
0303
0304
0305
0306
0307 if (process == 0 || (coherent && (process < 5))) {
0308 pOut.push_back(Parton(pLabel, Id, pStat, pVec, xVec));
0309 pOut[pOut.size() - 1].set_form_time(0.);
0310 pOut[pOut.size() - 1].set_jet_v(velocity_jet);
0311
0312 if (coherent) {
0313 pOut[pOut.size() - 1].set_user_info(
0314 new MARTINIUserInfo(coherent, sibling, pAtSplit));
0315 } else {
0316 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0317 }
0318
0319 return;
0320 }
0321
0322 if (std::abs(Id) == 1 || std::abs(Id) == 2 || std::abs(Id) == 3) {
0323
0324
0325 if (process == 1) {
0326 if (pRest / T < AMYpCut)
0327 return;
0328
0329
0330 kRest = getNewMomentumRad(pRest, T, process);
0331 if (kRest > pRest)
0332 return;
0333
0334
0335 pNewRest = pRest - kRest;
0336
0337 pNew = pNewRest * boostBack;
0338 pVecNew.Set((px / pAbs) * pNew, (py / pAbs) * pNew, (pz / pAbs) * pNew,
0339 pNew);
0340 pOut.push_back(Parton(pLabel, Id, pStat, pVecNew, xVec));
0341 pOut[pOut.size() - 1].set_form_time(0.);
0342 pOut[pOut.size() - 1].set_jet_v(
0343 velocity_jet);
0344 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0345
0346 if (kRest > pcut) {
0347 IncrementpLable();
0348 k = kRest * boostBack;
0349 kVec.Set((px / pAbs) * k, (py / pAbs) * k, (pz / pAbs) * k, k);
0350 pOut.push_back(Parton(pLabelNew, 21, pStat, kVec, xVec));
0351 pOut[pOut.size() - 1].set_form_time(0.);
0352 pOut[pOut.size() - 1].set_jet_v(
0353 velocity_jet);
0354 }
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364 return;
0365 } else if (process == 2) {
0366
0367 if (pRest / T < AMYpCut)
0368 return;
0369
0370
0371 kRest = getNewMomentumRad(pRest, T, process);
0372 if (kRest > pRest)
0373 return;
0374
0375
0376 pNewRest = pRest - kRest;
0377
0378 pNew = pNewRest * boostBack;
0379 pVecNew.Set((px / pAbs) * pNew, (py / pAbs) * pNew, (pz / pAbs) * pNew,
0380 pNew);
0381 pOut.push_back(Parton(pLabel, Id, pStat, pVecNew, xVec));
0382 pOut[pOut.size() - 1].set_form_time(0.);
0383 pOut[pOut.size() - 1].set_jet_v(
0384 velocity_jet);
0385 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0386
0387
0388
0389 if (kRest > 0.) {
0390 IncrementpLable();
0391 k = kRest * boostBack;
0392 kVec.Set((px / pAbs) * k, (py / pAbs) * k, (pz / pAbs) * k, k);
0393 pOut.push_back(Parton(pLabelNew, 21, pStat, kVec, xVec));
0394 pOut[pOut.size() - 1].set_form_time(0.);
0395 pOut[pOut.size() - 1].set_jet_v(
0396 velocity_jet);
0397 }
0398
0399 return;
0400 } else if (process == 5 || process == 6) {
0401
0402 omega = getEnergyTransfer(pRest, T, process);
0403 q = getMomentumTransfer(pRest, omega, T, process);
0404
0405
0406 if (q < fabs(omega))
0407 return;
0408
0409 pVecNewRest = getNewMomentumElas(pVecRest, omega, q);
0410
0411 pNewRest = pVecNewRest.t();
0412
0413
0414 if (beta < 1e-10) {
0415
0416 pVecNew = pVecNewRest;
0417 } else {
0418
0419 pxNew =
0420 vx * gamma * pVecNewRest.t() +
0421 (1. + (gamma - 1.) * vx * vx / (beta * beta)) * pVecNewRest.x() +
0422 (gamma - 1.) * vx * vy / (beta * beta) * pVecNewRest.y() +
0423 (gamma - 1.) * vx * vz / (beta * beta) * pVecNewRest.z();
0424 pyNew =
0425 vy * gamma * pVecNewRest.t() +
0426 (1. + (gamma - 1.) * vy * vy / (beta * beta)) * pVecNewRest.y() +
0427 (gamma - 1.) * vx * vy / (beta * beta) * pVecNewRest.x() +
0428 (gamma - 1.) * vy * vz / (beta * beta) * pVecNewRest.z();
0429 pzNew =
0430 vz * gamma * pVecNewRest.t() +
0431 (1. + (gamma - 1.) * vz * vz / (beta * beta)) * pVecNewRest.z() +
0432 (gamma - 1.) * vx * vz / (beta * beta) * pVecNewRest.x() +
0433 (gamma - 1.) * vy * vz / (beta * beta) * pVecNewRest.y();
0434
0435 pNew = sqrt(pxNew * pxNew + pyNew * pyNew + pzNew * pzNew);
0436 pVecNew.Set(pxNew, pyNew, pzNew, pNew);
0437 }
0438
0439 pOut.push_back(Parton(pLabel, Id, pStat, pVecNew, xVec));
0440 pOut[pOut.size() - 1].set_form_time(0.);
0441 pOut[pOut.size() - 1].set_jet_v(
0442 velocity_jet);
0443
0444 if (coherent) {
0445 pOut[pOut.size() - 1].set_user_info(
0446 new MARTINIUserInfo(coherent, sibling, pAtSplit));
0447 } else {
0448 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0449 }
0450
0451 if (recoil_on) {
0452
0453 qVec = pVecRest;
0454 qVec -= pVecNewRest;
0455
0456 pVecThermalRest = getThermalVec(qVec, T, Id);
0457 pVecRecoilRest = qVec;
0458 pVecRecoilRest += pVecThermalRest;
0459 double pRecoilRest = pVecRecoilRest.t();
0460
0461 if (pRecoilRest > pcut) {
0462
0463
0464 if (beta < 1e-10) {
0465
0466 pVecThermal = pVecThermalRest;
0467 pVecRecoil = pVecRecoilRest;
0468 } else {
0469
0470 pxThermal =
0471 vx * gamma * pVecThermalRest.t() +
0472 (1. + (gamma - 1.) * vx * vx / (beta * beta)) *
0473 pVecThermalRest.x() +
0474 (gamma - 1.) * vx * vy / (beta * beta) * pVecThermalRest.y() +
0475 (gamma - 1.) * vx * vz / (beta * beta) * pVecThermalRest.z();
0476 pyThermal =
0477 vy * gamma * pVecThermalRest.t() +
0478 (1. + (gamma - 1.) * vy * vy / (beta * beta)) *
0479 pVecThermalRest.y() +
0480 (gamma - 1.) * vx * vy / (beta * beta) * pVecThermalRest.x() +
0481 (gamma - 1.) * vy * vz / (beta * beta) * pVecThermalRest.z();
0482 pzThermal =
0483 vz * gamma * pVecThermalRest.t() +
0484 (1. + (gamma - 1.) * vz * vz / (beta * beta)) *
0485 pVecThermalRest.z() +
0486 (gamma - 1.) * vx * vz / (beta * beta) * pVecThermalRest.x() +
0487 (gamma - 1.) * vy * vz / (beta * beta) * pVecThermalRest.y();
0488
0489 pThermal = sqrt(pxThermal * pxThermal + pyThermal * pyThermal +
0490 pzThermal * pzThermal);
0491 pVecThermal.Set(pxThermal, pyThermal, pzThermal, pThermal);
0492
0493 pxRecoil =
0494 vx * gamma * pVecRecoilRest.t() +
0495 (1. + (gamma - 1.) * vx * vx / (beta * beta)) *
0496 pVecRecoilRest.x() +
0497 (gamma - 1.) * vx * vy / (beta * beta) * pVecRecoilRest.y() +
0498 (gamma - 1.) * vx * vz / (beta * beta) * pVecRecoilRest.z();
0499 pyRecoil =
0500 vy * gamma * pVecRecoilRest.t() +
0501 (1. + (gamma - 1.) * vy * vy / (beta * beta)) *
0502 pVecRecoilRest.y() +
0503 (gamma - 1.) * vx * vy / (beta * beta) * pVecRecoilRest.x() +
0504 (gamma - 1.) * vy * vz / (beta * beta) * pVecRecoilRest.z();
0505 pzRecoil =
0506 vz * gamma * pVecRecoilRest.t() +
0507 (1. + (gamma - 1.) * vz * vz / (beta * beta)) *
0508 pVecRecoilRest.z() +
0509 (gamma - 1.) * vx * vz / (beta * beta) * pVecRecoilRest.x() +
0510 (gamma - 1.) * vy * vz / (beta * beta) * pVecRecoilRest.y();
0511
0512 pRecoil = sqrt(pxRecoil * pxRecoil + pyRecoil * pyRecoil +
0513 pzRecoil * pzRecoil);
0514 pVecRecoil.Set(pxRecoil, pyRecoil, pzRecoil, pRecoil);
0515 }
0516
0517
0518 if (process == 5) {
0519
0520 double r = ZeroOneDistribution(*GetMt19937Generator());
0521 if (r < 1. / 3.)
0522 newId = 1;
0523 else if (r < 2. / 3.)
0524 newId = 2;
0525 else
0526 newId = 3;
0527 } else {
0528 newId = 21;
0529 }
0530
0531 if (pVecThermal.t() > 1e-5) {
0532 IncrementpLable();
0533 pOut.push_back(Parton(pLabelNew, newId, -1, pVecThermal, xVec));
0534 pOut[pOut.size() - 1].set_form_time(0.);
0535 pOut[pOut.size() - 1].set_jet_v(
0536 velocity_jet);
0537
0538 }
0539
0540 IncrementpLable();
0541 pOut.push_back(Parton(pLabelNew, newId, 1, pVecRecoil, xVec));
0542 pOut[pOut.size() - 1].set_form_time(0.);
0543 pOut[pOut.size() - 1].set_jet_v(
0544 velocity_jet);
0545
0546 }
0547 }
0548 return;
0549 } else if (process == 9) {
0550
0551 pOut.push_back(Parton(pLabel, 21, pStat, pVec, xVec));
0552 pOut[pOut.size() - 1].set_form_time(0.);
0553 pOut[pOut.size() - 1].set_jet_v(
0554 velocity_jet);
0555
0556 if (coherent) {
0557 pOut[pOut.size() - 1].set_user_info(
0558 new MARTINIUserInfo(coherent, sibling, pAtSplit));
0559 } else {
0560 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0561 }
0562
0563 return;
0564 } else if (process == 10) {
0565
0566 pOut.push_back(Parton(pLabel, 22, pStat, pVec, xVec));
0567 pOut[pOut.size() - 1].set_form_time(0.);
0568 pOut[pOut.size() - 1].set_jet_v(
0569 velocity_jet);
0570
0571 return;
0572 }
0573 } else if (Id == 21) {
0574
0575
0576 if (process == 3) {
0577 if (pRest / T < AMYpCut)
0578 return;
0579
0580
0581 kRest = getNewMomentumRad(pRest, T, process);
0582 if (kRest > pRest)
0583 return;
0584
0585
0586 pNewRest = pRest - kRest;
0587
0588 pNew = pNewRest * boostBack;
0589 pVecNew.Set((px / pAbs) * pNew, (py / pAbs) * pNew, (pz / pAbs) * pNew,
0590 pNew);
0591 pOut.push_back(Parton(pLabel, Id, pStat, pVecNew, xVec));
0592 pOut[pOut.size() - 1].set_form_time(0.);
0593 pOut[pOut.size() - 1].set_jet_v(
0594 velocity_jet);
0595 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0596
0597 if (kRest > pcut) {
0598 IncrementpLable();
0599 k = kRest * boostBack;
0600 kVec.Set((px / pAbs) * k, (py / pAbs) * k, (pz / pAbs) * k, k);
0601 pOut.push_back(Parton(pLabelNew, Id, pStat, kVec, xVec));
0602 pOut[pOut.size() - 1].set_form_time(0.);
0603 pOut[pOut.size() - 1].set_jet_v(
0604 velocity_jet);
0605 }
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615 return;
0616 } else if (process == 4) {
0617
0618 if (pRest / T < AMYpCut)
0619 return;
0620
0621
0622 kRest = getNewMomentumRad(pRest, T, process);
0623 if (kRest > pRest)
0624 return;
0625
0626
0627 pNewRest = pRest - kRest;
0628
0629
0630 double r = ZeroOneDistribution(*GetMt19937Generator());
0631 if (r < 1. / 3.)
0632 newId = 1;
0633 else if (r < 2. / 3.)
0634 newId = 2;
0635 else
0636 newId = 3;
0637
0638
0639 pNew = pNewRest * boostBack;
0640 pVecNew.Set((px / pAbs) * pNew, (py / pAbs) * pNew, (pz / pAbs) * pNew,
0641 pNew);
0642 pOut.push_back(Parton(pLabel, newId, pStat, pVecNew, xVec));
0643 pOut[pOut.size() - 1].set_form_time(0.);
0644 pOut[pOut.size() - 1].set_jet_v(
0645 velocity_jet);
0646 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0647
0648 if (kRest > pcut) {
0649 IncrementpLable();
0650 k = kRest * boostBack;
0651 kVec.Set((px / pAbs) * k, (py / pAbs) * k, (pz / pAbs) * k, k);
0652 pOut.push_back(Parton(pLabelNew, -newId, pStat, kVec, xVec));
0653 pOut[pOut.size() - 1].set_form_time(0.);
0654 pOut[pOut.size() - 1].set_jet_v(
0655 velocity_jet);
0656 }
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666 return;
0667 } else if (process == 7 || process == 8) {
0668
0669 omega = getEnergyTransfer(pRest, T, process);
0670 q = getMomentumTransfer(pRest, omega, T, process);
0671
0672
0673 if (q < fabs(omega))
0674 return;
0675
0676 pVecNewRest = getNewMomentumElas(pVecRest, omega, q);
0677
0678 pNewRest = pVecNewRest.t();
0679
0680
0681 if (beta < 1e-10) {
0682
0683 pVecNew = pVecNewRest;
0684 } else {
0685
0686 pxNew =
0687 vx * gamma * pVecNewRest.t() +
0688 (1. + (gamma - 1.) * vx * vx / (beta * beta)) * pVecNewRest.x() +
0689 (gamma - 1.) * vx * vy / (beta * beta) * pVecNewRest.y() +
0690 (gamma - 1.) * vx * vz / (beta * beta) * pVecNewRest.z();
0691 pyNew =
0692 vy * gamma * pVecNewRest.t() +
0693 (1. + (gamma - 1.) * vy * vy / (beta * beta)) * pVecNewRest.y() +
0694 (gamma - 1.) * vx * vy / (beta * beta) * pVecNewRest.x() +
0695 (gamma - 1.) * vy * vz / (beta * beta) * pVecNewRest.z();
0696 pzNew =
0697 vz * gamma * pVecNewRest.t() +
0698 (1. + (gamma - 1.) * vz * vz / (beta * beta)) * pVecNewRest.z() +
0699 (gamma - 1.) * vx * vz / (beta * beta) * pVecNewRest.x() +
0700 (gamma - 1.) * vy * vz / (beta * beta) * pVecNewRest.y();
0701
0702 pNew = sqrt(pxNew * pxNew + pyNew * pyNew + pzNew * pzNew);
0703 pVecNew.Set(pxNew, pyNew, pzNew, pNew);
0704 }
0705
0706 pOut.push_back(Parton(pLabel, Id, pStat, pVecNew, xVec));
0707 pOut[pOut.size() - 1].set_form_time(0.);
0708 pOut[pOut.size() - 1].set_jet_v(
0709 velocity_jet);
0710
0711 if (coherent) {
0712 pOut[pOut.size() - 1].set_user_info(
0713 new MARTINIUserInfo(coherent, sibling, pAtSplit));
0714 } else {
0715 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0716 }
0717
0718 if (recoil_on) {
0719
0720 qVec = pVecRest;
0721 qVec -= pVecNewRest;
0722
0723 pVecThermalRest = getThermalVec(qVec, T, Id);
0724 pVecRecoilRest = qVec;
0725 pVecRecoilRest += pVecThermalRest;
0726 double pRecoilRest = pVecRecoilRest.t();
0727
0728 if (pRecoilRest > pcut) {
0729
0730
0731 if (beta < 1e-10) {
0732
0733 pVecThermal = pVecThermalRest;
0734 pVecRecoil = pVecRecoilRest;
0735 } else {
0736
0737 pxThermal =
0738 vx * gamma * pVecThermalRest.t() +
0739 (1. + (gamma - 1.) * vx * vx / (beta * beta)) *
0740 pVecThermalRest.x() +
0741 (gamma - 1.) * vx * vy / (beta * beta) * pVecThermalRest.y() +
0742 (gamma - 1.) * vx * vz / (beta * beta) * pVecThermalRest.z();
0743 pyThermal =
0744 vy * gamma * pVecThermalRest.t() +
0745 (1. + (gamma - 1.) * vy * vy / (beta * beta)) *
0746 pVecThermalRest.y() +
0747 (gamma - 1.) * vx * vy / (beta * beta) * pVecThermalRest.x() +
0748 (gamma - 1.) * vy * vz / (beta * beta) * pVecThermalRest.z();
0749 pzThermal =
0750 vz * gamma * pVecThermalRest.t() +
0751 (1. + (gamma - 1.) * vz * vz / (beta * beta)) *
0752 pVecThermalRest.z() +
0753 (gamma - 1.) * vx * vz / (beta * beta) * pVecThermalRest.x() +
0754 (gamma - 1.) * vy * vz / (beta * beta) * pVecThermalRest.y();
0755
0756 pThermal = sqrt(pxThermal * pxThermal + pyThermal * pyThermal +
0757 pzThermal * pzThermal);
0758 pVecThermal.Set(pxThermal, pyThermal, pzThermal, pThermal);
0759
0760 pxRecoil =
0761 vx * gamma * pVecRecoilRest.t() +
0762 (1. + (gamma - 1.) * vx * vx / (beta * beta)) *
0763 pVecRecoilRest.x() +
0764 (gamma - 1.) * vx * vy / (beta * beta) * pVecRecoilRest.y() +
0765 (gamma - 1.) * vx * vz / (beta * beta) * pVecRecoilRest.z();
0766 pyRecoil =
0767 vy * gamma * pVecRecoilRest.t() +
0768 (1. + (gamma - 1.) * vy * vy / (beta * beta)) *
0769 pVecRecoilRest.y() +
0770 (gamma - 1.) * vx * vy / (beta * beta) * pVecRecoilRest.x() +
0771 (gamma - 1.) * vy * vz / (beta * beta) * pVecRecoilRest.z();
0772 pzRecoil =
0773 vz * gamma * pVecRecoilRest.t() +
0774 (1. + (gamma - 1.) * vz * vz / (beta * beta)) *
0775 pVecRecoilRest.z() +
0776 (gamma - 1.) * vx * vz / (beta * beta) * pVecRecoilRest.x() +
0777 (gamma - 1.) * vy * vz / (beta * beta) * pVecRecoilRest.y();
0778
0779 pRecoil = sqrt(pxRecoil * pxRecoil + pyRecoil * pyRecoil +
0780 pzRecoil * pzRecoil);
0781 pVecRecoil.Set(pxRecoil, pyRecoil, pzRecoil, pRecoil);
0782 }
0783
0784
0785 if (process == 7) {
0786
0787 double r = ZeroOneDistribution(*GetMt19937Generator());
0788 if (r < 1. / 3.)
0789 newId = 1;
0790 else if (r < 2. / 3.)
0791 newId = 2;
0792 else
0793 newId = 3;
0794 } else {
0795 newId = 21;
0796 }
0797
0798 if (pVecThermal.t() > 1e-5) {
0799 IncrementpLable();
0800 pOut.push_back(Parton(pLabelNew, newId, -1, pVecThermal, xVec));
0801 pOut[pOut.size() - 1].set_form_time(0.);
0802 pOut[pOut.size() - 1].set_jet_v(
0803 velocity_jet);
0804
0805 }
0806
0807 IncrementpLable();
0808 pOut.push_back(Parton(pLabelNew, newId, 1, pVecRecoil, xVec));
0809 pOut[pOut.size() - 1].set_form_time(0.);
0810 pOut[pOut.size() - 1].set_jet_v(
0811 velocity_jet);
0812
0813 }
0814 }
0815
0816 return;
0817 } else if (process == 11) {
0818
0819
0820 double r = ZeroOneDistribution(*GetMt19937Generator());
0821 if (r < 1. / 3.)
0822 newId = 1;
0823 else if (r < 2. / 3.)
0824 newId = 2;
0825 else
0826 newId = 3;
0827
0828 double antiquark = ZeroOneDistribution(*GetMt19937Generator());
0829 if (antiquark < 0.5)
0830 newId *= -1;
0831
0832 pOut.push_back(Parton(pLabel, newId, pStat, pVec, xVec));
0833 pOut[pOut.size() - 1].set_form_time(0.);
0834 pOut[pOut.size() - 1].set_jet_v(
0835 velocity_jet);
0836
0837 if (coherent) {
0838 pOut[pOut.size() - 1].set_user_info(
0839 new MARTINIUserInfo(coherent, sibling, pAtSplit));
0840 } else {
0841 pOut[pOut.size() - 1].set_user_info(new MARTINIUserInfo());
0842 }
0843
0844 return;
0845 }
0846 }
0847 }
0848 }
0849
0850 double Martini::RunningAlphaS(double mu) {
0851
0852 if (mu < 1.0) return alpha_s0;
0853
0854 double beta0 = 9./(4.*M_PI);
0855 double LambdaQCD = exp( -1./(2.*beta0*alpha_s0) );
0856 double running_alphas = 1./(beta0 * log( pow(mu/LambdaQCD, 2.) ));
0857 return running_alphas;
0858 }
0859
0860 int Martini::DetermineProcess(double pRest, double T, double deltaTRest,
0861 int Id) {
0862
0863 double dT = deltaTRest / hbarc;
0864
0865
0866
0867 RateRadiative rateRad;
0868 rateRad = getRateRadTotal(pRest, T);
0869 RateElastic rateElas;
0870 rateElas = getRateElasTotal(pRest, T);
0871 RateConversion rateConv;
0872 rateConv = getRateConv(pRest, T);
0873
0874
0875 if (std::abs(Id) == 1 || std::abs(Id) == 2 || std::abs(Id) == 3) {
0876
0877 if (abs(Id) == 1) {
0878 rateRad.qqgamma *= 4. / 9.;
0879 rateConv.qgamma *= 4. / 9.;
0880 } else {
0881 rateRad.qqgamma *= 1. / 9.;
0882 rateConv.qgamma *= 1. / 9.;
0883 }
0884
0885 double totalQuarkProb = 0.;
0886
0887
0888
0889
0890
0891 if (pRest / T > AMYpCut)
0892 totalQuarkProb += rateRad.qqg * dT;
0893 totalQuarkProb += (rateElas.qq + rateElas.qg + rateConv.qg) * dT;
0894
0895
0896 if (totalQuarkProb > 1.) {
0897 JSWARN << " : Total Probability for quark processes exceeds 1 ("
0898 << totalQuarkProb << "). "
0899 << " : Most likely this means you should choose a smaller deltaT "
0900 "in the xml"
0901 << " (e.g. 0.01). "
0902 << "pRest=" << pRest << " T=" << T << " pRest/T=" << pRest / T;
0903
0904 }
0905
0906 double accumProb = 0.;
0907 double nextProb = 0.;
0908 double Prob = 0.;
0909
0910 if (ZeroOneDistribution(*GetMt19937Generator()) < totalQuarkProb) {
0911
0912
0913
0914
0915 double randProb = ZeroOneDistribution(*GetMt19937Generator());
0916
0917
0918
0919 if (pRest / T > AMYpCut) {
0920 Prob = rateRad.qqg * dT / totalQuarkProb;
0921 if (accumProb <= randProb && randProb < (accumProb + Prob))
0922 return 1;
0923
0924 accumProb += Prob;
0925 Prob = rateRad.qqgamma * dT / totalQuarkProb;
0926 if (accumProb <= randProb && randProb < (accumProb + Prob))
0927 return 2;
0928 }
0929
0930 accumProb += Prob;
0931 Prob = rateElas.qq * dT / totalQuarkProb;
0932 if (accumProb <= randProb && randProb < (accumProb + Prob))
0933 return 5;
0934
0935 accumProb += Prob;
0936 Prob = rateElas.qg * dT / totalQuarkProb;
0937 if (accumProb <= randProb && randProb < (accumProb + Prob))
0938 return 6;
0939
0940 accumProb += Prob;
0941 Prob = rateConv.qg * dT / totalQuarkProb;
0942 if (accumProb <= randProb && randProb < (accumProb + Prob))
0943 return 9;
0944
0945 accumProb += Prob;
0946 Prob = rateConv.qgamma * dT / totalQuarkProb;
0947 if (accumProb <= randProb && randProb < (accumProb + Prob))
0948 return 10;
0949 } else {
0950
0951 return 0;
0952 }
0953 } else if (Id == 21) {
0954
0955 double totalGluonProb = 0.;
0956
0957 if (pRest / T > AMYpCut)
0958 totalGluonProb += (rateRad.ggg + rateRad.gqq) * dT;
0959 totalGluonProb += (rateElas.gq + rateElas.gg + rateConv.gq) * dT;
0960
0961
0962 if (totalGluonProb > 1.) {
0963 JSWARN << " : Total Probability for gluon processes exceeds 1 ("
0964 << totalGluonProb << "). "
0965 << " : Most likely this means you should choose a smaller deltaT "
0966 "in the xml"
0967 << " (e.g. 0.01). "
0968 << "pRest=" << pRest << " T=" << T << " pRest/T=" << pRest / T;
0969
0970 }
0971
0972 double accumProb = 0.;
0973 double nextProb = 0.;
0974 double Prob = 0.;
0975
0976 if (ZeroOneDistribution(*GetMt19937Generator()) < totalGluonProb) {
0977
0978
0979
0980
0981 double randProb = ZeroOneDistribution(*GetMt19937Generator());
0982
0983
0984
0985 if (pRest / T > AMYpCut) {
0986 Prob = rateRad.ggg * dT / totalGluonProb;
0987 if (accumProb <= randProb && randProb < (accumProb + Prob))
0988 return 3;
0989
0990 accumProb += Prob;
0991 Prob = rateRad.gqq * dT / totalGluonProb;
0992 if (accumProb <= randProb && randProb < (accumProb + Prob))
0993 return 4;
0994 }
0995
0996 accumProb += Prob;
0997 Prob = rateElas.gq * dT / totalGluonProb;
0998 if (accumProb <= randProb && randProb < (accumProb + Prob))
0999 return 7;
1000
1001 accumProb += Prob;
1002 Prob = rateElas.gg * dT / totalGluonProb;
1003 if (accumProb <= randProb && randProb < (accumProb + Prob))
1004 return 8;
1005
1006 accumProb += Prob;
1007 Prob = rateConv.gq * dT / totalGluonProb;
1008 if (accumProb <= randProb && randProb < (accumProb + Prob))
1009 return 11;
1010 } else {
1011
1012 return 0;
1013 }
1014 }
1015
1016
1017 return 0;
1018 }
1019
1020 RateRadiative Martini::getRateRadTotal(double pRest, double T) {
1021 RateRadiative rate;
1022
1023 double u = pRest / T;
1024
1025 if (u > AMYpCut) {
1026 rate.qqg = (0.8616 - 3.2913 / (u * u) + 2.1102 / u - 0.9485 / sqrt(u)) *
1027 pow(g, 4.) * T;
1028 rate.ggg = (1.9463 + 61.7856 / (u * u * u) - 30.7877 / (u * u) +
1029 8.0409 / u - 2.6249 / sqrt(u)) *
1030 pow(g, 4.) * T;
1031 rate.gqq = (2.5830 / (u * u * u) - 1.7010 / (u * u) + 1.4977 / u -
1032 1.1961 / pow(u, 0.8) + 0.1807 / sqrt(u)) *
1033 pow(g, 4.) * T * nf;
1034 rate.qqgamma =
1035 (0.0053056 + 2.3279 / pow(u, 3.) - 0.6676 / u + 0.3223 / sqrt(u)) *
1036 pow(g, 4.) * alpha_em / alpha_s * T;
1037
1038 double runningFactor =
1039 log(g * T * pow(10., 0.25) / .175) / log(g * T * pow(u, 0.25) / .175);
1040 if (runningFactor < 1.) {
1041 rate.qqg *= runningFactor;
1042 rate.gqq *= runningFactor;
1043 rate.ggg *= runningFactor;
1044 rate.qqgamma *= runningFactor;
1045 }
1046 } else {
1047 rate.qqg = 0.;
1048 rate.ggg = 0.;
1049 rate.gqq = 0.;
1050 rate.qqgamma = 0.;
1051 }
1052
1053 return rate;
1054 }
1055
1056 RateRadiative Martini::getRateRadPos(double u, double T) {
1057 RateRadiative rate;
1058
1059 rate.qqg = (0.5322 - 3.1037 / (u * u) + 2.0139 / u - 0.9417 / sqrt(u)) *
1060 pow(g, 4.) * T;
1061 rate.ggg = (1.1923 - 11.5250 / (u * u * u) + 3.3010 / u - 1.9049 / sqrt(u)) *
1062 pow(g, 4.) * T;
1063 rate.gqq =
1064 (0.0004656 - 0.04621 / (u * u) + 0.0999 / u - 0.08171 / pow(u, 0.8) +
1065 0.008090 / pow(u, 0.2) - 1.2525 * pow(10., -8.) * u) *
1066 pow(g, 4.) * T * nf;
1067 rate.qqgamma = 0.;
1068
1069 return rate;
1070 }
1071
1072 RateRadiative Martini::getRateRadNeg(double u, double T) {
1073 RateRadiative rate;
1074
1075 rate.qqg = (0.3292 - 0.6759 / (u * u) + 0.4871 / pow(u, 1.5) - 0.05393 / u +
1076 0.007878 / sqrt(u)) *
1077 pow(g, 4.) * T;
1078 rate.ggg = (0.7409 + 1.8608 / (u * u * u) - 0.1353 / (u * u) + 0.1401 / u) *
1079 pow(g, 4.) * T;
1080 rate.gqq = (0.03215 / (u * u * u) + 0.01419 / (u * u) + 0.004338 / u -
1081 0.00001246 / sqrt(u)) *
1082 pow(g, 4.) * T * nf;
1083 rate.qqgamma = 0.;
1084
1085 return rate;
1086 }
1087
1088 double Martini::getNewMomentumRad(double pRest, double T, int process) {
1089 double u = pRest / T;
1090
1091 double kNew = 0.;
1092 double y;
1093 double x;
1094 double randA;
1095 double fy;
1096 double fyAct;
1097
1098 RateRadiative Pos, Neg;
1099 Pos = getRateRadPos(u, T);
1100 Neg = getRateRadNeg(u, T);
1101
1102
1103
1104 int posNegSwitch = 1;
1105
1106
1107
1108
1109
1110
1111 if (process == 1) {
1112
1113
1114 if (ZeroOneDistribution(*GetMt19937Generator()) <
1115 Neg.qqg / (Neg.qqg + Pos.qqg))
1116 posNegSwitch = 0;
1117
1118 if (posNegSwitch == 1)
1119 {
1120 do {
1121 randA = ZeroOneDistribution(*GetMt19937Generator()) *
1122 area(u + 12., u, posNegSwitch, 1);
1123 y = 2.5 / (LambertW(2.59235 * pow(10., 23.) * exp(-100. * randA)));
1124
1125 fy = 0.025 / (y * y) + 0.01 / y;
1126 fyAct = function(u, y, process);
1127
1128 x = ZeroOneDistribution(*GetMt19937Generator());
1129
1130 } while (x > fyAct / fy);
1131
1132 kNew = y;
1133 } else
1134 {
1135 do {
1136 randA = ZeroOneDistribution(*GetMt19937Generator()) *
1137 area(-0.05, u, posNegSwitch, 1);
1138 y = -12. / (1. + 480. * randA);
1139
1140 fy = 0.025 / (y * y);
1141 fyAct = function(u, y, process);
1142
1143 x = ZeroOneDistribution(*GetMt19937Generator());
1144
1145 } while (x > fyAct / fy);
1146
1147 kNew = y;
1148 }
1149 } else if (process == 2) {
1150 do {
1151 randA = ZeroOneDistribution(*GetMt19937Generator()) *
1152 area(1.15 * u, u, posNegSwitch, 2);
1153 y = 83895.3 * pow(pow(u, 0.5) * randA, 10. / 3.);
1154
1155 fy = (0.01 / (pow(y, 0.7))) / pow(u, 0.5);
1156 fyAct = function(u, y, process);
1157
1158 x = ZeroOneDistribution(*GetMt19937Generator());
1159
1160 } while (x > fyAct / fy);
1161
1162 kNew = y;
1163 } else if (process == 3) {
1164
1165
1166 if (ZeroOneDistribution(*GetMt19937Generator()) <
1167 Neg.ggg / (Neg.ggg + Pos.ggg))
1168 posNegSwitch = 0;
1169
1170 if (posNegSwitch == 1)
1171 {
1172 do {
1173 randA = ZeroOneDistribution(*GetMt19937Generator()) *
1174 area(u / 2., u, posNegSwitch, 3);
1175 y = 5. / (LambertW(2.68812 * pow(10., 45.) * exp(-50. * randA)));
1176
1177 fy = 0.1 / (y * y) + 0.02 / y;
1178 fyAct = function(u, y, process);
1179
1180 x = ZeroOneDistribution(*GetMt19937Generator());
1181
1182 } while (x > fyAct / fy);
1183
1184 kNew = y;
1185 } else
1186 {
1187 do {
1188 randA = ZeroOneDistribution(*GetMt19937Generator()) *
1189 area(-0.05, u, posNegSwitch, 3);
1190 y = -12. / (1. + 120. * randA);
1191
1192 fy = 0.1 / (y * y);
1193 fyAct = function(u, y, process);
1194
1195 x = ZeroOneDistribution(*GetMt19937Generator());
1196
1197 } while (x > fyAct / fy);
1198
1199 kNew = y;
1200 }
1201 } else if (process == 4) {
1202
1203
1204 if (ZeroOneDistribution(*GetMt19937Generator()) <
1205 Neg.gqq / (Neg.gqq + Pos.gqq))
1206 posNegSwitch = 0;
1207
1208 if (posNegSwitch == 1)
1209 {
1210 do {
1211 randA = ZeroOneDistribution(*GetMt19937Generator()) *
1212 area(u / 2., u, posNegSwitch, 4);
1213 y = 0.83333 * (0.06 * function(u, 0.05, process) + randA) /
1214 function(u, 0.05, process);
1215
1216 fy = 1.2 * function(u, 0.05, process);
1217 fyAct = function(u, y, process);
1218
1219 x = ZeroOneDistribution(*GetMt19937Generator());
1220
1221 } while (x > fyAct / fy);
1222
1223 kNew = y;
1224 } else
1225 {
1226 do {
1227 randA = ZeroOneDistribution(*GetMt19937Generator()) *
1228 area(-0.05, u, posNegSwitch, 4);
1229 y = (2.5 - u * log(7.81082 * pow(10., -6.) * exp(14.5 / u) +
1230 (-115.883 + 113.566 * u) * randA)) /
1231 (1. - 0.98 * u);
1232
1233 fy = 0.98 * exp((1. - 1. / u) * (-2.5 + y)) / u;
1234 fyAct = function(u, y, process);
1235
1236 x = ZeroOneDistribution(*GetMt19937Generator());
1237
1238 } while (x > fyAct / fy);
1239
1240 kNew = y;
1241 }
1242 } else {
1243 JSWARN << "Invalid process number (" << process << ")";
1244 }
1245
1246 return kNew * T;
1247 }
1248
1249
1250
1251 double Martini::area(double y, double u, int posNegSwitch, int process) {
1252 if (process == 1) {
1253 if (posNegSwitch == 1)
1254 return (0.5299 - 0.025 / y + 0.01 * log(y));
1255 else
1256 return (-0.002083 - 0.025 / y);
1257 } else if (process == 2) {
1258 return ((0.03333 * pow(y, 0.3)) / pow(u, 0.5));
1259 } else if (process == 3) {
1260 if (posNegSwitch == 1)
1261 return (2.05991 - 0.1 / y + 0.02 * log(y));
1262 else
1263 return (-0.008333 - 0.1 / y);
1264 } else if (process == 4) {
1265 if (posNegSwitch == 1)
1266 return (1.2 * function(u, 0.05, process) * (y - 0.05));
1267 else
1268 return ((6.8778 * pow(10., -8.) * exp(14.5 / u) -
1269 0.008805 * exp((2.5 - y + 0.98 * u * y) / u)) /
1270 (1.0204 - u));
1271 }
1272
1273 return 0.;
1274 }
1275
1276 double Martini::function(double u, double y, int process) {
1277 if (process == 1)
1278 return getRate_qqg(u, y);
1279 else if (process == 2)
1280 return getRate_qqgamma(u, y);
1281 else if (process == 3)
1282 return getRate_ggg(u, y);
1283 else if (process == 4)
1284 return getRate_gqq(u, y);
1285
1286 return 0.;
1287 }
1288
1289 bool Martini::isCoherent(Parton &pIn, int sibling, double T) {
1290 bool coherentNow = false;
1291 const weak_ptr<PartonShower> pShower = pIn.shower();
1292 auto shower = pShower.lock();
1293
1294 PartonShower::edge_iterator eIt, eEnd;
1295 for (eIt = shower->edges_begin(), eEnd = shower->edges_end(); eIt != eEnd;
1296 ++eIt) {
1297 if (eIt->target().outdeg() < 1) {
1298
1299 auto p = shower->GetParton(*eIt);
1300 if (p->plabel() == sibling) {
1301
1302
1303 if (p->has_user_info<MARTINIUserInfo>()) {
1304 bool coherentSibling = p->user_info<MARTINIUserInfo>().coherent();
1305 if (!coherentSibling)
1306 return coherentSibling;
1307 } else {
1308 JSWARN << "MARTINIUserInfo not set!!"
1309 << " plabel:" << p->plabel()
1310 << " Make this parton in de-coherent state";
1311 return false;
1312 }
1313
1314
1315 bool activeCoherent = (fabs(p->x_in().t() - pIn.x_in().t()) < 0.015);
1316 if (!activeCoherent)
1317 return activeCoherent;
1318
1319 JSDEBUG << " [Sibling]" << p->plabel() << " " << p->pid() << " "
1320 << p->x_in().t() << " " << p->x_in().x();
1321
1322
1323 FourVector pInitVec = pIn.user_info<MARTINIUserInfo>().p_at_split();
1324 double pxInit = pInitVec.x();
1325 double pyInit = pInitVec.y();
1326 double pzInit = pInitVec.z();
1327 double pInit = pInitVec.t();
1328
1329 if (pInit < 1e-2)
1330 return false;
1331
1332
1333 double xDelta = pIn.x_in().x() - p->x_in().x();
1334 double yDelta = pIn.x_in().x() - p->x_in().x();
1335 double zDelta = pIn.x_in().x() - p->x_in().x();
1336
1337
1338 double xCrox = yDelta * pzInit - zDelta * pyInit;
1339 double yCrox = zDelta * pxInit - xDelta * pzInit;
1340 double zCrox = xDelta * pyInit - yDelta * pxInit;
1341
1342
1343 double rPerp =
1344 sqrt(xCrox * xCrox + yCrox * yCrox + zCrox * zCrox) / pInit;
1345
1346
1347 double pxDelta = pIn.px() - p->px();
1348 double pyDelta = pIn.py() - p->py();
1349 double pzDelta = pIn.pz() - p->pz();
1350
1351
1352 double pxCrox = pyDelta * pzInit - pzDelta * pyInit;
1353 double pyCrox = pzDelta * pxInit - pxDelta * pzInit;
1354 double pzCrox = pxDelta * pyInit - pyDelta * pxInit;
1355
1356
1357 double pPerp =
1358 sqrt(pxCrox * pxCrox + pyCrox * pyCrox + pzCrox * pzCrox) / pInit;
1359
1360 double Crperp = 0.25 * pow(p->e() / T, 0.11);
1361 if (rPerp * pPerp < Crperp * hbarc)
1362 return true;
1363 }
1364 }
1365 }
1366
1367 return coherentNow;
1368 }
1369 RateElastic Martini::getRateElasTotal(double pRest, double T) {
1370
1371
1372
1373
1374
1375
1376
1377
1378 RateElastic rate;
1379
1380 double u = pRest / T;
1381
1382 double alpha0 = 0.15;
1383 double deltaAlpha = 0.03;
1384 double iAlpha = floor((alpha_s - alpha0) / deltaAlpha + 0.001);
1385 double alphaFrac = (alpha_s - alpha0) / deltaAlpha - iAlpha;
1386 double rateLower, rateUpper;
1387 double c[2][6], d[2][6];
1388
1389 for (int i = 0; i < 2; i++)
1390 for (int j = 0; j < 6; j++) {
1391 c[i][j] = 0.;
1392 d[i][j] = 0.;
1393 }
1394
1395 if (alpha_s >= 0.15 && alpha_s < 0.18) {
1396 c[0][0] = 0.18172488396136807;
1397 c[1][0] = 0.224596478395945;
1398 c[0][1] = 0.6004740049060965;
1399 c[1][1] = 1.0874259848101948;
1400 c[0][2] = 0.36559627257898347;
1401 c[1][2] = 0.6436398538984057;
1402 c[0][3] = 0.10607576568373664;
1403 c[1][3] = 0.11585154613692052;
1404 c[0][4] = 0.004322466954618182;
1405 c[1][4] = -0.001719701730785056;
1406 c[0][5] = 0.04731599462749122;
1407 c[1][5] = 0.06734745496415469;
1408 } else if (alpha_s >= 0.18 && alpha_s < 0.21) {
1409 c[0][0] = 0.224596478395945;
1410 c[1][0] = 0.2686436092048326;
1411 c[0][1] = 1.0874259848101948;
1412 c[1][1] = 1.7286136256785387;
1413 c[0][2] = 0.6436398538984057;
1414 c[1][2] = 0.9826325498183079;
1415 c[0][3] = 0.11585154613692052;
1416 c[1][3] = 0.13136670133029682;
1417 c[0][4] = -0.001719701730785056;
1418 c[1][4] = -0.004876376882437649;
1419 c[0][5] = 0.06734745496415469;
1420 c[1][5] = 0.09140316977554151;
1421 } else if (alpha_s >= 0.21 && alpha_s < 0.24) {
1422 c[0][0] = 0.2686436092048326;
1423 c[1][0] = 0.3137234778163784;
1424 c[0][1] = 1.7286136256785387;
1425 c[1][1] = 2.445764079999846;
1426 c[0][2] = 0.9826325498183079;
1427 c[1][2] = 1.3083241146035964;
1428 c[0][3] = 0.13136670133029682;
1429 c[1][3] = 0.18341717903923757;
1430 c[0][4] = -0.004876376882437649;
1431 c[1][4] = 0.006098371807040589;
1432 c[0][5] = 0.09140316977554151;
1433 c[1][5] = 0.12054238276023879;
1434 } else if (alpha_s >= 0.24 && alpha_s < 0.27) {
1435 c[0][0] = 0.3137234778163784;
1436 c[1][0] = 0.3597255453974444;
1437 c[0][1] = 2.445764079999846;
1438 c[1][1] = 3.140669321831845;
1439 c[0][2] = 1.3083241146035964;
1440 c[1][2] = 1.535549334026633;
1441 c[0][3] = 0.18341717903923757;
1442 c[1][3] = 0.30505450230754705;
1443 c[0][4] = 0.006098371807040589;
1444 c[1][4] = 0.04285103618362223;
1445 c[0][5] = 0.12054238276023879;
1446 c[1][5] = 0.1558288379712527;
1447 } else if (alpha_s >= 0.27 && alpha_s < 0.3) {
1448 c[0][0] = 0.3597255453974444;
1449 c[1][0] = 0.40656130602563223;
1450 c[0][1] = 3.140669321831845;
1451 c[1][1] = 3.713430971987352;
1452 c[0][2] = 1.535549334026633;
1453 c[1][2] = 1.5818298058630476;
1454 c[0][3] = 0.30505450230754705;
1455 c[1][3] = 0.5269042544852683;
1456 c[0][4] = 0.04285103618362223;
1457 c[1][4] = 0.11594975218839362;
1458 c[0][5] = 0.1558288379712527;
1459 c[1][5] = 0.1982063104156748;
1460 } else if (alpha_s >= 0.3 && alpha_s < 0.33) {
1461 c[0][0] = 0.40656130602563223;
1462 c[1][0] = 0.45415805200862863;
1463 c[0][1] = 3.713430971987352;
1464 c[1][1] = 4.0758813206143785;
1465 c[0][2] = 1.5818298058630476;
1466 c[1][2] = 1.3775134184861555;
1467 c[0][3] = 0.5269042544852683;
1468 c[1][3] = 0.873527536823307;
1469 c[0][4] = 0.11594975218839362;
1470 c[1][4] = 0.23371456949506658;
1471 c[0][5] = 0.1982063104156748;
1472 c[1][5] = 0.24840524848507203;
1473 } else if (alpha_s >= 0.33 && alpha_s < 0.36) {
1474 c[0][0] = 0.45415805200862863;
1475 c[1][0] = 0.5024541413891354;
1476 c[0][1] = 4.0758813206143785;
1477 c[1][1] = 4.159425815179756;
1478 c[0][2] = 1.3775134184861555;
1479 c[1][2] = 0.8719749565879445;
1480 c[0][3] = 0.873527536823307;
1481 c[1][3] = 1.3606690530660879;
1482 c[0][4] = 0.23371456949506658;
1483 c[1][4] = 0.4010658149846402;
1484 c[0][5] = 0.24840524848507203;
1485 c[1][5] = 0.3067901992139913;
1486 } else if (alpha_s >= 0.36 && alpha_s < 0.39) {
1487 c[0][0] = 0.5024541413891354;
1488 c[1][0] = 0.5513999693402064;
1489 c[0][1] = 4.159425815179756;
1490 c[1][1] = 3.893153859527746;
1491 c[0][2] = 0.8719749565879445;
1492 c[1][2] = 0.009578762778659829;
1493 c[0][3] = 1.3606690530660879;
1494 c[1][3] = 2.0095157488463244;
1495 c[0][4] = 0.4010658149846402;
1496 c[1][4] = 0.6260756501912864;
1497 c[0][5] = 0.3067901992139913;
1498 c[1][5] = 0.37424991045026396;
1499 } else if (alpha_s >= 0.39 && alpha_s <= 0.42) {
1500 c[0][0] = 0.5513999693402064;
1501 c[1][0] = 0.600941593540798;
1502 c[0][1] = 3.893153859527746;
1503 c[1][1] = 3.293344337592684;
1504 c[0][2] = 0.009578762778659829;
1505 c[1][2] = -1.1764805445298645;
1506 c[0][3] = 2.0095157488463244;
1507 c[1][3] = 2.792180001243466;
1508 c[0][4] = 0.6260756501912864;
1509 c[1][4] = 0.8949534049225013;
1510 c[0][5] = 0.37424991045026396;
1511 c[1][5] = 0.44878529934031575;
1512 }
1513
1514 rateLower = T * (c[0][0] + c[0][1] / pow(u, 4.) - c[0][2] / pow(u, 3.) -
1515 c[0][3] / pow(u, 2.) + c[0][4] / pow(u, 1.5) - c[0][5] / u);
1516 rateUpper = T * (c[1][0] + c[1][1] / pow(u, 4.) - c[1][2] / pow(u, 3.) -
1517 c[1][3] / pow(u, 2.) + c[1][4] / pow(u, 1.5) - c[1][5] / u);
1518
1519 rate.qq = (1. - alphaFrac) * rateLower + alphaFrac * rateUpper;
1520 rate.qq *= nf / 3.;
1521
1522 rate.gq = rate.qq * 9. / 4.;
1523
1524 if (alpha_s >= 0.15 && alpha_s < 0.18) {
1525 d[0][0] = 0.9364689080337059;
1526 d[1][0] = 1.1485486950080581;
1527 d[0][1] = 2.626076478553979;
1528 d[1][1] = 4.993647646894147;
1529 d[0][2] = 2.1171556605834274;
1530 d[1][2] = 3.7295251994302876;
1531 d[0][3] = 0.13123339226210134;
1532 d[1][3] = -0.0017620287506503757;
1533 d[0][4] = 0.02875811664147147;
1534 d[1][4] = 0.010598257485913224;
1535 d[0][5] = 0.27736469898722244;
1536 d[1][5] = 0.3949856219367327;
1537 } else if (alpha_s >= 0.18 && alpha_s < 0.21) {
1538 d[0][0] = 1.1485486950080581;
1539 d[1][0] = 1.3645568637616001;
1540 d[0][1] = 4.993647646894147;
1541 d[1][1] = 8.174225869366722;
1542 d[0][2] = 3.7295251994302876;
1543 d[1][2] = 5.732101892684938;
1544 d[0][3] = -0.001762028750650376;
1545 d[1][3] = -0.1416811579957863;
1546 d[0][4] = 0.010598257485913224;
1547 d[1][4] = 0.011703596451947428;
1548 d[0][5] = 0.3949856219367327;
1549 d[1][5] = 0.5354757997870718;
1550 } else if (alpha_s >= 0.21 && alpha_s < 0.24) {
1551 d[0][0] = 1.3645568637616001;
1552 d[1][0] = 1.5839378568555678;
1553 d[0][1] = 8.174225869366722;
1554 d[1][1] = 11.785897000063443;
1555 d[0][2] = 5.732101892684938;
1556 d[1][2] = 7.758388282689373;
1557 d[0][3] = -0.1416811579957863;
1558 d[1][3] = -0.13163385415183002;
1559 d[0][4] = 0.011703596451947428;
1560 d[1][4] = 0.09016386041913003;
1561 d[0][5] = 0.5354757997870718;
1562 d[1][5] = 0.7042577279136836;
1563 } else if (alpha_s >= 0.24 && alpha_s < 0.27) {
1564 d[0][0] = 1.5839378568555678;
1565 d[1][0] = 1.8062676019060235;
1566 d[0][1] = 11.785897000063443;
1567 d[1][1] = 15.344112642069764;
1568 d[0][2] = 7.758388282689373;
1569 d[1][2] = 9.384190917330093;
1570 d[0][3] = -0.13163385415183002;
1571 d[1][3] = 0.19709400976261568;
1572 d[0][4] = 0.09016386041913003;
1573 d[1][4] = 0.30577623140224813;
1574 d[0][5] = 0.7042577279136836;
1575 d[1][5] = 0.9066501895009754;
1576 } else if (alpha_s >= 0.27 && alpha_s < 0.3) {
1577 d[0][0] = 1.8062676019060235;
1578 d[1][0] = 2.0312125903238236;
1579 d[0][1] = 15.344112642069764;
1580 d[1][1] = 18.36844006721506;
1581 d[0][2] = 9.384190917330093;
1582 d[1][2] = 10.209988454804193;
1583 d[0][3] = 0.19709400976261568;
1584 d[1][3] = 0.9957025988944573;
1585 d[0][4] = 0.30577623140224813;
1586 d[1][4] = 0.7109302867706849;
1587 d[0][5] = 0.9066501895009754;
1588 d[1][5] = 1.1472148515742653;
1589 } else if (alpha_s >= 0.3 && alpha_s < 0.33) {
1590 d[0][0] = 2.0312125903238236;
1591 d[1][0] = 2.258502734110078;
1592 d[0][1] = 18.36844006721506;
1593 d[1][1] = 20.43444928479894;
1594 d[0][2] = 10.209988454804193;
1595 d[1][2] = 9.896928897847518;
1596 d[0][3] = 0.9957025988944573;
1597 d[1][3] = 2.3867073785159003;
1598 d[0][4] = 0.7109302867706849;
1599 d[1][4] = 1.3473328178504662;
1600 d[0][5] = 1.1472148515742653;
1601 d[1][5] = 1.429497460496924;
1602 } else if (alpha_s >= 0.33 && alpha_s < 0.36) {
1603 d[0][0] = 2.258502734110078;
1604 d[1][0] = 2.4879110920956653;
1605 d[0][1] = 20.43444928479894;
1606 d[1][1] = 21.220550462966102;
1607 d[0][2] = 9.896928897847518;
1608 d[1][2] = 8.20639681844989;
1609 d[0][3] = 2.3867073785159003;
1610 d[1][3] = 4.445222616370339;
1611 d[0][4] = 1.3473328178504662;
1612 d[1][4] = 2.2381176005506016;
1613 d[0][5] = 1.429497460496924;
1614 d[1][5] = 1.7550164762706189;
1615 } else if (alpha_s >= 0.36 && alpha_s < 0.39) {
1616 d[0][0] = 2.4879110920956653;
1617 d[1][0] = 2.7192501243929903;
1618 d[0][1] = 21.220550462966102;
1619 d[1][1] = 20.470583876561985;
1620 d[0][2] = 8.20639681844989;
1621 d[1][2] = 4.954737209403953;
1622 d[0][3] = 4.445222616370339;
1623 d[1][3] = 7.227667929705693;
1624 d[0][4] = 2.2381176005506016;
1625 d[1][4] = 3.401378906197122;
1626 d[0][5] = 1.7550164762706189;
1627 d[1][5] = 2.1251383942923474;
1628 } else if (alpha_s >= 0.39 && alpha_s <= 0.42) {
1629 d[0][0] = 2.7192501243929903;
1630 d[1][0] = 2.9523522354248817;
1631 d[0][1] = 20.470583876561985;
1632 d[1][1] = 18.027772799078463;
1633 d[0][2] = 4.954737209403953;
1634 d[1][2] = 0.050298242947981846;
1635 d[0][3] = 7.227667929705693;
1636 d[1][3] = 10.747352232336384;
1637 d[0][4] = 3.401378906197122;
1638 d[1][4] = 4.8378133911595285;
1639 d[0][5] = 2.1251383942923474;
1640 d[1][5] = 2.5391647730624003;
1641 }
1642
1643 rateLower = T * (d[0][0] + d[0][1] / pow(u, 4.) - d[0][2] / pow(u, 3.) -
1644 d[0][3] / pow(u, 2.) + d[0][4] / pow(u, 1.5) - d[0][5] / u);
1645 rateUpper = T * (d[1][0] + d[1][1] / pow(u, 4.) - d[1][2] / pow(u, 3.) -
1646 d[1][3] / pow(u, 2.) + d[1][4] / pow(u, 1.5) - d[1][5] / u);
1647
1648 rate.qg = (1. - alphaFrac) * rateLower + alphaFrac * rateUpper;
1649 rate.qg /= 3.;
1650
1651 rate.gg = rate.qg * 9. / 4.;
1652
1653 return rate;
1654 }
1655
1656 RateElastic Martini::getRateElasPos(double u, double T) {
1657 RateElastic rate;
1658
1659 double alpha0 = 0.15;
1660 double deltaAlpha = 0.03;
1661 double iAlpha = floor((alpha_s - alpha0) / deltaAlpha + 0.001);
1662 double alphaFrac = (alpha_s - alpha0) / deltaAlpha - iAlpha;
1663 double rateLower, rateUpper;
1664 double c[2][6], d[2][6];
1665
1666 for (int i = 0; i < 2; i++)
1667 for (int j = 0; j < 6; j++) {
1668 c[i][j] = 0.;
1669 d[i][j] = 0.;
1670 }
1671
1672 if (alpha_s >= 0.15 && alpha_s < 0.18) {
1673 c[0][0] = 0.12199410313320332;
1674 c[1][0] = 0.15243607717720586;
1675 c[0][1] = 0.23732051765097376;
1676 c[1][1] = 0.5403120875137825;
1677 c[0][2] = -0.03285419708803458;
1678 c[1][2] = 0.06440920730334501;
1679 c[0][3] = 0.2255419254079952;
1680 c[1][3] = 0.2881594349535524;
1681 c[0][4] = 0.03991522899907729;
1682 c[1][4] = 0.04948438583750772;
1683 c[0][5] = 0.05022641428394594;
1684 c[1][5] = 0.07152523367501308;
1685 } else if (alpha_s >= 0.18 && alpha_s < 0.21) {
1686 c[0][0] = 0.15243607717720586;
1687 c[1][0] = 0.15243607717720586;
1688 c[0][1] = 0.5403120875137825;
1689 c[1][1] = 0.5403120875137825;
1690 c[0][2] = 0.06440920730334501;
1691 c[1][2] = 0.06440920730334501;
1692 c[0][3] = 0.2881594349535524;
1693 c[1][3] = 0.2881594349535524;
1694 c[0][4] = 0.04948438583750772;
1695 c[1][4] = 0.04948438583750772;
1696 c[0][5] = 0.07152523367501308;
1697 c[1][5] = 0.07152523367501308;
1698 } else if (alpha_s >= 0.21 && alpha_s < 0.24) {
1699 c[0][0] = 0.15243607717720586;
1700 c[1][0] = 0.21661000995329158;
1701 c[0][1] = 0.5403120875137825;
1702 c[1][1] = 1.4087570376612657;
1703 c[0][2] = 0.06440920730334501;
1704 c[1][2] = 0.2713885880193171;
1705 c[0][3] = 0.2881594349535524;
1706 c[1][3] = 0.48681971936565244;
1707 c[0][4] = 0.04948438583750772;
1708 c[1][4] = 0.09567346780679847;
1709 c[0][5] = 0.07152523367501308;
1710 c[1][5] = 0.12780677622585393;
1711 } else if (alpha_s >= 0.24 && alpha_s < 0.27) {
1712 c[0][0] = 0.21661000995329158;
1713 c[1][0] = 0.2501007467879627;
1714 c[0][1] = 1.4087570376612657;
1715 c[1][1] = 1.8034683081244214;
1716 c[0][2] = 0.2713885880193171;
1717 c[1][2] = 0.228092470920281;
1718 c[0][3] = 0.48681971936565244;
1719 c[1][3] = 0.6841577896561725;
1720 c[0][4] = 0.09567346780679847;
1721 c[1][4] = 0.15430793601338547;
1722 c[0][5] = 0.12780677622585393;
1723 c[1][5] = 0.1648297331159989;
1724 } else if (alpha_s >= 0.27 && alpha_s < 0.3) {
1725 c[0][0] = 0.2501007467879627;
1726 c[1][0] = 0.28440720063047276;
1727 c[0][1] = 1.8034683081244214;
1728 c[1][1] = 2.0448244620634055;
1729 c[0][2] = 0.228092470920281;
1730 c[1][2] = -0.018574547528236382;
1731 c[0][3] = 0.6841577896561725;
1732 c[1][3] = 0.9863974758613413;
1733 c[0][4] = 0.15430793601338547;
1734 c[1][4] = 0.2503738253300167;
1735 c[0][5] = 0.1648297331159989;
1736 c[1][5] = 0.2090067594645225;
1737 } else if (alpha_s >= 0.3 && alpha_s < 0.33) {
1738 c[0][0] = 0.28440720063047276;
1739 c[1][0] = 0.31945943548344036;
1740 c[0][1] = 2.0448244620634055;
1741 c[1][1] = 2.0482495934952256;
1742 c[0][2] = -0.018574547528236382;
1743 c[1][2] = -0.5350999123662686;
1744 c[0][3] = 0.9863974758613413;
1745 c[1][3] = 1.4169725257394696;
1746 c[0][4] = 0.2503738253300167;
1747 c[1][4] = 0.3918202096574105;
1748 c[0][5] = 0.2090067594645225;
1749 c[1][5] = 0.26103455441873036;
1750 } else if (alpha_s >= 0.33 && alpha_s < 0.36) {
1751 c[0][0] = 0.31945943548344036;
1752 c[1][0] = 0.35519799231686516;
1753 c[0][1] = 2.0482495934952256;
1754 c[1][1] = 1.7485135425544152;
1755 c[0][2] = -0.5350999123662686;
1756 c[1][2] = -1.3692232011881413;
1757 c[0][3] = 1.4169725257394696;
1758 c[1][3] = 1.9906086576701993;
1759 c[0][4] = 0.3918202096574105;
1760 c[1][4] = 0.5832315715098879;
1761 c[0][5] = 0.26103455441873036;
1762 c[1][5] = 0.32124694953933486;
1763 } else if (alpha_s >= 0.36 && alpha_s < 0.39) {
1764 c[0][0] = 0.35519799231686516;
1765 c[1][0] = 0.39157507493019383;
1766 c[0][1] = 1.7485135425544152;
1767 c[1][1] = 1.0778995684787331;
1768 c[0][2] = -1.3692232011881413;
1769 c[1][2] = -2.5738838613236457;
1770 c[0][3] = 1.9906086576701993;
1771 c[1][3] = 2.727543221296746;
1772 c[0][4] = 0.5832315715098879;
1773 c[1][4] = 0.8323699786704292;
1774 c[0][5] = 0.32124694953933486;
1775 c[1][5] = 0.3905055907877247;
1776 } else if (alpha_s >= 0.39 && alpha_s <= 0.42) {
1777 c[0][0] = 0.39157507493019383;
1778 c[1][0] = 0.4285382777192131;
1779 c[0][1] = 1.0778995684787331;
1780 c[1][1] = 0.05505396151716547;
1781 c[0][2] = -2.5738838613236457;
1782 c[1][2] = -4.113979132685303;
1783 c[0][3] = 2.727543221296746;
1784 c[1][3] = 3.5992808060371506;
1785 c[0][4] = 0.8323699786704292;
1786 c[1][4] = 1.1252568207814462;
1787 c[0][5] = 0.3905055907877247;
1788 c[1][5] = 0.4667953957378259;
1789 }
1790
1791 rateLower = T * (c[0][0] + c[0][1] / pow(u, 4.) - c[0][2] / pow(u, 3.) -
1792 c[0][3] / pow(u, 2.) + c[0][4] / pow(u, 1.5) - c[0][5] / u);
1793 rateUpper = T * (c[1][0] + c[1][1] / pow(u, 4.) - c[1][2] / pow(u, 3.) -
1794 c[1][3] / pow(u, 2.) + c[1][4] / pow(u, 1.5) - c[1][5] / u);
1795
1796 rate.qq = (1. - alphaFrac) * rateLower + alphaFrac * rateUpper;
1797 rate.qq *= nf / 3.;
1798
1799 rate.gq = rate.qq * 9. / 4.;
1800
1801 if (alpha_s >= 0.15 && alpha_s < 0.18) {
1802 d[0][0] = 0.6197775378922895;
1803 d[1][0] = 0.7680959463632293;
1804 d[0][1] = 1.5268694134079064;
1805 d[1][1] = 3.282164035377037;
1806 d[0][2] = 0.6939337312845367;
1807 d[1][2] = 1.6359849897319092;
1808 d[0][3] = 0.5967602676773388;
1809 d[1][3] = 0.6770046238563808;
1810 d[0][4] = 0.17320784052297564;
1811 d[1][4] = 0.22074166337990309;
1812 d[0][5] = 0.28964614117694565;
1813 d[1][5] = 0.4128184793199476;
1814 } else if (alpha_s >= 0.18 && alpha_s < 0.21) {
1815 d[0][0] = 0.7680959463632293;
1816 d[1][0] = 0.9206225398305536;
1817 d[0][1] = 3.282164035377037;
1818 d[1][1] = 5.690562370150853;
1819 d[0][2] = 1.6359849897319092;
1820 d[1][2] = 2.8341906487774318;
1821 d[0][3] = 0.6770046238563808;
1822 d[1][3] = 0.7900156706763937;
1823 d[0][4] = 0.22074166337990309;
1824 d[1][4] = 0.2995126102416747;
1825 d[0][5] = 0.4128184793199476;
1826 d[1][5] = 0.5598645426609049;
1827 } else if (alpha_s >= 0.21 && alpha_s < 0.24) {
1828 d[0][0] = 0.9206225398305536;
1829 d[1][0] = 1.0767954081327265;
1830 d[0][1] = 5.690562370150853;
1831 d[1][1] = 8.378841394880034;
1832 d[0][2] = 2.8341906487774318;
1833 d[1][2] = 3.9338968631891396;
1834 d[0][3] = 0.7900156706763937;
1835 d[1][3] = 1.0874771229885156;
1836 d[0][4] = 0.2995126102416747;
1837 d[1][4] = 0.46570985770548107;
1838 d[0][5] = 0.5598645426609049;
1839 d[1][5] = 0.7360069767362173;
1840 } else if (alpha_s >= 0.24 && alpha_s < 0.27) {
1841 d[0][0] = 1.0767954081327265;
1842 d[1][0] = 1.2361819653856791;
1843 d[0][1] = 8.378841394880034;
1844 d[1][1] = 10.877148035367144;
1845 d[0][2] = 3.9338968631891396;
1846 d[1][2] = 4.526191560392149;
1847 d[0][3] = 1.0874771229885156;
1848 d[1][3] = 1.731930015138816;
1849 d[0][4] = 0.46570985770548107;
1850 d[1][4] = 0.7769917594310469;
1851 d[0][5] = 0.7360069767362173;
1852 d[1][5] = 0.9463662091275489;
1853 } else if (alpha_s >= 0.27 && alpha_s < 0.3) {
1854 d[0][0] = 1.2361819653856791;
1855 d[1][0] = 1.3984393292278847;
1856 d[0][1] = 10.877148035367144;
1857 d[1][1] = 12.72181515837248;
1858 d[0][2] = 4.526191560392149;
1859 d[1][2] = 4.227297031355039;
1860 d[0][3] = 1.731930015138816;
1861 d[1][3] = 2.868526983329731;
1862 d[0][4] = 0.7769917594310469;
1863 d[1][4] = 1.2836917844304823;
1864 d[0][5] = 0.9463662091275489;
1865 d[1][5] = 1.1953148369630755;
1866 } else if (alpha_s >= 0.3 && alpha_s < 0.33) {
1867 d[0][0] = 1.3984393292278847;
1868 d[1][0] = 1.5632880021613935;
1869 d[0][1] = 12.72181515837248;
1870 d[1][1] = 13.502896915302873;
1871 d[0][2] = 4.227297031355039;
1872 d[1][2] = 2.7113406243010467;
1873 d[0][3] = 2.868526983329731;
1874 d[1][3] = 4.615035662049938;
1875 d[0][4] = 1.2836917844304823;
1876 d[1][4] = 2.0259357821768784;
1877 d[0][5] = 1.1953148369630755;
1878 d[1][5] = 1.486253368704046;
1879 } else if (alpha_s >= 0.33 && alpha_s < 0.36) {
1880 d[0][0] = 1.5632880021613935;
1881 d[1][0] = 1.730492163581557;
1882 d[0][1] = 13.502896915302873;
1883 d[1][1] = 12.913294655478987;
1884 d[0][2] = 2.7113406243010467;
1885 d[1][2] = -0.2477159937428581;
1886 d[0][3] = 4.615035662049938;
1887 d[1][3] = 7.042004003229154;
1888 d[0][4] = 2.0259357821768784;
1889 d[1][4] = 3.0253452576771465;
1890 d[0][5] = 1.486253368704046;
1891 d[1][5] = 1.8205651561017433;
1892 } else if (alpha_s >= 0.36 && alpha_s < 0.39) {
1893 d[0][0] = 1.730492163581557;
1894 d[1][0] = 1.8998560359992867;
1895 d[0][1] = 12.913294655478987;
1896 d[1][1] = 10.708892844334745;
1897 d[0][2] = -0.2477159937428581;
1898 d[1][2] = -4.823210983922782;
1899 d[0][3] = 7.042004003229154;
1900 d[1][3] = 10.202109059054063;
1901 d[0][4] = 3.0253452576771465;
1902 d[1][4] = 4.298747764427364;
1903 d[0][5] = 1.8205651561017433;
1904 d[1][5] = 2.199497022778097;
1905 } else if (alpha_s >= 0.39 && alpha_s <= 0.42) {
1906 d[0][0] = 1.8998560359992867;
1907 d[1][0] = 2.071204284004704;
1908 d[0][1] = 10.708892844334745;
1909 d[1][1] = 6.741738604119316;
1910 d[0][2] = -4.823210983922782;
1911 d[1][2] = -11.099716230158746;
1912 d[0][3] = 10.202109059054063;
1913 d[1][3] = 14.106488110189458;
1914 d[0][4] = 4.298747764427364;
1915 d[1][4] = 5.846203546614067;
1916 d[0][5] = 2.199497022778097;
1917 d[1][5] = 2.62230136903594;
1918 }
1919
1920 rateLower = T * (d[0][0] + d[0][1] / pow(u, 4.) - d[0][2] / pow(u, 3.) -
1921 d[0][3] / pow(u, 2.) + d[0][4] / pow(u, 1.5) - d[0][5] / u);
1922 rateUpper = T * (d[1][0] + d[1][1] / pow(u, 4.) - d[1][2] / pow(u, 3.) -
1923 d[1][3] / pow(u, 2.) + d[1][4] / pow(u, 1.5) - d[1][5] / u);
1924
1925 rate.qg = (1. - alphaFrac) * rateLower + alphaFrac * rateUpper;
1926 rate.qg /= 3.;
1927
1928 rate.gg = rate.qg * 9. / 4.;
1929
1930 return rate;
1931 }
1932
1933 RateElastic Martini::getRateElasNeg(double u, double T) {
1934 RateElastic rate;
1935
1936 double alpha0 = 0.15;
1937 double deltaAlpha = 0.03;
1938 double iAlpha = floor((alpha_s - alpha0) / deltaAlpha + 0.001);
1939 double alphaFrac = (alpha_s - alpha0) / deltaAlpha - iAlpha;
1940 double rateLower, rateUpper;
1941 double c[2][6], d[2][6];
1942
1943 for (int i = 0; i < 2; i++)
1944 for (int j = 0; j < 6; j++) {
1945 c[i][j] = 0.;
1946 d[i][j] = 0.;
1947 }
1948
1949 if (alpha_s >= 0.15 && alpha_s < 0.18) {
1950 c[0][0] = 0.059730780828164666;
1951 c[1][0] = 0.07216040121873951;
1952 c[0][1] = 0.3631534872548789;
1953 c[1][1] = 0.5471138972952214;
1954 c[0][2] = 0.39845046966687;
1955 c[1][2] = 0.5792306465939813;
1956 c[0][3] = 0.11946615972422633;
1957 c[1][3] = 0.1723078888161528;
1958 c[0][4] = 0.03559276204445307;
1959 c[1][4] = 0.05120408756812135;
1960 c[0][5] = 0.00291041965645416;
1961 c[1][5] = 0.0041777787108426695;
1962 } else if (alpha_s >= 0.18 && alpha_s < 0.21) {
1963 c[0][0] = 0.07216040121873951;
1964 c[1][0] = 0.0846236909779996;
1965 c[0][1] = 0.5471138972952214;
1966 c[1][1] = 0.7725791286875564;
1967 c[0][2] = 0.5792306465939813;
1968 c[1][2] = 0.7931123494736929;
1969 c[0][3] = 0.1723078888161528;
1970 c[1][3] = 0.23406373724706608;
1971 c[0][4] = 0.05120408756812135;
1972 c[1][4] = 0.06935459958589639;
1973 c[0][5] = 0.0041777787108426695;
1974 c[1][5] = 0.005644055718614478;
1975 } else if (alpha_s >= 0.21 && alpha_s < 0.24) {
1976 c[0][0] = 0.0846236909779996;
1977 c[1][0] = 0.09711346786308672;
1978 c[0][1] = 0.7725791286875564;
1979 c[1][1] = 1.0370070423372528;
1980 c[0][2] = 0.7931123494736929;
1981 c[1][2] = 1.036935526583188;
1982 c[0][3] = 0.23406373724706608;
1983 c[1][3] = 0.3034025403259155;
1984 c[0][4] = 0.06935459958589639;
1985 c[1][4] = 0.08957509599955729;
1986 c[0][5] = 0.005644055718614478;
1987 c[1][5] = 0.007264393465593115;
1988 } else if (alpha_s >= 0.24 && alpha_s < 0.27) {
1989 c[0][0] = 0.09711346786308672;
1990 c[1][0] = 0.10962479860948156;
1991 c[0][1] = 1.0370070423372528;
1992 c[1][1] = 1.3372010137066646;
1993 c[0][2] = 1.036935526583188;
1994 c[1][2] = 1.307456863105879;
1995 c[0][3] = 0.3034025403259155;
1996 c[1][3] = 0.37910328734850873;
1997 c[0][4] = 0.08957509599955729;
1998 c[1][4] = 0.111456899829735;
1999 c[0][5] = 0.007264393465593115;
2000 c[1][5] = 0.009000895144744121;
2001 } else if (alpha_s >= 0.27 && alpha_s < 0.3) {
2002 c[0][0] = 0.10962479860948156;
2003 c[1][0] = 0.1221541053951596;
2004 c[0][1] = 1.3372010137066646;
2005 c[1][1] = 1.6686065099273535;
2006 c[0][2] = 1.307456863105879;
2007 c[1][2] = 1.600404353394210;
2008 c[0][3] = 0.37910328734850873;
2009 c[1][3] = 0.4594932213772782;
2010 c[0][4] = 0.111456899829735;
2011 c[1][4] = 0.13442407314203592;
2012 c[0][5] = 0.009000895144744121;
2013 c[1][5] = 0.010800449048880756;
2014 } else if (alpha_s >= 0.3 && alpha_s < 0.33) {
2015 c[0][0] = 0.1221541053951596;
2016 c[1][0] = 0.13469861652518803;
2017 c[0][1] = 1.6686065099273535;
2018 c[1][1] = 2.0276317271182074;
2019 c[0][2] = 1.600404353394210;
2020 c[1][2] = 1.912613330851788;
2021 c[0][3] = 0.4594932213772782;
2022 c[1][3] = 0.5434449889160747;
2023 c[0][4] = 0.13442407314203592;
2024 c[1][4] = 0.15810564016236883;
2025 c[0][5] = 0.010800449048880756;
2026 c[1][5] = 0.012629305933671075;
2027 } else if (alpha_s >= 0.33 && alpha_s < 0.36) {
2028 c[0][0] = 0.13469861652518803;
2029 c[1][0] = 0.14725614907227047;
2030 c[0][1] = 2.0276317271182074;
2031 c[1][1] = 2.4109122726272654;
2032 c[0][2] = 1.912613330851788;
2033 c[1][2] = 2.241198157777867;
2034 c[0][3] = 0.5434449889160747;
2035 c[1][3] = 0.6299396046048817;
2036 c[0][4] = 0.15810564016236883;
2037 c[1][4] = 0.18216575652552597;
2038 c[0][5] = 0.012629305933671075;
2039 c[1][5] = 0.014456750325370632;
2040 } else if (alpha_s >= 0.36 && alpha_s < 0.39) {
2041 c[0][0] = 0.14725614907227047;
2042 c[1][0] = 0.15982489441001274;
2043 c[0][1] = 2.4109122726272654;
2044 c[1][1] = 2.815254291049982;
2045 c[0][2] = 2.241198157777867;
2046 c[1][2] = 2.583462624103292;
2047 c[0][3] = 0.6299396046048817;
2048 c[1][3] = 0.7180274724508857;
2049 c[0][4] = 0.18216575652552597;
2050 c[1][4] = 0.20629432847931367;
2051 c[0][5] = 0.014456750325370632;
2052 c[1][5] = 0.01625568033747704;
2053 } else if (alpha_s >= 0.39 && alpha_s <= 0.42) {
2054 c[0][0] = 0.15982489441001274;
2055 c[1][0] = 0.17240331582158486;
2056 c[0][1] = 2.815254291049982;
2057 c[1][1] = 3.238290376079149;
2058 c[0][2] = 2.583462624103292;
2059 c[1][2] = 2.9374985881586273;
2060 c[0][3] = 0.7180274724508857;
2061 c[1][3] = 0.8071008047950518;
2062 c[0][4] = 0.20629432847931367;
2063 c[1][4] = 0.23030341585944009;
2064 c[0][5] = 0.01625568033747704;
2065 c[1][5] = 0.018010096397556033;
2066 }
2067
2068 rateLower = T * (c[0][0] + c[0][1] / pow(u, 4.) - c[0][2] / pow(u, 3.) -
2069 c[0][3] / pow(u, 2.) + c[0][4] / pow(u, 1.5) - c[0][5] / u);
2070 rateUpper = T * (c[1][0] + c[1][1] / pow(u, 4.) - c[1][2] / pow(u, 3.) -
2071 c[1][3] / pow(u, 2.) + c[1][4] / pow(u, 1.5) - c[1][5] / u);
2072
2073 rate.qq = (1. - alphaFrac) * rateLower + alphaFrac * rateUpper;
2074 rate.qq *= nf / 3.;
2075
2076 rate.gq = rate.qq * 9. / 4.;
2077
2078 if (alpha_s >= 0.15 && alpha_s < 0.18) {
2079 d[0][0] = 0.3166913701414167;
2080 d[1][0] = 0.3804527486448292;
2081 d[0][1] = 1.0992070651449564;
2082 d[1][1] = 1.7114836115114735;
2083 d[0][2] = 1.4232219292986843;
2084 d[1][2] = 2.093540209692791;
2085 d[0][3] = 0.4655268754156213;
2086 d[1][3] = 0.6787666526042345;
2087 d[0][4] = 0.1444497238817506;
2088 d[1][4] = 0.21014340589291994;
2089 d[0][5] = 0.012281442189758532;
2090 d[1][5] = 0.017832857383112792;
2091 } else if (alpha_s >= 0.18 && alpha_s < 0.21) {
2092 d[0][0] = 0.3804527486448292;
2093 d[1][0] = 0.44393432393104637;
2094 d[0][1] = 1.7114836115114735;
2095 d[1][1] = 2.483663499207573;
2096 d[0][2] = 2.093540209692791;
2097 d[1][2] = 2.8979112438999044;
2098 d[0][3] = 0.6787666526042345;
2099 d[1][3] = 0.9316968286688833;
2100 d[0][4] = 0.21014340589291994;
2101 d[1][4] = 0.28780901378857465;
2102 d[0][5] = 0.017832857383112792;
2103 d[1][5] = 0.02438874287373154;
2104 } else if (alpha_s >= 0.21 && alpha_s < 0.24) {
2105 d[0][0] = 0.44393432393104637;
2106 d[1][0] = 0.5071424487228405;
2107 d[0][1] = 2.483663499207573;
2108 d[1][1] = 3.4070556051784515;
2109 d[0][2] = 2.8979112438999044;
2110 d[1][2] = 3.824491419496227;
2111 d[0][3] = 0.9316968286688833;
2112 d[1][3] = 1.2191109771387096;
2113 d[0][4] = 0.28780901378857465;
2114 d[1][4] = 0.3755459972857442;
2115 d[0][5] = 0.02438874287373154;
2116 d[1][5] = 0.03174924882247299;
2117 } else if (alpha_s >= 0.24 && alpha_s < 0.27) {
2118 d[0][0] = 0.5071424487228405;
2119 d[1][0] = 0.5700856365203443;
2120 d[0][1] = 3.4070556051784515;
2121 d[1][1] = 4.466964606692036;
2122 d[0][2] = 3.824491419496227;
2123 d[1][2] = 4.857999356928031;
2124 d[0][3] = 1.2191109771387096;
2125 d[1][3] = 1.5348360053714125;
2126 d[0][4] = 0.3755459972857442;
2127 d[1][4] = 0.471215528026891;
2128 d[0][5] = 0.03174924882247299;
2129 d[1][5] = 0.03971601962636114;
2130 } else if (alpha_s >= 0.27 && alpha_s < 0.3) {
2131 d[0][0] = 0.5700856365203443;
2132 d[1][0] = 0.6327732610959403;
2133 d[0][1] = 4.466964606692036;
2134 d[1][1] = 5.646624908846933;
2135 d[0][2] = 4.857999356928031;
2136 d[1][2] = 5.982691423451806;
2137 d[0][3] = 1.5348360053714125;
2138 d[1][3] = 1.8728243844356356;
2139 d[0][4] = 0.471215528026891;
2140 d[1][4] = 0.572761497659723;
2141 d[0][5] = 0.03971601962636114;
2142 d[1][5] = 0.04809998538877525;
2143 } else if (alpha_s >= 0.3 && alpha_s < 0.33) {
2144 d[0][0] = 0.6327732610959403;
2145 d[1][0] = 0.6952147319486842;
2146 d[0][1] = 5.646624908846933;
2147 d[1][1] = 6.931552369487635;
2148 d[0][2] = 5.982691423451806;
2149 d[1][2] = 7.185588273540373;
2150 d[0][3] = 1.8728243844356356;
2151 d[1][3] = 2.228328283532209;
2152 d[0][4] = 0.572761497659723;
2153 d[1][4] = 0.6786029643259804;
2154 d[0][5] = 0.04809998538877525;
2155 d[1][5] = 0.056755908207122875;
2156 } else if (alpha_s >= 0.33 && alpha_s < 0.36) {
2157 d[0][0] = 0.6952147319486842;
2158 d[1][0] = 0.7574189285141091;
2159 d[0][1] = 6.931552369487635;
2160 d[1][1] = 8.307255807497631;
2161 d[0][2] = 7.185588273540373;
2162 d[1][2] = 8.454112812202247;
2163 d[0][3] = 2.228328283532209;
2164 d[1][3] = 2.596781386863294;
2165 d[0][4] = 0.6786029643259804;
2166 d[1][4] = 0.7872276571283385;
2167 d[0][5] = 0.056755908207122875;
2168 d[1][5] = 0.06554867983133447;
2169 } else if (alpha_s >= 0.36 && alpha_s < 0.39) {
2170 d[0][0] = 0.7574189285141091;
2171 d[1][0] = 0.8193940883937045;
2172 d[0][1] = 8.307255807497631;
2173 d[1][1] = 9.761691032241623;
2174 d[0][2] = 8.454112812202247;
2175 d[1][2] = 9.777948193339808;
2176 d[0][3] = 2.596781386863294;
2177 d[1][3] = 2.9744411293541457;
2178 d[0][4] = 0.7872276571283385;
2179 d[1][4] = 0.8973688582323887;
2180 d[0][5] = 0.06554867983133447;
2181 d[1][5] = 0.07435862848596686;
2182 } else if (alpha_s >= 0.39 && alpha_s <= 0.42) {
2183 d[0][0] = 0.8193940883937045;
2184 d[1][0] = 0.8811479514201789;
2185 d[0][1] = 9.761691032241623;
2186 d[1][1] = 11.286034194965852;
2187 d[0][2] = 9.777948193339808;
2188 d[1][2] = 11.15001447311135;
2189 d[0][3] = 2.9744411293541457;
2190 d[1][3] = 3.3591358778545803;
2191 d[0][4] = 0.8973688582323887;
2192 d[1][4] = 1.0083901554550654;
2193 d[0][5] = 0.07435862848596686;
2194 d[1][5] = 0.08313659597360733;
2195 }
2196
2197 rateLower = T * (d[0][0] + d[0][1] / pow(u, 4.) - d[0][2] / pow(u, 3.) -
2198 d[0][3] / pow(u, 2.) + d[0][4] / pow(u, 1.5) - d[0][5] / u);
2199 rateUpper = T * (d[1][0] + d[1][1] / pow(u, 4.) - d[1][2] / pow(u, 3.) -
2200 d[1][3] / pow(u, 2.) + d[1][4] / pow(u, 1.5) - d[1][5] / u);
2201
2202 rate.qg = (1. - alphaFrac) * rateLower + alphaFrac * rateUpper;
2203 rate.qg /= 3.;
2204
2205 rate.gg = rate.qg * 9. / 4.;
2206
2207 return rate;
2208 }
2209
2210 RateConversion Martini::getRateConv(double pRest, double T) {
2211 RateConversion rate;
2212
2213 rate.qg = 4. / 3. * 2. * M_PI * alpha_s * alpha_s * T * T / (3. * pRest) *
2214 (0.5 * log(pRest * T / ((1. / 6.) * pow(g * T, 2.))) - 0.36149);
2215 rate.gq = nf * 3. / 8. * 4. / 3. * 2. * M_PI * alpha_s * alpha_s * T * T /
2216 (3. * pRest) *
2217 (0.5 * log(pRest * T / ((1. / 6.) * pow(g * T, 2.))) - 0.36149);
2218 rate.qgamma = 2. * M_PI * alpha_s * alpha_em * T * T / (3. * pRest) *
2219 (0.5 * log(pRest * T / ((1. / 6.) * pow(g * T, 2.))) - 0.36149);
2220
2221 return rate;
2222 }
2223
2224 double Martini::getEnergyTransfer(double pRest, double T, int process) {
2225 double u = pRest / T;
2226
2227 double omega = 0.;
2228 double y;
2229 double x;
2230 double randA;
2231 double fy;
2232 double fyAct;
2233
2234 RateElastic Pos, Neg;
2235 Pos = getRateElasPos(u, T);
2236 Neg = getRateElasNeg(u, T);
2237
2238
2239
2240 int posNegSwitch = 1;
2241
2242
2243
2244
2245
2246
2247 if (process == 5 || process == 7)
2248 {
2249
2250
2251 if (process == 5) {
2252 if (ZeroOneDistribution(*GetMt19937Generator()) <
2253 Neg.qq / (Neg.qq + Pos.qq))
2254 posNegSwitch = 0;
2255 } else {
2256 if (ZeroOneDistribution(*GetMt19937Generator()) <
2257 Neg.gq / (Neg.gq + Pos.gq))
2258 posNegSwitch = 0;
2259 }
2260
2261 if (posNegSwitch == 1)
2262 {
2263 do {
2264 randA = ZeroOneDistribution(*GetMt19937Generator()) *
2265 areaOmega(u, posNegSwitch, process);
2266 y = exp((-1.41428 * pow(10., 9.) * alpha_s -
2267 8.08158 * pow(10., 8.) * alpha_s * alpha_s +
2268 2.02327 * pow(10., 9.) * randA) /
2269 (alpha_s *
2270 (4.72097 * pow(10., 8.) + 2.6977 * pow(10., 8.) * alpha_s)));
2271
2272 fy = alpha_s / 0.15 * (0.035 + alpha_s * 0.02) / sqrt(y * y);
2273 fyAct = functionOmega(u, y, process);
2274
2275 x = ZeroOneDistribution(*GetMt19937Generator());
2276
2277 } while (x > fyAct / fy);
2278
2279 omega = y;
2280 } else
2281 {
2282 do {
2283 randA = ZeroOneDistribution(*GetMt19937Generator()) *
2284 areaOmega(-0.05, posNegSwitch, process);
2285 y = -12. * exp(-30. * randA / (alpha_s * (7. + 4. * alpha_s)));
2286
2287 fy = alpha_s / 0.15 * (0.035 + alpha_s * 0.02) / sqrt(y * y);
2288 fyAct = functionOmega(u, y, process);
2289
2290 x = ZeroOneDistribution(*GetMt19937Generator());
2291
2292 } while (x > fyAct / fy);
2293
2294 omega = y;
2295 }
2296 } else if (process == 6 || process == 8)
2297 {
2298
2299
2300 if (process == 6) {
2301 if (ZeroOneDistribution(*GetMt19937Generator()) <
2302 Neg.qg / (Neg.qg + Pos.qg))
2303 posNegSwitch = 0;
2304 } else {
2305 if (ZeroOneDistribution(*GetMt19937Generator()) <
2306 Neg.gg / (Neg.gg + Pos.gg))
2307 posNegSwitch = 0;
2308 }
2309
2310 if (posNegSwitch == 1)
2311 {
2312 do {
2313 randA = ZeroOneDistribution(*GetMt19937Generator()) *
2314 areaOmega(u, posNegSwitch, process);
2315 y = exp((-2.32591 * pow(10., 17.) * alpha_s -
2316 1.32909 * pow(10., 17.) * alpha_s * alpha_s +
2317 2.2183 * pow(10., 17.) * randA) /
2318 (alpha_s * (7.76406 * pow(10., 16.) +
2319 4.43661 * pow(10., 16.) * alpha_s)));
2320
2321 fy = 1.5 * alpha_s / 0.15 * (0.035 + alpha_s * 0.02) / sqrt(y * y);
2322 fyAct = functionOmega(u, y, process);
2323
2324 x = ZeroOneDistribution(*GetMt19937Generator());
2325
2326 } while (x > fyAct / fy);
2327
2328 omega = y;
2329 } else
2330 {
2331 do {
2332 randA = ZeroOneDistribution(*GetMt19937Generator()) *
2333 areaOmega(-0.05, posNegSwitch, process);
2334 y = -12. * exp(-2.81475 * pow(10., 15.) * randA /
2335 (alpha_s * (9.85162 * pow(10., 14.) +
2336 5.6295 * pow(10., 14.) * alpha_s)));
2337
2338 fy = 1.5 * alpha_s / 0.15 * (0.035 + alpha_s * 0.02) / sqrt(y * y);
2339 fyAct = functionOmega(u, y, process);
2340
2341 x = ZeroOneDistribution(*GetMt19937Generator());
2342
2343 } while (x > fyAct / fy);
2344
2345 omega = y;
2346 }
2347 } else {
2348 JSWARN << "Invalid process number (" << process << ")";
2349
2350 omega = 0.;
2351 }
2352
2353 return omega * T;
2354 }
2355
2356 double Martini::getMomentumTransfer(double pRest, double omega, double T,
2357 int process) {
2358 double u = pRest / T;
2359 omega /= T;
2360
2361 double q = 0.;
2362 double y;
2363 double x;
2364 double randA;
2365 double fy;
2366 double fyAct;
2367
2368 double A, B;
2369
2370
2371
2372
2373
2374
2375
2376 if (omega < 10. && omega > -3.) {
2377 if (process == 5 || process == 7)
2378 {
2379 A = (0.7 + alpha_s) * 0.0014 *
2380 (1000. + 40. / sqrt(omega * omega) + 10.5 * pow(omega, 4.)) * alpha_s;
2381 B = 2. * sqrt(omega * omega) + 0.01;
2382 } else if (process == 6 || process == 8)
2383 {
2384 A = (0.7 + alpha_s) * 0.0022 *
2385 (1000. + 40. / sqrt(omega * omega) + 10.5 * pow(omega, 4.)) * alpha_s;
2386 B = 2. * sqrt(omega * omega) + 0.002;
2387 } else {
2388 JSWARN << "Invalid process number (" << process << ")";
2389
2390 A = 0.;
2391 B = 0.;
2392 }
2393
2394 do {
2395 randA = ZeroOneDistribution(*GetMt19937Generator()) *
2396 areaQ(u, omega, process);
2397 y = pow(B, 0.25) *
2398 sqrt(tan((2. * sqrt(B) * randA + A * atan(omega * omega / sqrt(B))) /
2399 A));
2400
2401 fy = A * y / (pow(y, 4.) + B);
2402 fyAct = functionQ(u, omega, y, process);
2403
2404 x = ZeroOneDistribution(*GetMt19937Generator());
2405
2406 } while (x > fyAct / fy);
2407
2408 q = y;
2409 }
2410
2411 else if (omega < 40.) {
2412 double g = 0, g_new = 0;
2413 double ratio;
2414 double y_new;
2415
2416
2417 const double y_min = sqrt(omega * omega);
2418 const double y_max = u;
2419
2420 int count = 0;
2421
2422 do {
2423 y = y_min + ZeroOneDistribution(*GetMt19937Generator()) * (y_max - y_min);
2424 g = functionQ(u, omega, y, process);
2425
2426
2427 if (count > 100)
2428 return 0.;
2429 count++;
2430 } while (g == 0.);
2431
2432
2433 const int n_steps = 500;
2434
2435 for (int i = 0; i < n_steps; i++) {
2436 do {
2437 y_new = y_min +
2438 ZeroOneDistribution(*GetMt19937Generator()) * (y_max - y_min);
2439 } while (y_new < y_min || y_new > y_max);
2440
2441
2442
2443 g_new = functionQ(u, omega, y_new, process);
2444
2445 ratio = g_new / g;
2446
2447
2448 if (ZeroOneDistribution(*GetMt19937Generator()) < ratio) {
2449 y = y_new;
2450 g = g_new;
2451 }
2452 }
2453 q = y;
2454 }
2455
2456 else {
2457 q = omega;
2458 }
2459
2460 return q * T;
2461 }
2462
2463
2464
2465 double Martini::areaOmega(double u, int posNegSwitch, int process) {
2466 if (process == 5 || process == 7) {
2467 if (posNegSwitch == 1)
2468 return (0.0333333 * alpha_s * (7. + 4. * alpha_s) * (2.99573 + log(u)));
2469 else
2470 return (-0.133333 * alpha_s * (1.75 + alpha_s) * log(-0.0833333 * u));
2471 } else if (process == 6 || process == 8) {
2472 if (posNegSwitch == 1)
2473 return (0.05 * alpha_s * (7. + 4. * alpha_s) * (2.99573 + log(u)));
2474 else
2475 return (-0.2 * alpha_s * (1.75 + alpha_s) * log(-0.0833333 * u));
2476 } else {
2477 JSWARN << "Invalid process number (" << process << ")";
2478 }
2479
2480 return 0.;
2481 }
2482
2483 double Martini::areaQ(double u, double omega, int process) {
2484 double A, B;
2485 double areaQ;
2486
2487 if (process == 5 || process == 7) {
2488 A = (0.7 + alpha_s - 0.3) * 0.0014 * alpha_s *
2489 (1000. + 40. / sqrt(omega * omega) + 10.5 * pow(omega, 4.));
2490 B = 2. * sqrt(omega * omega) + 0.01;
2491 } else if (process == 6 || process == 8) {
2492 A = (0.7 + alpha_s - 0.3) * 0.0022 * alpha_s *
2493 (1000. + 40. / sqrt(omega * omega) + 10.5 * pow(omega, 4.));
2494 B = 2. * sqrt(omega * omega) + 0.002;
2495 } else {
2496 JSWARN << "Invalid process number (" << process << ")";
2497
2498 A = 0.;
2499 B = 0.;
2500 }
2501 areaQ = (0.5 * A * (atan(u * u / sqrt(B)) - atan(omega * omega / sqrt(B)))) /
2502 sqrt(B);
2503
2504 return areaQ;
2505 }
2506
2507 FourVector Martini::getNewMomentumElas(FourVector pVec, double omega,
2508 double q) {
2509 FourVector pVecNew, pVecNewTemp;
2510 FourVector etVec, qtVec, qlVec;
2511 FourVector r;
2512 double qt, ql;
2513 double cosTheta_pq;
2514 double pAbs = pVec.t();
2515 double phi;
2516 double M[3][3];
2517 double u;
2518 double xx, yy, zz, tt;
2519
2520 if (omega == q) {
2521 xx = pVec.x() * (pAbs - omega) / pAbs;
2522 yy = pVec.y() * (pAbs - omega) / pAbs;
2523 zz = pVec.z() * (pAbs - omega) / pAbs;
2524 tt = pVec.t() * (pAbs - omega) / pAbs;
2525
2526 pVecNew.Set(xx, yy, zz, tt);
2527 return pVecNew;
2528 }
2529
2530 cosTheta_pq = (-omega * omega + 2. * pAbs * omega + q * q) / (2. * pAbs * q);
2531 qt = q * sqrt(1. - cosTheta_pq * cosTheta_pq);
2532 ql = q * cosTheta_pq;
2533
2534 if (pVec.y() * pVec.y() > pVec.x() * pVec.x()) {
2535 xx = 0.;
2536 yy = -pVec.z();
2537 zz = pVec.y();
2538 } else {
2539 xx = pVec.z();
2540 yy = 0.;
2541 zz = -pVec.x();
2542 }
2543
2544 tt = sqrt(xx * xx + yy * yy + zz * zz);
2545 etVec.Set(xx / tt, yy / tt, zz / tt, 1.);
2546
2547
2548 qtVec.Set(etVec.x() * qt, etVec.y() * qt, etVec.z() * qt, etVec.t() * qt);
2549
2550 qlVec.Set(pVec.x() / pAbs * ql, pVec.y() / pAbs * ql, pVec.z() / pAbs * ql,
2551 pVec.t() / pAbs * ql);
2552
2553 pVecNewTemp = pVec;
2554 pVecNewTemp -= qtVec;
2555 pVecNewTemp -= qlVec;
2556
2557 phi = 2. * M_PI * ZeroOneDistribution(*GetMt19937Generator());
2558 r.Set(pVec.x() / pVec.t(), pVec.y() / pVec.t(), pVec.z() / pVec.t(), 1.);
2559 u = 1. - cos(phi);
2560
2561
2562 M[0][0] = r.x() * r.x() * u + cos(phi);
2563 M[1][0] = r.x() * r.y() * u - r.z() * sin(phi);
2564 M[2][0] = r.x() * r.z() * u + r.y() * sin(phi);
2565
2566 M[0][1] = r.y() * r.x() * u + r.z() * sin(phi);
2567 M[1][1] = r.y() * r.y() * u + cos(phi);
2568 M[2][1] = r.y() * r.z() * u - r.x() * sin(phi);
2569
2570 M[0][2] = r.z() * r.x() * u - r.y() * sin(phi);
2571 M[1][2] = r.z() * r.y() * u + r.x() * sin(phi);
2572 M[2][2] = r.z() * r.z() * u + cos(phi);
2573
2574 xx = M[0][0] * pVecNewTemp.x() + M[0][1] * pVecNewTemp.y() +
2575 M[0][2] * pVecNewTemp.z();
2576 yy = M[1][0] * pVecNewTemp.x() + M[1][1] * pVecNewTemp.y() +
2577 M[1][2] * pVecNewTemp.z();
2578 zz = M[2][0] * pVecNewTemp.x() + M[2][1] * pVecNewTemp.y() +
2579 M[2][2] * pVecNewTemp.z();
2580 tt = sqrt(xx * xx + yy * yy + zz * zz);
2581
2582 pVecNew.Set(xx, yy, zz, tt);
2583 return pVecNew;
2584 }
2585
2586 FourVector Martini::getThermalVec(FourVector qVec, double T, int id) {
2587 int kind = 1;
2588 if (fabs(id) < 4)
2589 kind = 1;
2590 else if (id == 21)
2591 kind = -1;
2592
2593 FourVector kVec;
2594 double k, k_min;
2595 double cosTh, sinTh;
2596 double u1[3], u2[3];
2597 double M1[3][3], M2[3][3];
2598 double xx, yy, zz, tt;
2599
2600 double q =
2601 sqrt(qVec.x() * qVec.x() + qVec.y() * qVec.y() + qVec.z() * qVec.z());
2602 double omega = qVec.t();
2603
2604
2605
2606 if (q - fabs(omega) < 1e-5) {
2607 return FourVector(0., 0., 0., 0.);
2608 }
2609
2610
2611 k_min = (q - omega) / 2.;
2612
2613
2614 k = getThermal(k_min, T, kind);
2615
2616 cosTh = (2. * k * omega - q * q + omega * omega) / (2. * k * q);
2617 sinTh = sqrt(1. - cosTh * cosTh);
2618
2619
2620
2621 double norm = sqrt(qVec.x() * qVec.x() + qVec.y() * qVec.y());
2622 if (norm > 1e-10) {
2623 u1[0] = qVec.y() / norm;
2624 u1[1] = -qVec.x() / norm;
2625 u1[2] = 0.;
2626 }
2627
2628 else {
2629 u1[0] = 1.;
2630 u1[1] = 0.;
2631 u1[2] = 0.;
2632 }
2633
2634
2635 M1[0][0] = u1[0] * u1[0] * (1. - cosTh) + cosTh;
2636 M1[1][0] = u1[0] * u1[1] * (1. - cosTh) - u1[2] * sinTh;
2637 M1[2][0] = u1[0] * u1[2] * (1. - cosTh) + u1[1] * sinTh;
2638
2639 M1[0][1] = u1[1] * u1[0] * (1. - cosTh) + u1[2] * sinTh;
2640 M1[1][1] = u1[1] * u1[1] * (1. - cosTh) + cosTh;
2641 M1[2][1] = u1[1] * u1[2] * (1. - cosTh) - u1[0] * sinTh;
2642
2643 M1[0][2] = u1[2] * u1[0] * (1. - cosTh) - u1[1] * sinTh;
2644 M1[1][2] = u1[2] * u1[1] * (1. - cosTh) + u1[0] * sinTh;
2645 M1[2][2] = u1[2] * u1[2] * (1. - cosTh) + cosTh;
2646
2647
2648 xx = M1[0][0] * qVec.x() + M1[0][1] * qVec.y() + M1[0][2] * qVec.z();
2649 yy = M1[1][0] * qVec.x() + M1[1][1] * qVec.y() + M1[1][2] * qVec.z();
2650 zz = M1[2][0] * qVec.x() + M1[2][1] * qVec.y() + M1[2][2] * qVec.z();
2651
2652
2653 tt = sqrt(xx * xx + yy * yy + zz * zz);
2654 xx /= tt / k;
2655 yy /= tt / k;
2656 zz /= tt / k;
2657
2658 kVec.Set(xx, yy, zz, k);
2659
2660
2661 double phi = 2. * M_PI * ZeroOneDistribution(*GetMt19937Generator());
2662
2663 xx = qVec.x();
2664 yy = qVec.y();
2665 zz = qVec.z();
2666 tt = sqrt(xx * xx + yy * yy + zz * zz);
2667
2668 u2[0] = xx / tt;
2669 u2[1] = yy / tt;
2670 u2[2] = zz / tt;
2671
2672 M2[0][0] = u2[0] * u2[0] * (1. - cos(phi)) + cos(phi);
2673 M2[1][0] = u2[0] * u2[1] * (1. - cos(phi)) - u2[2] * sin(phi);
2674 M2[2][0] = u2[0] * u2[2] * (1. - cos(phi)) + u2[1] * sin(phi);
2675
2676 M2[0][1] = u2[1] * u2[0] * (1. - cos(phi)) + u2[2] * sin(phi);
2677 M2[1][1] = u2[1] * u2[1] * (1. - cos(phi)) + cos(phi);
2678 M2[2][1] = u2[1] * u2[2] * (1. - cos(phi)) - u2[0] * sin(phi);
2679
2680 M2[0][2] = u2[2] * u2[0] * (1. - cos(phi)) - u2[1] * sin(phi);
2681 M2[1][2] = u2[2] * u2[1] * (1. - cos(phi)) + u2[0] * sin(phi);
2682 M2[2][2] = u2[2] * u2[2] * (1. - cos(phi)) + cos(phi);
2683
2684 xx = M2[0][0] * kVec.x() + M2[0][1] * kVec.y() + M2[0][2] * kVec.z();
2685 yy = M2[1][0] * kVec.x() + M2[1][1] * kVec.y() + M2[1][2] * kVec.z();
2686 zz = M2[2][0] * kVec.x() + M2[2][1] * kVec.y() + M2[2][2] * kVec.z();
2687 tt = sqrt(xx * xx + yy * yy + zz * zz);
2688
2689 kVec.Set(xx, yy, zz, tt);
2690
2691 return kVec;
2692 }
2693
2694 double Martini::getThermal(double k_min, double T, int kind) {
2695
2696
2697
2698
2699
2700 double p;
2701 double gm = 5.5;
2702 int repeat = 1;
2703 double gx = 0.;
2704 double px;
2705 double px2;
2706 double ex;
2707
2708 do {
2709 px = k_min / T +
2710 tan(M_PI * ZeroOneDistribution(*GetMt19937Generator()) / 2.0);
2711 px2 = px * px;
2712 ex = sqrt(px2);
2713 if (kind == 0)
2714 gx = px2 * (1.0 + px2) * exp(-ex);
2715 else if (kind == -1)
2716 gx = px2 * (1.0 + px2) * 1 / (exp(ex) - 1);
2717 else if (kind == +1)
2718 gx = px2 * (1.0 + px2) * 1 / (exp(ex) + 1);
2719 if (ZeroOneDistribution(*GetMt19937Generator()) < gx / gm) {
2720 repeat = 0;
2721 p = ex;
2722 }
2723 } while (repeat);
2724
2725 return p * T;
2726 }
2727
2728
2729 void Martini::readRadiativeRate(Gamma_info *dat, dGammas *Gam) {
2730 FILE *rfile;
2731 string filename;
2732 filename = PathToTables + "/radgamma";
2733
2734 JSINFO << "Reading rates of inelastic collisions from file ";
2735 JSINFO << filename.c_str() << " ... ";
2736 size_t bytes_read;
2737
2738 rfile = fopen(filename.c_str(), "rb");
2739 if (rfile == NULL) {
2740 JSWARN << "[readRadiativeRate]: ERROR: Unable to open file " << filename;
2741 throw std::runtime_error(
2742 "[readRadiativeRate]: ERROR: Unable to open Radiative rate file");
2743 }
2744
2745 bytes_read = fread((char *)(&dat->ddf), sizeof(double), 1, rfile);
2746 bytes_read = fread((char *)(&dat->dda), sizeof(double), 1, rfile);
2747 bytes_read = fread((char *)(&dat->dcf), sizeof(double), 1, rfile);
2748 bytes_read = fread((char *)(&dat->dca), sizeof(double), 1, rfile);
2749 bytes_read = fread((char *)(&dat->Nc), sizeof(int), 1, rfile);
2750 bytes_read = fread((char *)(&dat->Nf), sizeof(int), 1, rfile);
2751 bytes_read = fread((char *)(&dat->BetheHeitler), sizeof(int), 1, rfile);
2752 bytes_read = fread((char *)(&dat->BDMPS), sizeof(int), 1, rfile);
2753 bytes_read = fread((char *)(&dat->include_gluons), sizeof(int), 1, rfile);
2754 bytes_read = fread((char *)Gam->qqg, sizeof(double), NP * NK, rfile);
2755 bytes_read = fread((char *)Gam->tau_qqg, sizeof(double), NP * NK, rfile);
2756 bytes_read = fread((char *)Gam->gqq, sizeof(double), NP * NK, rfile);
2757 bytes_read = fread((char *)Gam->tau_gqq, sizeof(double), NP * NK, rfile);
2758 bytes_read = fread((char *)Gam->ggg, sizeof(double), NP * NK, rfile);
2759 bytes_read = fread((char *)Gam->tau_ggg, sizeof(double), NP * NK, rfile);
2760 bytes_read = fread((char *)Gam->qqgamma, sizeof(double), NP * NK, rfile);
2761 bytes_read = fread((char *)Gam->tau_qqgamma, sizeof(double), NP * NK, rfile);
2762 fclose(rfile);
2763
2764 dat->Nf = nf;
2765 dat->dp = 0.05;
2766 dat->p_max = 20;
2767 dat->p_min =
2768 0;
2769 dat->n_p = static_cast<int>(
2770 1.001 + dat->p_max / dat->dp);
2771 dat->p_max = dat->dp * dat->n_p;
2772 dat->n_pmin = static_cast<int>(
2773 1.001 + dat->p_min / dat->dp);
2774 dat->n_p -= dat->n_pmin - 1;
2775 dat->p_min = dat->dp * dat->n_pmin;
2776 dat->n_kmin = 1 + 2 * (static_cast<int>(2. / dat->dp));
2777 dat->k_min = -dat->dp * dat->n_kmin;
2778 dat->n_k = static_cast<int>((8 + dat->p_max) / (2 * dat->dp));
2779 dat->k_max = 2 * dat->dp * (dat->n_k - 1) + dat->k_min;
2780 }
2781
2782 void Martini::readElasticRateOmega() {
2783 ifstream fin;
2784 string filename[2];
2785
2786 double as, omega;
2787 double dGamma;
2788
2789
2790 filename[0] = PathToTables + "/logEnDtrqq";
2791 filename[1] = PathToTables + "/logEnDtrqg";
2792
2793 JSINFO << "Reading rates of elastic collisions from files";
2794 JSINFO << filename[0];
2795 JSINFO << filename[1] << " ...";
2796
2797 fin.open(filename[0].c_str(), ios::in);
2798 if (!fin) {
2799 JSWARN << "[readElasticRateOmega]: ERROR: Unable to open file "
2800 << filename[0];
2801 throw std::runtime_error(
2802 "[readElasticRateQ]: ERROR: Unable to open ElasticRateOmega file");
2803 }
2804
2805 int ik = 0;
2806 while (!fin.eof()) {
2807 fin >> as;
2808 fin >> omega;
2809 fin >> dGamma;
2810 dGamma_qq->push_back(dGamma);
2811
2812 ik++;
2813 }
2814 fin.close();
2815
2816 fin.open(filename[1].c_str(), ios::in);
2817 if (!fin) {
2818 JSWARN << "[readElasticRateOmega]: ERROR: Unable to open file "
2819 << filename[1];
2820 throw std::runtime_error(
2821 "[readElasticRateQ]: ERROR: Unable to open ElasticRateOmega file");
2822 }
2823
2824 ik = 0;
2825 while (!fin.eof()) {
2826 fin >> as;
2827 fin >> omega;
2828 fin >> dGamma;
2829 dGamma_qg->push_back(dGamma);
2830
2831 ik++;
2832 }
2833 fin.close();
2834 }
2835
2836 void Martini::readElasticRateQ() {
2837 ifstream fin;
2838 string filename[2];
2839
2840 double as, omega, q;
2841 double dGamma;
2842
2843
2844 filename[0] = PathToTables + "/logEnDqtrqq";
2845 filename[1] = PathToTables + "/logEnDqtrqg";
2846
2847 JSINFO << "Reading rates of elastic collisions from files";
2848 JSINFO << filename[0];
2849 JSINFO << filename[1] << " ...";
2850
2851 fin.open(filename[0].c_str(), ios::in);
2852 if (!fin) {
2853 JSWARN << "[readElasticRateQ]: ERROR: Unable to open file " << filename[0];
2854 throw std::runtime_error(
2855 "[readElasticRateQ]: ERROR: Unable to open ElasticRateQ file");
2856 }
2857
2858 int ik = 0;
2859 while (!fin.eof()) {
2860 fin >> as;
2861 fin >> omega;
2862 fin >> q;
2863 fin >> dGamma;
2864 dGamma_qq_q->push_back(dGamma);
2865
2866 ik++;
2867 }
2868 fin.close();
2869
2870 fin.open(filename[1].c_str(), ios::in);
2871 if (!fin) {
2872 JSWARN << "[readElasticRateQ]: ERROR: Unable to open file " << filename[1];
2873 throw std::runtime_error(
2874 "[readElasticRateQ]: ERROR: Unable to open ElasticRateQ file");
2875 }
2876
2877 ik = 0;
2878 while (!fin.eof()) {
2879 fin >> as;
2880 fin >> omega;
2881 fin >> q;
2882 fin >> dGamma;
2883 dGamma_qg_q->push_back(dGamma);
2884
2885 ik++;
2886 }
2887 fin.close();
2888 }
2889
2890 double Martini::getRate_qqg(double p, double k) {
2891 return use_table(p, k, Gam.qqg, 0);
2892 }
2893
2894 double Martini::getRate_gqq(double p, double k) {
2895 if (k < p / 2.)
2896 return use_table(p, k, Gam.gqq, 1);
2897 else
2898 return 0.;
2899 }
2900
2901 double Martini::getRate_ggg(double p, double k) {
2902 if (k < p / 2.)
2903 return use_table(p, k, Gam.ggg, 2);
2904 else
2905 return 0.;
2906 }
2907
2908 double Martini::getRate_qqgamma(double p, double k) {
2909 return use_table(p, k, Gam.qqgamma, 3);
2910 }
2911
2912 double Martini::use_table(double p, double k, double dGamma[NP][NK],
2913 int which_kind)
2914
2915
2916
2917
2918
2919 {
2920 double a, b, result;
2921 int n_p, n_k;
2922
2923
2924 if ((p < 4.01) || (p > 46000.) || (k < -12.) || (k > p + 12.))
2925 return 0.;
2926
2927 if ((which_kind % 3) && (k > p / 2))
2928 k = p - k;
2929
2930 a = 24.7743737154026 * log(p * 0.2493765586034912718l);
2931 n_p = (int)a;
2932 a -= n_p;
2933 if (k < 2.) {
2934 if (k < -1) {
2935 if (k < -2)
2936 b = 60. + 5. * k;
2937 else
2938 b = 70. + 10. * k;
2939 } else {
2940 if (k < 1.)
2941 b = 80. + 20. * k;
2942 else
2943 b = 90. + 10. * k;
2944 }
2945 } else if (k < p - 2.) {
2946 b = 190. - 10. * log(1.000670700260932956l /
2947 (0.0003353501304664781l + (k - 2.) / (p - 4.)) -
2948 1.);
2949 } else {
2950 if (k < p + 1.) {
2951 if (k < p - 1.)
2952 b = 290. + 10. * (k - p);
2953 else
2954 b = 300. + 20. * (k - p);
2955 } else {
2956 if (k < p + 2.)
2957 b = 310. + 10. * (k - p);
2958 else
2959 b = 320. + 5. * (k - p);
2960 }
2961 }
2962
2963 n_k = (int)b;
2964 b -= n_k;
2965 result = (1. - a) * ((1. - b) * dGamma[n_p][n_k] + b * dGamma[n_p][n_k + 1]) +
2966 a * ((1. - b) * dGamma[n_p + 1][n_k] + b * dGamma[n_p + 1][n_k + 1]);
2967
2968 if (std::abs(k) > 0.001)
2969 {
2970 switch (which_kind) {
2971 case 0:
2972 result /= k;
2973 if (k < 20.)
2974 result /= 1. - exp(-k);
2975 if (k > p - 20.)
2976 result /= 1. + exp(k - p);
2977 break;
2978 case 1:
2979 result /= p;
2980 if (k < 20.)
2981 result /= 1 + exp(-k);
2982 if (k > p - 20.)
2983 result /= 1. + exp(k - p);
2984 break;
2985 case 2:
2986 result /= k * (p - k) / p;
2987 if (k < 20.)
2988 result /= 1. - exp(-k);
2989 if (k > p - 20.)
2990 result /= 1. - exp(k - p);
2991 break;
2992 case 3:
2993 result /= k;
2994 if (k < 0)
2995 result = 0.;
2996 if (k > p - 20.)
2997 result /= 1. + exp(k - p);
2998 break;
2999 }
3000 }
3001
3002 return result;
3003 }
3004
3005 double Martini::getElasticRateOmega(double u, double omega, int process) {
3006 if ((omega > 0. && omega < u) || (omega < 0. && omega > -u))
3007 return use_elastic_table_omega(omega, process);
3008
3009 return 0.;
3010 }
3011
3012 double Martini::getElasticRateQ(double u, double omega, double q, int process) {
3013 if (q > std::abs(omega) &&
3014 ((omega > 0 && omega < u) || (omega < 0 && omega > -u)))
3015 return use_elastic_table_q(omega, q, process);
3016
3017 return 0.;
3018 }
3019
3020 double Martini::use_elastic_table_omega(double omega, int which_kind)
3021
3022
3023 {
3024 double result;
3025 double alphaFrac, omegaFrac;
3026 int iOmega, iAlphas;
3027 int position, positionAlphaUp, positionOmegaUp, positionAlphaUpOmegaUp;
3028 double rate, rateAlphaUp, rateOmegaUp, rateAlphaUpOmegaUp;
3029 double rateOmegaAv, rateAlphaUpOmegaAv;
3030
3031 if (omega > 0.)
3032 iOmega = Nomega / 2 + floor((log(omega) + 5) / omegaStep);
3033 else
3034 iOmega = Nomega / 2 - ceil((log(-omega) + 5) / omegaStep) - 1;
3035 iAlphas = floor((alpha_s - 0.15) / alphaStep);
3036
3037 position = iOmega + Nomega * (iAlphas);
3038 positionAlphaUp = iOmega + Nomega * (iAlphas + 1);
3039 positionOmegaUp = iOmega + 1 + Nomega * (iAlphas);
3040 positionAlphaUpOmegaUp = iOmega + 1 + Nomega * (iAlphas + 1);
3041
3042 alphaFrac = (alpha_s - (floor((alpha_s - alphaMin) / alphaStep) * alphaStep +
3043 alphaMin)) /
3044 alphaStep;
3045 if (omega > 0.) {
3046 if (exp(ceil((log(omega) + 5) / omegaStep) * omegaStep - 5) !=
3047 exp(floor((log(omega) + 5) / omegaStep) * omegaStep - 5))
3048 omegaFrac =
3049 (omega - (exp(floor((log(omega) + 5) / omegaStep) * omegaStep - 5))) /
3050 ((exp(ceil((log(omega) + 5) / omegaStep) * omegaStep - 5)) -
3051 exp(floor((log(omega) + 5) / omegaStep) * omegaStep - 5));
3052 else
3053 omegaFrac = 0.;
3054 } else {
3055 if (exp(ceil((log(-omega) + 5) / omegaStep) * omegaStep - 5) !=
3056 exp(floor((log(-omega) + 5) / omegaStep) * omegaStep - 5))
3057 omegaFrac =
3058 (-omega -
3059 (exp(floor((log(-omega) + 5) / omegaStep) * omegaStep - 5))) /
3060 ((exp(ceil((log(-omega) + 5) / omegaStep) * omegaStep - 5)) -
3061 exp(floor((log(-omega) + 5) / omegaStep) * omegaStep - 5));
3062 else
3063 omegaFrac = 0.;
3064 }
3065
3066 if (which_kind == 5 || which_kind == 7) {
3067 if (position > 0 && iAlphas < Nalphas && iOmega < Nomega)
3068 rate = dGamma_qq->at(position);
3069 else
3070 rate = 0.;
3071
3072 if (iAlphas + 1 < Nalphas)
3073 rateAlphaUp = dGamma_qq->at(positionAlphaUp);
3074 else
3075 rateAlphaUp = rate;
3076
3077 if (iOmega + 1 < Nomega)
3078 rateOmegaUp = dGamma_qq->at(positionOmegaUp);
3079 else
3080 rateOmegaUp = rate;
3081
3082 if (iAlphas < Nalphas && iOmega < Nomega)
3083 rateAlphaUpOmegaUp = dGamma_qq->at(positionAlphaUpOmegaUp);
3084 else
3085 rateAlphaUpOmegaUp = rate;
3086 } else {
3087 if (position > 0 && iAlphas < Nalphas && iOmega < Nomega)
3088 rate = dGamma_qg->at(position);
3089 else
3090 rate = 0.;
3091
3092 if (iAlphas + 1 < Nalphas)
3093 rateAlphaUp = dGamma_qg->at(positionAlphaUp);
3094 else
3095 rateAlphaUp = rate;
3096
3097 if (iOmega + 1 < Nomega)
3098 rateOmegaUp = dGamma_qg->at(positionOmegaUp);
3099 else
3100 rateOmegaUp = rate;
3101
3102 if (iAlphas < Nalphas && iOmega < Nomega)
3103 rateAlphaUpOmegaUp = dGamma_qg->at(positionAlphaUpOmegaUp);
3104 else
3105 rateAlphaUpOmegaUp = rate;
3106 }
3107
3108 if (omega > 0.) {
3109 rateOmegaAv = (1. - omegaFrac) * rate + omegaFrac * rateOmegaUp;
3110 rateAlphaUpOmegaAv =
3111 (1. - omegaFrac) * rateAlphaUp + omegaFrac * rateAlphaUpOmegaUp;
3112 } else {
3113 rateOmegaAv = (omegaFrac)*rate + (1. - omegaFrac) * rateOmegaUp;
3114 rateAlphaUpOmegaAv =
3115 (omegaFrac)*rateAlphaUp + (1. - omegaFrac) * rateAlphaUpOmegaUp;
3116 }
3117 result = (1. - alphaFrac) * rateOmegaAv + alphaFrac * rateAlphaUpOmegaAv;
3118
3119
3120 return result;
3121 }
3122
3123 double Martini::use_elastic_table_q(double omega, double q, int which_kind)
3124
3125
3126 {
3127 double result;
3128 double alphaFrac, omegaFrac, qFrac;
3129 int iOmega, iAlphas, iQ;
3130 int position, positionAlphaUp, positionOmegaUp, positionAlphaUpOmegaUp;
3131 int positionQUp, positionAlphaUpQUp, positionOmegaUpQUp,
3132 positionAlphaUpOmegaUpQUp;
3133 int position2QUp;
3134 double rate, rateAlphaUp, rateOmegaUp, rateAlphaUpOmegaUp;
3135 double rateQUp, rateAlphaUpQUp, rateOmegaUpQUp, rateAlphaUpOmegaUpQUp;
3136 double rate2QUp, rateAlphaUp2QUp, rateOmegaUp2QUp, rateAlphaUpOmegaUp2QUp;
3137 double rateOmegaAv, rateAlphaUpOmegaAv, rateQUpOmegaAv, rateAlphaUpQUpOmegaAv;
3138 double rate2QUpOmegaAv, rateAlphaUp2QUpOmegaAv;
3139 double rateQAv, rateAlphaUpQAv;
3140 double slope, slopeAlphaUp;
3141
3142 rate2QUp = 0.;
3143 rateAlphaUp2QUp = 0.;
3144 rateOmegaUp2QUp = 0.;
3145 rateAlphaUpOmegaUp2QUp = 0.;
3146 rateOmegaAv = 0.;
3147 rateAlphaUpOmegaAv = 0.;
3148 rateQUpOmegaAv = 0.;
3149 rateAlphaUpQUpOmegaAv = 0.;
3150 rate2QUpOmegaAv = 0.;
3151 rateAlphaUp2QUpOmegaAv = 0.;
3152
3153 if (omega > 0.)
3154 iOmega = Nomega / 2 + floor((log(omega) + 5) / omegaStep);
3155 else
3156 iOmega = Nomega / 2 - ceil((log(-omega) + 5) / omegaStep) - 1;
3157 iQ = floor((log(q) + 5) / qStep + 0.0001);
3158 iAlphas = floor((alpha_s - 0.15) / alphaStep + 0.0001);
3159
3160 position = iQ + Nq * (iOmega + Nomega * (iAlphas));
3161 positionAlphaUp = iQ + Nq * (iOmega + Nomega * (iAlphas + 1));
3162 positionOmegaUp = iQ + Nq * (iOmega + 1 + Nomega * (iAlphas));
3163 positionQUp = iQ + 1 + Nq * (iOmega + Nomega * (iAlphas));
3164 position2QUp = iQ + 2 + Nq * (iOmega + Nomega * (iAlphas));
3165 positionAlphaUpOmegaUp = iQ + Nq * (iOmega + 1 + Nomega * (iAlphas + 1));
3166 positionAlphaUpQUp = iQ + 1 + Nq * (iOmega + Nomega * (iAlphas + 1));
3167 positionOmegaUpQUp = iQ + 1 + Nq * (iOmega + 1 + Nomega * (iAlphas));
3168 positionAlphaUpOmegaUpQUp =
3169 iQ + 1 + Nq * (iOmega + 1 + Nomega * (iAlphas + 1));
3170
3171 alphaFrac = (alpha_s - (floor((alpha_s - alphaMin) / alphaStep) * alphaStep +
3172 alphaMin)) /
3173 alphaStep;
3174 if (omega > 0.) {
3175 if (exp(ceil((log(omega) + 5) / omegaStep) * omegaStep - 5) !=
3176 exp(floor((log(omega) + 5) / omegaStep) * omegaStep - 5))
3177 omegaFrac =
3178 (omega - (exp(floor((log(omega) + 5) / omegaStep) * omegaStep - 5))) /
3179 ((exp(ceil((log(omega) + 5) / omegaStep) * omegaStep - 5)) -
3180 exp(floor((log(omega) + 5) / omegaStep) * omegaStep - 5));
3181 else
3182 omegaFrac = 0.;
3183 } else {
3184 if (exp(ceil((log(-omega) + 5) / omegaStep) * omegaStep - 5) !=
3185 exp(floor((log(-omega) + 5) / omegaStep) * omegaStep - 5))
3186 omegaFrac =
3187 (-omega -
3188 (exp(floor((log(-omega) + 5) / omegaStep) * omegaStep - 5))) /
3189 ((exp(ceil((log(-omega) + 5) / omegaStep) * omegaStep - 5)) -
3190 exp(floor((log(-omega) + 5) / omegaStep) * omegaStep - 5));
3191 else
3192 omegaFrac = 0.;
3193 }
3194
3195
3196
3197 if (omega > 20.) {
3198 qFrac = (log(q) - (floor((log(q) + 5.) / qStep) * qStep - 5.)) / qStep;
3199 }
3200
3201 else {
3202 if (exp(ceil((log(q) + 5.) / qStep) * qStep - 5.) !=
3203 exp(floor((log(q) + 5.) / qStep) * qStep - 5.))
3204 qFrac = (q - (exp(floor((log(q) + 5.) / qStep) * qStep - 5.))) /
3205 ((exp(ceil((log(q) + 5.) / qStep) * qStep - 5.)) -
3206 exp(floor((log(q) + 5.) / qStep) * qStep - 5.));
3207 else
3208 qFrac = 0.;
3209 }
3210
3211 if (which_kind == 5 || which_kind == 7) {
3212 if (position >= 0 && iAlphas < Nalphas && iOmega < Nomega && iQ < Nq)
3213 rate = dGamma_qq_q->at(position);
3214 else
3215 rate = 0.;
3216
3217 if (iAlphas + 1 < Nalphas)
3218 rateAlphaUp = dGamma_qq_q->at(positionAlphaUp);
3219 else
3220 rateAlphaUp = rate;
3221
3222 if (iOmega + 1 < Nomega)
3223 rateOmegaUp = dGamma_qq_q->at(positionOmegaUp);
3224 else
3225 rateOmegaUp = rate;
3226
3227 if (iQ + 1 < Nq)
3228 rateQUp = dGamma_qq_q->at(positionQUp);
3229 else
3230 rateQUp = rate;
3231
3232 if (iAlphas < Nalphas && iOmega < Nomega)
3233 rateAlphaUpOmegaUp = dGamma_qq_q->at(positionAlphaUpOmegaUp);
3234 else
3235 rateAlphaUpOmegaUp = rate;
3236
3237 if (iAlphas < Nalphas && iQ < Nq)
3238 rateAlphaUpQUp = dGamma_qq_q->at(positionAlphaUpQUp);
3239 else
3240 rateAlphaUpQUp = rate;
3241
3242 if (iOmega + 1 < Nomega && iQ + 1 < Nq)
3243 rateOmegaUpQUp = dGamma_qq_q->at(positionOmegaUpQUp);
3244 else
3245 rateOmegaUpQUp = rate;
3246
3247 if (iAlphas < Nalphas && iOmega < Nomega && iQ < Nq)
3248 rateAlphaUpOmegaUpQUp = dGamma_qq_q->at(positionAlphaUpOmegaUpQUp);
3249 else
3250 rateAlphaUpOmegaUpQUp = rate;
3251
3252
3253 if (omega > 20.) {
3254 if (iQ + 2 < Nq)
3255 rate2QUp = dGamma_qq_q->at(position2QUp);
3256 else
3257 rate2QUp = rateQUp;
3258
3259 if (iAlphas < Nalphas && iQ + 2 < Nq)
3260 rateAlphaUp2QUp = dGamma_qq_q->at(positionAlphaUpQUp + 1);
3261 else
3262 rateAlphaUp2QUp = rateAlphaUpQUp;
3263
3264 if (iOmega < Nomega && iQ + 2 < Nq)
3265 rateOmegaUp2QUp = dGamma_qq_q->at(positionOmegaUpQUp + 1);
3266 else
3267 rateOmegaUp2QUp = rateOmegaUpQUp;
3268
3269 if (iAlphas < Nalphas && iOmega < Nomega && iQ + 2 < Nq)
3270 rateAlphaUpOmegaUp2QUp = dGamma_qq_q->at(positionAlphaUpOmegaUpQUp + 1);
3271 else
3272 rateAlphaUpOmegaUp2QUp = rateAlphaUpOmegaUpQUp;
3273 }
3274 } else {
3275 if (position > 0 && iAlphas < Nalphas && iOmega < Nomega && iQ < Nq)
3276 rate = dGamma_qg_q->at(position);
3277 else
3278 rate = 0.;
3279
3280 if (iAlphas + 1 < Nalphas)
3281 rateAlphaUp = dGamma_qg_q->at(positionAlphaUp);
3282 else
3283 rateAlphaUp = rate;
3284
3285 if (iOmega + 1 < Nomega)
3286 rateOmegaUp = dGamma_qg_q->at(positionOmegaUp);
3287 else
3288 rateOmegaUp = rate;
3289
3290 if (iQ + 1 < Nq)
3291 rateQUp = dGamma_qg_q->at(positionQUp);
3292 else
3293 rateQUp = rate;
3294
3295 if (iAlphas < Nalphas && iOmega < Nomega)
3296 rateAlphaUpOmegaUp = dGamma_qg_q->at(positionAlphaUpOmegaUp);
3297 else
3298 rateAlphaUpOmegaUp = rate;
3299
3300 if (iAlphas < Nalphas && iQ < Nq)
3301 rateAlphaUpQUp = dGamma_qg_q->at(positionAlphaUpQUp);
3302 else
3303 rateAlphaUpQUp = rate;
3304
3305 if (iOmega + 1 < Nomega && iQ + 1 < Nq)
3306 rateOmegaUpQUp = dGamma_qg_q->at(positionOmegaUpQUp);
3307 else
3308 rateOmegaUpQUp = rate;
3309
3310 if (iAlphas < Nalphas && iOmega < Nomega && iQ < Nq)
3311 rateAlphaUpOmegaUpQUp = dGamma_qg_q->at(positionAlphaUpOmegaUpQUp);
3312 else
3313 rateAlphaUpOmegaUpQUp = rate;
3314
3315
3316 if (omega > 20.) {
3317 if (iQ + 2 < Nq)
3318 rate2QUp = dGamma_qg_q->at(position2QUp);
3319 else
3320 rate2QUp = rateQUp;
3321
3322 if (iAlphas < Nalphas && iQ + 2 < Nq)
3323 rateAlphaUp2QUp = dGamma_qg_q->at(positionAlphaUpQUp + 1);
3324 else
3325 rateAlphaUp2QUp = rateAlphaUpQUp;
3326
3327 if (iOmega < Nomega && iQ + 2 < Nq)
3328 rateOmegaUp2QUp = dGamma_qg_q->at(positionOmegaUpQUp + 1);
3329 else
3330 rateOmegaUp2QUp = rateOmegaUpQUp;
3331
3332 if (iAlphas < Nalphas && iOmega < Nomega && iQ + 2 < Nq)
3333 rateAlphaUpOmegaUp2QUp = dGamma_qg_q->at(positionAlphaUpOmegaUpQUp + 1);
3334 else
3335 rateAlphaUpOmegaUp2QUp = rateAlphaUpOmegaUpQUp;
3336 }
3337 }
3338
3339 if (omega > 0. && omega <= 20.) {
3340 rateOmegaAv = (1. - omegaFrac) * rate + omegaFrac * rateOmegaUp;
3341 rateAlphaUpOmegaAv =
3342 (1. - omegaFrac) * rateAlphaUp + omegaFrac * rateAlphaUpOmegaUp;
3343 rateQUpOmegaAv = (1. - omegaFrac) * rateQUp + omegaFrac * rateOmegaUpQUp;
3344 rateAlphaUpQUpOmegaAv =
3345 (1. - omegaFrac) * rateAlphaUpQUp + omegaFrac * rateAlphaUpOmegaUpQUp;
3346 } else if (omega > 20.) {
3347 if (rate != 0. && rateOmegaUp != 0.)
3348 rateOmegaAv =
3349 exp((1. - omegaFrac) * log(rate) + omegaFrac * log(rateOmegaUp));
3350 else if (rate == 0.)
3351 rateOmegaAv = rateOmegaUp;
3352 else if (rateOmegaUp == 0.)
3353 rateOmegaAv = rate;
3354 else
3355 rateOmegaAv = 0.;
3356
3357 if (rateAlphaUpOmegaUp != 0. && rateAlphaUp != 0.)
3358 rateAlphaUpOmegaAv = exp((1. - omegaFrac) * log(rateAlphaUp) +
3359 omegaFrac * log(rateAlphaUpOmegaUp));
3360 else if (rateAlphaUp == 0.)
3361 rateAlphaUpOmegaAv = rateAlphaUpOmegaUp;
3362 else if (rateAlphaUpOmegaUp == 0.)
3363 rateAlphaUpOmegaAv = rateAlphaUp;
3364 else
3365 rateAlphaUpOmegaAv = 0.;
3366
3367 if (rateOmegaUpQUp != 0. && rateQUp != 0.)
3368 rateQUpOmegaAv = exp((1. - omegaFrac) * log(rateQUp) +
3369 omegaFrac * log(rateOmegaUpQUp));
3370 else if (rateOmegaUpQUp == 0.)
3371 rateQUpOmegaAv = rateQUp;
3372 else if (rateQUp == 0.)
3373 rateQUpOmegaAv = rateOmegaUpQUp;
3374 else
3375 rateQUpOmegaAv = 0.;
3376
3377 if (rateAlphaUpOmegaUpQUp != 0. && rateAlphaUpQUp != 0.)
3378 rateAlphaUpQUpOmegaAv = exp((1. - omegaFrac) * log(rateAlphaUpQUp) +
3379 omegaFrac * log(rateAlphaUpOmegaUpQUp));
3380 else if (rateAlphaUpQUp == 0.)
3381 rateAlphaUpQUpOmegaAv = rateAlphaUpOmegaUpQUp;
3382 else if (rateAlphaUpOmegaUpQUp == 0.)
3383 rateAlphaUpQUpOmegaAv = rateAlphaUpQUp;
3384 else
3385 rateAlphaUpQUpOmegaAv = 0.;
3386
3387 rate2QUpOmegaAv = exp((1. - omegaFrac) * log(rate2QUp) +
3388 omegaFrac * log(rateOmegaUp2QUp));
3389 rateAlphaUp2QUpOmegaAv = exp((1. - omegaFrac) * log(rateAlphaUp2QUp) +
3390 omegaFrac * log(rateAlphaUpOmegaUp2QUp));
3391 } else if (omega < 0.) {
3392 rateOmegaAv = (omegaFrac)*rate + (1. - omegaFrac) * rateOmegaUp;
3393 rateQUpOmegaAv = (omegaFrac)*rateQUp + (1. - omegaFrac) * rateOmegaUpQUp;
3394 rateAlphaUpOmegaAv =
3395 (omegaFrac)*rateAlphaUp + (1. - omegaFrac) * rateAlphaUpOmegaUp;
3396 rateAlphaUpQUpOmegaAv =
3397 (omegaFrac)*rateAlphaUpQUp + (1. - omegaFrac) * rateAlphaUpOmegaUpQUp;
3398 }
3399
3400
3401 if (omega > 20.) {
3402 if (rateOmegaAv > 0.) {
3403 rateQAv =
3404 exp((1. - qFrac) * log(rateOmegaAv) + qFrac * log(rateQUpOmegaAv));
3405 } else if (rateOmegaAv < 0.)
3406 {
3407 slope = (log(rate2QUpOmegaAv) - log(rateQUpOmegaAv)) / qStep;
3408 rateQAv = exp(log(rateQUpOmegaAv) - slope * ((1. - qFrac) * qStep));
3409 } else {
3410 rateQAv = 0.;
3411 }
3412
3413 if (rateAlphaUpOmegaAv > 0.) {
3414 rateAlphaUpQAv = exp((1. - qFrac) * log(rateAlphaUpOmegaAv) +
3415 qFrac * log(rateAlphaUpQUpOmegaAv));
3416 } else if (rateAlphaUpOmegaAv < 0.)
3417 {
3418 slopeAlphaUp =
3419 (log(rateAlphaUp2QUpOmegaAv) - log(rateAlphaUpQUpOmegaAv)) / qStep;
3420 rateAlphaUpQAv = exp(log(rateAlphaUpQUpOmegaAv) -
3421 slopeAlphaUp * ((1. - qFrac) * qStep));
3422 } else {
3423 rateAlphaUpQAv = 0.;
3424 }
3425 }
3426
3427 else {
3428 rateQAv = (1. - qFrac) * rateOmegaAv + qFrac * rateQUpOmegaAv;
3429 rateAlphaUpQAv =
3430 (1. - qFrac) * rateAlphaUpOmegaAv + qFrac * rateAlphaUpQUpOmegaAv;
3431 }
3432
3433 result = (1. - alphaFrac) * rateQAv + alphaFrac * rateAlphaUpQAv;
3434
3435
3436
3437 return result;
3438 }
3439
3440 double LambertW(double z) {
3441 double w_new, w_old, ratio, e_old, tol;
3442 int n;
3443
3444 tol = 1.0e-14;
3445
3446 if (z <= -exp(-1.0)) {
3447 JSWARN << "LambertW is not defined for z = " << z;
3448 JSWARN << "z needs to be bigger than " << -exp(-1.0);
3449 throw std::runtime_error("LambertW small z problem");
3450 }
3451
3452 if (z > 3.0) {
3453 w_old = log(z) - log(log(z));
3454 } else {
3455 w_old = 1.0;
3456 }
3457
3458 w_new = 0.0;
3459 ratio = 1.0;
3460 n = 0;
3461 while (std::abs(ratio) > tol) {
3462 e_old = exp(w_old);
3463 ratio = w_old * e_old - z;
3464 ratio /= (e_old * (w_old + 1.0) -
3465 (w_old + 2.0) * (w_old * e_old - z) / (2.0 * w_old + 2.0));
3466 w_new = w_old - ratio;
3467 w_old = w_new;
3468 n++;
3469 if (n > 99) {
3470 JSWARN << "LambertW is not converging after 100 iterations.";
3471 JSWARN << "LambertW: z = " << z;
3472 JSWARN << "LambertW: w_old = " << w_old;
3473 JSWARN << "LambertW: w_new = " << w_new;
3474 JSWARN << "LambertW: ratio = " << ratio;
3475 throw std::runtime_error("LambertW not conversing");
3476 }
3477 }
3478
3479 return w_new;
3480 }