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

          Line data    Source code
       1             : // FragmentationSystems.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             : // ColConfig, StringRegion and StringSystem classes.
       8             : 
       9             : #include "Pythia8/FragmentationSystems.h"
      10             : 
      11             : namespace Pythia8 {
      12             : 
      13             : //==========================================================================
      14             : 
      15             : // The ColConfig 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             : // A typical u/d constituent mass.
      23             : const double ColConfig::CONSTITUENTMASS = 0.325;
      24             : 
      25             : //--------------------------------------------------------------------------
      26             : 
      27             : // Initialize and save pointers.
      28             : 
      29             : void ColConfig::init(Info* infoPtrIn, Settings& settings,
      30             :   StringFlav* flavSelPtrIn) {
      31             : 
      32             :   // Save pointers.
      33           0 :   infoPtr       = infoPtrIn;
      34           0 :   flavSelPtr    = flavSelPtrIn;
      35             : 
      36             :   // Joining of nearby partons along the string.
      37           0 :   mJoin         = settings.parm("FragmentationSystems:mJoin");
      38             : 
      39             :   // For consistency ensure that mJoin is bigger than in StringRegion.
      40           0 :   mJoin         = max( mJoin, 2. * StringRegion::MJOIN);
      41             : 
      42             :   // Simplification of q q q junction topology to quark - diquark one.
      43           0 :   mJoinJunction = settings.parm("FragmentationSystems:mJoinJunction");
      44           0 :   mStringMin    = settings.parm("HadronLevel:mStringMin");
      45             : 
      46           0 : }
      47             : 
      48             : //--------------------------------------------------------------------------
      49             : 
      50             : // Insert a new colour singlet system in ascending mass order.
      51             : // Calculate its properties. Join nearby partons.
      52             : 
      53             : bool ColConfig::insert( vector<int>& iPartonIn, Event& event) {
      54             : 
      55             :   // Find momentum and invariant mass of system, minus endpoint masses.
      56           0 :   Vec4 pSumIn;
      57             :   double mSumIn = 0.;
      58             :   bool hasJunctionIn = false;
      59             :   int  nJunctionLegs = 0;
      60           0 :   for (int i = 0; i < int(iPartonIn.size()); ++i) {
      61           0 :     if (iPartonIn[i] < 0) {
      62             :       hasJunctionIn = true;
      63           0 :       ++nJunctionLegs;
      64           0 :     } else {
      65           0 :       pSumIn += event[ iPartonIn[i] ].p();
      66           0 :       if (!event[ iPartonIn[i] ].isGluon())
      67           0 :         mSumIn += event[ iPartonIn[i] ].constituentMass();
      68             :     }
      69             :   }
      70           0 :   double massIn = pSumIn.mCalc();
      71           0 :   double massExcessIn = massIn - mSumIn;
      72             : 
      73             :   // Check for rare triple- and higher junction systems (like J-Jbar-J)
      74           0 :   if (nJunctionLegs >= 5) {
      75           0 :     infoPtr->errorMsg("Error in ColConfig::insert: "
      76             :       "junction topology too complicated; too many junction legs");
      77           0 :     return false;
      78             :   }
      79             :   // Check that junction systems have at least three legs.
      80           0 :   else if (nJunctionLegs > 0 && nJunctionLegs <= 2) {
      81           0 :     infoPtr->errorMsg("Error in ColConfig::insert: "
      82             :       "junction topology inconsistent; too few junction legs");
      83           0 :     return false;
      84             :   }
      85             : 
      86             :   // Check that momenta do not contain not-a-number.
      87           0 :   if (abs(massExcessIn) >= 0.);
      88             :   else {
      89           0 :     infoPtr->errorMsg("Error in ColConfig::insert: "
      90             :       "not-a-number system mass");
      91           0 :     return false;
      92             :   }
      93             : 
      94             :   // Identify closed gluon loop. Assign "endpoint" masses as light quarks.
      95           0 :   bool isClosedIn = (iPartonIn[0] >= 0 && event[ iPartonIn[0] ].col() != 0
      96           0 :     && event[ iPartonIn[0] ].acol() != 0 );
      97           0 :   if (isClosedIn) massExcessIn -= 2. * CONSTITUENTMASS;
      98             : 
      99             :   // For junction topology: join two nearby legs into a diquark.
     100           0 :   if (hasJunctionIn && joinJunction( iPartonIn, event, massExcessIn))
     101           0 :     hasJunctionIn = false;
     102             : 
     103             :   // Loop while > 2 partons left and hope of finding joining pair.
     104             :   bool hasJoined = true;
     105           0 :   while (hasJoined && iPartonIn.size() > 2) {
     106             : 
     107             :     // Look for the pair of neighbour partons (along string) with
     108             :     // the smallest invariant mass (subtracting quark masses).
     109             :     int iJoinMin = -1;
     110           0 :     double mJoinMin = 2. * mJoin;
     111           0 :     int nSize = iPartonIn.size();
     112           0 :     int nPair = (isClosedIn) ? nSize : nSize - 1;
     113           0 :     for (int i = 0; i < nPair; ++i) {
     114             :       // Keep three legs of junction separate.
     115           0 :       if (iPartonIn[i] < 0 || iPartonIn[(i + 1)%nSize] < 0) continue;
     116           0 :       Particle& parton1 = event[ iPartonIn[i] ];
     117           0 :       Particle& parton2 = event[ iPartonIn[(i + 1)%nSize] ];
     118             :       // Avoid joining non-partons, e.g. gluino/squark for R-hadron.
     119           0 :       if (!parton1.isParton() || !parton2.isParton()) continue;
     120           0 :       Vec4 pSumNow;
     121           0 :       pSumNow += (parton1.isGluon()) ? 0.5 * parton1.p() : parton1.p();
     122           0 :       pSumNow += (parton2.isGluon()) ? 0.5 * parton2.p() : parton2.p();
     123           0 :       double mJoinNow = pSumNow.mCalc();
     124           0 :       if (!parton1.isGluon()) mJoinNow -= parton1.m();
     125           0 :       if (!parton2.isGluon()) mJoinNow -= parton2.m();
     126           0 :       if (mJoinNow < mJoinMin) { iJoinMin = i; mJoinMin = mJoinNow; }
     127           0 :     }
     128             : 
     129             :     // If sufficiently nearby then join into one new parton.
     130             :     // Note: error sensitivity to mJoin indicates unstable precedure??
     131             :     hasJoined = false;
     132           0 :     if (mJoinMin < mJoin) {
     133           0 :       int iJoin1  = iPartonIn[iJoinMin];
     134           0 :       int iJoin2  = iPartonIn[(iJoinMin + 1)%nSize];
     135           0 :       int idNew   = (event[iJoin1].isGluon()) ? event[iJoin2].id()
     136           0 :                                               : event[iJoin1].id();
     137           0 :       int iMoth1  = min(iJoin1, iJoin2);
     138           0 :       int iMoth2  = max(iJoin1, iJoin2);
     139             :       // When g + q -> q flip to ensure that mother1 = q.
     140           0 :       if (event[iMoth1].id() == 21 && event[iMoth2].id() != 21)
     141           0 :         swap( iMoth1, iMoth2);
     142           0 :       int colNew  = event[iJoin1].col();
     143           0 :       int acolNew = event[iJoin2].acol();
     144           0 :       if (colNew == acolNew) {
     145           0 :         colNew    = event[iJoin2].col();
     146           0 :         acolNew   = event[iJoin1].acol();
     147           0 :       }
     148           0 :       Vec4 pNew   = event[iJoin1].p() + event[iJoin2].p();
     149             : 
     150             :       int statusHad = 73;
     151             :       // Need to keep status as 74 for junctions in order to keep track
     152             :       // of them.
     153           0 :       if (event[iMoth1].statusAbs() == 74) statusHad = 74;
     154             : 
     155             :       // Append joined parton to event record.
     156           0 :       int iNew = event.append( idNew, statusHad, iMoth1, iMoth2, 0, 0,
     157           0 :         colNew, acolNew, pNew, pNew.mCalc() );
     158             : 
     159             :       // Displaced lifetime/vertex; mothers should be same but prefer quark.
     160           0 :       int iVtx = (event[iJoin1].isGluon()) ? iJoin2 : iJoin1;
     161           0 :       event[iNew].tau( event[iVtx].tau() );
     162           0 :       if (event[iVtx].hasVertex()) event[iNew].vProd( event[iVtx].vProd() );
     163             : 
     164             :       // Mark joined partons and reduce remaining system.
     165           0 :       event[iJoin1].statusNeg();
     166           0 :       event[iJoin2].statusNeg();
     167           0 :       event[iJoin1].daughter1(iNew);
     168           0 :       event[iJoin2].daughter1(iNew);
     169           0 :       if (iJoinMin == nSize - 1) iPartonIn[0] = iNew;
     170             :       else {
     171           0 :         iPartonIn[iJoinMin] = iNew;
     172           0 :         for (int i = iJoinMin + 1; i < nSize - 1; ++i)
     173           0 :           iPartonIn[i] = iPartonIn[i + 1];
     174             :       }
     175           0 :       iPartonIn.pop_back();
     176             : 
     177             :       // If joined,then loopback to look for more.
     178             :       hasJoined = true;
     179           0 :     }
     180             :   }
     181             : 
     182             :   // Store new colour singlet system at the end.
     183           0 :   singlets.push_back( ColSinglet(iPartonIn, pSumIn, massIn,
     184           0 :     massExcessIn, hasJunctionIn, isClosedIn) );
     185             : 
     186             :   // Now move around, so that smallest mass excesses come first.
     187           0 :   int iInsert = singlets.size() - 1;
     188           0 :   for (int iSub = singlets.size() - 2; iSub >= 0; --iSub) {
     189           0 :     if (massExcessIn > singlets[iSub].massExcess) break;
     190           0 :     singlets[iSub + 1] = singlets[iSub];
     191             :     iInsert = iSub;
     192             :   }
     193           0 :   if (iInsert < int(singlets.size()) - 1) singlets[iInsert] =
     194           0 :     ColSinglet(iPartonIn, pSumIn, massIn, massExcessIn,
     195             :     hasJunctionIn, isClosedIn);
     196             : 
     197             :   // Done.
     198             :   return true;
     199           0 : }
     200             : 
     201             : //--------------------------------------------------------------------------
     202             : 
     203             : // Join two legs of junction to a diquark for small invariant masses.
     204             : // Note: for junction system, iPartonIn points to structure
     205             : // (-code0) g...g.q0 (-code1) g...g.q1 (-code2) g...g.q2
     206             : 
     207             : bool ColConfig::joinJunction( vector<int>& iPartonIn, Event& event,
     208             :   double massExcessIn) {
     209             : 
     210             :   // Find four-momentum and endpoint quarks and masses on the three legs.
     211           0 :   Vec4   pLeg[3];
     212           0 :   double mLeg[3] = { 0., 0., 0.};
     213           0 :   int    idAbsLeg[3];
     214             :   int leg = -1;
     215           0 :   for (int i = 0; i < int(iPartonIn.size()); ++ i) {
     216           0 :     if (iPartonIn[i] < 0) ++leg;
     217             :     else {
     218           0 :       pLeg[leg]    += event[ iPartonIn[i] ].p();
     219           0 :       mLeg[leg]     = event[ iPartonIn[i] ].m();
     220           0 :       idAbsLeg[leg] = event[ iPartonIn[i] ].idAbs();
     221             :     }
     222             :   }
     223             : 
     224             :   // Calculate invariant mass of three pairs, minus endpoint masses.
     225           0 :   double m01  = (pLeg[0] + pLeg[1]).mCalc() - mLeg[0] - mLeg[1];
     226           0 :   double m02  = (pLeg[0] + pLeg[2]).mCalc() - mLeg[0] - mLeg[2];
     227           0 :   double m12  = (pLeg[1] + pLeg[2]).mCalc() - mLeg[1] - mLeg[2];
     228             : 
     229             :   // Find lowest-mass pair not involving diquark.
     230           0 :   double mMin = mJoinJunction + 1.;
     231             :   int    legA = -1;
     232             :   int    legB = -1;
     233           0 :   if (m01 < mMin && idAbsLeg[0] < 9 && idAbsLeg[1] < 9) {
     234             :     mMin = m01;
     235             :     legA = 0;
     236             :     legB = 1;
     237           0 :   }
     238           0 :   if (m02 < mMin && idAbsLeg[0] < 9 && idAbsLeg[2] < 9) {
     239             :     mMin = m02;
     240             :     legA = 0;
     241             :     legB = 2;
     242           0 :   }
     243           0 :   if (m12 < mMin && idAbsLeg[1] < 9 && idAbsLeg[2] < 9) {
     244             :     mMin = m12;
     245             :     legA = 1;
     246             :     legB = 2;
     247           0 :   }
     248           0 :   int legC = 3 - legA - legB;
     249             : 
     250             :   // Nothing to do if no two legs have small invariant mass, and
     251             :   // system as a whole is above MiniStringFragmentation threshold.
     252           0 :   if (legA == -1 || (mMin > mJoinJunction && massExcessIn > mStringMin))
     253           0 :     return false;
     254             : 
     255             :   // Construct separate index arrays for the three legs.
     256           0 :   vector<int> iLegA, iLegB, iLegC;
     257             :   leg = -1;
     258           0 :   for (int i = 0; i < int(iPartonIn.size()); ++ i) {
     259           0 :     if (iPartonIn[i] < 0) ++leg;
     260           0 :     else if( leg == legA) iLegA.push_back( iPartonIn[i] );
     261           0 :     else if( leg == legB) iLegB.push_back( iPartonIn[i] );
     262           0 :     else if( leg == legC) iLegC.push_back( iPartonIn[i] );
     263             :   }
     264             : 
     265             :   // First step: successively combine any gluons on the two legs.
     266             :   // (Presumably overkill; not likely to be (m)any extra gluons.)
     267             :   // (Do as successive binary joinings, so only need two mothers.)
     268           0 :   for (leg = 0; leg < 2; ++leg) {
     269           0 :     vector<int>& iLegNow = (leg == 0) ? iLegA : iLegB;
     270           0 :     int sizeNow = iLegNow.size();
     271           0 :     for (int i = sizeNow - 2; i >= 0; --i) {
     272           0 :       int iQ = iLegNow.back();
     273           0 :       int iG = iLegNow[i];
     274           0 :       int colNew = (event[iQ].id() > 0) ? event[iG].col() : 0;
     275           0 :       int acolNew = (event[iQ].id() < 0) ? event[iG].acol() : 0;
     276           0 :       Vec4 pNew = event[iQ].p() + event[iG].p();
     277           0 :       int iNew = event.append( event[iQ].id(), 74, iQ, iG, 0, 0,
     278           0 :         colNew, acolNew, pNew, pNew.mCalc() );
     279             : 
     280             :       // Mark joined partons and update iLeg end.
     281           0 :       event[iQ].statusNeg();
     282           0 :       event[iG].statusNeg();
     283           0 :       event[iQ].daughter1(iNew);
     284           0 :       event[iG].daughter1(iNew);
     285           0 :       iLegNow.back() = iNew;
     286           0 :     }
     287             :   }
     288             : 
     289             :   // Second step: combine two quarks into a diquark.
     290           0 :   int iQA     = iLegA.back();
     291           0 :   int iQB     = iLegB.back();
     292           0 :   int idQA    = event[iQA].id();
     293           0 :   int idQB    = event[iQB].id();
     294           0 :   int idNew   = flavSelPtr->makeDiquark( idQA, idQB );
     295             :   // Diquark colour is opposite to parton closest to junction on third leg.
     296           0 :   int colNew  = (idNew > 0) ? 0 : event[ iLegC[0] ].acol();
     297           0 :   int acolNew = (idNew > 0) ? event[ iLegC[0] ].col() : 0;
     298           0 :   Vec4 pNew   = pLeg[legA] + pLeg[legB];
     299           0 :   int iNew    = event.append( idNew, 74, min(iQA, iQB), max( iQA, iQB),
     300           0 :      0, 0, colNew, acolNew, pNew, pNew.mCalc() );
     301             : 
     302             :   // Mark joined partons and reduce remaining system.
     303           0 :   event[iQA].statusNeg();
     304           0 :   event[iQB].statusNeg();
     305           0 :   event[iQA].daughter1(iNew);
     306           0 :   event[iQB].daughter1(iNew);
     307           0 :   iPartonIn.resize(0);
     308           0 :   iPartonIn.push_back( iNew);
     309           0 :   for (int i = 0; i < int(iLegC.size()) ; ++i)
     310           0 :     iPartonIn.push_back( iLegC[i]);
     311             : 
     312             :   // Remove junction from event record list, identifying by colour.
     313             :   int iJun = -1;
     314           0 :   for (int i = 0; i < event.sizeJunction(); ++i)
     315           0 :     for (int j = 0; j < 3; ++ j)
     316           0 :       if ( event.colJunction(i,j) == max(colNew, acolNew) ) iJun = i;
     317           0 :   if (iJun >= 0) event.eraseJunction(iJun);
     318             : 
     319             :   // Done, having eliminated junction.
     320             :   return true;
     321             : 
     322           0 : }
     323             : 
     324             : //--------------------------------------------------------------------------
     325             : 
     326             : // Collect all partons of singlet to be consecutively ordered.
     327             : 
     328             : void ColConfig::collect(int iSub, Event& event, bool skipTrivial) {
     329             : 
     330             :   // Check that all partons have positive energy.
     331           0 :   for (int i = 0; i < singlets[iSub].size(); ++i) {
     332           0 :     int iNow = singlets[iSub].iParton[i];
     333           0 :     if (iNow > 0 && event[iNow].e() < 0.)
     334           0 :     infoPtr->errorMsg("Warning in ColConfig::collect: "
     335             :       "negative-energy parton encountered");
     336             :   }
     337             : 
     338             :   // Partons may already have been collected, e.g. at ministring collapse.
     339           0 :   if (singlets[iSub].isCollected) return;
     340           0 :   singlets[iSub].isCollected = true;
     341             : 
     342             :   // Check if partons already "by chance" happen to be ordered.
     343             :   bool inOrder = true;
     344           0 :   for (int i = 0; i < singlets[iSub].size() - 1; ++i) {
     345           0 :     int iFirst = singlets[iSub].iParton[i];
     346           0 :     if (iFirst < 0) continue;
     347           0 :     int iSecond = singlets[iSub].iParton[i + 1];
     348           0 :     if (iSecond < 0) iSecond = singlets[iSub].iParton[i + 2];
     349           0 :     if (iSecond != iFirst + 1) { inOrder = false; break;}
     350           0 :   }
     351             : 
     352             :   // Normally done if in order, but sometimes may need to copy anyway.
     353           0 :   if (inOrder && skipTrivial) return;
     354             : 
     355             :   // Copy down system. Update current partons.
     356           0 :   for (int i = 0; i < singlets[iSub].size(); ++i) {
     357           0 :     int iOld = singlets[iSub].iParton[i];
     358           0 :     if (iOld < 0) continue;
     359             :     int iNew;
     360           0 :     if (event[iOld].status() == 74) iNew = event.copy(iOld, 74);
     361           0 :     else iNew = event.copy(iOld, 71);
     362           0 :     singlets[iSub].iParton[i] = iNew;
     363           0 :   }
     364             : 
     365             :   // Done.
     366           0 : }
     367             : 
     368             : //--------------------------------------------------------------------------
     369             : 
     370             : // Find to which singlet system a particle belongs.
     371             : 
     372             : int ColConfig::findSinglet(int i) {
     373             : 
     374             :   // Loop through all systems and all members in them.
     375           0 :   for (int iSub = 0; iSub < int(singlets.size()); ++iSub)
     376           0 :   for (int iMem = 0; iMem < singlets[iSub].size(); ++iMem)
     377           0 :     if (singlets[iSub].iParton[iMem] == i) return iSub;
     378             : 
     379             :   // Done without having found particle; return -1 = error code.
     380           0 :   return -1;
     381           0 : }
     382             : 
     383             : //--------------------------------------------------------------------------
     384             : 
     385             : // List all currently identified singlets.
     386             : 
     387             : void ColConfig::list(ostream& os) const {
     388             : 
     389             :   // Header. Loop over all individual singlets.
     390           0 :   os << "\n --------  Colour Singlet Systems Listing -------------------\n";
     391           0 :   for (int iSub = 0; iSub < int(singlets.size()); ++iSub) {
     392             : 
     393             :     // List all partons belonging to each singlet.
     394           0 :     os << " singlet " << iSub << " contains " ;
     395           0 :     for (int i = 0; i < singlets[iSub].size(); ++i)
     396           0 :       os << singlets[iSub].iParton[i] << " ";
     397           0 :     os << "\n";
     398             : 
     399             :   // Done.
     400             :   }
     401           0 : }
     402             : 
     403             : //==========================================================================
     404             : 
     405             : // The StringRegion class.
     406             : 
     407             : // Currently a number of simplifications, in particular ??
     408             : // 1) No popcorn baryon production.
     409             : // 2) Simplified treatment of pT in stepping and joining.
     410             : 
     411             : //--------------------------------------------------------------------------
     412             : 
     413             : // Constants: could be changed here if desired, but normally should not.
     414             : // These are of technical nature, as described for each.
     415             : 
     416             : // If a string region is smaller thsan this it is assumed empty.
     417             : const double StringRegion::MJOIN = 0.1;
     418             : 
     419             : // Avoid division by zero.
     420             : const double StringRegion::TINY  = 1e-20;
     421             : 
     422             : //--------------------------------------------------------------------------
     423             : 
     424             : // Set up four-vectors for longitudinal and transverse directions.
     425             : 
     426             : void StringRegion::setUp(Vec4 p1, Vec4 p2, bool isMassless) {
     427             : 
     428             :   // Simple case: the two incoming four-vectors guaranteed massless.
     429           0 :   if (isMassless) {
     430             : 
     431             :     // Calculate w2, minimum value. Lightcone directions = input.
     432           0 :     w2 = 2. * (p1 * p2);
     433           0 :     if (w2 < MJOIN*MJOIN) {isSetUp = true; isEmpty = true; return;}
     434           0 :     pPos = p1;
     435           0 :     pNeg = p2;
     436             : 
     437             :   // Else allow possibility of masses for incoming partons (also gluons!).
     438           0 :   } else {
     439             : 
     440             :     // Generic four-momentum combinations.
     441           0 :     double m1Sq = p1 * p1;
     442           0 :     double m2Sq = p2 * p2;
     443           0 :     double p1p2 = p1 * p2;
     444           0 :     w2 = m1Sq + 2. * p1p2 + m2Sq;
     445           0 :     double rootSq = pow2(p1p2) - m1Sq * m2Sq;
     446             : 
     447             :     // If crazy kinematics (should not happen!) modify energies.
     448           0 :     if (w2 <= 0. || rootSq <= 0.) {
     449           0 :       if (m1Sq < 0.) m1Sq = 0.;
     450           0 :       p1.e( sqrt(m1Sq + p1.pAbs2()) );
     451           0 :       if (m2Sq < 0.) m2Sq = 0.;
     452           0 :       p2.e( sqrt(m2Sq + p2.pAbs2()) );
     453           0 :       p1p2 = p1 * p2;
     454           0 :       w2 = m1Sq + 2. * p1p2 + m2Sq;
     455           0 :       rootSq = pow2(p1p2) - m1Sq * m2Sq;
     456           0 :     }
     457             : 
     458             :     // If still small invariant mass then empty region (e.g. in gg system).
     459           0 :     if (w2 < MJOIN*MJOIN) {isSetUp = true; isEmpty = true; return;}
     460             : 
     461             :     // Find two lightconelike longitudinal four-vector directions.
     462           0 :     double root = sqrt( max(TINY, rootSq) );
     463           0 :     double k1 = 0.5 * ( (m2Sq + p1p2) / root - 1.);
     464           0 :     double k2 = 0.5 * ( (m1Sq + p1p2) / root - 1.);
     465           0 :     pPos = (1. + k1) * p1 - k2 * p2;
     466           0 :     pNeg = (1. + k2) * p2 - k1 * p1;
     467           0 :   }
     468             : 
     469             :   // Find two spacelike transverse four-vector directions.
     470             :   // Begin by picking two sensible trial directions.
     471           0 :   Vec4 eDiff = pPos / pPos.e() - pNeg / pNeg.e();
     472           0 :   double eDx = pow2( eDiff.px() );
     473           0 :   double eDy = pow2( eDiff.py() );
     474           0 :   double eDz = pow2( eDiff.pz() );
     475           0 :   if (eDx < min(eDy, eDz)) {
     476           0 :     eX = Vec4( 1., 0., 0., 0.);
     477           0 :     eY = (eDy < eDz) ? Vec4( 0., 1., 0., 0.) : Vec4( 0., 0., 1., 0.);
     478           0 :   } else if (eDy < eDz) {
     479           0 :     eX = Vec4( 0., 1., 0., 0.);
     480           0 :     eY = (eDx < eDz) ? Vec4( 1., 0., 0., 0.) : Vec4( 0., 0., 1., 0.);
     481           0 :   } else {
     482           0 :     eX = Vec4( 0., 0., 1., 0.);
     483           0 :     eY = (eDx < eDy) ? Vec4( 1., 0., 0., 0.) : Vec4( 0., 1., 0., 0.);
     484             :   }
     485             : 
     486             :   // Then construct orthogonal linear combinations.
     487           0 :   double pPosNeg = pPos * pNeg;
     488           0 :   double kXPos = eX * pPos / pPosNeg;
     489           0 :   double kXNeg = eX * pNeg / pPosNeg;
     490           0 :   double kXX = 1. / sqrt( 1. + 2. * kXPos * kXNeg * pPosNeg );
     491           0 :   double kYPos = eY * pPos / pPosNeg;
     492           0 :   double kYNeg = eY * pNeg / pPosNeg;
     493           0 :   double kYX = kXX * (kXPos * kYNeg + kXNeg * kYPos) * pPosNeg;
     494           0 :   double kYY = 1. / sqrt(1. + 2. * kYPos * kYNeg * pPosNeg - pow2(kYX));
     495           0 :   eX = kXX * (eX - kXNeg * pPos - kXPos * pNeg);
     496           0 :   eY = kYY * (eY - kYNeg * pPos - kYPos * pNeg - kYX * eX);
     497             : 
     498             :   // Done.
     499           0 :   isSetUp = true;
     500           0 :   isEmpty = false;
     501             : 
     502           0 : }
     503             : 
     504             : //--------------------------------------------------------------------------
     505             : 
     506             : // Project a four-momentum onto (x+, x-, px, py).
     507             : 
     508             : void StringRegion::project(Vec4 pIn) {
     509             : 
     510             :   // Perform projections by four-vector multiplication.
     511           0 :   xPosProj = 2. * (pIn * pNeg) / w2;
     512           0 :   xNegProj = 2. * (pIn * pPos) / w2;
     513           0 :   pxProj = - (pIn * eX);
     514           0 :   pyProj = - (pIn * eY);
     515             : 
     516           0 : }
     517             : 
     518             : //==========================================================================
     519             : 
     520             : // The StringSystem class.
     521             : 
     522             : //--------------------------------------------------------------------------
     523             : 
     524             : // Set up system from parton list.
     525             : 
     526             : void StringSystem::setUp(vector<int>& iSys, Event& event) {
     527             : 
     528             :   // Figure out how big the system is. (Closed gluon loops?)
     529           0 :   sizePartons = iSys.size();
     530           0 :   sizeStrings = sizePartons - 1;
     531           0 :   sizeRegions = (sizeStrings * (sizeStrings + 1)) / 2;
     532           0 :   indxReg = 2 * sizeStrings + 1;
     533           0 :   iMax = sizeStrings - 1;
     534             : 
     535             :   // Reserve space for the required number of regions.
     536           0 :   system.clear();
     537           0 :   system.resize(sizeRegions);
     538             : 
     539             :   // Set up the lowest-lying regions.
     540           0 :   for (int i = 0; i < sizeStrings; ++i) {
     541           0 :     Vec4 p1 = event[ iSys[i] ].p();
     542           0 :     if ( event[ iSys[i] ].isGluon() ) p1 *= 0.5;
     543           0 :     Vec4 p2 = event[ iSys[i+1] ].p();
     544           0 :     if ( event[ iSys[i+1] ].isGluon() ) p2 *= 0.5;
     545           0 :     system[ iReg(i, iMax - i) ].setUp( p1, p2, false);
     546           0 :   }
     547             : 
     548           0 : }
     549             : 
     550             : //==========================================================================
     551             : 
     552             : } // end namespace Pythia8

Generated by: LCOV version 1.11