LCOV - code coverage report
Current view: top level - PYTHIA8/pythia8210dev/src - FragmentationFlavZpT.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 422 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 11 0.0 %

          Line data    Source code
       1             : // FragmentationFlavZpT.cc is a part of the PYTHIA event generator.
       2             : // Copyright (C) 2015 Torbjorn Sjostrand.
       3             : // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
       4             : // Please respect the MCnet Guidelines, see GUIDELINES for details.
       5             : 
       6             : // Function definitions (not found in the header) for the
       7             : // StringFlav, StringZ and StringPT classes.
       8             : 
       9             : #include "Pythia8/FragmentationFlavZpT.h"
      10             : 
      11             : namespace Pythia8 {
      12             : 
      13             : //==========================================================================
      14             : 
      15             : // The StringFlav class.
      16             : 
      17             : //--------------------------------------------------------------------------
      18             : 
      19             : // Constants: could be changed here if desired, but normally should not.
      20             : // These are of technical nature, as described for each.
      21             : 
      22             : // Offset for different meson multiplet id values.
      23             : const int StringFlav::mesonMultipletCode[6]
      24             :   = { 1, 3, 10003, 10001, 20003, 5};
      25             : 
      26             : // Clebsch-Gordan coefficients for baryon octet and decuplet are
      27             : // fixed once and for all, so only weighted sum needs to be edited.
      28             : // Order: ud0 + u, ud0 + s, uu1 + u, uu1 + d, ud1 + u, ud1 + s.
      29             : const double StringFlav::baryonCGOct[6]
      30             :   = { 0.75, 0.5, 0., 0.1667, 0.0833, 0.1667};
      31             : const double StringFlav::baryonCGDec[6]
      32             :   = { 0.,  0.,  1., 0.3333, 0.6667, 0.3333};
      33             : 
      34             : //--------------------------------------------------------------------------
      35             : 
      36             : // Initialize data members of the flavour generation.
      37             : 
      38             : void StringFlav::init(Settings& settings, Rndm* rndmPtrIn) {
      39             : 
      40             :   // Save pointer.
      41           0 :   rndmPtr         = rndmPtrIn;
      42             : 
      43             :   // Basic parameters for generation of new flavour.
      44           0 :   probQQtoQ       = settings.parm("StringFlav:probQQtoQ");
      45           0 :   probStoUD       = settings.parm("StringFlav:probStoUD");
      46           0 :   probSQtoQQ      = settings.parm("StringFlav:probSQtoQQ");
      47           0 :   probQQ1toQQ0    = settings.parm("StringFlav:probQQ1toQQ0");
      48             : 
      49             :   // Parameters derived from above.
      50           0 :   probQandQQ      = 1. + probQQtoQ;
      51           0 :   probQandS       = 2. + probStoUD;
      52           0 :   probQandSinQQ   = 2. + probSQtoQQ * probStoUD;
      53           0 :   probQQ1corr     = 3. * probQQ1toQQ0;
      54           0 :   probQQ1corrInv  = 1. / probQQ1corr;
      55           0 :   probQQ1norm     = probQQ1corr / (1. + probQQ1corr);
      56             : 
      57             :   // Spin parameters for combining two quarks to a diquark.
      58           0 :   vector<double> pQQ1tmp = settings.pvec("StringFlav:probQQ1toQQ0join");
      59           0 :   for (int i = 0; i < 4; ++i)
      60           0 :     probQQ1join[i] = 3. * pQQ1tmp[i] / (1. + 3. * pQQ1tmp[i]);
      61             : 
      62             :   // Parameters for normal meson production.
      63           0 :   for (int i = 0; i < 4; ++i) mesonRate[i][0] = 1.;
      64           0 :   mesonRate[0][1] = settings.parm("StringFlav:mesonUDvector");
      65           0 :   mesonRate[1][1] = settings.parm("StringFlav:mesonSvector");
      66           0 :   mesonRate[2][1] = settings.parm("StringFlav:mesonCvector");
      67           0 :   mesonRate[3][1] = settings.parm("StringFlav:mesonBvector");
      68             : 
      69             :   // Parameters for L=1 excited-meson production.
      70           0 :   mesonRate[0][2] = settings.parm("StringFlav:mesonUDL1S0J1");
      71           0 :   mesonRate[1][2] = settings.parm("StringFlav:mesonSL1S0J1");
      72           0 :   mesonRate[2][2] = settings.parm("StringFlav:mesonCL1S0J1");
      73           0 :   mesonRate[3][2] = settings.parm("StringFlav:mesonBL1S0J1");
      74           0 :   mesonRate[0][3] = settings.parm("StringFlav:mesonUDL1S1J0");
      75           0 :   mesonRate[1][3] = settings.parm("StringFlav:mesonSL1S1J0");
      76           0 :   mesonRate[2][3] = settings.parm("StringFlav:mesonCL1S1J0");
      77           0 :   mesonRate[3][3] = settings.parm("StringFlav:mesonBL1S1J0");
      78           0 :   mesonRate[0][4] = settings.parm("StringFlav:mesonUDL1S1J1");
      79           0 :   mesonRate[1][4] = settings.parm("StringFlav:mesonSL1S1J1");
      80           0 :   mesonRate[2][4] = settings.parm("StringFlav:mesonCL1S1J1");
      81           0 :   mesonRate[3][4] = settings.parm("StringFlav:mesonBL1S1J1");
      82           0 :   mesonRate[0][5] = settings.parm("StringFlav:mesonUDL1S1J2");
      83           0 :   mesonRate[1][5] = settings.parm("StringFlav:mesonSL1S1J2");
      84           0 :   mesonRate[2][5] = settings.parm("StringFlav:mesonCL1S1J2");
      85           0 :   mesonRate[3][5] = settings.parm("StringFlav:mesonBL1S1J2");
      86             : 
      87             :   // Store sum over multiplets for Monte Carlo generation.
      88           0 :   for (int i = 0; i < 4; ++i) mesonRateSum[i]
      89           0 :     = mesonRate[i][0] + mesonRate[i][1] + mesonRate[i][2]
      90           0 :     + mesonRate[i][3] + mesonRate[i][4] + mesonRate[i][5];
      91             : 
      92             :   // Parameters for uubar - ddbar - ssbar meson mixing.
      93           0 :   for (int spin = 0; spin < 6; ++spin) {
      94             :     double theta;
      95           0 :     if      (spin == 0) theta = settings.parm("StringFlav:thetaPS");
      96           0 :     else if (spin == 1) theta = settings.parm("StringFlav:thetaV");
      97           0 :     else if (spin == 2) theta = settings.parm("StringFlav:thetaL1S0J1");
      98           0 :     else if (spin == 3) theta = settings.parm("StringFlav:thetaL1S1J0");
      99           0 :     else if (spin == 4) theta = settings.parm("StringFlav:thetaL1S1J1");
     100           0 :     else                theta = settings.parm("StringFlav:thetaL1S1J2");
     101           0 :     double alpha = (spin == 0) ? 90. - (theta + 54.7) : theta + 54.7;
     102           0 :     alpha *= M_PI / 180.;
     103             :     // Fill in (flavour, spin)-dependent probability of producing
     104             :     // the lightest or the lightest two mesons of the nonet.
     105           0 :     mesonMix1[0][spin] = 0.5;
     106           0 :     mesonMix2[0][spin] = 0.5 * (1. + pow2(sin(alpha)));
     107           0 :     mesonMix1[1][spin] = 0.;
     108           0 :     mesonMix2[1][spin] = pow2(cos(alpha));
     109             :   }
     110             : 
     111             :   // Additional suppression of eta and etaPrime.
     112           0 :   etaSup      = settings.parm("StringFlav:etaSup");
     113           0 :   etaPrimeSup = settings.parm("StringFlav:etaPrimeSup");
     114             : 
     115             :   // Sum of baryon octet and decuplet weights.
     116           0 :   decupletSup = settings.parm("StringFlav:decupletSup");
     117           0 :   for (int i = 0; i < 6; ++i) baryonCGSum[i]
     118           0 :     = baryonCGOct[i] + decupletSup * baryonCGDec[i];
     119             : 
     120             :   // Maximum SU(6) weight for ud0, ud1, uu1 types.
     121           0 :   baryonCGMax[0] = max( baryonCGSum[0], baryonCGSum[1]);
     122           0 :   baryonCGMax[1] = baryonCGMax[0];
     123           0 :   baryonCGMax[2] = max( baryonCGSum[2], baryonCGSum[3]);
     124           0 :   baryonCGMax[3] = baryonCGMax[2];
     125           0 :   baryonCGMax[4] = max( baryonCGSum[4], baryonCGSum[5]);
     126           0 :   baryonCGMax[5] = baryonCGMax[4];
     127             : 
     128             :   // Popcorn baryon parameters.
     129           0 :   popcornRate    = settings.parm("StringFlav:popcornRate");
     130           0 :   popcornSpair   = settings.parm("StringFlav:popcornSpair");
     131           0 :   popcornSmeson  = settings.parm("StringFlav:popcornSmeson");
     132             : 
     133             :   // Suppression of leading (= first-rank) baryons.
     134           0 :   suppressLeadingB = settings.flag("StringFlav:suppressLeadingB");
     135           0 :   lightLeadingBSup = settings.parm("StringFlav:lightLeadingBSup");
     136           0 :   heavyLeadingBSup = settings.parm("StringFlav:heavyLeadingBSup");
     137             : 
     138             :   // Begin calculation of derived parameters for baryon production.
     139             : 
     140             :   // Enumerate distinguishable diquark types (in diquark first is popcorn q).
     141             :   enum Diquark {ud0, ud1, uu1, us0, su0, us1, su1, ss1};
     142             : 
     143             :   // Maximum SU(6) weight by diquark type.
     144           0 :   double barCGMax[8];
     145           0 :   barCGMax[ud0] = baryonCGMax[0];
     146           0 :   barCGMax[ud1] = baryonCGMax[4];
     147           0 :   barCGMax[uu1] = baryonCGMax[2];
     148           0 :   barCGMax[us0] = baryonCGMax[0];
     149           0 :   barCGMax[su0] = baryonCGMax[0];
     150           0 :   barCGMax[us1] = baryonCGMax[4];
     151           0 :   barCGMax[su1] = baryonCGMax[4];
     152           0 :   barCGMax[ss1] = baryonCGMax[2];
     153             : 
     154             :   // Diquark SU(6) survival = Sum_quark (quark tunnel weight) * SU(6).
     155           0 :   double dMB[8];
     156           0 :   dMB[ud0] = 2. * baryonCGSum[0] + probStoUD * baryonCGSum[1];
     157           0 :   dMB[ud1] = 2. * baryonCGSum[4] + probStoUD * baryonCGSum[5];
     158           0 :   dMB[uu1] = baryonCGSum[2] + (1. + probStoUD) * baryonCGSum[3];
     159           0 :   dMB[us0] = (1. + probStoUD) * baryonCGSum[0] + baryonCGSum[1];
     160           0 :   dMB[su0] = dMB[us0];
     161           0 :   dMB[us1] = (1. + probStoUD) * baryonCGSum[4] + baryonCGSum[5];
     162           0 :   dMB[su1] = dMB[us1];
     163           0 :   dMB[ss1] = probStoUD * baryonCGSum[2] + 2. * baryonCGSum[3];
     164           0 :   for (int i = 1; i < 8; ++i) dMB[i] = dMB[i] / dMB[0];
     165             : 
     166             :   // Tunneling factors for diquark production; only half a pair = sqrt.
     167           0 :   double probStoUDroot    = sqrt(probStoUD);
     168           0 :   double probSQtoQQroot   = sqrt(probSQtoQQ);
     169           0 :   double probQQ1toQQ0root = sqrt(probQQ1toQQ0);
     170           0 :   double qBB[8];
     171           0 :   qBB[ud1] = probQQ1toQQ0root;
     172           0 :   qBB[uu1] = probQQ1toQQ0root;
     173           0 :   qBB[us0] = probSQtoQQroot;
     174           0 :   qBB[su0] = probStoUDroot * probSQtoQQroot;
     175           0 :   qBB[us1] = probQQ1toQQ0root * qBB[us0];
     176           0 :   qBB[su1] = probQQ1toQQ0root * qBB[su0];
     177           0 :   qBB[ss1] = probStoUDroot * pow2(probSQtoQQroot) * probQQ1toQQ0root;
     178             : 
     179             :   // spin * (vertex factor) * (half-tunneling factor above).
     180           0 :   double qBM[8];
     181           0 :   qBM[ud1] = 3. * qBB[ud1];
     182           0 :   qBM[uu1] = 6. * qBB[uu1];
     183           0 :   qBM[us0] = probStoUD * qBB[us0];
     184           0 :   qBM[su0] = qBB[su0];
     185           0 :   qBM[us1] = probStoUD * 3. * qBB[us1];
     186           0 :   qBM[su1] = 3. * qBB[su1];
     187           0 :   qBM[ss1] = probStoUD * 6. * qBB[ss1];
     188             : 
     189             :   // Combine above two into total diquark weight for q -> B Bbar.
     190           0 :   for (int i = 1; i < 8; ++i) qBB[i] = qBB[i] * qBM[i];
     191             : 
     192             :   // Suppression from having strange popcorn meson.
     193           0 :   qBM[us0] *= popcornSmeson;
     194           0 :   qBM[us1] *= popcornSmeson;
     195           0 :   qBM[ss1] *= popcornSmeson;
     196             : 
     197             :   // Suppression for a heavy quark of a diquark to fit into a baryon
     198             :   // on the other side of popcorn meson: (0) s/u for q -> B M;
     199             :   // (1) s/u for rank 0 diquark su -> M B; (2) ditto for s -> c/b.
     200           0 :   double uNorm = 1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1];
     201           0 :   scbBM[0] = (2. * (qBM[su0] + qBM[su1]) + qBM[ss1]) / uNorm;
     202           0 :   scbBM[1] = scbBM[0] * popcornSpair * qBM[su0] / qBM[us0];
     203           0 :   scbBM[2] = (1. + qBM[ud1]) * (2. + qBM[us0]) / uNorm;
     204             : 
     205             :   // Include maximum of Clebsch-Gordan coefficients.
     206           0 :   for (int i = 1; i < 8; ++i) dMB[i] *= qBM[i];
     207           0 :   for (int i = 1; i < 8; ++i) qBM[i] *= barCGMax[i] / barCGMax[0];
     208           0 :   for (int i = 1; i < 8; ++i) qBB[i] *= barCGMax[i] / barCGMax[0];
     209             : 
     210             :   // Popcorn fraction for normal diquark production.
     211           0 :   double qNorm = uNorm * popcornRate / 3.;
     212           0 :   double sNorm = scbBM[0] * popcornSpair;
     213           0 :   popFrac = qNorm * (1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1]
     214           0 :     + sNorm * (qBM[su0] + qBM[su1] + 0.5 * qBM[ss1])) / (1. +  qBB[ud1]
     215           0 :     + qBB[uu1] + 2. * (qBB[us0] + qBB[us1]) + 0.5 * qBB[ss1]);
     216             : 
     217             :   // Popcorn fraction for rank 0 diquarks, depending on number of s quarks.
     218           0 :   popS[0] = qNorm * qBM[ud1] / qBB[ud1];
     219           0 :   popS[1] = qNorm * 0.5 * (qBM[us1] / qBB[us1]
     220           0 :     + sNorm * qBM[su1] / qBB[su1]);
     221           0 :   popS[2] = qNorm * sNorm * qBM[ss1] / qBB[ss1];
     222             : 
     223             :   // Recombine diquark weights to flavour and spin ratios. Second index:
     224             :   // 0 = s/u popcorn quark ratio.
     225             :   // 1, 2 = s/u ratio for vertex quark if popcorn quark is u/d or s.
     226             :   // 3 = q/q' vertex quark ratio if popcorn quark is light and = q.
     227             :   // 4, 5, 6 = (spin 1)/(spin 0) ratio for su, us and ud.
     228             : 
     229             :   // Case 0: q -> B B.
     230           0 :   dWT[0][0] = (2. * (qBB[su0] + qBB[su1]) + qBB[ss1])
     231           0 :     / (1. + qBB[ud1] + qBB[uu1] + qBB[us0] + qBB[us1]);
     232           0 :   dWT[0][1] = 2. * (qBB[us0] + qBB[us1]) / (1. + qBB[ud1] + qBB[uu1]);
     233           0 :   dWT[0][2] = qBB[ss1] / (qBB[su0] + qBB[su1]);
     234           0 :   dWT[0][3] = qBB[uu1] / (1. + qBB[ud1] + qBB[uu1]);
     235           0 :   dWT[0][4] = qBB[su1] / qBB[su0];
     236           0 :   dWT[0][5] = qBB[us1] / qBB[us0];
     237           0 :   dWT[0][6] = qBB[ud1];
     238             : 
     239             :   // Case 1: q -> B M B.
     240           0 :   dWT[1][0] = (2. * (qBM[su0] + qBM[su1]) + qBM[ss1])
     241           0 :     / (1. + qBM[ud1] + qBM[uu1] + qBM[us0] + qBM[us1]);
     242           0 :   dWT[1][1] = 2. * (qBM[us0] + qBM[us1]) / (1. + qBM[ud1] + qBM[uu1]);
     243           0 :   dWT[1][2] = qBM[ss1] / (qBM[su0] + qBM[su1]);
     244           0 :   dWT[1][3] = qBM[uu1] / (1. + qBM[ud1] + qBM[uu1]);
     245           0 :   dWT[1][4] = qBM[su1] / qBM[su0];
     246           0 :   dWT[1][5] = qBM[us1] / qBM[us0];
     247           0 :   dWT[1][6] = qBM[ud1];
     248             : 
     249             :   // Case 2: qq -> M B; diquark inside chain.
     250           0 :   dWT[2][0] = (2. * (dMB[su0] + dMB[su1]) + dMB[ss1])
     251           0 :     / (1. + dMB[ud1] + dMB[uu1] + dMB[us0] + dMB[us1]);
     252           0 :   dWT[2][1] = 2. * (dMB[us0] + dMB[us1]) / (1. + dMB[ud1] + dMB[uu1]);
     253           0 :   dWT[2][2] = dMB[ss1] / (dMB[su0] + dMB[su1]);
     254           0 :   dWT[2][3] = dMB[uu1] / (1. + dMB[ud1] + dMB[uu1]);
     255           0 :   dWT[2][4] = dMB[su1] / dMB[su0];
     256           0 :   dWT[2][5] = dMB[us1] / dMB[us0];
     257           0 :   dWT[2][6] = dMB[ud1];
     258             : 
     259           0 : }
     260             : 
     261             : //--------------------------------------------------------------------------
     262             : 
     263             : // Pick a new flavour (including diquarks) given an incoming one.
     264             : 
     265             : FlavContainer StringFlav::pick(FlavContainer& flavOld) {
     266             : 
     267             :   // Initial values for new flavour.
     268           0 :   FlavContainer flavNew;
     269           0 :   flavNew.rank = flavOld.rank + 1;
     270             : 
     271             :   // For original diquark assign popcorn quark and whether popcorn meson.
     272           0 :   int idOld = abs(flavOld.id);
     273           0 :   if (flavOld.rank == 0 && idOld > 1000) assignPopQ(flavOld);
     274             : 
     275             :   // Diquark exists, to be forced into baryon now.
     276           0 :   bool doOldBaryon    = (idOld > 1000 && flavOld.nPop == 0);
     277             :   // Diquark exists, but do meson now.
     278           0 :   bool doPopcornMeson = flavOld.nPop > 0;
     279             :   // Newly created diquark gives baryon now, antibaryon later.
     280             :   bool doNewBaryon    = false;
     281             : 
     282             :   // Choose whether to generate a new meson or a new baryon.
     283           0 :   if (!doOldBaryon && !doPopcornMeson && probQandQQ * rndmPtr->flat() > 1.) {
     284             :     doNewBaryon = true;
     285           0 :     if ((1. + popFrac) * rndmPtr->flat() > 1.) flavNew.nPop = 1;
     286             :   }
     287             : 
     288             :   // Optional suppression of first-rank baryon.
     289           0 :   if (flavOld.rank == 0 && doNewBaryon && suppressLeadingB) {
     290           0 :     double leadingBSup = (idOld < 4) ? lightLeadingBSup : heavyLeadingBSup;
     291           0 :     if (rndmPtr->flat() > leadingBSup) {
     292             :       doNewBaryon = false;
     293           0 :       flavNew.nPop = 0;
     294           0 :     }
     295           0 :   }
     296             : 
     297             :   // Single quark for new meson or for baryon where diquark already exists.
     298           0 :   if (!doPopcornMeson && !doNewBaryon) {
     299           0 :     flavNew.id = pickLightQ();
     300           0 :     if ( (flavOld.id > 0 && flavOld.id < 9) || flavOld.id < -1000 )
     301           0 :       flavNew.id = -flavNew.id;
     302             : 
     303             :     // Done for simple-quark case.
     304           0 :     return flavNew;
     305             :   }
     306             : 
     307             :   // Case: 0 = q -> B B, 1 = q -> B M B, 2 = qq -> M B.
     308           0 :   int iCase = flavNew.nPop;
     309           0 :   if (flavOld.nPop == 1) iCase = 2;
     310             : 
     311             :   // Flavour of popcorn quark (= q shared between B and Bbar).
     312           0 :   if (doNewBaryon) {
     313           0 :     double sPopWT = dWT[iCase][0];
     314           0 :     if (iCase == 1) sPopWT *= scbBM[0] * popcornSpair;
     315           0 :     double rndmFlav = (2. + sPopWT) * rndmPtr->flat();
     316           0 :     flavNew.idPop = 1;
     317           0 :     if (rndmFlav > 1.) flavNew.idPop = 2;
     318           0 :     if (rndmFlav > 2.) flavNew.idPop = 3;
     319           0 :   } else flavNew.idPop = flavOld.idPop;
     320             : 
     321             :   // Flavour of vertex quark.
     322           0 :   double sVtxWT = dWT[iCase][1];
     323           0 :   if (flavNew.idPop >= 3) sVtxWT = dWT[iCase][2];
     324           0 :   if (flavNew.idPop > 3) sVtxWT *= 0.5 * (1. + 1./dWT[iCase][4]);
     325           0 :   double rndmFlav = (2. + sVtxWT) * rndmPtr->flat();
     326           0 :   flavNew.idVtx = 1;
     327           0 :   if (rndmFlav > 1.) flavNew.idVtx = 2;
     328           0 :   if (rndmFlav > 2.) flavNew.idVtx = 3;
     329             : 
     330             :   // Special case for light flavours, possibly identical.
     331           0 :   if (flavNew.idPop < 3 && flavNew.idVtx < 3) {
     332           0 :     flavNew.idVtx = flavNew.idPop;
     333           0 :     if (rndmPtr->flat() > dWT[iCase][3]) flavNew.idVtx = 3 - flavNew.idPop;
     334             :   }
     335             : 
     336             :   // Pick 2 * spin + 1.
     337             :   int spin = 3;
     338           0 :   if (flavNew.idVtx != flavNew.idPop) {
     339           0 :     double spinWT = dWT[iCase][6];
     340           0 :     if (flavNew.idVtx == 3) spinWT = dWT[iCase][5];
     341           0 :     if (flavNew.idPop >= 3) spinWT = dWT[iCase][4];
     342           0 :     if ((1. + spinWT) * rndmPtr->flat() < 1.) spin = 1;
     343           0 :   }
     344             : 
     345             :   // Form outgoing diquark. Done.
     346           0 :   flavNew.id = 1000 * max(flavNew.idVtx, flavNew.idPop)
     347           0 :     + 100 * min(flavNew.idVtx, flavNew.idPop) + spin;
     348           0 :   if ( (flavOld.id < 0 && flavOld.id > -9) || flavOld.id > 1000 )
     349           0 :     flavNew.id = -flavNew.id;
     350             :   return flavNew;
     351             : 
     352           0 : }
     353             : 
     354             : //--------------------------------------------------------------------------
     355             : 
     356             : // Combine two flavours (including diquarks) to produce a hadron.
     357             : // The weighting of the combination may fail, giving output 0.
     358             : 
     359             : int StringFlav::combine(FlavContainer& flav1, FlavContainer& flav2) {
     360             : 
     361             :   // Recognize largest and smallest flavour.
     362           0 :   int id1Abs = abs(flav1.id);
     363           0 :   int id2Abs = abs(flav2.id);
     364           0 :   int idMax = max(id1Abs, id2Abs);
     365           0 :   int idMin = min(id1Abs, id2Abs);
     366             : 
     367             :   // Construct a meson.
     368           0 :   if (idMax < 9 || idMin > 1000) {
     369             : 
     370             :     // Popcorn meson: use only vertex quarks. Fail if none.
     371           0 :     if (idMin > 1000) {
     372           0 :       id1Abs = flav1.idVtx;
     373           0 :       id2Abs = flav2.idVtx;
     374           0 :       idMax = max(id1Abs, id2Abs);
     375           0 :       idMin = min(id1Abs, id2Abs);
     376           0 :       if (idMin == 0) return 0;
     377             :     }
     378             : 
     379             :     // Pick spin state and preliminary code.
     380           0 :     int flav = (idMax < 3) ? 0 : idMax - 2;
     381           0 :     double rndmSpin = mesonRateSum[flav] * rndmPtr->flat();
     382             :     int spin = -1;
     383           0 :     do rndmSpin -= mesonRate[flav][++spin];
     384           0 :     while (rndmSpin > 0.);
     385           0 :     int idMeson = 100 * idMax + 10 * idMin + mesonMultipletCode[spin];
     386             : 
     387             :     // For nondiagonal mesons distinguish particle/antiparticle.
     388           0 :     if (idMax != idMin) {
     389           0 :       int sign = (idMax%2 == 0) ? 1 : -1;
     390           0 :       if ( (idMax == id1Abs && flav1.id < 0)
     391           0 :         || (idMax == id2Abs && flav2.id < 0) ) sign = -sign;
     392           0 :       idMeson *= sign;
     393             : 
     394             :     // For light diagonal mesons include uubar - ddbar - ssbar mixing.
     395           0 :     } else if (flav < 2) {
     396           0 :       double rMix = rndmPtr->flat();
     397           0 :       if      (rMix < mesonMix1[flav][spin]) idMeson = 110;
     398           0 :       else if (rMix < mesonMix2[flav][spin]) idMeson = 220;
     399             :       else                                   idMeson = 330;
     400           0 :       idMeson += mesonMultipletCode[spin];
     401             : 
     402             :       // Additional suppression of eta and eta' may give failure.
     403           0 :       if (idMeson == 221 && etaSup < rndmPtr->flat()) return 0;
     404           0 :       if (idMeson == 331 && etaPrimeSup < rndmPtr->flat()) return 0;
     405           0 :     }
     406             : 
     407             :     // Finished for mesons.
     408           0 :     return idMeson;
     409             :   }
     410             : 
     411             :   // SU(6) factors for baryon production may give failure.
     412           0 :   int idQQ1 = idMax / 1000;
     413           0 :   int idQQ2 = (idMax / 100) % 10;
     414           0 :   int spinQQ = idMax % 10;
     415           0 :   int spinFlav = spinQQ - 1;
     416           0 :   if (spinFlav == 2 && idQQ1 != idQQ2) spinFlav = 4;
     417           0 :   if (idMin != idQQ1 && idMin != idQQ2) spinFlav++;
     418           0 :   if (baryonCGSum[spinFlav] < rndmPtr->flat() * baryonCGMax[spinFlav])
     419           0 :     return 0;
     420             : 
     421             :   // Order quarks to form baryon. Pick spin.
     422           0 :   int idOrd1 = max( idMin, max( idQQ1, idQQ2) );
     423           0 :   int idOrd3 = min( idMin, min( idQQ1, idQQ2) );
     424           0 :   int idOrd2 = idMin + idQQ1 + idQQ2 - idOrd1 - idOrd3;
     425           0 :   int spinBar = (baryonCGSum[spinFlav] * rndmPtr->flat()
     426           0 :     < baryonCGOct[spinFlav]) ? 2 : 4;
     427             : 
     428             :   // Distinguish Lambda- and Sigma-like.
     429             :   bool LambdaLike = false;
     430           0 :   if (spinBar == 2 && idOrd1 > idOrd2 && idOrd2 > idOrd3) {
     431           0 :     LambdaLike = (spinQQ == 1);
     432           0 :     if (idOrd1 != idMin && spinQQ == 1) LambdaLike = (rndmPtr->flat() < 0.25);
     433           0 :     else if (idOrd1 != idMin)           LambdaLike = (rndmPtr->flat() < 0.75);
     434             :   }
     435             : 
     436             :   // Form baryon code and return with sign.
     437           0 :   int idBaryon = (LambdaLike)
     438           0 :     ? 1000 * idOrd1 + 100 * idOrd3 + 10 * idOrd2 + spinBar
     439           0 :     : 1000 * idOrd1 + 100 * idOrd2 + 10 * idOrd3 + spinBar;
     440           0 :    return (flav1.id > 0) ? idBaryon : -idBaryon;
     441             : 
     442           0 : }
     443             : 
     444             : //--------------------------------------------------------------------------
     445             : 
     446             : // Assign popcorn quark inside an original (= rank 0) diquark.
     447             : 
     448             : void StringFlav::assignPopQ(FlavContainer& flav) {
     449             : 
     450             :   // Safety check that intended to do something.
     451           0 :   int idAbs = abs(flav.id);
     452           0 :   if (flav.rank > 0 || idAbs < 1000) return;
     453             : 
     454             :   // Make choice of popcorn quark.
     455           0 :   int id1 = (idAbs/1000)%10;
     456           0 :   int id2 = (idAbs/100)%10;
     457             :   double pop2WT = 1.;
     458           0 :        if (id1 == 3) pop2WT = scbBM[1];
     459           0 :   else if (id1 >  3) pop2WT = scbBM[2];
     460           0 :        if (id2 == 3) pop2WT /= scbBM[1];
     461           0 :   else if (id2 >  3) pop2WT /= scbBM[2];
     462             :   // Agrees with Patrik code, but opposite to intention??
     463           0 :   flav.idPop = ((1. + pop2WT) * rndmPtr->flat() > 1.) ? id2 : id1;
     464           0 :   flav.idVtx = id1 + id2 - flav.idPop;
     465             : 
     466             :   // Also determine if to produce popcorn meson.
     467           0 :   flav.nPop = 0;
     468           0 :   double popWT = popS[0];
     469           0 :   if (id1 == 3) popWT = popS[1];
     470           0 :   if (id2 == 3) popWT = popS[2];
     471           0 :   if (idAbs%10 == 1) popWT *= sqrt(probQQ1toQQ0);
     472           0 :   if ((1. + popWT) * rndmPtr->flat() > 1.) flav.nPop = 1;
     473             : 
     474           0 : }
     475             : 
     476             : //--------------------------------------------------------------------------
     477             : 
     478             : // Combine two quarks to produce a diquark.
     479             : // Normally according to production composition, but nonvanishing idHad
     480             : // means diquark from known hadron content, so use SU(6) wave fucntion.
     481             : 
     482             : int StringFlav::makeDiquark(int id1, int id2, int idHad) {
     483             : 
     484             :   // Initial values.
     485           0 :   int idMin = min( abs(id1), abs(id2));
     486           0 :   int idMax = max( abs(id1), abs(id2));
     487             :   int spin = 1;
     488             : 
     489             :   // Select spin of diquark formed from two valence quarks in proton.
     490             :   // (More hadron cases??)
     491           0 :   if (abs(idHad) == 2212 || abs(idHad) == 2112) {
     492           0 :     if (idMin == 1 && idMax == 2 && rndmPtr->flat() < 0.75) spin = 0;
     493             : 
     494             :   // Else select spin of diquark according to assumed spin-1 suppression.
     495           0 :   } else if (idMin != idMax) {
     496           0 :     if (rndmPtr->flat() > probQQ1join[min(idMax,5) - 2]) spin = 0;
     497             :   }
     498             : 
     499             :   // Combined diquark code.
     500           0 :   int idNewAbs = 1000 * idMax + 100 * idMin + 2 * spin + 1;
     501           0 :   return (id1 > 0) ? idNewAbs : -idNewAbs;
     502             : 
     503           0 : }
     504             : 
     505             : //==========================================================================
     506             : 
     507             : // The StringZ class.
     508             : 
     509             : //--------------------------------------------------------------------------
     510             : 
     511             : // Constants: could be changed here if desired, but normally should not.
     512             : // These are of technical nature, as described for each.
     513             : 
     514             : // When a or c are close to special cases, default to these.
     515             : const double StringZ::CFROMUNITY = 0.01;
     516             : const double StringZ::AFROMZERO  = 0.02;
     517             : const double StringZ::AFROMC     = 0.01;
     518             : 
     519             : // Do not take exponent of too large or small number.
     520             : const double StringZ::EXPMAX     = 50.;
     521             : 
     522             : //--------------------------------------------------------------------------
     523             : 
     524             : // Initialize data members of the string z selection.
     525             : 
     526             : void StringZ::init(Settings& settings, ParticleData& particleData,
     527             :   Rndm* rndmPtrIn) {
     528             : 
     529             :   // Save pointer.
     530           0 :   rndmPtr       = rndmPtrIn;
     531             : 
     532             :   // c and b quark masses.
     533           0 :   mc2           = pow2( particleData.m0(4));
     534           0 :   mb2           = pow2( particleData.m0(5));
     535             : 
     536             :   // Paramaters of Lund/Bowler symmetric fragmentation function.
     537           0 :   aLund         = settings.parm("StringZ:aLund");
     538           0 :   bLund         = settings.parm("StringZ:bLund");
     539           0 :   aExtraSQuark  = settings.parm("StringZ:aExtraSQuark");
     540           0 :   aExtraDiquark = settings.parm("StringZ:aExtraDiquark");
     541           0 :   rFactC        = settings.parm("StringZ:rFactC");
     542           0 :   rFactB        = settings.parm("StringZ:rFactB");
     543           0 :   rFactH        = settings.parm("StringZ:rFactH");
     544             : 
     545             :   // Flags and parameters of nonstandard Lund fragmentation functions.
     546           0 :   useNonStandC  = settings.flag("StringZ:useNonstandardC");
     547           0 :   useNonStandB  = settings.flag("StringZ:useNonstandardB");
     548           0 :   useNonStandH  = settings.flag("StringZ:useNonstandardH");
     549           0 :   aNonC         = settings.parm("StringZ:aNonstandardC");
     550           0 :   aNonB         = settings.parm("StringZ:aNonstandardB");
     551           0 :   aNonH         = settings.parm("StringZ:aNonstandardH");
     552           0 :   bNonC         = settings.parm("StringZ:bNonstandardC");
     553           0 :   bNonB         = settings.parm("StringZ:bNonstandardB");
     554           0 :   bNonH         = settings.parm("StringZ:bNonstandardH");
     555             : 
     556             :   // Flags and parameters of Peterson/SLAC fragmentation function.
     557           0 :   usePetersonC  = settings.flag("StringZ:usePetersonC");
     558           0 :   usePetersonB  = settings.flag("StringZ:usePetersonB");
     559           0 :   usePetersonH  = settings.flag("StringZ:usePetersonH");
     560           0 :   epsilonC      = settings.parm("StringZ:epsilonC");
     561           0 :   epsilonB      = settings.parm("StringZ:epsilonB");
     562           0 :   epsilonH      = settings.parm("StringZ:epsilonH");
     563             : 
     564             :   // Parameters for joining procedure.
     565           0 :   stopM         = settings.parm("StringFragmentation:stopMass");
     566           0 :   stopNF        = settings.parm("StringFragmentation:stopNewFlav");
     567           0 :   stopS         = settings.parm("StringFragmentation:stopSmear");
     568             : 
     569           0 : }
     570             : 
     571             : //--------------------------------------------------------------------------
     572             : 
     573             : // Generate the fraction z that the next hadron will take,
     574             : // using either Lund/Bowler or, for heavy, Peterson/SLAC functions.
     575             : // Note: for a heavy new coloured particle we assume pT negligible.
     576             : 
     577             : double StringZ::zFrag( int idOld, int idNew, double mT2) {
     578             : 
     579             :   // Find if old or new flavours correspond to diquarks.
     580           0 :   int idOldAbs = abs(idOld);
     581           0 :   int idNewAbs = abs(idNew);
     582           0 :   bool isOldSQuark = (idOldAbs == 3);
     583           0 :   bool isNewSQuark = (idNewAbs == 3);
     584           0 :   bool isOldDiquark = (idOldAbs > 1000 && idOldAbs < 10000);
     585           0 :   bool isNewDiquark = (idNewAbs > 1000 && idNewAbs < 10000);
     586             : 
     587             :   // Find heaviest quark in fragmenting parton/diquark.
     588             :   int idFrag = idOldAbs;
     589           0 :   if (isOldDiquark) idFrag = max( idOldAbs / 1000, (idOldAbs / 100) % 10);
     590             : 
     591             :   // Use Peterson where explicitly requested for heavy flavours.
     592           0 :   if (idFrag == 4 && usePetersonC) return zPeterson( epsilonC);
     593           0 :   if (idFrag == 5 && usePetersonB) return zPeterson( epsilonB);
     594           0 :   if (idFrag >  5 && usePetersonH) {
     595           0 :     double epsilon = epsilonH * mb2 / mT2;
     596           0 :     return zPeterson( epsilon);
     597             :   }
     598             : 
     599             :   // Nonstandard a and b values implemented for heavy flavours.
     600           0 :   double aNow = aLund;
     601           0 :   double bNow = bLund;
     602           0 :   if (idFrag == 4 && useNonStandC) {
     603           0 :     aNow = aNonC;
     604           0 :     bNow = bNonC;
     605           0 :   } else if (idFrag == 5 && useNonStandB) {
     606           0 :     aNow = aNonB;
     607           0 :     bNow = bNonB;
     608           0 :   } else if (idFrag >  5 && useNonStandH) {
     609           0 :     aNow = aNonH;
     610           0 :     bNow = bNonH;
     611           0 :   }
     612             : 
     613             :   // Shape parameters of Lund symmetric fragmentation function.
     614             :   double aShape = aNow;
     615           0 :   if (isOldSQuark)  aShape += aExtraSQuark;
     616           0 :   if (isOldDiquark) aShape += aExtraDiquark;
     617           0 :   double bShape = bNow * mT2;
     618             :   double cShape = 1.;
     619           0 :   if (isOldSQuark)  cShape -= aExtraSQuark;
     620           0 :   if (isNewSQuark)  cShape += aExtraSQuark;
     621           0 :   if (isOldDiquark) cShape -= aExtraDiquark;
     622           0 :   if (isNewDiquark) cShape += aExtraDiquark;
     623           0 :   if (idFrag == 4) cShape += rFactC * bNow * mc2;
     624           0 :   if (idFrag == 5) cShape += rFactB * bNow * mb2;
     625           0 :   if (idFrag >  5) cShape += rFactH * bNow * mT2;
     626           0 :   return zLund( aShape, bShape, cShape);
     627             : 
     628           0 : }
     629             : 
     630             : //--------------------------------------------------------------------------
     631             : 
     632             : // Generate a random z according to the Lund/Bowler symmetric
     633             : // fragmentation function f(z) = (1 -z)^a * exp(-b/z) / z^c.
     634             : // Normalized so that f(z_max) = 1  it can also be written as
     635             : // f(z) = exp( a * ln( (1 - z) / (1 - z_max) ) + b * (1/z_max - 1/z)
     636             : //           + c * ln(z_max/z) ).
     637             : 
     638             : double StringZ::zLund( double a, double b, double c) {
     639             : 
     640             :   // Special cases for c = 1, a = 0 and a = c.
     641           0 :   bool cIsUnity = (abs( c - 1.) < CFROMUNITY);
     642           0 :   bool aIsZero = (a < AFROMZERO);
     643           0 :   bool aIsC = (abs(a - c) < AFROMC);
     644             : 
     645             :   // Determine position of maximum.
     646           0 :   double zMax;
     647           0 :   if (aIsZero) zMax = (c > b) ? b / c : 1.;
     648           0 :   else if (aIsC) zMax = b / (b + c);
     649           0 :   else { zMax = 0.5 * (b + c - sqrt( pow2(b - c) + 4. * a * b)) / (c - a);
     650           0 :          if (zMax > 0.9999 && b > 100.) zMax = min(zMax, 1. - a / b); }
     651             : 
     652             :   // Subdivide z range if distribution very peaked near either endpoint.
     653           0 :   bool peakedNearZero = (zMax < 0.1);
     654           0 :   bool peakedNearUnity = (zMax > 0.85 && b > 1.);
     655             : 
     656             :   // Find integral of trial function everywhere bigger than f.
     657             :   // (Dummy start values.)
     658             :   double fIntLow = 1.;
     659             :   double fIntHigh = 1.;
     660             :   double fInt = 2.;
     661           0 :   double zDiv = 0.5;
     662             :   double zDivC = 0.5;
     663             :   // When z_max is small use that f(z)
     664             :   //   < 1     for z < z_div = 2.75 * z_max,
     665             :   //   < (z_div/z)^c for z > z_div (=> logarithm for c = 1, else power).
     666           0 :   if (peakedNearZero) {
     667           0 :     zDiv = 2.75 * zMax;
     668             :     fIntLow = zDiv;
     669           0 :     if (cIsUnity) fIntHigh = -zDiv * log(zDiv);
     670           0 :     else { zDivC = pow( zDiv, 1. - c);
     671           0 :            fIntHigh = zDiv * (1. - 1./zDivC) / (c - 1.);}
     672           0 :     fInt = fIntLow + fIntHigh;
     673             :   // When z_max large use that f(z)
     674             :   //   < exp( b * (z - z_div) ) for z < z_div with z_div messy expression,
     675             :   //   < 1   for z > z_div.
     676             :   // To simplify expressions the integral is extended to z =  -infinity.
     677           0 :   } else if (peakedNearUnity) {
     678           0 :     double rcb = sqrt(4. + pow2(c / b));
     679           0 :     zDiv = rcb - 1./zMax - (c / b) * log( zMax * 0.5 * (rcb + c / b) );
     680           0 :     if (!aIsZero) zDiv += (a/b) * log(1. - zMax);
     681           0 :     zDiv = min( zMax, max(0., zDiv));
     682           0 :     fIntLow = 1. / b;
     683           0 :     fIntHigh = 1. - zDiv;
     684           0 :     fInt = fIntLow + fIntHigh;
     685           0 :   }
     686             : 
     687             :   // Choice of z, preweighted for peaks at low or high z. (Dummy start values.)
     688             :   double z = 0.5;
     689             :   double fPrel = 1.;
     690             :   double fVal = 1.;
     691           0 :   do {
     692             :     // Choice of z flat good enough for distribution peaked in the middle;
     693             :     // if not this z can be reused as a random number in general.
     694           0 :     z = rndmPtr->flat();
     695             :     fPrel = 1.;
     696             :     // When z_max small use flat below z_div and 1/z^c above z_div.
     697           0 :     if (peakedNearZero) {
     698           0 :       if (fInt * rndmPtr->flat() < fIntLow) z = zDiv * z;
     699           0 :       else if (cIsUnity) {z = pow( zDiv, z); fPrel = zDiv / z;}
     700           0 :       else { z = pow( zDivC + (1. - zDivC) * z, 1. / (1. - c) );
     701           0 :              fPrel = pow( zDiv / z, c); }
     702             :     // When z_max large use exp( b * (z -z_div) ) below z_div
     703             :     // and flat above it.
     704           0 :     } else if (peakedNearUnity) {
     705           0 :       if (fInt * rndmPtr->flat() < fIntLow) {
     706           0 :         z = zDiv + log(z) / b;
     707           0 :         fPrel = exp( b * (z - zDiv) );
     708           0 :       } else z = zDiv + (1. - zDiv) * z;
     709             :     }
     710             : 
     711             :     // Evaluate actual f(z) (if in physical range) and correct.
     712           0 :     if (z > 0 && z < 1) {
     713           0 :       double fExp = b * (1. / zMax - 1. / z)+ c * log(zMax / z);
     714           0 :       if (!aIsZero) fExp += a * log( (1. - z) / (1. - zMax) );
     715           0 :       fVal = exp( max( -EXPMAX, min( EXPMAX, fExp) ) ) ;
     716           0 :     } else fVal = 0.;
     717           0 :   } while (fVal < rndmPtr->flat() * fPrel);
     718             : 
     719             :   // Done.
     720           0 :   return z;
     721             : 
     722           0 : }
     723             : 
     724             : //--------------------------------------------------------------------------
     725             : 
     726             : // Generate a random z according to the Peterson/SLAC formula
     727             : // f(z) = 1 / ( z * (1 - 1/z - epsilon/(1-z))^2 )
     728             : //      = z * (1-z)^2 / ((1-z)^2 + epsilon * z)^2.
     729             : 
     730             : double StringZ::zPeterson( double epsilon) {
     731             : 
     732             :   double z, fVal;
     733             : 
     734             :   // For large epsilon pick z flat and reject,
     735             :   // knowing that 4 * epsilon * f(z) < 1 everywhere.
     736           0 :   if (epsilon > 0.01) {
     737             :     do {
     738           0 :       z = rndmPtr->flat();
     739           0 :       fVal = 4. * epsilon * z * pow2(1. - z)
     740           0 :         / pow2( pow2(1. - z) + epsilon * z);
     741           0 :     } while (fVal < rndmPtr->flat());
     742           0 :     return z;
     743             :   }
     744             : 
     745             :   // Else split range, using that 4 * epsilon * f(z)
     746             :   //   < 4 * epsilon / (1 - z)^2 for 0 < z < 1 - 2 * sqrt(epsilon)
     747             :   //   < 1                       for 1 - 2 * sqrt(epsilon) < z < 1
     748           0 :   double epsRoot = sqrt(epsilon);
     749           0 :   double epsComb = 0.5 / epsRoot - 1.;
     750           0 :   double fIntLow = 4. * epsilon * epsComb;
     751           0 :   double fInt = fIntLow + 2. * epsRoot;
     752           0 :   do {
     753           0 :     if (rndmPtr->flat() * fInt < fIntLow) {
     754           0 :       z = 1. - 1. / (1. + rndmPtr->flat() * epsComb);
     755           0 :       fVal = z * pow2( pow2(1. - z) / (pow2(1. - z) + epsilon * z) );
     756           0 :     } else {
     757           0 :       z = 1. - 2. * epsRoot * rndmPtr->flat();
     758           0 :       fVal = 4. * epsilon * z * pow2(1. - z)
     759           0 :         / pow2( pow2(1. - z) + epsilon * z);
     760             :     }
     761           0 :   } while (fVal < rndmPtr->flat());
     762             :   return z;
     763             : 
     764           0 : }
     765             : 
     766             : //==========================================================================
     767             : 
     768             : // The StringPT class.
     769             : 
     770             : //--------------------------------------------------------------------------
     771             : 
     772             : // Constants: could be changed here if desired, but normally should not.
     773             : // These are of technical nature, as described for each.
     774             : 
     775             : // To avoid division by zero one must have sigma > 0.
     776             : const double StringPT::SIGMAMIN     = 0.2;
     777             : 
     778             : //--------------------------------------------------------------------------
     779             : 
     780             : // Initialize data members of the string pT selection.
     781             : 
     782             : void StringPT::init(Settings& settings,  ParticleData& , Rndm* rndmPtrIn) {
     783             : 
     784             :   // Save pointer.
     785           0 :   rndmPtr        = rndmPtrIn;
     786             : 
     787             :   // Parameters of the pT width and enhancement.
     788           0 :   double sigma     = settings.parm("StringPT:sigma");
     789           0 :   sigmaQ           = sigma / sqrt(2.);
     790           0 :   enhancedFraction = settings.parm("StringPT:enhancedFraction");
     791           0 :   enhancedWidth    = settings.parm("StringPT:enhancedWidth");
     792             : 
     793             :   // Parameter for pT suppression in MiniStringFragmentation.
     794           0 :   sigma2Had        = 2. * pow2( max( SIGMAMIN, sigma) );
     795             : 
     796           0 : }
     797             : 
     798             : //--------------------------------------------------------------------------
     799             : 
     800             : // Generate Gaussian pT such that <p_x^2> = <p_x^2> = sigma^2 = width^2/2,
     801             : // but with small fraction multiplied up to a broader spectrum.
     802             : 
     803             : pair<double, double> StringPT::pxy() {
     804             : 
     805           0 :   double sigma = sigmaQ;
     806           0 :   if (rndmPtr->flat() < enhancedFraction) sigma *= enhancedWidth;
     807           0 :   pair<double, double> gauss2 = rndmPtr->gauss2();
     808           0 :   return pair<double, double>(sigma * gauss2.first, sigma * gauss2.second);
     809             : 
     810           0 : }
     811             : 
     812             : //==========================================================================
     813             : 
     814             : } // end namespace Pythia8

Generated by: LCOV version 1.11