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

          Line data    Source code
       1             : // ColosurReconnection.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             : // ColourReconnection class.
       8             : 
       9             : #include "Pythia8/ColourReconnection.h"
      10             : namespace Pythia8 {
      11             : 
      12             : //==========================================================================
      13             : 
      14             : // The BeamDipole class is purely internal to reconnectMPIs.
      15             : 
      16             : class BeamDipole {
      17             : 
      18             : public:
      19             : 
      20             :   // Constructor.
      21             :   BeamDipole( int colIn = 0, int iColIn = 0, int iAcolIn = 0)
      22           0 :     : col(colIn), iCol(iColIn), iAcol(iAcolIn) {}
      23             : 
      24             :   // Members.
      25             :   int    col, iCol, iAcol;
      26             :   double p1p2;
      27             : 
      28             : };
      29             : 
      30             : //==========================================================================
      31             : 
      32             : // The ColourDipole class.
      33             : 
      34             : //--------------------------------------------------------------------------
      35             : 
      36             : // Printing function, inteded for debugging.
      37             : 
      38             : void ColourDipole::print() {
      39             : 
      40           0 :   cout << setw(10) << this << setw(6) << col << setw(3) << colReconnection
      41           0 :        << setw(6) << iCol << setw(5) << iAcol << setw(6) << iColLeg << setw(5)
      42           0 :        << iAcolLeg << setw(6) << isJun << setw(5) << isAntiJun  << setw(10)
      43           0 :        << p1p2 << " colDips: ";
      44           0 :   for (int i = 0;i < int(colDips.size());++i)
      45           0 :     cout << setw(10) << colDips[i];
      46           0 :   cout  <<  " acolDips: ";
      47           0 :   for (int i = 0;i < int(acolDips.size());++i)
      48           0 :     cout << setw(10) << acolDips[i];
      49           0 :   cout << setw(3) << isActive << endl;
      50             : 
      51           0 : }
      52             : 
      53             : //==========================================================================
      54             : 
      55             : // The InfoGluonMove class is purely internal to reconnectMove.
      56             : 
      57             : class InfoGluonMove{
      58             : 
      59             : public:
      60             : 
      61             :   // Constructors.
      62             :   InfoGluonMove(int i1in, int col1in, int acol1in, int iCol1in, int iAcol1in,
      63             :     int col2in, int iCol2in, int iAcol2in, double lambdaRefIn,
      64           0 :     double dLambdaIn) : i1(i1in), i2(0), col1(col1in), acol1(acol1in),
      65           0 :     iCol1(iCol1in), iAcol1(iAcol1in), col2(col2in), iCol2(iCol2in),
      66           0 :     iAcol2(iAcol2in), lambdaRef(lambdaRefIn), dLambda(dLambdaIn) {}
      67             :   InfoGluonMove(int i1in, int i2in, int iCol1in, int iAcol1in, int iCol2in,
      68           0 :     int iAcol2in, int dLambdaIn) : i1(i1in), i2(i2in), col1(0), acol1(0),
      69           0 :     iCol1(iCol1in), iAcol1(iAcol1in), col2(0), iCol2(iCol2in),
      70           0 :     iAcol2(iAcol2in), lambdaRef(0.), dLambda(dLambdaIn) {}
      71             : 
      72             :   // Members.
      73             :   int i1, i2, col1, acol1, iCol1, iAcol1, col2, iCol2, iAcol2;
      74             :   double lambdaRef, dLambda;
      75             : 
      76             : };
      77             : 
      78             : //==========================================================================
      79             : 
      80             : // The ColourJunction class.
      81             : 
      82             : //--------------------------------------------------------------------------
      83             : 
      84             : // Printing function, inteded for debugging.
      85             : 
      86             : void ColourJunction::print() {
      87             : 
      88           0 :   cout << setw(6) << kind() << setw(6)
      89           0 :        << col(0) << setw(6) << col(1) << setw(6) << col(2) << setw(6)
      90           0 :        << endCol(0) << setw(6) << endCol(1) << setw(6) << endCol(2) << setw(6)
      91           0 :        << status(0) << setw(6) << status(1) << setw(6) << status(2) << setw(10)
      92           0 :        << dips[0] << setw(10) << dips[1] << setw(10) << dips[2] << setw(10)
      93           0 :        << "\n";
      94           0 :   cout << "     " << setw(10) << dipsOrig[0] << setw(10) << dipsOrig[1]
      95           0 :        << setw(10) << dipsOrig[2] << endl;
      96             : 
      97           0 : }
      98             : 
      99             : //==========================================================================
     100             : 
     101             : // The ColourParticle class.
     102             : 
     103             : //--------------------------------------------------------------------------
     104             : 
     105             : // Printing function, inteded for debugging.
     106             : 
     107             : void ColourParticle::list() {
     108             : 
     109           0 :   const Particle& pt = (*this);
     110             : 
     111             :   // Basic line for a particle, always printed.
     112           0 :   cout << setw(10) << pt.id() << "   " << left
     113           0 :        << setw(18) << pt.nameWithStatus(18) << right << setw(4)
     114           0 :        << pt.status() << setw(6) << pt.mother1() << setw(6)
     115           0 :        << pt.mother2() << setw(6) << pt.daughter1() << setw(6)
     116           0 :        << pt.daughter2() << setw(6) << pt.col() << setw(6) << pt.acol()
     117           0 :        << setprecision(3)
     118           0 :        << setw(11) << pt.px() << setw(11) << pt.py() << setw(11)
     119           0 :        << pt.pz() << setw(11) << pt.e() << setw(11) << pt.m() << "\n";
     120             : 
     121           0 : }
     122             : 
     123             : //--------------------------------------------------------------------------
     124             : 
     125             : // Printing function, inteded for debugging.
     126             : 
     127             : void ColourParticle::listActiveDips() {
     128             : 
     129           0 :   cout << "active dips: " << endl;
     130           0 :   for (int i = 0; i < int(activeDips.size()); ++i)
     131           0 :     activeDips[i]->print();
     132             : 
     133           0 : }
     134             : 
     135             : //--------------------------------------------------------------------------
     136             : 
     137             : // Printing function, inteded for debugging.
     138             : 
     139             : void ColourParticle::print() {
     140             : 
     141           0 :   cout << "---   Particle   ---" << endl;
     142           0 :   for (int i = 0; i < int(dips.size()); ++i) {
     143           0 :     cout << "(" <<colEndIncluded[i] << ") ";
     144           0 :     for (int j = 0; j < int(dips[i].size()); ++j) {
     145           0 :       cout << dips[i][j]->iCol << " (" << dips[i][j]->col << ") ";
     146           0 :       if (j == int(dips[i].size() - 1))
     147           0 :         cout << dips[i][j]->iAcol << " (" << acolEndIncluded[i] << ")" << endl;
     148             :     }
     149             :   }
     150             : 
     151           0 : }
     152             : 
     153             : //==========================================================================
     154             : 
     155             : // The ColourReconnection class.
     156             : 
     157             : // Minimum needed gain in lambda for a reconnection (to avoid infinity loops).
     158             : const double ColourReconnection::MINIMUMGAIN = 1E-10;
     159             : 
     160             : // Minimum needed gain in lambda for a junction.
     161             : const double ColourReconnection::MINIMUMGAINJUN = 1E-10;
     162             : 
     163             : // Conversion of GeV^{-1} to fm for time calculations.
     164             : const double ColourReconnection::HBAR = 0.197327;
     165             : 
     166             : // Maximum number of reconnection per trial.
     167             : // For very large number of outgoing partons, ie. if multiple pp collisions
     168             : // are stacked on top of each other, this number needs to be raised.
     169             : const int ColourReconnection::MAXRECONNECTIONS = 1000;
     170             : 
     171             : //--------------------------------------------------------------------------
     172             : 
     173             : // Simple comparison function for sort.
     174             : 
     175             : bool cmpTrials(TrialReconnection j1, TrialReconnection j2) {
     176           0 :     return (j1.lambdaDiff < j2.lambdaDiff);
     177             : }
     178             : 
     179             : //--------------------------------------------------------------------------
     180             : 
     181             : // Initialization.
     182             : 
     183             : bool ColourReconnection::init( Info* infoPtrIn, Settings& settings,
     184             :   Rndm* rndmPtrIn, ParticleData* particleDataPtrIn,  BeamParticle* beamAPtrIn,
     185             :   BeamParticle* beamBPtrIn, PartonSystems* partonSystemsPtrIn) {
     186             : 
     187             :   // Save pointers.
     188           0 :   infoPtr             = infoPtrIn;
     189           0 :   rndmPtr             = rndmPtrIn;
     190           0 :   particleDataPtr     = particleDataPtrIn;
     191           0 :   beamAPtr            = beamAPtrIn;
     192           0 :   beamBPtr            = beamBPtrIn;
     193           0 :   partonSystemsPtr    = partonSystemsPtrIn;
     194             : 
     195             :   // Total and squared CM energy at nominal energy.
     196           0 :   eCM                 = infoPtr->eCM();
     197           0 :   sCM                 = eCM * eCM;
     198             : 
     199             :   // Choice of reconnection model.
     200           0 :   reconnectMode       = settings.mode("ColourReconnection:mode");
     201             : 
     202             :   // pT0 scale of MPI; used in the MPI-based reconnection model.
     203           0 :   pT0Ref              = settings.parm("MultipartonInteractions:pT0Ref");
     204           0 :   ecmRef              = settings.parm("MultipartonInteractions:ecmRef");
     205           0 :   ecmPow              = settings.parm("MultipartonInteractions:ecmPow");
     206           0 :   pT0                 = pT0Ref * pow(eCM / ecmRef, ecmPow);
     207             : 
     208             :   // Parameter of the MPI-based reconnection model.
     209           0 :   reconnectRange      = settings.parm("ColourReconnection:range");
     210           0 :   pT20Rec             = pow2(reconnectRange * pT0);
     211             : 
     212             :   // Parameters of the new reconnection model.
     213           0 :   m0                  = settings.parm("ColourReconnection:m0");
     214           0 :   m0sqr               = pow2(m0);
     215           0 :   allowJunctions      = settings.flag("ColourReconnection:allowJunctions");
     216           0 :   nReconCols          = settings.mode("ColourReconnection:nColours");
     217           0 :   sameNeighbourCol  = settings.flag("ColourReconnection:sameNeighbourColours");
     218             : 
     219           0 :   timeDilationMode    = settings.mode("ColourReconnection:timeDilationMode");
     220           0 :   timeDilationPar     = settings.parm("ColourReconnection:timeDilationPar");
     221           0 :   timeDilationParGeV  = timeDilationPar / HBAR;
     222             : 
     223             :   // Parameters of gluon-move model.
     224           0 :   m2Lambda            = settings.parm("ColourReconnection:m2Lambda");
     225           0 :   fracGluon           = settings.parm("ColourReconnection:fracGluon");
     226           0 :   dLambdaCut          = settings.parm("ColourReconnection:dLambdaCut");
     227           0 :   flipMode            = settings.mode("ColourReconnection:flipMode");
     228             : 
     229             :   // Parameters of the e+e- CR models.
     230           0 :   singleReconOnly     = settings.flag("ColourReconnection:singleReconnection");
     231           0 :   lowerLambdaOnly     = settings.flag("ColourReconnection:lowerLambdaOnly");
     232           0 :   tfrag               = settings.parm("ColourReconnection:fragmentationTime");
     233           0 :   blowR               = settings.parm("ColourReconnection:blowR");
     234           0 :   blowT               = settings.parm("ColourReconnection:blowT");
     235           0 :   rHadron             = settings.parm("ColourReconnection:rHadron");
     236           0 :   kI                  = settings.parm("ColourReconnection:kI");
     237             : 
     238             :   // Initialize StringLength class.
     239           0 :   stringLength.init(infoPtr, settings);
     240             : 
     241             :   // Done.
     242           0 :   return true;
     243             : 
     244           0 : }
     245             : 
     246             : //--------------------------------------------------------------------------
     247             : 
     248             : // Do colour reconnection for current event.
     249             : 
     250             : bool ColourReconnection::next( Event& event, int iFirst) {
     251             : 
     252             :   // MPI-based reconnection model.
     253           0 :   if (reconnectMode == 0) return reconnectMPIs(event, iFirst);
     254             : 
     255             :   // New reconnection model.
     256           0 :   else if (reconnectMode == 1) return nextNew(event, iFirst);
     257             : 
     258             :   // Gluon-move model.
     259           0 :   else if (reconnectMode == 2) return reconnectMove(event, iFirst);
     260             : 
     261             :   // e+e- Type I CR model.
     262           0 :   else if (reconnectMode == 3 || reconnectMode == 4)
     263           0 :     return reconnectTypeCommon(event, iFirst);
     264             : 
     265             :   // Undefined.
     266             :   else {
     267           0 :     infoPtr->errorMsg("Warning in ColourReconnection::next: "
     268             :                       "Colour reconnecion mode not found");
     269           0 :     return true;
     270             :   }
     271             : 
     272           0 : }
     273             : 
     274             : //--------------------------------------------------------------------------
     275             : 
     276             : // Do new colour reconnection for current event.
     277             : 
     278             : bool ColourReconnection::nextNew( Event& event, int iFirst) {
     279             : 
     280             :   // Clear old records.
     281           0 :   while (!dipoles.empty()) {
     282           0 :     delete dipoles.back();
     283           0 :     dipoles.pop_back();
     284             :   }
     285           0 :   particles.clear();
     286           0 :   junctions.clear();
     287           0 :   junTrials.clear();
     288           0 :   dipTrials.clear();
     289           0 :   formationTimes.clear();
     290             : 
     291             :   // Setup dipoles and make pseudo particles.
     292           0 :   setupDipoles(event, iFirst);
     293           0 :   makeAllPseudoParticles(event, iFirst);
     294             : 
     295             :   // Setup all dipole reconnections.
     296             :   // Split dipoles into the 9 different "colours".
     297           0 :   vector<vector<int> > iDips;
     298           0 :   iDips.resize(nReconCols);
     299           0 :   for (int i = 0; i < int(iDips.size()); ++i)
     300           0 :     iDips[i] = vector<int>();
     301             : 
     302           0 :   for (int i = 0; i < int(dipoles.size()); ++i)
     303           0 :     if (dipoles[i]->isActive)
     304           0 :       iDips[dipoles[i]->colReconnection].push_back(i);
     305             : 
     306             :   // Loop over each colour individually.
     307           0 :   for (int i = 0;i < int(iDips.size()); ++i)
     308           0 :     for (int j = 0; j < int(iDips[i].size()); ++j)
     309           0 :       for (int k = j + 1; k < int(iDips[i].size()); ++k)
     310           0 :         singleReconnection(dipoles[iDips[i][j]], dipoles[iDips[i][k]]);
     311             : 
     312             :   // Only do warning once per event.
     313             :   bool alreadyWarned = false;
     314             : 
     315             :   // Start outer loop over reconnections.
     316           0 :   for (int iOuterLoop = 0; iOuterLoop < 20; ++iOuterLoop) {
     317             :     bool finished = true;
     318             : 
     319             :     // Do inner loop for string reconnections
     320           0 :     for (int iInnerLoop = 0;dipTrials.size() > 0; ++iInnerLoop) {
     321             : 
     322             :       // Break if too many reonnections are carried out.
     323           0 :       if (iInnerLoop > MAXRECONNECTIONS) {
     324           0 :         if (!alreadyWarned)
     325           0 :           infoPtr->errorMsg("Warning in ColourReconnection::nextNew:"
     326             :             "Too many reconnections, stopping before minimum reached.");
     327             :         alreadyWarned = true;
     328           0 :         break;
     329             :       }
     330             : 
     331             :       // Store all dipoles connected to the chosen dipole.
     332           0 :       usedDipoles.clear();
     333           0 :       storeUsedDips(dipTrials.back());
     334             : 
     335             :       // Do the reconnection.
     336           0 :       doDipoleTrial(dipTrials.back());
     337             : 
     338             :       // Sort the used dipoles and remove copies of the same.
     339           0 :       sort(usedDipoles.begin(), usedDipoles.end());
     340           0 :       for (int i = 0;i < int(usedDipoles.size() - 1); ++i)
     341           0 :         if (usedDipoles[i] == usedDipoles[i + 1]) {
     342           0 :           usedDipoles.erase(usedDipoles.begin() + i);
     343           0 :           i--;
     344           0 :         }
     345             : 
     346             :       // Updating the dipole trials.
     347           0 :       updateDipoleTrials();
     348             :     }
     349             : 
     350             :     // Loop over list of dipoles to try and form junction structures.
     351           0 :     if (allowJunctions) {
     352             : 
     353             :       // Split dipoles into three categories.
     354           0 :       iDips.clear();
     355           0 :       iDips.resize(3);
     356           0 :       for (int i = 0; i < int(iDips.size()); ++i)
     357           0 :         iDips[i] = vector<int>();
     358             : 
     359           0 :       for (int i = 0; i < int(dipoles.size()); ++i)
     360           0 :         if (dipoles[i]->isActive)
     361           0 :           iDips[dipoles[i]->colReconnection % 3].push_back(i);
     362             : 
     363             :       // Loop over different "colours" (now only three different groups).
     364           0 :       for (int i = 0;i < int(iDips.size()); ++i)
     365           0 :         for (int j = 0; j < int(iDips[i].size()); ++j)
     366           0 :           for (int k = j + 1; k < int(iDips[i].size()); ++k)
     367           0 :             singleJunction(dipoles[iDips[i][j]], dipoles[iDips[i][k]]);
     368             : 
     369             : 
     370             :       // Loop over different "colours" (now only three different groups).
     371           0 :       for (int i = 0;i < int(iDips.size()); ++i)
     372           0 :         for (int j = 0; j < int(iDips[i].size()); ++j)
     373           0 :           for (int k = j + 1; k < int(iDips[i].size()); ++k)
     374           0 :             for (int l = k + 1; l < int(iDips[i].size()); ++l)
     375           0 :               singleJunction(dipoles[iDips[i][j]], dipoles[iDips[i][k]],
     376           0 :                                 dipoles[iDips[i][l]]);
     377             : 
     378             :       // Do inner loop for junction reconnections
     379           0 :       for (int iInnerLoop = 0;junTrials.size() > 0; ++iInnerLoop) {
     380             : 
     381             :         // Break if too many reonnections are carried out.
     382           0 :         if (iInnerLoop > MAXRECONNECTIONS) {
     383           0 :           if (!alreadyWarned)
     384           0 :             infoPtr->errorMsg("Warning in ColourReconnection::nextNew:"
     385             :               "Too many reconnections, stopping before minimum reached.");
     386             :           alreadyWarned = true;
     387           0 :           break;
     388             :         }
     389             : 
     390             :         // Find all dipoles connected to the reconnection.
     391           0 :         usedDipoles.clear();
     392           0 :         storeUsedDips(junTrials.back());
     393             : 
     394             :         // Do the reconnection.
     395           0 :         doJunctionTrial(event, junTrials.back());
     396             : 
     397             :         // Sort the used dipoles and remove copies of the same.
     398           0 :         sort(usedDipoles.begin(), usedDipoles.end());
     399           0 :         for (int i = 0;i < int(usedDipoles.size() - 1); ++i)
     400           0 :           if (usedDipoles[i] == usedDipoles[i + 1]) {
     401           0 :             usedDipoles.erase(usedDipoles.begin() + i);
     402           0 :             i--;
     403           0 :           }
     404             : 
     405             :         // Update lists.
     406           0 :         updateJunctionTrials();
     407           0 :         updateDipoleTrials();
     408             : 
     409             :         finished = false;
     410             :       }
     411           0 :     }
     412             : 
     413             :     // If no junctions were made, the overall loop is finished.
     414           0 :     if (finished)
     415           0 :       break;
     416           0 :   }
     417             : 
     418           0 :   updateEvent(event, iFirst);
     419             : 
     420             :   // Done.
     421             :   return true;
     422           0 : }
     423             : 
     424             : 
     425             : //--------------------------------------------------------------------------
     426             : 
     427             : // Setup initial guess on dipoles, here all colours are assumed
     428             : // to be found in the final state.
     429             : 
     430             : void ColourReconnection::setupDipoles( Event& event, int iFirst) {
     431             : 
     432             :   // Make vectors needed for storage of chains.
     433           0 :   vector< vector<int > > chains;
     434           0 :   vector<bool> isJun;
     435           0 :   vector<bool> isAntiJun;
     436           0 :   vector<bool> isGluonLoop;
     437           0 :   vector<bool> inChain(event.size(),false);
     438             : 
     439             :   // Find all quarks and anti-diquarks and follow untill no more colour.
     440           0 :   for (int i = iFirst; i < event.size(); ++i) {
     441           0 :     if ( (event[i].isFinal() && !inChain[i]
     442           0 :       &&  event[i].isQuark() && event[i].id() > 0)
     443           0 :       || (event[i].isFinal() && !inChain[i]
     444           0 :       &&  event[i].isDiquark() && event[i].id() < 0) ) {
     445           0 :       int curCol = event[i].col();
     446           0 :       inChain[i] = true;
     447           0 :       vector<int> chain;
     448           0 :       chain.push_back(i);
     449           0 :       isAntiJun.push_back(false);
     450           0 :       isJun.push_back(false);
     451           0 :       isGluonLoop.push_back(false);
     452           0 :       for (int iSteps = 0; curCol != 0 && iSteps < 1000; ++iSteps) {
     453             : 
     454             :         // Check for particles with correct anti colour.
     455           0 :         for (int j = iFirst; j < event.size(); j++) {
     456           0 :           if (event[j].isFinal() && !inChain[j] && event[j].acol() == curCol) {
     457           0 :             chain.push_back(j);
     458           0 :             inChain[j] = true;
     459           0 :             curCol = event[j].col();
     460           0 :             break;
     461             :           }
     462             :         }
     463             : 
     464             :         // Check for junction with correct colour.
     465           0 :         for (int iJun = 0; iJun < event.sizeJunction(); ++iJun) {
     466           0 :           for (int j = 0; j < 3; ++j) {
     467           0 :             if (event.colJunction(iJun,j) == curCol) {
     468           0 :               isJun[isJun.size() -1] = true;
     469             :               curCol = 0;
     470           0 :               chain.push_back( -(10 + 10 * iJun + j) );
     471             :             }
     472             :           }
     473             :         }
     474             :       }
     475           0 :       chains.push_back(chain);
     476           0 :     }
     477             :   }
     478             : 
     479             :   // Start from anti-junction and make chains.
     480           0 :   for (int i = 0; i < event.sizeJunction(); ++i) {
     481             : 
     482             :     // First check if junction belongs to the right diffractive system.
     483           0 :     int checkCol = event.colJunction(i,0);
     484             :     bool wrongSystem = false;
     485           0 :     for (int j = 0; j < iFirst; ++j)
     486           0 :       if (event[j].isFinal() && event[j].acol() == checkCol)
     487           0 :         wrongSystem = true;
     488           0 :     if (wrongSystem)
     489           0 :       continue;
     490             : 
     491             :     // Loop over legs of anti junction.
     492           0 :     if (event.kindJunction(i) == 2)
     493           0 :     for (int jCol = 0; jCol < 3; ++jCol) {
     494           0 :       int curCol = event.colJunction(i,jCol);
     495           0 :       vector<int> chain;
     496           0 :       chain.push_back( -(10 + 10 * i + jCol));
     497           0 :       isAntiJun.push_back(true);
     498           0 :       isJun.push_back(false);
     499           0 :       isGluonLoop.push_back(false);
     500           0 :       for (int iSteps = 0; curCol != 0 && iSteps < 1000; ++iSteps) {
     501             : 
     502             :         // Check for particles with correct anti colour.
     503           0 :         for (int j = iFirst; j < event.size(); ++j)
     504           0 :         if (event[j].isFinal() && !inChain[j] &&
     505           0 :             event[j].acol() == curCol) {
     506           0 :           chain.push_back(j);
     507           0 :           inChain[j] = true;
     508           0 :           curCol = event[j].col();
     509           0 :           break;
     510             :         }
     511             : 
     512             :         // Check for junction with correct colour.
     513           0 :         for (int iJun = 0; iJun < event.sizeJunction(); ++iJun)
     514           0 :         if (event.kindJunction(iJun) == 1)
     515           0 :         for (int j = 0; j < 3; ++j)
     516           0 :         if (event.colJunction(iJun,j) == curCol) {
     517           0 :           isJun[isJun.size() - 1] = true;
     518             :           curCol = 0;
     519           0 :           chain.push_back( -(10 + 10 * iJun + j));
     520           0 :         }
     521             :       }
     522           0 :       chains.push_back(chain);
     523           0 :     }
     524           0 :   }
     525             : 
     526             :   // Find all gluon loops.
     527           0 :   for (int i = iFirst; i < event.size(); ++i)
     528           0 :   if (event[i].isFinal() && !inChain[i] && event[i].col() != 0) {
     529           0 :     int curCol = event[i].col();
     530           0 :     inChain[i] = true;
     531           0 :     vector<int> chain;
     532           0 :     chain.push_back(i);
     533           0 :     isAntiJun.push_back(false);
     534           0 :     isJun.push_back(false);
     535           0 :     isGluonLoop.push_back(true);
     536           0 :     for (int iSteps = 0; curCol != 0 && iSteps < 1000; ++iSteps) {
     537             :       bool foundNext = false;
     538           0 :       for (int j = iFirst; j < event.size(); ++j)
     539           0 :       if (event[j].isFinal() && !inChain[j] && event[j].acol() == curCol) {
     540           0 :         chain.push_back(j);
     541           0 :         inChain[j] = true;
     542           0 :         curCol = event[j].col();
     543             :         foundNext = true;
     544           0 :         break;
     545             :       }
     546             : 
     547           0 :       if (!foundNext)
     548           0 :         break;
     549           0 :     }
     550           0 :     chains.push_back(chain);
     551           0 :   }
     552             : 
     553             :   // Form dipoles from chains.
     554           0 :   for (int i = 0; i < int(chains.size()); ++i) {
     555           0 :     if (chains[i].size() == 1) continue;
     556             :     int lastCol = -1;
     557             :     int firstCol = 0;
     558             : 
     559             :     // Start from the first and form the dipoles.
     560             :     // Two consececutive dipoles can not share the same colour.
     561           0 :     for (int j = 0; j < int(chains[i].size()); ++j) {
     562           0 :       if (j != int(chains[i].size() - 1)) {
     563             : 
     564             :         // Start by picking new colour.
     565           0 :         int newCol = int(rndmPtr->flat() * nReconCols);
     566           0 :         while (newCol == lastCol && !sameNeighbourCol) {
     567           0 :           newCol = int(rndmPtr->flat() * nReconCols);
     568             :         }
     569             : 
     570             :         // Need to check whether the quark comes from a g->qqbar split.
     571             :         // If that is the case, it can not have the same as qbar.
     572           0 :         if (j == 0 && !isAntiJun[i] && !isGluonLoop[i]) {
     573             : 
     574           0 :           int iMother = event[event[ chains[i][j] ].iTopCopy()].mother1();
     575           0 :           if ( event[iMother].idAbs() == 21) {
     576           0 :             vector<int> sisters = event[ chains[i][j] ].sisterList(true);
     577             :             // Need to have only one sister and need to be the anti particle.
     578           0 :             if (sisters.size() == 1 && event[ chains[i][j] ].id()
     579           0 :                 == - event[ sisters[0] ].id()) {
     580             : 
     581             :               // Try to find dipole with sister.
     582             :               int colSis = -1;
     583           0 :               for (int k = 0; k < int(dipoles.size()); ++k)
     584           0 :                 if (dipoles[k]->iAcol == sisters[0]) {
     585           0 :                   colSis = dipoles[k]->colReconnection;
     586           0 :                   break;
     587             :                 }
     588             : 
     589             :               // If the two colours are the same, pick a new.
     590           0 :               while (colSis == newCol && !sameNeighbourCol)
     591           0 :                 newCol = int(rndmPtr->flat() * nReconCols);
     592           0 :             }
     593           0 :           }
     594           0 :         }
     595             : 
     596             :         // Check if quark end comes from g->qqbar split.
     597             :         // If so check that the two quarks get different colours.
     598           0 :         if (j == int(chains[i].size() - 2) && !isJun[i] && !isGluonLoop[i]) {
     599             : 
     600           0 :           int iMother = event[event[chains[i][j + 1]].iTopCopy()].mother1();
     601           0 :           if (event[iMother].idAbs() == 21) {
     602           0 :             vector<int> sisters = event[ chains[i][j + 1] ].sisterList(true);
     603             :             // Need to have only one sister and need to be the anti particle.
     604           0 :             if (sisters.size() == 1 && event[ chains[i][j + 1] ].id()
     605           0 :                 == - event[ sisters[0] ].id()) {
     606             : 
     607             :               // Try to find dipole with sister.
     608             :               int colSis = -1;
     609           0 :               for (int k = 0; k < int(dipoles.size()); ++k)
     610           0 :                 if (dipoles[k]->iCol == sisters[0]) {
     611           0 :                   colSis = dipoles[k]->colReconnection;
     612           0 :                   break;
     613             :                 }
     614             : 
     615             :               // If the two colours are the same, pick a new.
     616           0 :               while ((colSis == newCol || newCol == lastCol)
     617           0 :                      && !sameNeighbourCol)
     618           0 :                 newCol = int(rndmPtr->flat() * nReconCols);
     619           0 :             }
     620           0 :           }
     621           0 :         }
     622             : 
     623             :         // Special case for junction splitting if multiple gluons
     624             :         // between the junctions.
     625           0 :         if ((chains[i][j] > 0 && event[chains[i][j]].status() == 75) ||
     626           0 :             (chains[i][j + 1] > 0 &&
     627           0 :              event[ chains[i][j + 1] ].status() == 75) ) {
     628             : 
     629             :           // Find sisters.
     630           0 :           vector<int> sisters;
     631           0 :           if (chains[i][j] > 0 && event[ chains[i][j] ].status() == 75)
     632           0 :             sisters = event[ chains[i][j] ].sisterList();
     633             :           else
     634           0 :             sisters = event[ chains[i][j + 1] ].sisterList();
     635             : 
     636           0 :           if (sisters.size() == 3 ) {
     637             : 
     638             :             // Find colour of sisters.
     639             :             int acolSis1 = -1, acolSis2 = -1, acolSis3 = -1;
     640             :             int colSis1 = -1, colSis2 = -1, colSis3 = -1;
     641           0 :             for (int k = 0;k < int(dipoles.size()); ++k)  {
     642           0 :               if (dipoles[k]->iAcol == sisters[0])
     643           0 :                 acolSis1 = dipoles[k]->colReconnection;
     644             : 
     645           0 :               if (dipoles[k]->iAcol == sisters[1])
     646           0 :                 acolSis2 = dipoles[k]->colReconnection;
     647             : 
     648           0 :               if (dipoles[k]->iAcol == sisters[2])
     649           0 :                 acolSis3 = dipoles[k]->colReconnection;
     650             : 
     651           0 :               if (dipoles[k]->iCol == sisters[0])
     652           0 :                 colSis1 = dipoles[k]->colReconnection;
     653             : 
     654           0 :               if (dipoles[k]->iCol == sisters[1])
     655           0 :                 colSis2 = dipoles[k]->colReconnection;
     656             : 
     657           0 :               if (dipoles[k]->iCol == sisters[2])
     658           0 :                 colSis3 = dipoles[k]->colReconnection;
     659             :             }
     660             : 
     661             :             // If the two colours are the same, pick a new.
     662           0 :             while ((colSis1 == newCol || colSis2 == newCol ||
     663           0 :                    colSis3 == newCol || acolSis1 == newCol ||
     664           0 :                    acolSis2 == newCol || acolSis3 == newCol)
     665           0 :                    && !sameNeighbourCol)
     666           0 :               newCol = int(rndmPtr->flat() * nReconCols);
     667           0 :           }
     668           0 :         }
     669             : 
     670             :         // Update stored colours.
     671           0 :         if (j == 0) firstCol = newCol;
     672             :         lastCol = newCol;
     673             : 
     674             :         // Check if it is anti junction need special dipole.
     675           0 :         if (j == 0 && isAntiJun[i]) {
     676           0 :           int col = event.colJunction( - int(chains[i][j]/10) - 1,
     677           0 :                                        -chains[i][j] % 10);
     678           0 :           dipoles.push_back(new ColourDipole(col, chains[i][j],
     679           0 :             chains[i][j+1], newCol));
     680           0 :           dipoles.back()->isAntiJun = true;
     681           0 :         }
     682             : 
     683             :         // Otherwise just make the dipole.
     684           0 :         else dipoles.push_back(new ColourDipole(event[ chains[i][j] ].col(),
     685           0 :           chains[i][j], chains[i][j+1], newCol));
     686             : 
     687             :         // If the chain in end a junction mark it.
     688           0 :         if (j == int(chains[i].size() - 2) && isJun[i])
     689           0 :           dipoles.back()->isJun = true;
     690             : 
     691             :         // Update the links between dipoles.
     692           0 :         if (j > 0) {
     693           0 :           dipoles[dipoles.size() - 1]->leftDip  = dipoles[dipoles.size() - 2];
     694           0 :           dipoles[dipoles.size() - 2]->rightDip = dipoles[dipoles.size() - 1];
     695           0 :         }
     696           0 :       }
     697             : 
     698             :       // If last particle has anti colour it should be possible to connect it
     699             :       // to the first particle in the chain. (e.g. gluon loop)
     700             :       else
     701           0 :       if (isGluonLoop[i])
     702           0 :       if (event[ chains[i][j] ].col() == event[ chains[i][0] ].acol()) {
     703           0 :         int newCol = int(rndmPtr->flat() * nReconCols);
     704           0 :         while ( (newCol == lastCol || newCol == firstCol)
     705           0 :                 && !sameNeighbourCol) {
     706           0 :           newCol = int(rndmPtr->flat() * nReconCols);
     707             :         }
     708           0 :         dipoles.push_back(new ColourDipole(event[ chains[i][j] ].col(),
     709           0 :           chains[i][j], chains[i][0], newCol));
     710             : 
     711             :         // Update links between dipoles.
     712           0 :         dipoles[dipoles.size() - 1]->leftDip = dipoles[dipoles.size() - 2];
     713           0 :         dipoles[dipoles.size() - 2]->rightDip = dipoles[dipoles.size() - 1];
     714           0 :         dipoles[dipoles.size() - chains[i].size()]->leftDip =
     715           0 :           dipoles[dipoles.size() -1];
     716           0 :         dipoles[dipoles.size() - 1]->rightDip =
     717           0 :           dipoles[dipoles.size() - chains[i].size()];
     718             : 
     719           0 :       }
     720             :     }
     721           0 :   }
     722             : 
     723             :   // Setup junction list.
     724           0 :   iColJun.clear();
     725           0 :   iColJun.resize(event.sizeJunction());
     726           0 :   for (int i = 0; i < int(iColJun.size()); ++i) iColJun[i] = vector<int>(3,0);
     727             : 
     728             :   // Loop over event and store indices.
     729           0 :   for (int i = iFirst; i < event.size(); ++i)
     730           0 :   if (event[i].isFinal())
     731           0 :   for (int j = 0; j < event.sizeJunction(); ++j)
     732           0 :   for (int jLeg = 0; jLeg < 3; ++jLeg)
     733           0 :   if (event[i].col() == event.colJunction(j,jLeg) ||
     734           0 :       event[i].acol() == event.colJunction(j,jLeg))
     735           0 :     iColJun[j][jLeg] = i;
     736             : 
     737             :   // Loop over junction and store indices.
     738           0 :   for (int i = 0;i < event.sizeJunction(); ++i)
     739           0 :   for (int iLeg = 0; iLeg < 3; ++iLeg)
     740           0 :   for (int j = i + 1;j < event.sizeJunction(); ++j)
     741           0 :   for (int jLeg = 0; jLeg < 3; ++jLeg)
     742           0 :   if (event.colJunction(i, iLeg) == event.colJunction(j, jLeg)) {
     743           0 :     iColJun[i][iLeg] = -(10*j + 10 + jLeg);
     744           0 :     iColJun[j][jLeg] = -(10*i + 10 + iLeg);
     745           0 :   }
     746             : 
     747             :   // Setup formation times.
     748           0 :   setupFormationTimes(event);
     749             : 
     750             :   // Done.
     751           0 : }
     752             : 
     753             : //--------------------------------------------------------------------------
     754             : 
     755             : // Calculate the string length of a dipole.
     756             : 
     757             : double ColourReconnection::calculateStringLength(ColourDipole * dip,
     758             :   vector<ColourDipole *> &dips) {
     759             : 
     760             :   // Check if dipole was already included.
     761           0 :   for (int i = 0; i < int(dips.size()); ++i)
     762           0 :     if (dips[i] == dip) return 0.;
     763             : 
     764             :   // Ordinay dipole.
     765           0 :   if (!dip->isJun && !dip->isAntiJun)  {
     766           0 :     return calculateStringLength(dip->iCol, dip->iAcol);
     767             :   }
     768             :   else {
     769             : 
     770             :     // Start by finding all particles connected to the junction system.
     771           0 :     vector<int> iParticles;
     772           0 :     vector<bool> usedJuns(junctions.size(),false);
     773           0 :     int nJuns = 0;
     774           0 :     if (dip->isJun) {
     775           0 :       if (!findJunctionParticles( -int(dip->iAcol/10) - 1, iParticles,
     776           0 :                                   usedJuns, nJuns, dips)) return 1e9;
     777             :     } else
     778           0 :       if (!findJunctionParticles(-int(dip->iCol/10) - 1, iParticles,
     779           0 :                                  usedJuns, nJuns, dips)) return 1e9;
     780             : 
     781             :     // If it is a single junction.
     782           0 :     if (int(iParticles.size()) == 3)
     783           0 :       return calculateJunctionLength(iParticles[0], iParticles[1],
     784           0 :                                      iParticles[2]);
     785             : 
     786             :     // If it is a junction pair.
     787           0 :     else if (int(iParticles.size()) == 4) {
     788           0 :       return calculateDoubleJunctionLength(iParticles[0], iParticles[1],
     789           0 :                                            iParticles[2], iParticles[3]);
     790             :     }
     791             :     // If any other number of junction legs return high number.
     792           0 :     else return 1e9;
     793           0 :   }
     794             : 
     795           0 : }
     796             : //--------------------------------------------------------------------------
     797             : 
     798             : // Update all colours in the event.
     799             : 
     800             : void ColourReconnection::updateEvent( Event& event, int iFirst) {
     801             : 
     802             :   // Start by making a new copy of particles.
     803           0 :   int oldSize = event.size();
     804           0 :   for (int i = iFirst; i < oldSize;++i)
     805           0 :     if (event[i].isFinal()) event.copy(i, 79);
     806             : 
     807             :   // Copy over junctions.
     808           0 :   event.clearJunctions();
     809           0 :   for (int i = 0; i < int(junctions.size()); ++i) {
     810           0 :     for (int j = 0; j < 3; ++j) {
     811           0 :       if ( junctions[i].dipsOrig[j] != 0) {
     812           0 :         junctions[i].col(j, junctions[i].dipsOrig[j]->col);
     813           0 :       }
     814             :     }
     815           0 :     event.appendJunction(Junction(junctions[i]));
     816             :   }
     817             : 
     818             :   // Assign colour according to the real dipoles.
     819           0 :   for (int i = 0; i < int(dipoles.size()); ++i)
     820           0 :     if (dipoles[i]->isReal) {
     821           0 :       if (dipoles[i]->iCol >= 0)
     822           0 :         event[ event[ dipoles[i]->iCol ].daughter1() ].col(dipoles[i]->col);
     823             :       else
     824           0 :         event.colJunction(-(dipoles[i]->iCol/10 + 1), -dipoles[i]->iCol % 10,
     825           0 :           dipoles[i]->col);
     826           0 :       if (dipoles[i]->iAcol >= 0)
     827           0 :         event[ event[ dipoles[i]->iAcol ].daughter1() ].acol(dipoles[i]->col);
     828             :       else
     829           0 :         event.colJunction(-(dipoles[i]->iAcol/10 + 1), -dipoles[i]->iAcol % 10,
     830           0 :           dipoles[i]->col);
     831             :     }
     832           0 : }
     833             : 
     834             : //--------------------------------------------------------------------------
     835             : 
     836             : // Find all the particles connected in the junction.
     837             : // If a single junction, the size of iParticles should be 3.
     838             : // For multiple junction structures, the size will increase.
     839             : 
     840             : bool ColourReconnection::findJunctionParticles(int iJun,
     841             :   vector<int>& iParticles, vector<bool> &usedJuns, int &nJuns,
     842             :   vector<ColourDipole*> &dips ) {
     843             : 
     844             :   // Mark current junction as used.
     845           0 :   usedJuns[iJun] = true;
     846           0 :   nJuns++;
     847             : 
     848             :   // It is not possible to handle junction structures larger than two.
     849           0 :   if (nJuns > 2)
     850           0 :     return false;
     851             : 
     852             :   // Find particles connected to the
     853           0 :   if (junctions[iJun].kind() % 2 == 1)
     854           0 :     for (int i = 0; i < 3; ++i)
     855           0 :       iParticles.push_back(junctions[iJun].dips[i]->iCol);
     856             :   else
     857           0 :     for (int i = 0; i < 3; ++i)
     858           0 :       iParticles.push_back(junctions[iJun].dips[i]->iAcol);
     859             : 
     860             :   // Add dipoles if not already included.
     861           0 :   for (int i = 0; i < 3; ++i) {
     862             :     bool addDip = true;
     863           0 :     for (int j = 0; j < int(dips.size()); ++j) {
     864           0 :       if (dips[j] == junctions[iJun].dips[i]) {
     865             :         addDip = false;
     866           0 :         break;
     867             :       }
     868             :     }
     869           0 :     if (addDip) dips.push_back(junctions[iJun].dips[i]);
     870             :   }
     871             : 
     872             :   // Check whether it connects to any other junctions.
     873           0 :   for (int i = 0; i < int(iParticles.size()); ++i)
     874           0 :   if (iParticles[i] < 0) {
     875           0 :     int iNewJun = - int(iParticles[i] / 10) -1;
     876           0 :     iParticles.erase(iParticles.begin() + i);
     877           0 :     i--;
     878           0 :     if (!usedJuns[iNewJun] && !findJunctionParticles( iNewJun, iParticles,
     879             :       usedJuns, nJuns, dips) )
     880           0 :       return false;
     881           0 :   }
     882             : 
     883             :   // Done.
     884           0 :   return true;
     885           0 : }
     886             : 
     887             : //--------------------------------------------------------------------------
     888             : 
     889             : // Calculate string length for two indices in the particles record.
     890             : 
     891             : double ColourReconnection::calculateStringLength(int i, int j) {
     892           0 :   return stringLength.getStringLength(particles[i].p(), particles[j].p());
     893             : }
     894             : 
     895             : //--------------------------------------------------------------------------
     896             : 
     897             : // Calculate the length of a single junction given the 3 entries in the event.
     898             : 
     899             : double ColourReconnection::calculateJunctionLength(int i,
     900             :   int j, int k) {
     901             : 
     902             :   // Need to be separate indices.
     903           0 :   if ( i == j || i == k || j == k) return 1e9;
     904             : 
     905           0 :   Vec4 p1 = particles[i].p();
     906           0 :   Vec4 p2 = particles[j].p();
     907           0 :   Vec4 p3 = particles[k].p();
     908             : 
     909           0 :   return stringLength.getJuncLength(p1, p2, p3);
     910             : 
     911           0 : }
     912             : 
     913             : //--------------------------------------------------------------------------
     914             : 
     915             : // Calculate the length of a double junction given the 4 particle entries.
     916             : // The first two are expected to be quarks, the second two to be antiquarks.
     917             : 
     918             : double ColourReconnection::calculateDoubleJunctionLength( int i, int j,
     919             :   int k, int l) {
     920             : 
     921             :   // Need to be separate indices.
     922           0 :   if (i == j || i == k || i == l || j == k || j == l || k == l) return 1e9;
     923             : 
     924           0 :   Vec4 p1 = particles[i].p();
     925           0 :   Vec4 p2 = particles[j].p();
     926           0 :   Vec4 p3 = particles[k].p();
     927           0 :   Vec4 p4 = particles[l].p();
     928             : 
     929           0 :   return stringLength.getJuncLength(p1, p2, p3, p4);
     930             : 
     931           0 : }
     932             : 
     933             : //--------------------------------------------------------------------------
     934             : 
     935             : // Do a single trial emission.
     936             : 
     937             : void ColourReconnection::singleReconnection(ColourDipole* dip1,
     938             :       ColourDipole* dip2) {
     939             : 
     940             :   // Do nothing if it is the same dipole.
     941           0 :   if (dip1 == dip2) return;
     942             : 
     943             :   // No colour reconnection if colours do not match.
     944           0 :   if (dip1->colReconnection != dip2->colReconnection) return;
     945             : 
     946             :   // If it is not active return
     947           0 :   if (!dip1->isActive || !dip2->isActive) return;
     948             : 
     949             :   // Not possible to connect a gluon with itself.
     950           0 :   if (dip1->iCol == dip2->iAcol || dip1->iAcol == dip2->iCol) return;
     951             : 
     952             :   // Check that reconnection is allowed by time dilation.
     953           0 :   if (!checkTimeDilation(dip1, dip2)) return;
     954             : 
     955             :   // Calculate the difference in lambda.
     956           0 :   double lambdaDiff = getLambdaDiff(dip1, dip2);
     957             : 
     958             :   // Insert into trial reconnection if anything is gained.
     959           0 :   if (lambdaDiff > MINIMUMGAIN) {
     960           0 :     TrialReconnection dipTrial(dip1, dip2, 0, 0, 5, lambdaDiff);
     961           0 :     dipTrials.insert(lower_bound(dipTrials.begin(), dipTrials.end(),
     962             :          dipTrial, cmpTrials), dipTrial);
     963           0 :   }
     964             : 
     965           0 : }
     966             : 
     967             : //--------------------------------------------------------------------------
     968             : 
     969             : // Simple test swap between two dipoles.
     970             : 
     971             : void ColourReconnection::swapDipoles(ColourDipole* dip1,
     972             :   ColourDipole* dip2, bool back) {
     973             : 
     974             :   // Swap the anti colour of the dipoles.
     975           0 :   swap(dip1->iAcol, dip2->iAcol);
     976           0 :   swap(dip1->isJun, dip2->isJun);
     977           0 :   swap(dip1->iAcolLeg, dip2->iAcolLeg);
     978             : 
     979             :   // Update the active dipoles. Only change 1 active dipole;
     980             :   // this is to avoid problems when switching back.
     981           0 :   if (dip1->iAcol != dip2->iAcol) {
     982           0 :     if (!back) {
     983           0 :       if (dip1->iAcol >= 0)
     984           0 :       for (int i = 0; i < int(particles[dip1->iAcol].activeDips.size()); ++i)
     985           0 :       if (particles[dip1->iAcol].activeDips[i] == dip2) {
     986           0 :         particles[dip1->iAcol].activeDips[i] = dip1;
     987           0 :         swap1 = i;
     988           0 :         break;
     989           0 :       }
     990           0 :       if (dip2->iAcol >= 0)
     991           0 :       for (int i = 0; i < int(particles[dip2->iAcol].activeDips.size()); ++i)
     992           0 :       if (particles[dip2->iAcol].activeDips[i] == dip1) {
     993           0 :         particles[dip2->iAcol].activeDips[i] = dip2;
     994           0 :         swap2 = i;
     995           0 :         break;
     996           0 :       }
     997             :     } else {
     998           0 :       if (dip1->iAcol >= 0) particles[dip1->iAcol].activeDips[swap2] = dip1;
     999           0 :       if (dip2->iAcol >= 0) particles[dip2->iAcol].activeDips[swap1] = dip2;
    1000             :     }
    1001             :   }
    1002             : 
    1003             :   // Update list of junctions (only junctions, anti junctions stay the same).
    1004           0 :   for (int i = 0; i < int(junctions.size()); ++i)
    1005           0 :   if (junctions[i].kind() % 2 == 1)
    1006           0 :   for (int iLeg = 0; iLeg < 3; ++iLeg) {
    1007           0 :     if (junctions[i].dips[iLeg] == dip1) {
    1008           0 :       junctions[i].dips[iLeg] = dip2;
    1009           0 :       continue;
    1010             :     }
    1011           0 :     if (junctions[i].dips[iLeg] == dip2) {
    1012           0 :       junctions[i].dips[iLeg] = dip1;
    1013           0 :       continue;
    1014             :     }
    1015           0 :   }
    1016             : 
    1017             :   // Done.
    1018           0 : }
    1019             : 
    1020             : //--------------------------------------------------------------------------
    1021             : 
    1022             : // Do a single trial reconnection to form a junction.
    1023             : 
    1024             : void ColourReconnection::singleJunction(ColourDipole* dip1,
    1025             :   ColourDipole* dip2) {
    1026             : 
    1027             :    // Do nothing if it is the same dipole.
    1028           0 :   if (dip1 == dip2)
    1029             :     return;
    1030             : 
    1031           0 :   int iCol1  = dip1->iCol;
    1032           0 :   int iCol2  = dip2->iCol;
    1033           0 :   int iAcol1 = dip1->iAcol;
    1034           0 :   int iAcol2 = dip2->iAcol;
    1035             : 
    1036             :   // Not possible to connect a gluon with itself.
    1037           0 :   if (iCol1 == iCol2) return;
    1038           0 :   if (iAcol1 == iAcol2) return;
    1039             : 
    1040             :   // Check that all dipoles are active.
    1041           0 :   if (!dip1->isActive || !dip2->isActive) return;
    1042             : 
    1043             :   // Do nothing if one of the dipoles is a junction or anti junction.
    1044           0 :   if (dip1->isJun || dip1->isAntiJun) return;
    1045           0 :   if (dip2->isJun || dip2->isAntiJun) return;
    1046             : 
    1047             :   // Do nothing if it is a pseudo particle that already contains a
    1048             :   // baryon number inside of it.
    1049           0 :   if (int(particles[iCol1].dips.size()) != 1  ||
    1050           0 :       int(particles[iAcol1].dips.size()) != 1 ||
    1051           0 :       int(particles[iCol2].dips.size()) != 1  ||
    1052           0 :       int(particles[iAcol2].dips.size()) != 1)
    1053           0 :     return;
    1054             : 
    1055             :   // Only accept 2/9 of the colour configurations.
    1056           0 :   if ( (dip1->colReconnection) % 3 !=
    1057           0 :         dip2->colReconnection % 3) return;
    1058             : 
    1059           0 :   if ( (dip1->colReconnection) ==
    1060           0 :        dip2->colReconnection) return;
    1061             : 
    1062             :   // Check that reconnection is allowed by time dilation.
    1063           0 :   if (!checkTimeDilation(dip1, dip2)) return;
    1064             : 
    1065             :   // Find the colour of the last junction leg.
    1066           0 :   int junCol = (3 - (dip1->colReconnection / 3)
    1067           0 :     - (dip2->colReconnection / 3) ) * 3
    1068           0 :     + (dip1->colReconnection % 3);
    1069             : 
    1070             :   // if other than 9 colours.
    1071           0 :   if (nReconCols != 9) {
    1072           0 :     while (junCol < 0 || junCol % 3 != dip1->colReconnection % 3 ||
    1073           0 :            junCol == dip1->colReconnection || junCol == dip2->colReconnection)
    1074           0 :       junCol = int(nReconCols * rndmPtr->flat());
    1075             :   }
    1076             : 
    1077             :   // Store two new dipoles, these will form the anti-junction.
    1078           0 :   ColourDipole* dip3 = dip1;
    1079           0 :   ColourDipole* dip4 = dip2;
    1080             : 
    1081           0 :   double lambdaDiff = getLambdaDiff(dip1, dip2, dip3, dip4, 0);
    1082           0 :   if (lambdaDiff > MINIMUMGAINJUN) {
    1083           0 :     TrialReconnection junTrial(dip1, dip2, dip3, dip4, 0, lambdaDiff);
    1084           0 :     junTrials.insert(lower_bound(junTrials.begin(), junTrials.end(),
    1085             :          junTrial, cmpTrials), junTrial);
    1086           0 :   }
    1087             :   // Outer loop
    1088             :   while (true) {
    1089             : 
    1090             :     // Reset dip4.
    1091           0 :     dip4 = dip2;
    1092             : 
    1093             :     // If the colour matches that of the junction.
    1094           0 :     if (dip3->colReconnection == junCol)
    1095             :     while (true) {
    1096             :       // Check if the new colour matches.
    1097           0 :       if (dip4->colReconnection == dip2->colReconnection)
    1098           0 :       if (checkTimeDilation(dip1, dip2, dip3, dip4)) {
    1099             : 
    1100             :         // Calculate lambda measure and store new dipole if anything is gained.
    1101           0 :         lambdaDiff = getLambdaDiff(dip1, dip2, dip3, dip4, 1);
    1102             : 
    1103           0 :         if (lambdaDiff > MINIMUMGAINJUN) {
    1104             : 
    1105           0 :           TrialReconnection junTrial(dip1, dip2, dip3, dip4, 1, lambdaDiff);
    1106           0 :           junTrials.insert(lower_bound(junTrials.begin(), junTrials.end(),
    1107             :              junTrial, cmpTrials), junTrial);
    1108           0 :         }
    1109             :       }
    1110             : 
    1111             : 
    1112             :       // Find the next neighbour.
    1113           0 :       if (!findAntiNeighbour(dip4))
    1114             :         break;
    1115             : 
    1116             :       // Check for gluon loop.
    1117           0 :       if (dip4 == dip2 || dip4 == dip1)
    1118             :         break;
    1119             : 
    1120             :     } // Done with inner loop.
    1121             : 
    1122             :     // Reset dip4.
    1123           0 :     dip4 = dip2;
    1124             : 
    1125             :     // If the colour matches that of the other dipole.
    1126           0 :     if (dip3->colReconnection == dip1->colReconnection)
    1127             :     while (true) {
    1128             :       // Check if the new colour matches.
    1129           0 :       if (dip4->colReconnection == junCol)
    1130           0 :       if (checkTimeDilation(dip1, dip2, dip3, dip4)) {
    1131             : 
    1132             :         // Calculate lambda measure and store new dipole if anything is gained.
    1133           0 :         lambdaDiff = getLambdaDiff(dip1, dip2, dip3, dip4, 2);
    1134             : 
    1135           0 :         if (lambdaDiff > MINIMUMGAINJUN) {
    1136             : 
    1137           0 :           TrialReconnection junTrial(dip1, dip2, dip3, dip4, 2, lambdaDiff);
    1138           0 :           junTrials.insert(lower_bound(junTrials.begin(), junTrials.end(),
    1139             :              junTrial, cmpTrials), junTrial);
    1140           0 :         }
    1141             :       }
    1142             : 
    1143             :       // Find the next neighbour.
    1144           0 :       if (!findAntiNeighbour(dip4))
    1145             :         break;
    1146             : 
    1147             :       // Check for gluon loop.
    1148           0 :       if (dip4 == dip2 || dip4 == dip1)
    1149             :         break;
    1150             : 
    1151             :     } // Done with inner loop.
    1152             : 
    1153             :     // Find the next neighbour.
    1154           0 :     if (!findAntiNeighbour(dip3))
    1155             :       break;
    1156             : 
    1157             :     // Check for gluon loop.
    1158           0 :     if (dip3 == dip1 || dip3 == dip2)
    1159             :       break;
    1160             :   }
    1161             : 
    1162             :   // Done.
    1163             : 
    1164           0 : }
    1165             : 
    1166             : //--------------------------------------------------------------------------
    1167             : 
    1168             : // Do a single trial reconnection to form a junction.
    1169             : 
    1170             : void ColourReconnection::singleJunction(ColourDipole* dip1,
    1171             :   ColourDipole* dip2, ColourDipole* dip3) {
    1172             : 
    1173             :   // Do nothing if one of the dipoles is a junction or anti junction.
    1174           0 :   if (dip1->isJun || dip1->isAntiJun) return;
    1175           0 :   if (dip2->isJun || dip2->isAntiJun) return;
    1176           0 :   if (dip3->isJun || dip3->isAntiJun) return;
    1177             : 
    1178             : 
    1179             :   // Check that all dipoles are active.
    1180           0 :   if (!dip1->isActive || !dip2->isActive || !dip3->isActive) return;
    1181             : 
    1182             :   // Only allow 0-3-6, 1-4-7 or 2-5-8.
    1183           0 :   if ( dip1->colReconnection % 3 != dip2->colReconnection % 3
    1184           0 :     || dip1->colReconnection % 3 != dip3->colReconnection % 3) return;
    1185             : 
    1186           0 :   if ( !(dip1->colReconnection != dip2->colReconnection
    1187           0 :       && dip1->colReconnection != dip3->colReconnection
    1188           0 :       && dip2->colReconnection != dip3->colReconnection) )
    1189             :     return;
    1190             : 
    1191             : 
    1192           0 :   if (int(particles[dip1->iCol].dips.size()) != 1  ||
    1193           0 :       int(particles[dip1->iAcol].dips.size()) != 1 ||
    1194           0 :       int(particles[dip2->iCol].dips.size()) != 1  ||
    1195           0 :       int(particles[dip2->iAcol].dips.size()) != 1 ||
    1196           0 :       int(particles[dip3->iCol].dips.size()) != 1  ||
    1197           0 :       int(particles[dip3->iAcol].dips.size()) != 1 )
    1198             :     return;
    1199             : 
    1200             :   // Check that reconnection is allowed by time dilation.
    1201           0 :   if (!checkTimeDilation(dip1, dip2, dip3)) return;
    1202             : 
    1203           0 :   double lambdaDiff = getLambdaDiff(dip1, dip2, dip3, 0, 3);
    1204             : 
    1205           0 :   if (lambdaDiff > MINIMUMGAINJUN) {
    1206           0 :     TrialReconnection junTrial(dip1, dip2, dip3, 0, 3, lambdaDiff);
    1207           0 :     junTrials.insert(lower_bound(junTrials.begin(), junTrials.end(), junTrial,
    1208             :                                  cmpTrials), junTrial);
    1209           0 :   }
    1210             : 
    1211             :   // Done.
    1212             :   return;
    1213           0 : }
    1214             : 
    1215             : // ------------------------------------------------------------------
    1216             : 
    1217             : // Form pseuparticle of a given dipole (or junction system).
    1218             : 
    1219             : void ColourReconnection::makePseudoParticle(ColourDipole* dip , int status,
    1220             :   bool setupDone) {
    1221             : 
    1222             :   // If it is a normal dipole that needs to be combined.
    1223           0 :   if (!dip->isJun && !dip->isAntiJun) {
    1224             : 
    1225             :     // Start by storing variables for easier use.
    1226           0 :     int iCol = dip->iCol;
    1227           0 :     int iAcol = dip->iAcol;
    1228           0 :     int iColLeg = dip->iColLeg;
    1229           0 :     int iAcolLeg = dip->iAcolLeg;
    1230             : 
    1231             :     // Make new pseudo particle.
    1232           0 :     int iNew = particles.size();
    1233           0 :     particles.push_back(particles[iCol]);
    1234           0 :     particles[iNew].acol(particles[iCol].acol());
    1235           0 :     particles[iNew].col(particles[iAcol].col());
    1236           0 :     particles[iNew].mother1(iCol);
    1237           0 :     particles[iNew].mother2(iAcol);
    1238           0 :     particles[iNew].id(99);
    1239           0 :     particles[iNew].status(status);
    1240           0 :     particles[iNew].isJun = false;
    1241           0 :     particles[iAcol].statusNeg();
    1242           0 :     particles[iAcol].daughter1(iNew);
    1243           0 :     particles[iCol].statusNeg();
    1244           0 :     particles[iCol].daughter1(iNew);
    1245           0 :     if (iCol != iAcol)
    1246           0 :       particles[iNew].p(particles[iCol].p() + particles[iAcol].p());
    1247             :     else
    1248           0 :       particles[iNew].p(particles[iCol].p());
    1249             : 
    1250             :     // Add all the dipoles from the old pseudo particle.
    1251             :     // First from particle 1.
    1252           0 :     particles[iNew].dips = particles[dip->iCol].dips;
    1253           0 :     particles[iNew].colEndIncluded = particles[dip->iCol].colEndIncluded;
    1254           0 :     particles[iNew].acolEndIncluded = particles[dip->iCol].acolEndIncluded;
    1255             : 
    1256             :     // Then particle 2.
    1257           0 :     if (iCol != iAcol) {
    1258           0 :       for (int i = 0; i < int(particles[dip->iAcol].dips.size()); ++i)  {
    1259           0 :         if (i != dip->iAcolLeg) {
    1260             :           // If it is not the same leg, add as separate vector.
    1261           0 :           particles[iNew].dips.push_back(particles[dip->iAcol].dips[i]);
    1262           0 :           particles[iNew].colEndIncluded.push_back(
    1263           0 :             particles[dip->iAcol].colEndIncluded[i]);
    1264           0 :           particles[iNew].acolEndIncluded.push_back(
    1265           0 :             particles[dip->iAcol].acolEndIncluded[i]);
    1266           0 :         } // If it is the same leg, at at the end of the vector.
    1267             :         else {
    1268           0 :           particles[iNew].acolEndIncluded[iColLeg] =
    1269           0 :             particles[iAcol].acolEndIncluded[i];
    1270           0 :           particles[iNew].dips[iColLeg].pop_back();
    1271           0 :           particles[iNew].dips[iColLeg].insert(
    1272           0 :             particles[iNew].dips[iColLeg].end(),
    1273           0 :             particles[iAcol].dips[i].begin(), particles[iAcol].dips[i].end() );
    1274             :         }
    1275             :       }
    1276           0 :     }
    1277           0 :     if (iCol != iAcol) {
    1278             :       // Update the dipole legs to the new particle.
    1279           0 :       for (int i = 0; i < int(particles[iAcol].activeDips.size()); ++i) {
    1280           0 :         if ( particles[iAcol].activeDips[i]->iAcol == iAcol) {
    1281           0 :           if (particles[iAcol].activeDips[i]->iAcolLeg < iAcolLeg)
    1282           0 :             particles[iAcol].activeDips[i]->iAcolLeg +=
    1283           0 :               particles[iCol].dips.size();
    1284           0 :           else if (particles[iAcol].activeDips[i]->iAcolLeg == iAcolLeg)
    1285           0 :             particles[iAcol].activeDips[i]->iAcolLeg = iColLeg;
    1286           0 :           else if (particles[iAcol].activeDips[i]->iAcolLeg > iAcolLeg)
    1287           0 :             particles[iAcol].activeDips[i]->iAcolLeg +=
    1288           0 :               particles[iCol].dips.size() - 1;
    1289             :         }
    1290           0 :         if (particles[iAcol].activeDips[i]->iCol == iAcol) {
    1291           0 :           if (particles[iAcol].activeDips[i]->iColLeg < iAcolLeg)
    1292           0 :             particles[iAcol].activeDips[i]->iColLeg +=
    1293           0 :               particles[iCol].dips.size();
    1294           0 :           else if (particles[iAcol].activeDips[i]->iColLeg == iAcolLeg)
    1295           0 :             particles[iAcol].activeDips[i]->iColLeg = iColLeg;
    1296           0 :           else if (particles[iAcol].activeDips[i]->iColLeg > iAcolLeg)
    1297           0 :             particles[iAcol].activeDips[i]->iColLeg +=
    1298           0 :               particles[iCol].dips.size() - 1;
    1299             :         }
    1300             :       }
    1301           0 :     }
    1302             : 
    1303             :     // Update list of active dipoles.
    1304           0 :     particles[iNew].activeDips.clear();
    1305           0 :     particles[iNew].activeDips.insert(particles[iNew].activeDips.end(),
    1306           0 :       particles[iCol].activeDips.begin(), particles[iCol].activeDips.end());
    1307           0 :     if (iCol != iAcol)
    1308           0 :     particles[iNew].activeDips.insert(particles[iNew].activeDips.end(),
    1309           0 :       particles[iAcol].activeDips.begin(), particles[iAcol].activeDips.end());
    1310             : 
    1311             :     // Remove the now inactive dipole.
    1312           0 :     for (int i = 0; i < int(particles[iNew].activeDips.size()); ++i)
    1313           0 :       if (particles[iNew].activeDips[i] == dip) {
    1314           0 :         particles[iNew].activeDips.erase(
    1315           0 :           particles[iNew].activeDips.begin() + i);
    1316           0 :         i--;
    1317           0 :       }
    1318             : 
    1319             :     // Update the indices in the active dipoles.
    1320           0 :     for (int i = 0; i < int(particles[iNew].activeDips.size()); ++i) {
    1321           0 :       if (particles[iNew].activeDips[i]->iCol == iAcol)
    1322           0 :         particles[iNew].activeDips[i]->iCol = iNew;
    1323           0 :       if (particles[iNew].activeDips[i]->iCol == iCol)
    1324           0 :         particles[iNew].activeDips[i]->iCol = iNew;
    1325           0 :       if (particles[iNew].activeDips[i]->iAcol == iAcol)
    1326           0 :         particles[iNew].activeDips[i]->iAcol = iNew;
    1327           0 :       if (particles[iNew].activeDips[i]->iAcol == iCol)
    1328           0 :         particles[iNew].activeDips[i]->iAcol = iNew;
    1329           0 :       particles[iNew].activeDips[i]->p1p2
    1330           0 :         = mDip(particles[iNew].activeDips[i]);
    1331             :     }
    1332             : 
    1333             :     // If it is a combination of the same particle,
    1334             :     // check if any double active dipoles
    1335           0 :     if (iCol == iAcol)
    1336           0 :     for (int i = 0; i < int(particles[iNew].activeDips.size()); ++i)
    1337           0 :     for (int j = i + 1; j < int(particles[iNew].activeDips.size()); ++j)
    1338           0 :     if (particles[iNew].activeDips[i] == particles[iNew].activeDips[j]) {
    1339           0 :       particles[iNew].activeDips.erase(particles[iNew].activeDips.begin() + j);
    1340           0 :       j--;
    1341           0 :     }
    1342             : 
    1343             :     // Add dips changed to used dips.
    1344           0 :     for (int i = 0; i < int(particles[iNew].activeDips.size()); ++i) {
    1345           0 :       if (particles[iNew].activeDips[i]->iCol >= 0)
    1346           0 :         usedDipoles.push_back(particles[iNew].activeDips[i]);
    1347             :       else
    1348           0 :         for (int j = 0;j < 3; ++j)
    1349           0 :           usedDipoles.push_back(junctions[-(particles[iNew].
    1350           0 :             activeDips[i]->iCol / 10 + 1)].getColDip(j));
    1351             : 
    1352           0 :       if (particles[iNew].activeDips[i]->iAcol >= 0)
    1353           0 :         usedDipoles.push_back(particles[iNew].activeDips[i]);
    1354             :       else
    1355           0 :         for (int j = 0;j < 3; ++j)
    1356           0 :           usedDipoles.push_back(junctions[-(particles[iNew].
    1357           0 :             activeDips[i]->iAcol / 10 + 1)].getColDip(j));
    1358             :     }
    1359             : 
    1360             :     // mark the internal dipole as not active.
    1361           0 :     dip->isActive = false;
    1362             : 
    1363             :     // Done.
    1364             :     return;
    1365             :   }
    1366             : 
    1367             :   // If both ends are connected to a junction something went wrong!
    1368           0 :   else if (dip->isJun && dip->isAntiJun) {
    1369             :     return;
    1370             :   }
    1371             :   else {
    1372             : 
    1373             :     // Find junction index and first leg to combine.
    1374           0 :     int iJun, i0, i1, i2, junLeg0, junLeg1, junLeg2;
    1375           0 :     getJunctionIndices(dip, iJun, i0, i1, i2, junLeg0, junLeg1, junLeg2);
    1376           0 :     ColourDipole* dip2 = junctions[iJun].dips[junLeg1];
    1377           0 :     ColourDipole* dip3 = junctions[iJun].dips[junLeg2];
    1378             : 
    1379             :     // Add new particle.
    1380           0 :     int iNew = particles.size();
    1381           0 :     particles.push_back(ColourParticle( Particle( 99, status, i0, i1, 0, 0, 0,
    1382           0 :       0, particles[i0].p() + particles[i1].p() ) ) );
    1383           0 :     particles[iNew].isJun = true;
    1384           0 :     particles[iNew].junKind = junctions[iJun].kind();
    1385           0 :     if (i0 == i1) particles[iNew].p(particles[i0].p());
    1386             : 
    1387             :     // Update old particles.
    1388           0 :     particles[i0].statusNeg();
    1389           0 :     particles[i0].daughter1(iNew);
    1390           0 :     particles[i1].statusNeg();
    1391           0 :     particles[i1].daughter1(iNew);
    1392             : 
    1393             :     // Update list of internal dipoles.
    1394           0 :     particles[iNew].dips.clear();
    1395           0 :     particles[iNew].dips.insert(particles[iNew].dips.end(),
    1396           0 :       particles[i0].dips.begin(),particles[i0].dips.end());
    1397           0 :     if (i0 != i1)
    1398           0 :       particles[iNew].dips.insert(particles[iNew].dips.end(),
    1399           0 :         particles[i1].dips.begin(),particles[i1].dips.end());
    1400             : 
    1401             :     // Update list of whether colour ending is included.
    1402           0 :     particles[iNew].colEndIncluded.clear();
    1403           0 :     particles[iNew].colEndIncluded.insert(
    1404           0 :       particles[iNew].colEndIncluded.end(),
    1405           0 :       particles[i0].colEndIncluded.begin(),
    1406           0 :       particles[i0].colEndIncluded.end() );
    1407           0 :     if (i0 != i1)
    1408           0 :       particles[iNew].colEndIncluded.insert(
    1409           0 :         particles[iNew].colEndIncluded.end(),
    1410           0 :         particles[i1].colEndIncluded.begin(),
    1411           0 :         particles[i1].colEndIncluded.end() );
    1412             : 
    1413             :     // Update list of whether anti colour ending is included.
    1414           0 :     particles[iNew].acolEndIncluded.clear();
    1415           0 :     particles[iNew].acolEndIncluded.insert(
    1416           0 :       particles[iNew].acolEndIncluded.end(),
    1417           0 :       particles[i0].acolEndIncluded.begin(),
    1418           0 :       particles[i0].acolEndIncluded.end() );
    1419           0 :     if (i0 != i1)
    1420           0 :       particles[iNew].acolEndIncluded.insert(
    1421           0 :         particles[iNew].acolEndIncluded.end(),
    1422           0 :         particles[i1].acolEndIncluded.begin(),
    1423           0 :         particles[i1].acolEndIncluded.end() );
    1424             : 
    1425             :     // Third particle just need to add one to list of dipoles.
    1426           0 :     if (dip->isJun && i2 >= 0 && i2 != i0 && i2 != i1) {
    1427           0 :       particles[iNew].dips.push_back(particles[i2].dips[dip3->iColLeg]);
    1428           0 :       particles[iNew].dips.back().erase(particles[iNew].dips.back().begin(),
    1429           0 :         particles[iNew].dips.back().end() - 1);
    1430             : 
    1431           0 :     }
    1432           0 :     if (dip->isAntiJun && i2 >= 0 && i2 != i0 && i2 != i1) {
    1433           0 :       particles[iNew].dips.push_back(particles[i2].dips[dip3->iAcolLeg]);
    1434           0 :       particles[iNew].dips.back().erase(
    1435           0 :         particles[iNew].dips.back().begin() + 1,
    1436           0 :         particles[iNew].dips.back().end() );
    1437           0 :     }
    1438             : 
    1439             :     // Add endings for the third particle.
    1440           0 :     if (i2 != i0 && i2 != i1) {
    1441           0 :       particles[iNew].acolEndIncluded.push_back(false);
    1442           0 :       particles[iNew].colEndIncluded.push_back(false);
    1443           0 :     }
    1444             : 
    1445             :     // Special case if it is J-J connection.
    1446           0 :     if (i2 < 0) {
    1447           0 :       particles[iNew].dips.push_back(vector<ColourDipole *>());
    1448             : 
    1449             :       // Find the real dipole to add to dipole list.
    1450           0 :       for (int i = 0; i < int(dipoles.size()); ++i)
    1451           0 :         if (dipoles[i]->isReal && dipoles[i]->iCol == dip3->iCol &&
    1452           0 :             dipoles[i]->iAcol == dip3->iAcol)
    1453           0 :           particles[iNew].dips.back().push_back(dipoles[i]);
    1454             : 
    1455             :       // Change ending.
    1456           0 :       particles[iNew].acolEndIncluded.back() = true;
    1457           0 :       particles[iNew].colEndIncluded.back()  = true;
    1458           0 :     }
    1459             : 
    1460             :     // The endings need to reflect the new junction structure.
    1461           0 :     if (dip->isJun)
    1462           0 :     for (int i = 0; i < int(particles[iNew].acolEndIncluded.size()); ++i)
    1463           0 :       particles[iNew].acolEndIncluded[i] = true;
    1464             :     else
    1465           0 :     for (int i = 0; i < int(particles[iNew].colEndIncluded.size()); ++i)
    1466           0 :       particles[iNew].colEndIncluded[i] = true;
    1467             : 
    1468             :     // Update active dipoles, first junction case.
    1469             :     // Set the now internal dipoles as inactive.
    1470           0 :     dip->isActive = false;
    1471           0 :     dip2->isActive = false;
    1472           0 :     dip3->isActive = true;
    1473             : 
    1474             :     // Update the dipole legs to the new particle.
    1475             :     // Only need to do it for the iAcol particle,
    1476             :     // since nothing changes for the iCol particle.
    1477           0 :     if (i0 != i1)
    1478           0 :     for (int i = 0; i < int(particles[i1].activeDips.size()); ++i) {
    1479           0 :       if (particles[i1].activeDips[i]->iAcol == i1)
    1480           0 :         particles[i1].activeDips[i]->iAcolLeg += particles[i0].dips.size();
    1481           0 :       if (particles[i1].activeDips[i]->iCol == i1)
    1482           0 :         particles[i1].activeDips[i]->iColLeg += particles[i0].dips.size();
    1483           0 :     }
    1484             : 
    1485             :     // Update list of active dipoles.
    1486           0 :     particles[iNew].activeDips.clear();
    1487           0 :     particles[iNew].activeDips.insert(particles[iNew].activeDips.end(),
    1488           0 :       particles[i0].activeDips.begin(), particles[i0].activeDips.end());
    1489           0 :     if (i0 != i1)
    1490           0 :       particles[iNew].activeDips.insert(particles[iNew].activeDips.end(),
    1491           0 :         particles[i1].activeDips.begin(), particles[i1].activeDips.end());
    1492           0 :     if (i2 != i0 && i2 != i1)
    1493           0 :       particles[iNew].activeDips.push_back(dip3);
    1494             : 
    1495             :     // Remove the now inactive dipoles.
    1496           0 :     for (int i = 0; i < int(particles[iNew].activeDips.size()); ++i) {
    1497           0 :       if (particles[iNew].activeDips[i] == dip) {
    1498           0 :         particles[iNew].activeDips.erase(
    1499           0 :           particles[iNew].activeDips.begin() + i);
    1500           0 :         i--;
    1501           0 :         continue;
    1502             :       }
    1503           0 :       if (particles[iNew].activeDips[i] == dip2) {
    1504           0 :         particles[iNew].activeDips.erase(
    1505           0 :           particles[iNew].activeDips.begin() + i);
    1506           0 :         i--;
    1507           0 :         continue;
    1508             :       }
    1509             :     }
    1510             : 
    1511             :     // Update the indices in the active dipoles.
    1512           0 :     for (int i = 0; i < int(particles[iNew].activeDips.size()); ++i) {
    1513           0 :       if (particles[iNew].activeDips[i]->iCol == i1)
    1514           0 :         particles[iNew].activeDips[i]->iCol = iNew;
    1515           0 :       if (particles[iNew].activeDips[i]->iCol == i0)
    1516           0 :         particles[iNew].activeDips[i]->iCol = iNew;
    1517           0 :       if (particles[iNew].activeDips[i]->iAcol == i1)
    1518           0 :         particles[iNew].activeDips[i]->iAcol = iNew;
    1519           0 :       if (particles[iNew].activeDips[i]->iAcol == i0)
    1520           0 :         particles[iNew].activeDips[i]->iAcol = iNew;
    1521           0 :       particles[iNew].activeDips[i]->p1p2
    1522           0 :         = mDip(particles[iNew].activeDips[i]);
    1523             :     }
    1524             : 
    1525             :     // The third dip is no longer connected to a junction.
    1526           0 :     if (dip->isJun) {
    1527           0 :       dip3->isJun = false;
    1528           0 :       dip3->iAcol = iNew;
    1529           0 :       if (i2 != i0 && i2 != i1)
    1530           0 :         dip3->iAcolLeg = particles[iNew].dips.size() - 1;
    1531             :     }
    1532             :     else  {
    1533           0 :       dip3->isAntiJun = false;
    1534           0 :       dip3->iCol = iNew;
    1535           0 :       if (i2 != i0 && i2 != i1)
    1536           0 :         dip3->iColLeg = particles[iNew].dips.size() - 1;
    1537             :     }
    1538             : 
    1539             :     // Add dips changed to used dips.
    1540           0 :     for (int i = 0; i < int(particles[iNew].activeDips.size()); ++i) {
    1541             :       bool added = false;
    1542           0 :       for (int j = 0;j < int(usedDipoles.size()); ++j)
    1543           0 :         if (particles[iNew].activeDips[i] == usedDipoles[j]) {
    1544             :           added = true;
    1545           0 :           break;
    1546             :         }
    1547           0 :       if (!added) usedDipoles.push_back(particles[iNew].activeDips[i]);
    1548             :     }
    1549           0 :     usedDipoles.push_back(dip);
    1550           0 :     usedDipoles.push_back(dip2);
    1551           0 :     usedDipoles.push_back(dip3);
    1552             : 
    1553             : 
    1554             :     // Possible for the new dip to have a low m0.
    1555           0 :     if (setupDone && mDip(dip3) < m0)
    1556           0 :       makePseudoParticle(dip3, status, true);
    1557           0 :   }
    1558             : 
    1559             :   // Done.
    1560             : 
    1561           0 : }
    1562             : 
    1563             : // ------------------------------------------------------------------
    1564             : 
    1565             : // Help function to sort dipoles in right order.
    1566             : 
    1567             : bool sortFunc(ColourDipole* a, ColourDipole* b) {
    1568           0 :     return (a->p1p2 < b->p1p2);
    1569             : }
    1570             : 
    1571             : // ------------------------------------------------------------------
    1572             : 
    1573             : // Form all pseudoparticles below m0.
    1574             : 
    1575             : void ColourReconnection::makeAllPseudoParticles( Event & event, int iFirst) {
    1576             : 
    1577             :   // Make junctions.
    1578           0 :   for (int i = 0; i < event.sizeJunction(); ++i)
    1579           0 :     junctions.push_back(event.getJunction(i));
    1580             : 
    1581             :   // Make new copy of all the dipoles.
    1582           0 :   int oldSize = int(dipoles.size());
    1583           0 :   for (int i = 0; i < oldSize; ++i) {
    1584           0 :     dipoles.push_back(new ColourDipole(*dipoles[i]));
    1585           0 :     dipoles[i + oldSize]->iColLeg = 0;
    1586           0 :     dipoles[i + oldSize]->iAcolLeg = 0;
    1587           0 :     dipoles[i]->iColLeg = 0;
    1588           0 :     dipoles[i]->iAcolLeg = 0;
    1589           0 :     dipoles[i]->isActive = false;
    1590           0 :     dipoles[i]->isReal = true;
    1591           0 :     dipoles[i + oldSize]->isReal = false;
    1592             : 
    1593             :     // Store original dipoles connected to junctions.
    1594           0 :     if (dipoles[i]->iCol < 0) {
    1595           0 :       junctions[-(dipoles[i]->iCol / 10 + 1)].dipsOrig[(-dipoles[i]->iCol)
    1596           0 :         % 10] = dipoles[i];
    1597           0 :     }
    1598           0 :     if (dipoles[i]->iAcol < 0) {
    1599           0 :       junctions[-(dipoles[i]->iAcol / 10 + 1)].dipsOrig[-(dipoles[i]->iAcol
    1600           0 :         % 10)] = dipoles[i];
    1601           0 :     }
    1602             :   }
    1603             : 
    1604             :   // Set up the coldDips and acolDips.
    1605           0 :   for (int i = 0; i < oldSize; ++i) {
    1606           0 :     if (dipoles[i]->leftDip != 0)
    1607           0 :     for (int j = 0; j < oldSize; ++j)
    1608           0 :     if (dipoles[i]->leftDip == dipoles[j]) {
    1609           0 :       dipoles[i + oldSize]->colDips.push_back(dipoles[j + oldSize]);
    1610           0 :       break;
    1611           0 :     }
    1612             : 
    1613           0 :     if (dipoles[i]->rightDip != 0)
    1614           0 :     for (int j = 0; j < oldSize; ++j)
    1615           0 :     if (dipoles[i]->rightDip == dipoles[j]) {
    1616           0 :       dipoles[i + oldSize]->acolDips.push_back(dipoles[j + oldSize]);
    1617           0 :       break;
    1618           0 :     }
    1619             :   }
    1620             : 
    1621             :   // Start by copying event record to make pseudoparticles.
    1622             :   // The pseudoparticles also need to gain
    1623           0 :   for (int i = iFirst; i < event.size(); ++i)
    1624           0 :   if (event[i].isFinal()) {
    1625           0 :     particles.push_back(ColourParticle(event[i]));
    1626           0 :     particles.back().dips.resize(1,vector<ColourDipole *>());
    1627             : 
    1628             :     // Set up dipoles.
    1629           0 :     for (int j = 0; j < int(dipoles.size()); ++j) {
    1630           0 :       if (dipoles[j]->iCol == i) {
    1631           0 :         if (dipoles[j]->isActive) {
    1632           0 :           dipoles[j]->iCol = particles.size() - 1;
    1633           0 :           particles.back().activeDips.push_back(dipoles[j]);
    1634           0 :         }
    1635           0 :         else particles.back().dips[0].push_back(dipoles[j]);
    1636             :       }
    1637             : 
    1638           0 :       if (dipoles[j]->iAcol == i) {
    1639           0 :         if (dipoles[j]->isActive) {
    1640           0 :           dipoles[j]->iAcol = particles.size() - 1;
    1641           0 :           particles.back().activeDips.push_back(dipoles[j]);
    1642           0 :         }
    1643           0 :         else particles.back().dips[0].insert(particles.back().dips[0].begin(),
    1644           0 :           dipoles[j]);
    1645             :       }
    1646             :     }
    1647             : 
    1648             :     // Tell whether dipoles are connected to other dipoles.
    1649           0 :     if (event[i].isQuark() && event[i].id() > 0)
    1650           0 :       particles.back().colEndIncluded.push_back(true);
    1651           0 :     else particles.back().colEndIncluded.push_back(false);
    1652             : 
    1653           0 :     if (event[i].isQuark() && event[i].id() < 0)
    1654           0 :       particles.back().acolEndIncluded.push_back(true);
    1655           0 :     else particles.back().acolEndIncluded.push_back(false);
    1656             :   }
    1657             : 
    1658             :   // Inserting a copy of the event record, but now with full
    1659             :   // pseudo particle setup.
    1660             :   // This is mainly to avoid having to distinguish between combining
    1661             :   // original particles and pseudoparticles.
    1662             : 
    1663             :   // Set right dipole connections in junctions.
    1664           0 :   for (int i = 0; i < int(dipoles.size()); ++i) {
    1665           0 :     if (dipoles[i]->iCol < 0) {
    1666           0 :       int j = (- dipoles[i]->iCol / 10) - 1;
    1667           0 :       int jLeg = - dipoles[i]->iCol % 10;
    1668           0 :       junctions[j].setColDip(jLeg, dipoles[i]);
    1669           0 :     }
    1670           0 :     if (dipoles[i]->iAcol < 0) {
    1671           0 :       int j = (- dipoles[i]->iAcol / 10) - 1;
    1672           0 :       int jLeg = - dipoles[i]->iAcol % 10;
    1673           0 :       junctions[j].setColDip(jLeg, dipoles[i]);
    1674           0 :     }
    1675             :   }
    1676             : 
    1677             :   // Make sure all dipoles masses are set correctly.
    1678           0 :   for (int i = 0; i < int(dipoles.size()); ++i) {
    1679           0 :     if (dipoles[i]->isActive)
    1680           0 :       dipoles[i]->p1p2 = mDip(dipoles[i]);
    1681             :     else
    1682           0 :       dipoles[i]->p1p2 = 1e9;
    1683             :   }
    1684             : 
    1685             :   // Keep making pseudo particles until they are above the threshold.
    1686           0 :   while (true) {
    1687           0 :     sort(dipoles.begin(), dipoles.end(), sortFunc);
    1688             :     bool finished = true;
    1689           0 :     for (int i = 0; i < int(dipoles.size()); ++i) {
    1690           0 :       if (!dipoles[i]->isActive) continue;
    1691           0 :       if (dipoles[i]->p1p2 < m0) {
    1692           0 :         makePseudoParticle( dipoles[i], 110);
    1693             :         finished = false;
    1694           0 :         break;
    1695             :       }
    1696           0 :       else break;
    1697             :     }
    1698           0 :     if (finished) break;
    1699           0 :   }
    1700             : 
    1701             :   // Sort the dipoles.
    1702           0 :   sort(dipoles.begin(), dipoles.end(), sortFunc);
    1703             : 
    1704             :   // Done.
    1705             :   return;
    1706             : 
    1707           0 : }
    1708             : 
    1709             : // ------------------------------------------------------------------
    1710             : 
    1711             : // Print statements if something is wrong in dipole setup.
    1712             : // Does not have a return statement -- DEBUG PURPOSE ONLY --.
    1713             : 
    1714             : void ColourReconnection::checkRealDipoles(Event& event, int iFirst) {
    1715           0 :   vector<int> dipConnections(event.size(),0);
    1716           0 :   for (int i = 0;i < int(dipoles.size()); ++i)
    1717           0 :     if (dipoles[i]->isReal) {
    1718           0 :       if (dipoles[i]->iCol >= 0)
    1719           0 :         dipConnections[dipoles[i]->iCol]++;
    1720           0 :       if (dipoles[i]->iAcol >= 0)
    1721           0 :         dipConnections[dipoles[i]->iAcol]++;
    1722             :     }
    1723             :   bool working = true;
    1724           0 :   for (int i = iFirst ;i < event.size(); ++i) {
    1725           0 :     if (event[i].isFinal()) {
    1726           0 :       if (event[i].isQuark() && dipConnections[i] != 1) {
    1727           0 :         cout << "quark " << i << " is wrong!!" << endl;
    1728             :         working = false;
    1729           0 :       }
    1730           0 :       else if (event[i].idAbs() == 21 && dipConnections[i] != 2) {
    1731           0 :         cout << "gluon " << i << " is wrong!!" << endl;
    1732             :         working = false;
    1733           0 :       }
    1734             :     }
    1735             :   }
    1736           0 :   if (!working) {
    1737           0 :     infoPtr->errorMsg("Error in ColourReconnection::checkRealDipoles:"
    1738             :       "Real dipoles not setup properply");
    1739             : 
    1740           0 :   }
    1741             : 
    1742           0 : }
    1743             : // ------------------------------------------------------------------
    1744             : 
    1745             : // Print statements if something is wrong in dipole setup.
    1746             : // Does not have a return statement -- DEBUG PURPOSE ONLY --.
    1747             : 
    1748             : void ColourReconnection::checkDipoles() {
    1749             : 
    1750           0 :   for (int i = 0;i < int(dipoles.size()); ++i) {
    1751           0 :     if (dipoles[i] == 0) { cout << "dipole empty" << endl;}
    1752           0 :     if (dipoles[i]->isActive) {
    1753           0 :       if (dipoles[i]->iCol >= 0) {
    1754             :         bool foundMyself = false;
    1755           0 :         for (int j = 0; j < int(particles[ dipoles[i]->iCol ].
    1756           0 :           activeDips.size()); ++j) {
    1757           0 :           if (!particles[dipoles[i]->iCol].activeDips[j]->isActive) {
    1758           0 :             infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1759             :               "Found inactive dipole, where only active was expected");
    1760           0 :           }
    1761           0 :           if (particles[dipoles[i]->iCol].activeDips[j] == dipoles[i])
    1762           0 :             foundMyself = true;
    1763             :         }
    1764             : 
    1765           0 :         if (!foundMyself) {
    1766           0 :           infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1767             :             "Linking between active dipoles and particles is wrong");
    1768           0 :         }
    1769           0 :         if (dipoles[i]->iColLeg
    1770           0 :           >= int(particles[dipoles[i]->iCol].dips.size())) {
    1771           0 :           infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1772             :             "Original dipoles not stored correct");
    1773           0 :         }
    1774             : 
    1775             :         // Check that linking to old dipoles work.
    1776           0 :         if (dipoles[i]->col !=
    1777           0 :            particles[dipoles[i]->iCol].dips[dipoles[i]->iColLeg].back()->col) {
    1778           0 :            infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1779             :             "Original dipoles do not match in");
    1780           0 :         }
    1781           0 :       }
    1782             : 
    1783           0 :       if (dipoles[i]->iAcol >= 0) {
    1784             :         bool foundMyself = false;
    1785           0 :         for (int j = 0;j < int(particles[ dipoles[i]->iAcol ].
    1786           0 :           activeDips.size()); ++j) {
    1787             : 
    1788           0 :           if (!particles[dipoles[i]->iAcol].activeDips[j]->isActive) {
    1789           0 :             infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1790             :               "Found inactive dipole, where only active was expected");
    1791           0 :           }
    1792           0 :            if (particles[dipoles[i]->iAcol].activeDips[j] == dipoles[i])
    1793           0 :             foundMyself = true;
    1794             :         }
    1795             : 
    1796           0 :         if (!foundMyself) {
    1797           0 :            infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1798             :             "Linking between active dipoles and particles is wrong");
    1799           0 :         }
    1800           0 :         if (dipoles[i]->iAcolLeg >= int(particles[dipoles[i]->iAcol].
    1801           0 :           dips.size() )) {
    1802           0 :           infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1803             :             "Original dipoles not stored correct");
    1804           0 :         }
    1805             : 
    1806             :         // Check that linking to old dipoles work
    1807           0 :         if (dipoles[i]->col != particles[dipoles[i]->iAcol].
    1808           0 :             dips[dipoles[i]->iAcolLeg].front()->col) {
    1809           0 :            infoPtr->errorMsg("Error in ColourReconnection::checkDipoles:"
    1810             :             "Original dipoles do not match in");
    1811           0 :         }
    1812           0 :       }
    1813             :     }
    1814             :   }
    1815           0 : }
    1816             : 
    1817             : // ------------------------------------------------------------------
    1818             : 
    1819             : // Print all the chains.
    1820             : 
    1821             : void ColourReconnection::listAllChains() {
    1822             : 
    1823           0 :   cout << "  ----- PRINTING CHAINS -----  " << dipoles.size() << endl;
    1824           0 :   for (int i = 0; i < int(dipoles.size()); ++i)
    1825           0 :     dipoles[i]->printed = false;
    1826             : 
    1827           0 :   for (int i = 0;i < int(dipoles.size()); ++i)
    1828           0 :     if (!dipoles[i]->printed)
    1829           0 :       listChain(dipoles[i]);
    1830           0 :   cout << "  ----- PRINTED CHAINS -----  " << endl;
    1831             : 
    1832           0 : }
    1833             : 
    1834             : // ------------------------------------------------------------------
    1835             : 
    1836             : // Print the chain containing the dipole.
    1837             : 
    1838             : void ColourReconnection::listChain(ColourDipole *dip) {
    1839             : 
    1840             :   // Make sure not an empty pointer.
    1841           0 :   if (dip == 0) return;
    1842             : 
    1843             :   // If chain is not active, just print it.
    1844           0 :   if (!dip->isActive) {
    1845             :     return;
    1846             :   }
    1847             : 
    1848           0 :   ColourDipole * colDip = dip;
    1849             : 
    1850             :   // Try to reach one end of the chain.
    1851           0 :   while (particles[colDip->iCol].dips.size() == 1 && findColNeighbour(colDip))
    1852           0 :     if (dip == colDip)
    1853             :       break;
    1854             : 
    1855           0 :   ColourDipole * endDip = colDip;
    1856           0 :   do {
    1857           0 :     cout << colDip->iCol << " (" << colDip->p1p2 << ", " << colDip->col
    1858           0 :          << ") (" << colDip->isActive << ") ";
    1859           0 :     colDip->printed = true;
    1860           0 :   }
    1861             :   // Start the printing.
    1862           0 :   while (particles[colDip->iAcol].dips.size() == 1 && findAntiNeighbour(colDip)
    1863           0 :          && colDip != endDip);
    1864             : 
    1865             :   // Print the last part.
    1866           0 :   cout << colDip->iAcol<< endl;
    1867             : 
    1868             :   // Done.
    1869           0 : }
    1870             : 
    1871             : // ------------------------------------------------------------------
    1872             : 
    1873             : // Return relevant indices for the junction.
    1874             : 
    1875             : bool ColourReconnection::getJunctionIndices(ColourDipole * dip, int &iJun,
    1876             :   int &i0, int &i1, int &i2, int &junLeg0, int &junLeg1, int &junLeg2) {
    1877             : 
    1878             :   // Find junction index and first leg to combine.
    1879           0 :   int indxJun = dip->iCol;
    1880           0 :   if (dip->iAcol < 0)
    1881           0 :       indxJun = dip->iAcol;
    1882           0 :   iJun = (- indxJun / 10) - 1;
    1883           0 :   junLeg0 = -(indxJun % 10);
    1884           0 :   junLeg1 = 1;
    1885           0 :   junLeg2 = 2;
    1886           0 :   if (junLeg0 == 1) junLeg1 = 0;
    1887           0 :   else if (junLeg0 == 2) junLeg2 = 0;
    1888             : 
    1889           0 :   if (dip->iCol < 0) {
    1890           0 :     i0 = dip->iAcol;
    1891           0 :     i1 = junctions[iJun].dips[junLeg1]->iAcol;
    1892           0 :     i2 = junctions[iJun].dips[junLeg2]->iAcol;
    1893           0 :   }
    1894             :   else {
    1895           0 :     i0 = dip->iCol;
    1896           0 :     i1 = junctions[iJun].dips[junLeg1]->iCol;
    1897           0 :     i2 = junctions[iJun].dips[junLeg2]->iCol;
    1898             :   }
    1899             : 
    1900             :   // It is not possible to form a pseudoparticle if only a single particle is
    1901             :   // connected to the junction.
    1902           0 :   if (i1 < 0 && i2 < 0) return false;
    1903             : 
    1904             :   // Check which two particle should form the pseudoparticle.
    1905             :   double m1 = 1e9, m2 = 1e9;
    1906           0 :   if (i1 >= 0)
    1907           0 :     m1 = m(particles[i0].p(),particles[i1].p());
    1908           0 :   if (i2 >= 0)
    1909           0 :     m2 = m(particles[i0].p(),particles[i2].p());
    1910             : 
    1911           0 :   if (m1 > m2) {
    1912           0 :     swap(i1,i2);
    1913           0 :     swap(junLeg1,junLeg2);
    1914           0 :   }
    1915             :   // Force switch if i0 == i2
    1916           0 :   if (i0 == i2) {
    1917           0 :     swap(i1,i2);
    1918           0 :     swap(junLeg1,junLeg2);
    1919           0 :   }
    1920             : 
    1921             :   return true;
    1922           0 : }
    1923             : 
    1924             : 
    1925             : // ------------------------------------------------------------------
    1926             : 
    1927             : // Check whether up to four dipoles are 'causally' connected.
    1928             : 
    1929             : bool ColourReconnection::checkTimeDilation(ColourDipole * dip1,
    1930             :   ColourDipole * dip2, ColourDipole * dip3, ColourDipole * dip4) {
    1931             : 
    1932           0 :   if (timeDilationMode == 0) return true;
    1933             : 
    1934             :   // 2 dipole case.
    1935           0 :   if (dip3 == 0) {
    1936           0 :     Vec4 p1 = getDipoleMomentum(dip1);
    1937           0 :     Vec4 p2 = getDipoleMomentum(dip2);
    1938           0 :     double t1 = formationTimes[dip1->col];
    1939           0 :     double t2 = formationTimes[dip2->col];
    1940           0 :     if (dip1 == dip2) return true;
    1941           0 :     else return checkTimeDilation(p1, p2, t1, t2);
    1942             : 
    1943             :   // 3 dipole case.
    1944           0 :   } else if (dip4 == 0) {
    1945           0 :     Vec4 p1 = getDipoleMomentum(dip1);
    1946           0 :     Vec4 p2 = getDipoleMomentum(dip2);
    1947           0 :     Vec4 p3 = getDipoleMomentum(dip3);
    1948           0 :     double t1 = formationTimes[dip1->col];
    1949           0 :     double t2 = formationTimes[dip2->col];
    1950           0 :     double t3 = formationTimes[dip3->col];
    1951             :     // Modes that require all dipoles to be causally connected.
    1952           0 :     if (timeDilationMode == 1 || timeDilationMode == 2 ||
    1953           0 :         timeDilationMode == 4) {
    1954           0 :       if (dip1 != dip2 && !checkTimeDilation(p1, p2, t1, t2)) return false;
    1955           0 :       if (dip1 != dip3 && !checkTimeDilation(p1, p3, t1, t3)) return false;
    1956           0 :       if (dip2 != dip3 && !checkTimeDilation(p2, p3, t2, t3)) return false;
    1957           0 :       return true;
    1958             :     // Modes that require a single pair of dipoles to be causally connected.
    1959             :     } else {
    1960           0 :       if (dip1 != dip2 && checkTimeDilation(p1, p2, t1, t2)) return true;
    1961           0 :       if (dip1 != dip3 && checkTimeDilation(p1, p3, t1, t3)) return true;
    1962           0 :       if (dip2 != dip3 && checkTimeDilation(p2, p3, t2, t3)) return true;
    1963           0 :       return false;
    1964             :     }
    1965             : 
    1966             :   // 4 dipole case.
    1967           0 :   } else {
    1968           0 :     Vec4 p1 = getDipoleMomentum(dip1);
    1969           0 :     Vec4 p2 = getDipoleMomentum(dip2);
    1970           0 :     Vec4 p3 = getDipoleMomentum(dip3);
    1971           0 :     Vec4 p4 = getDipoleMomentum(dip4);
    1972           0 :     double t1 = formationTimes[dip1->col];
    1973           0 :     double t2 = formationTimes[dip2->col];
    1974           0 :     double t3 = formationTimes[dip3->col];
    1975           0 :     double t4 = formationTimes[dip4->col];
    1976             :     // Modes that require all dipoles to be causally connected.
    1977           0 :     if (timeDilationMode == 1 || timeDilationMode == 2 ||
    1978           0 :         timeDilationMode == 4) {
    1979           0 :       if (dip1 != dip2 && !checkTimeDilation(p1, p2, t1, t2)) return false;
    1980           0 :       if (dip1 != dip3 && !checkTimeDilation(p1, p3, t1, t3)) return false;
    1981           0 :       if (dip1 != dip4 && !checkTimeDilation(p1, p4, t1, t4)) return false;
    1982           0 :       if (dip2 != dip3 && !checkTimeDilation(p2, p3, t2, t3)) return false;
    1983           0 :       if (dip2 != dip4 && !checkTimeDilation(p2, p4, t2, t4)) return false;
    1984           0 :       if (dip3 != dip4 && !checkTimeDilation(p3, p4, t3, t4)) return false;
    1985           0 :       return true;
    1986             :     // Modes that require a single pair of dipoles to be causally connected.
    1987             :     } else {
    1988           0 :       if (dip1 != dip2 && checkTimeDilation(p1, p2, t1, t2)) return true;
    1989           0 :       if (dip1 != dip3 && checkTimeDilation(p1, p3, t1, t3)) return true;
    1990           0 :       if (dip1 != dip4 && checkTimeDilation(p1, p4, t1, t4)) return true;
    1991           0 :       if (dip2 != dip3 && checkTimeDilation(p2, p3, t2, t3)) return true;
    1992           0 :       if (dip2 != dip4 && checkTimeDilation(p2, p4, t2, t4)) return true;
    1993           0 :       if (dip3 != dip4 && checkTimeDilation(p3, p4, t3, t4)) return true;
    1994           0 :       return false;
    1995             :     }
    1996           0 :   }
    1997             : 
    1998             :   // Done.
    1999           0 : }
    2000             : 
    2001             : // ------------------------------------------------------------------
    2002             : 
    2003             : // Find the momentum of the dipole.
    2004             : 
    2005             : Vec4 ColourReconnection::getDipoleMomentum(ColourDipole * dip) {
    2006           0 :   vector<int> iPar, usedJuncs;
    2007           0 :   if (!dip->isJun) iPar.push_back(dip->iAcol);
    2008           0 :   else addJunctionIndices(dip->iAcol, iPar, usedJuncs);
    2009           0 :   if (!dip->isAntiJun) iPar.push_back(dip->iCol);
    2010           0 :   else addJunctionIndices(dip->iCol, iPar, usedJuncs);
    2011             : 
    2012             :   // Remove any duplicates.
    2013           0 :   sort(iPar.begin(),iPar.end());
    2014           0 :   for (int i = 0;i < int(iPar.size()) - 1; ++i)
    2015           0 :     if (iPar[i] == iPar[i+1]) {
    2016           0 :       iPar.erase(iPar.begin()+i);
    2017           0 :       i--;
    2018           0 :     }
    2019             : 
    2020           0 :   if (iPar.size() == 0) {
    2021           0 :     infoPtr->errorMsg("Error in ColourReconnection::getDipoleMomentum: "
    2022             :                       "No particles connected to junction.");
    2023           0 :     return Vec4(0,0,0,0);
    2024             :   }
    2025             : 
    2026           0 :   Vec4 p = particles[iPar[0]].p();
    2027           0 :   for (int i = 1;i < int(iPar.size()); ++i)
    2028           0 :     p += particles[iPar[i]].p();
    2029             : 
    2030           0 :   return p;
    2031           0 : }
    2032             : 
    2033             : // ------------------------------------------------------------------
    2034             : 
    2035             : // Check whether two four momenta are 'causally' connected.
    2036             : 
    2037             : bool ColourReconnection::checkTimeDilation(Vec4 p1,
    2038             :   Vec4 p2, double t1, double t2) {
    2039             :   // No time dilation check.
    2040           0 :   if (timeDilationMode == 0) return true;
    2041             : 
    2042             :   // Check if gamma is below parameter.
    2043           0 :   else if (timeDilationMode == 1) {
    2044           0 :     p2.bstback(p1);
    2045           0 :     if (p2.e() / p2.mCalc() > timeDilationPar) return false;
    2046           0 :     else return true;
    2047             : 
    2048             :   // Check if gamma * mDip is below parameter for both dipoles.
    2049           0 :   } else if (timeDilationMode == 2) {
    2050             :     bool part1, part2;
    2051           0 :     p2.bstback(p1);
    2052           0 :     if (p2.e() / p2.mCalc() > timeDilationParGeV * p2.mCalc()) part1 = false;
    2053             :     else part1 = true;
    2054           0 :     p2.bst(p1);
    2055           0 :     p1.bstback(p2);
    2056           0 :     if (p1.e() / p1.mCalc() > timeDilationParGeV * p1.mCalc()) part2 = false;
    2057             :     else part2 = true;
    2058           0 :     if (part1 && part2) return true;
    2059           0 :     else return false;
    2060             : 
    2061             :   // Check if gamma * mDip is below parameter for a single dipole.
    2062           0 :   } else if (timeDilationMode == 3) {
    2063             :     bool part1, part2;
    2064           0 :     p2.bstback(p1);
    2065           0 :     if (p2.e() / p2.mCalc() > timeDilationParGeV * p2.mCalc()) part1 = false;
    2066             :     else part1 = true;
    2067           0 :     p2.bst(p1);
    2068           0 :     p1.bstback(p2);
    2069           0 :     if (p1.e() / p1.mCalc() > timeDilationParGeV * p1.mCalc()) part2 = false;
    2070             :     else part2 = true;
    2071           0 :     if (part1 || part2) return true;
    2072           0 :     else return false;
    2073             : 
    2074             :   // Check if gamma * mDip' is below parameter for both dipoles.
    2075           0 :   } else if (timeDilationMode == 4) {
    2076           0 :     p2.bstback(p1);
    2077           0 :     if (p2.e() / p2.mCalc() < timeDilationParGeV * min(t1,t2)) return true;
    2078           0 :     else return false;
    2079             : 
    2080             :   // Check if gamma * mDip' is below parameter for a single dipole.
    2081           0 :   } else if (timeDilationMode == 5) {
    2082           0 :     p2.bstback(p1);
    2083           0 :     if (p2.e() / p2.mCalc() < timeDilationParGeV * max(t1,t2)) return true;
    2084           0 :     else return false;
    2085             : 
    2086             :   // If mode is set wrong, should never happen.
    2087           0 :   } else return true;
    2088           0 : }
    2089             : 
    2090             : // ------------------------------------------------------------------
    2091             : 
    2092             : // Store the formation times.
    2093             : 
    2094             : void ColourReconnection::setupFormationTimes(Event & event) {
    2095             : 
    2096           0 :   for (int i = 0;i < event.size(); ++i) {
    2097             :     // First check the colour.
    2098           0 :     if (event[i].col() != 0 && formationTimes.count(event[i].col()) == 0) {
    2099           0 :       int col = event[i].col();
    2100             :       // Find first time the colour appears as an anticolour.
    2101             :       bool foundCol = false;
    2102             :       int iAcol = 0;
    2103           0 :       for (int j = i;j < event.size(); ++j) {
    2104           0 :         if (event[j].acol() == col) {
    2105             :           foundCol = true;
    2106             :           iAcol = j;
    2107           0 :           break;
    2108             :         }
    2109             :       }
    2110             : 
    2111             :       // If it was found add it to the list.
    2112           0 :       if (foundCol) {
    2113           0 :         formationTimes[col] = max( m0,
    2114           0 :           (event[i].p() + event[iAcol].p()).mCalc() );
    2115             :       // Otherwise it must be stored in a junction.
    2116           0 :       } else {
    2117           0 :         formationTimes[col] = max(m0, getJunctionMass(event, col));
    2118             :       }
    2119           0 :     }
    2120             : 
    2121             :     // Next check the anti colour.
    2122           0 :     if (event[i].acol() != 0 && formationTimes.count(event[i].acol()) == 0) {
    2123           0 :       int acol = event[i].acol();
    2124             :       // Find first time the colour appears as an anticolour.
    2125             :       bool foundCol = false;
    2126             :       int iCol = 0;
    2127           0 :       for (int j = i;j < event.size(); ++j) {
    2128           0 :         if (event[j].col() == acol) {
    2129             :           foundCol = true;
    2130             :           iCol = j;
    2131           0 :           break;
    2132             :         }
    2133             :       }
    2134             : 
    2135             :       // If it was found add it to the list.
    2136           0 :       if (foundCol) {
    2137           0 :         formationTimes[acol] = max(m0, (event[i].p() + event[iCol].p())
    2138             :           .mCalc());
    2139             :       // Otherwise it must be stored in a junction.
    2140           0 :       } else {
    2141           0 :         formationTimes[acol] = max(m0, getJunctionMass(event, acol));
    2142             :       }
    2143           0 :     }
    2144             :   }
    2145             : 
    2146             :   // Finally check if junction colours are stored.
    2147           0 :   for (int i = 0; i < event.sizeJunction(); ++i)
    2148           0 :     for (int j = 0; j < 3; ++j)
    2149           0 :       if (formationTimes.count(event.colJunction(i,j)) == 0)
    2150           0 :         formationTimes[event.colJunction(i,j)] = max(m0,
    2151           0 :           getJunctionMass(event, event.colJunction(i,j)));
    2152             : 
    2153             :   // Done.
    2154           0 : }
    2155             : 
    2156             : // ------------------------------------------------------------------
    2157             : 
    2158             : // Find the invariant mass of all the partons connected to a junction system.
    2159             : 
    2160             : double ColourReconnection::getJunctionMass(Event & event, int col) {
    2161             : 
    2162             :   // Find the partons connected to the junction system.
    2163           0 :   vector<int> iPar, usedJuncs;
    2164           0 :   addJunctionIndices(event, col, iPar, usedJuncs);
    2165             : 
    2166             :   // Check for doubles.
    2167           0 :   sort(iPar.begin(), iPar.end());
    2168           0 :   for (int i = 0;i < int(iPar.size() -1); ++i) {
    2169           0 :     if (iPar[i] == iPar[i + 1]) {
    2170           0 :       iPar.erase(iPar.begin() + i);
    2171           0 :       i--;
    2172           0 :     }
    2173             :   }
    2174             : 
    2175             :   // If no partons are connected to the junction system
    2176             :   // (or it was not a junction system).
    2177           0 :   if (int(iPar.size()) == 0) return 0;
    2178             : 
    2179           0 :   Vec4 p = event[iPar[0]].p();
    2180           0 :   for (int i = 1; i < int(iPar.size()); ++i)
    2181           0 :     p += event[iPar[i]].p();
    2182             : 
    2183           0 :   return p.mCalc();
    2184             : 
    2185           0 : }
    2186             : 
    2187             : // ------------------------------------------------------------------
    2188             : 
    2189             : // Find all particles connected to a junction system for junctions stored in
    2190             : // the event record.
    2191             : 
    2192             : void ColourReconnection::addJunctionIndices(Event & event, int col,
    2193             :   vector<int> &iPar, vector<int> &usedJuncs) {
    2194             : 
    2195             :   // Find the junction.
    2196           0 :   vector<int> juncs;
    2197           0 :   for (int j = 0;j < event.sizeJunction(); ++j) {
    2198           0 :     for (int k = 0; k < 3; ++k) {
    2199           0 :       if (event.colJunction(j,k) == col) {
    2200           0 :         juncs.push_back(j);
    2201           0 :         break;
    2202             :       }
    2203             :     }
    2204             :   }
    2205             : 
    2206             :   // Check if they were already used.
    2207           0 :   for (int i = 0;i < int(juncs.size()); ++i) {
    2208           0 :     for (int j = 0;j < int(usedJuncs.size()); ++j)  {
    2209           0 :       if (juncs[i] == usedJuncs[j]) {
    2210           0 :         juncs.erase(juncs.begin() + i);
    2211           0 :         i--;
    2212           0 :         break;
    2213             :       }
    2214             :     }
    2215             :   }
    2216             : 
    2217             :   // If list of junctions is empty return.
    2218           0 :   if (juncs.size() == 0) return;
    2219             : 
    2220             :   // Store the juncstions as used.
    2221           0 :   for (int i = 0;i < int(juncs.size()); ++i)
    2222           0 :     usedJuncs.push_back(juncs[i]);
    2223             : 
    2224             :   // Find the partons connected to it.
    2225           0 :   for (int iJunc = 0; iJunc < int(juncs.size()); ++iJunc) {
    2226           0 :     int iTempPars[3] = {-1,-1,-1};
    2227           0 :     int cols[3]  = {event.colJunction(juncs[iJunc],0),
    2228           0 :       event.colJunction(juncs[iJunc],1), event.colJunction(juncs[iJunc],2)};
    2229             : 
    2230             :     // Store the first time the colour appear.
    2231           0 :     for (int i = 0;i < event.size(); ++i) {
    2232           0 :       for (int j = 0;j < 3; ++j) {
    2233           0 :         if (iTempPars[j] == -1 && event.kindJunction(juncs[iJunc]) % 2 == 1 &&
    2234           0 :             event[i].col() == cols[j]) iTempPars[j] = i;
    2235           0 :         if (iTempPars[j] == -1 && event.kindJunction(juncs[iJunc]) % 2 == 0 &&
    2236           0 :             event[i].acol() == cols[j]) iTempPars[j] = i;
    2237             :       }
    2238             :     }
    2239             : 
    2240           0 :     for (int i = 0;i < 3;++i) {
    2241           0 :       if (iTempPars[i] >= 0) iPar.push_back(iTempPars[i]);
    2242           0 :       else addJunctionIndices(event, cols[i], iPar, usedJuncs);
    2243             :     }
    2244           0 :   }
    2245             : 
    2246             :   // Done.
    2247           0 : }
    2248             : 
    2249             : // ------------------------------------------------------------------
    2250             : 
    2251             : // Find all particles connected to a junction system.
    2252             : 
    2253             : void ColourReconnection::addJunctionIndices(int iSinglePar, vector<int> &iPar,
    2254             :   vector<int> &usedJuncs) {
    2255             : 
    2256             :   // Check if junction was already considered.
    2257           0 :   int iJun = -(1 + iSinglePar/10);
    2258           0 :   for (int i = 0;i < int(usedJuncs.size()); ++i)
    2259           0 :     if (iJun == usedJuncs[i]) return;
    2260             : 
    2261             :   // Add particles connected to the junction.
    2262           0 :   usedJuncs.push_back(iJun);
    2263           0 :   for (int i = 0; i < 3; ++i)
    2264           0 :     if (junctions[iJun].kind() % 2 == 1) {
    2265           0 :       int iCol = junctions[iJun].dips[i]->iCol;
    2266           0 :       if (iCol >= 0) iPar.push_back(iCol);
    2267           0 :       else addJunctionIndices(iCol, iPar, usedJuncs);
    2268           0 :     } else {
    2269           0 :       int iAcol = junctions[iJun].dips[i]->iAcol;
    2270           0 :       if (iAcol >= 0) iPar.push_back(iAcol);
    2271           0 :       else addJunctionIndices(iAcol, iPar, usedJuncs);
    2272           0 :     }
    2273           0 : }
    2274             : 
    2275             : // ------------------------------------------------------------------
    2276             : 
    2277             : // Calculate the invariant mass of a dipole.
    2278             : 
    2279             : double ColourReconnection::mDip(ColourDipole* dip) {
    2280             : 
    2281             :   // If double junction no invariant mass is given.
    2282           0 :   if (dip->isJun && dip->isAntiJun) return 1e9;
    2283             :   // If it has a single junction end.
    2284           0 :   else if (dip->isJun || dip->isAntiJun) {
    2285           0 :     int iJun, i0, i1, i2, junLeg0, junLeg1, junLeg2;
    2286           0 :     getJunctionIndices(dip, iJun, i0, i1, i2, junLeg0, junLeg1, junLeg2);
    2287           0 :     if (i0 == i1)
    2288           0 :       return particles[i0].m();
    2289           0 :     if (i1 < 0)
    2290           0 :       return 1e9;
    2291           0 :     return m(particles[i0].p(),particles[i1].p());
    2292           0 :   } // No junction ends.
    2293             :   else {
    2294           0 :     if (dip->iCol == dip->iAcol)
    2295           0 :       return particles[dip->iCol].m();
    2296             :     else
    2297           0 :       return m(particles[dip->iCol].p(),particles[dip->iAcol].p());
    2298             :   }
    2299             : 
    2300           0 : }
    2301             : 
    2302             : // ------------------------------------------------------------------
    2303             : 
    2304             : // Print dipoles, intended for debuggning purposes.
    2305             : 
    2306             : void ColourReconnection::listDipoles(bool onlyActive, bool onlyReal) {
    2307             : 
    2308           0 :   cout << " --- listing dipoles ---" << endl;
    2309           0 :   for (int i = 0; i < int(dipoles.size()); ++i) {
    2310           0 :     if (onlyActive && !dipoles[i]->isActive)
    2311             :       continue;
    2312           0 :     if (onlyReal && !dipoles[i]->isReal)
    2313             :       continue;
    2314           0 :     dipoles[i]->print();
    2315           0 :   }
    2316           0 :   cout << " --- finished listing ---" << endl;
    2317             : 
    2318           0 : }
    2319             : 
    2320             : // ------------------------------------------------------------------
    2321             : 
    2322             : // Print particles, intended for debugging purposes.
    2323             : 
    2324             : void ColourReconnection::listParticles() {
    2325             : 
    2326           0 :   for (int i = 0; i < int(particles.size()); ++i) {
    2327           0 :     const ColourParticle& pt = particles[i];
    2328             : 
    2329             :     // Basic line for a particle, always printed.
    2330           0 :     cout << setw(6) << i << setw(10) << pt.id() << "   " << left
    2331           0 :        << setw(18) << pt.nameWithStatus(18) << right << setw(4)
    2332           0 :        << pt.status() << setw(6) << pt.mother1() << setw(6)
    2333           0 :        << pt.mother2() << setw(6) << pt.daughter1() << setw(6)
    2334           0 :        << pt.daughter2() << setw(6) << pt.col() << setw(6) << pt.acol()
    2335           0 :        << setprecision(3)
    2336           0 :        << setw(11) << pt.px() << setw(11) << pt.py() << setw(11)
    2337           0 :        << pt.pz() << setw(11) << pt.e() << setw(11) << pt.m();
    2338           0 :     for (int j = 0;j < int(pt.activeDips.size());++j)
    2339           0 :       cout << setw(10) << pt.activeDips[j];
    2340           0 :     cout << "\n";
    2341             :   }
    2342             : 
    2343           0 : }
    2344             : 
    2345             : // ------------------------------------------------------------------
    2346             : 
    2347             : // Print junctions, intended for debugging purposes.
    2348             : 
    2349             : void ColourReconnection::listJunctions() {
    2350             : 
    2351           0 :   cout << " --- listing junctions ---" << endl;
    2352           0 :   for (int i = 0; i < int(junctions.size()); ++i)
    2353           0 :     junctions[i].print();
    2354           0 :   cout << " --- finished listing ---" << endl;
    2355             : 
    2356           0 : }
    2357             : 
    2358             : // ------------------------------------------------------------------
    2359             : 
    2360             : // Allow colour reconnections by mergings of MPI collision subsystems.
    2361             : // iRec is system that may be reconnected, by moving its gluons to iSys,
    2362             : // where minimal pT (or equivalently Lambda) is used to pick location.
    2363             : // Therefore all dipoles in iSys have to be found, and all gluons in iRec.
    2364             : // Matching q-qbar pairs are treated by analogy with gluons.
    2365             : // Note: owing to rescatterings some outgoing partons must be skipped.
    2366             : 
    2367             : bool ColourReconnection::reconnectMPIs( Event&  event, int oldSize) {
    2368             : 
    2369             :   // References to beams to simplify indexing.
    2370           0 :   BeamParticle& beamA = *beamAPtr;
    2371           0 :   BeamParticle& beamB = *beamBPtr;
    2372             : 
    2373             :   // Prepare record of which systems should be merged onto another.
    2374             :   // The iSys system must have colour in final state to attach to it.
    2375           0 :   nSys = partonSystemsPtr->sizeSys();
    2376           0 :   vector<int>  iMerge(nSys);
    2377           0 :   vector<bool> hasColour(nSys);
    2378           0 :   for (int iSys = 0; iSys < nSys; ++iSys) {
    2379           0 :     iMerge[iSys] = iSys;
    2380             :     bool hasCol = false;
    2381           0 :     for (int iMem = 0; iMem < partonSystemsPtr->sizeOut(iSys); ++iMem) {
    2382           0 :       int iNow = partonSystemsPtr->getOut( iSys, iMem);
    2383           0 :       if (event[iNow].isFinal() && (event[iNow].col() > 0
    2384           0 :         || event[iNow].acol() > 0) ) {
    2385             :         hasCol = true;
    2386           0 :         break;
    2387             :       }
    2388           0 :     }
    2389           0 :     hasColour[iSys] = hasCol;
    2390             :   }
    2391             : 
    2392             :   // Loop over systems to decide which should be reconnected.
    2393           0 :   for (int iRec = nSys - 1; iRec > 0; --iRec) {
    2394             : 
    2395             :     // Determine reconnection strength from pT scale of system.
    2396           0 :     double pT2Rec  = pow2( partonSystemsPtr->getPTHat(iRec) );
    2397           0 :     double probRec = pT20Rec / (pT20Rec + pT2Rec);
    2398             : 
    2399             :     // Loop over other systems iSys at higher pT scale and
    2400             :     // decide whether to reconnect the iRec gluons onto one of them.
    2401           0 :     for (int iSys = iRec - 1; iSys >= 0; --iSys)
    2402           0 :     if (hasColour[iSys] && probRec > rndmPtr->flat()) {
    2403             : 
    2404             :       // The iRec system and all merged with it to be merged with iSys.
    2405           0 :       iMerge[iRec] = iSys;
    2406           0 :       for (int iRec2 = iRec + 1; iRec2 < nSys; ++iRec2)
    2407           0 :       if (iMerge[iRec2] == iRec) iMerge[iRec2] = iSys;
    2408             : 
    2409             :       // Once a system has been merged do not test it anymore.
    2410           0 :       break;
    2411             :     }
    2412             :   }
    2413             : 
    2414             :   // Loop over systems. Check whether other systems to be merged with it.
    2415           0 :   for (int iSys = 0; iSys < nSys; ++iSys) {
    2416             :     int nMerge = 0;
    2417           0 :     for (int iRec = iSys + 1; iRec < nSys; ++iRec)
    2418           0 :     if (iMerge[iRec] == iSys) ++nMerge;
    2419           0 :     if (nMerge == 0) continue;
    2420             : 
    2421             :     // Incoming partons not counted if rescattered.
    2422           0 :     int  iInASys = partonSystemsPtr->getInA(iSys);
    2423           0 :     bool hasInA  = (beamA[iSys].isFromBeam());
    2424           0 :     int  iInBSys = partonSystemsPtr->getInB(iSys);
    2425           0 :     bool hasInB  = (beamB[iSys].isFromBeam());
    2426             : 
    2427             :     // Begin find dipoles in iSys system.
    2428           0 :     vector<BeamDipole> bmdipoles;
    2429           0 :     int sizeOut = partonSystemsPtr->sizeOut(iSys);
    2430           0 :     for (int iMem = 0; iMem < sizeOut; ++iMem) {
    2431             : 
    2432             :       // Find colour dipoles to beam remnant.
    2433           0 :       int iNow = partonSystemsPtr->getOut( iSys, iMem);
    2434           0 :       if (!event[iNow].isFinal()) continue;
    2435           0 :       int col = event[iNow].col();
    2436           0 :       if (col > 0) {
    2437           0 :         if      (hasInA && event[iInASys].col() == col)
    2438           0 :           bmdipoles.push_back( BeamDipole( col, iNow, iInASys ) );
    2439           0 :         else if (hasInB && event[iInBSys].col() == col)
    2440           0 :           bmdipoles.push_back( BeamDipole( col, iNow, iInBSys ) );
    2441             : 
    2442             :         // Find colour dipole between final-state partons.
    2443           0 :         else for (int iMem2 = 0; iMem2 < sizeOut; ++iMem2)
    2444           0 :         if (iMem2 != iMem) {
    2445           0 :           int iNow2 = partonSystemsPtr->getOut( iSys, iMem2);
    2446           0 :           if (!event[iNow2].isFinal()) continue;
    2447           0 :           if (event[iNow2].acol() == col) {
    2448           0 :             bmdipoles.push_back( BeamDipole( col, iNow, iNow2) );
    2449           0 :             break;
    2450             :           }
    2451           0 :         }
    2452             :       }
    2453             : 
    2454             :       // Find anticolour dipoles to beam remnant.
    2455           0 :       int acol = event[iNow].acol();
    2456           0 :       if (acol > 0) {
    2457           0 :         if      (hasInA && event[iInASys].acol() == acol)
    2458           0 :           bmdipoles.push_back( BeamDipole( acol, iInASys, iNow ) );
    2459           0 :         else if (hasInB && event[iInBSys].acol() == acol)
    2460           0 :           bmdipoles.push_back( BeamDipole( acol, iInBSys, iNow ) );
    2461             :       }
    2462           0 :     }
    2463             : 
    2464             :     // Skip mergings if no dipoles found.
    2465           0 :     if (bmdipoles.size() == 0) continue;
    2466             : 
    2467             :     // Find dipole sizes.
    2468           0 :     for (int iDip = 0; iDip < int(bmdipoles.size()); ++iDip)
    2469           0 :       bmdipoles[iDip].p1p2 = event[bmdipoles[iDip].iCol].p()
    2470           0 :                            * event[bmdipoles[iDip].iAcol].p();
    2471             : 
    2472             :     // Loop over systems iRec to be merged with iSys.
    2473           0 :     for (int iRec = iSys + 1; iRec < nSys; ++iRec) {
    2474           0 :       if (iMerge[iRec] != iSys) continue;
    2475             : 
    2476             :       // Information on iRec. Vectors for gluons and anything else.
    2477           0 :       int sizeRec = partonSystemsPtr->sizeOut(iRec);
    2478           0 :       int iInARec = partonSystemsPtr->getInA(iRec);
    2479           0 :       int iInBRec = partonSystemsPtr->getInB(iRec);
    2480             :       int nGluRec = 0;
    2481           0 :       vector<int>    iGluRec;
    2482           0 :       vector<double> pT2GluRec;
    2483             :       int nAnyRec = 0;
    2484           0 :       vector<int>    iAnyRec;
    2485           0 :       vector<bool>   freeAnyRec;
    2486             : 
    2487             :       // Copy of gluon positions in descending order.
    2488           0 :       for (int iMem = 0; iMem < sizeRec; ++iMem) {
    2489           0 :         int iNow = partonSystemsPtr->getOut( iRec, iMem);
    2490           0 :         if (!event[iNow].isFinal()) continue;
    2491           0 :         if (event[iNow].isGluon()) {
    2492           0 :           ++nGluRec;
    2493           0 :           iGluRec.push_back( iNow );
    2494           0 :           pT2GluRec.push_back( event[iNow].pT2() );
    2495           0 :           for (int i = nGluRec - 1; i > 1; --i) {
    2496           0 :             if (pT2GluRec[i - 1] > pT2GluRec[i]) break;
    2497           0 :             swap(   iGluRec[i - 1],   iGluRec[i] );
    2498           0 :             swap( pT2GluRec[i - 1], pT2GluRec[i] );
    2499             :           }
    2500             :         // Copy of anything else, mainly quarks, in no particular order.
    2501           0 :         } else {
    2502           0 :           ++nAnyRec;
    2503           0 :           iAnyRec.push_back( iNow );
    2504           0 :           freeAnyRec.push_back( true );
    2505             :         }
    2506           0 :       }
    2507             : 
    2508             :       // For each gluon in iRec now find the dipole that gives the smallest
    2509             :       // (pGlu * pI) (pGlu * pJ) / (pI * pJ), i.e. minimal pT (and Lambda).
    2510           0 :       for (int iGRec = 0; iGRec < nGluRec; ++iGRec) {
    2511           0 :         int    iGlu      = iGluRec[iGRec];
    2512           0 :         Vec4   pGlu      = event[iGlu].p();
    2513             :         int    iDipMin   = 0;
    2514           0 :         double pT2DipMin = sCM;
    2515           0 :         for (int iDip = 0; iDip < int(bmdipoles.size()); ++iDip) {
    2516           0 :           double pT2Dip = (pGlu * event[bmdipoles[iDip].iCol].p())
    2517           0 :             * (pGlu * event[bmdipoles[iDip].iAcol].p()) / bmdipoles[iDip].p1p2;
    2518           0 :           if (pT2Dip < pT2DipMin) {
    2519             :             iDipMin   = iDip;
    2520             :             pT2DipMin = pT2Dip;
    2521           0 :           }
    2522             :         }
    2523             : 
    2524             :         // Attach the gluon to the dipole, i.e. split the dipole in two.
    2525           0 :         int colGlu   = event[iGlu].col();
    2526           0 :         int acolGlu  = event[iGlu].acol();
    2527           0 :         int colDip   = bmdipoles[iDipMin].col;
    2528           0 :         int iColDip  = bmdipoles[iDipMin].iCol;
    2529           0 :         int iAcolDip = bmdipoles[iDipMin].iAcol;
    2530           0 :         event[iGlu].acol( colDip );
    2531           0 :         if (event[iAcolDip].acol() == colDip)
    2532           0 :              event[iAcolDip].acol( colGlu );
    2533           0 :         else event[iAcolDip].col(  colGlu );
    2534           0 :         bmdipoles[iDipMin].iAcol = iGlu;
    2535           0 :         bmdipoles[iDipMin].p1p2 = event[iColDip].p() * pGlu;
    2536           0 :         bmdipoles.push_back( BeamDipole( colGlu, iGlu, iAcolDip ) );
    2537           0 :         bmdipoles.back().p1p2 = pGlu * event[iAcolDip].p();
    2538             : 
    2539             :         // Remove gluon from old system: reconnect colours.
    2540           0 :         for (int i = oldSize; i < event.size(); ++i)
    2541           0 :         if (i != iGlu && i != iAcolDip) {
    2542           0 :           if (event[i].isFinal()) {
    2543           0 :             if (event[i].acol() == colGlu) event[i].acol( acolGlu );
    2544             :           } else {
    2545           0 :               if (event[i].col()  == colGlu) event[i].col( acolGlu );
    2546             :           }
    2547             :         }
    2548             : 
    2549             :         // Update any junction legs that match reconnected dipole.
    2550           0 :         for (int iJun = 0; iJun < event.sizeJunction(); ++iJun) {
    2551             : 
    2552             :           // Only junctions need to be updated, not antijunctions.
    2553           0 :           if (event.kindJunction(iJun) % 2 == 0) continue;
    2554           0 :           for (int leg = 0; leg < 3; ++leg) {
    2555           0 :             int col = event.colJunction(iJun, leg);
    2556           0 :             if (col == colDip)
    2557           0 :               event.colJunction(iJun, leg, colGlu);
    2558             :           }
    2559           0 :         }
    2560             : 
    2561           0 :       }
    2562             : 
    2563             :       // See if any matching quark-antiquark pairs among the rest.
    2564           0 :       for (int iQRec = 0; iQRec < nAnyRec; ++iQRec) {
    2565           0 :         int iQ  = iAnyRec[iQRec];
    2566           0 :         int idQ = event[iQ].id();
    2567           0 :         if (freeAnyRec[iQRec] && idQ > 0 && idQ < 6)
    2568           0 :         for (int iQbarRec = 0; iQbarRec < nAnyRec; ++iQbarRec) {
    2569           0 :           int iQbar  = iAnyRec[iQbarRec];
    2570           0 :           if (freeAnyRec[iQbarRec] && event[iQbar].id() == -idQ) {
    2571             : 
    2572             :             // Check that these can be traced back to same gluon splitting.
    2573             :             // For now also avoid qqbar pairs produced in rescatterings.??
    2574           0 :             int iTopQ    = event[iQ].iTopCopyId();
    2575           0 :             int iTopQbar = event[iQbar].iTopCopyId();
    2576           0 :             int iMother  = event[iTopQ].mother1();
    2577           0 :             if (event[iTopQbar].mother1() == iMother
    2578           0 :               && event[iMother].isGluon() && event[iMother].status() != -34
    2579           0 :               && event[iMother + 1].status() != -34 ) {
    2580             : 
    2581             :               // Now find the dipole that gives the smallest
    2582             :               // ((pQ + pQbar) * pI) ((pQ + pQbar) * pJ) / (pI * pJ).
    2583           0 :               Vec4   pGlu      = event[iQ].p() + event[iQbar].p();
    2584             :               int    iDipMin   = 0;
    2585           0 :               double pT2DipMin = sCM;
    2586           0 :               for (int iDip = 0; iDip < int(bmdipoles.size()); ++iDip) {
    2587           0 :                 double pT2Dip = (pGlu * event[bmdipoles[iDip].iCol].p())
    2588           0 :                   * (pGlu * event[bmdipoles[iDip].iAcol].p())
    2589           0 :                   / bmdipoles[iDip].p1p2;
    2590           0 :                 if (pT2Dip < pT2DipMin) {
    2591             :                   iDipMin   = iDip;
    2592             :                   pT2DipMin = pT2Dip;
    2593           0 :                 }
    2594             :               }
    2595             : 
    2596             :               // Attach the q-qbar pair to the dipole, i.e. split the dipole.
    2597           0 :               int colGlu   = event[iQ].col();
    2598           0 :               int acolGlu  = event[iQbar].acol();
    2599           0 :               int colDip   = bmdipoles[iDipMin].col;
    2600           0 :               int iColDip  = bmdipoles[iDipMin].iCol;
    2601           0 :               int iAcolDip = bmdipoles[iDipMin].iAcol;
    2602           0 :               event[iQbar].acol( colDip );
    2603           0 :               if (event[iAcolDip].acol() == colDip)
    2604           0 :                    event[iAcolDip].acol( colGlu );
    2605           0 :               else event[iAcolDip].col(  colGlu );
    2606           0 :               bmdipoles[iDipMin].iAcol = iQbar;
    2607           0 :               bmdipoles[iDipMin].p1p2 = event[iColDip].p() * event[iQbar].p();
    2608           0 :               bmdipoles.push_back( BeamDipole( colGlu, iQ, iAcolDip ) );
    2609           0 :               bmdipoles.back().p1p2 = event[iQ].p() * event[iAcolDip].p();
    2610             : 
    2611             :               // Remove q-qbar pair from old system: reconnect colours.
    2612           0 :               freeAnyRec[iQRec]    = false;
    2613           0 :               freeAnyRec[iQbarRec] = false;
    2614           0 :               for (int i = oldSize; i < event.size(); ++i)
    2615           0 :               if (i != iQRec && i != iQbarRec && i != iColDip
    2616           0 :                 && i != iAcolDip) {
    2617           0 :                 if (event[i].isFinal()) {
    2618           0 :                   if (event[i].acol() == colGlu) event[i].acol( acolGlu );
    2619             :                 } else {
    2620           0 :                     if (event[i].col()  == colGlu) event[i].col( acolGlu );
    2621             :                 }
    2622             :               }
    2623             : 
    2624             :               // Update any junction legs that match reconnected dipole.
    2625           0 :               for (int iJun = 0; iJun < event.sizeJunction(); ++iJun) {
    2626             : 
    2627             :                 // Only junctions need to be updated, not antijunctions.
    2628           0 :                 if (event.kindJunction(iJun) % 2 == 0) continue;
    2629           0 :                 for (int leg = 0; leg < 3; ++leg) {
    2630           0 :                   int col = event.colJunction(iJun, leg);
    2631           0 :                   if (col == colDip)
    2632           0 :                     event.colJunction(iJun, leg, colGlu);
    2633             :                 }
    2634           0 :               }
    2635             : 
    2636             :               // Done with processing of q-qbar pairs.
    2637           0 :             }
    2638           0 :           }
    2639           0 :         }
    2640             :       }
    2641             : 
    2642             :       // If only two beam gluons left of system, set their colour = anticolour.
    2643             :       // Used by BeamParticle::remnantColours to skip irrelevant gluons.
    2644           0 :       if ( event[iInARec].isGluon() && !event[iInARec].isRescatteredIncoming()
    2645           0 :         && event[iInBRec].isGluon() && !event[iInBRec].isRescatteredIncoming()
    2646           0 :         && event[iInARec].col() == event[iInBRec].acol()
    2647           0 :         && event[iInARec].acol() == event[iInBRec].col() ) {
    2648           0 :           event[iInARec].acol( event[iInARec].col() );
    2649           0 :           event[iInBRec].acol( event[iInBRec].col() );
    2650           0 :       }
    2651             : 
    2652             :     // End of loops over iRec and iSys systems.
    2653           0 :     }
    2654           0 :   }
    2655             : 
    2656             :   // Done.
    2657             :   return true;
    2658           0 : }
    2659             : 
    2660             : //--------------------------------------------------------------------------
    2661             : 
    2662             : // Find the neighbour to the anticolour side. Return false if the dipole
    2663             : // is connected to a junction or the new particle has a junction inside of it.
    2664             : 
    2665             : bool ColourReconnection::findAntiNeighbour(ColourDipole*& dip) {
    2666             :   // If only one active dipole, it has to be an antiquark.
    2667           0 :   if (int(particles[dip->iAcol].activeDips.size())  == 1)
    2668           0 :     return false;
    2669             : 
    2670             :   // Has to have to active dipoles, otherwise something went wrong.
    2671           0 :   if (int(particles[dip->iAcol].activeDips.size())  != 2) {
    2672           0 :     infoPtr->errorMsg("Warning in ColourReconnection::findAntiNeighbour: "
    2673             :                       "Wrong number of active dipoles");
    2674           0 :     return false;
    2675             :   }
    2676             : 
    2677             :   // Otherwise find new dipole.
    2678           0 :   if (dip == particles[dip->iAcol].activeDips[0])
    2679           0 :     dip = particles[dip->iAcol].activeDips[1];
    2680           0 :   else dip = particles[dip->iAcol].activeDips[0];
    2681             : 
    2682             :   // Do not allow the new dipole to be connected to an antijunction.
    2683           0 :   if (dip->isAntiJun || dip->isJun)
    2684           0 :     return false;
    2685             : 
    2686             :   // Do not allow new dipole to have a pseudoparticle with
    2687             :   // a baryon number inside.
    2688           0 :   if (int(particles[dip->iAcol].dips.size()) != 1)
    2689           0 :     return false;
    2690             : 
    2691           0 :   return true;
    2692           0 : }
    2693             : 
    2694             : //--------------------------------------------------------------------------
    2695             : 
    2696             : // Check that trials do not contain junctions/ unusable pseudoparticles.
    2697             : 
    2698             : bool ColourReconnection::checkJunctionTrials() {
    2699           0 :   for (int i = 0;i < int(junTrials.size());++i) {
    2700             :     int minus = 0;
    2701           0 :     if (junTrials[i].mode == 3)
    2702           0 :       minus = 1;
    2703           0 :     for (int j = 0;j < int(junTrials[i].dips.size()) - minus; ++j) {
    2704           0 :       ColourDipole* dip = junTrials[i].dips[j];
    2705           0 :       if (dip->isJun || dip->isAntiJun) {
    2706           0 :         junTrials[i].list();
    2707           0 :         return false;
    2708             :       }
    2709           0 :       if (particles[dip->iCol].dips.size() != 1 ||
    2710           0 :           particles[dip->iAcol].dips.size() != 1) {
    2711           0 :         junTrials[i].list();
    2712           0 :         return false;
    2713             :       }
    2714           0 :     }
    2715           0 :   }
    2716           0 :   return true;
    2717           0 : }
    2718             : 
    2719             : 
    2720             : //--------------------------------------------------------------------------
    2721             : 
    2722             : // Find the neighbour to the colour side. Return false if the dipole
    2723             : // is connected to a junction or the new particle has a junction inside of it.
    2724             : 
    2725             : bool ColourReconnection::findColNeighbour(ColourDipole*& dip) {
    2726             :   // If only one active dipole, it has to be an antiquark.
    2727           0 :   if (int(particles[dip->iCol].activeDips.size())  == 1)
    2728           0 :     return false;
    2729             : 
    2730             :   // Has to have to active dipoles, otherwise something went wrong.
    2731           0 :   if (int(particles[dip->iCol].activeDips.size())  != 2) {
    2732           0 :     infoPtr->errorMsg("Warning in ColourReconnection::findAntiNeighbour: "
    2733             :                       "Wrong number of active dipoles");
    2734           0 :     return false;
    2735             :   }
    2736             :   // Otherwise find new dipole.
    2737           0 :   if (dip == particles[dip->iCol].activeDips[0])
    2738           0 :     dip = particles[dip->iCol].activeDips[1];
    2739           0 :   else dip = particles[dip->iCol].activeDips[0];
    2740             : 
    2741             :   // Do not allow the new dipole to be connected to an antijunction.
    2742           0 :   if (dip->isJun || dip->isAntiJun)
    2743           0 :     return false;
    2744             : 
    2745             :   // Do not allow new dipole to have a pseudoparticle with
    2746             :   // a baryon number inside.
    2747           0 :   if (int(particles[dip->iCol].dips.size()) != 1)
    2748           0 :     return false;
    2749             : 
    2750           0 :   return true;
    2751           0 : }
    2752             : 
    2753             : //--------------------------------------------------------------------------
    2754             : 
    2755             : // Store used dipoles for a junction formation.
    2756             : 
    2757             : void ColourReconnection::storeUsedDips(TrialReconnection& trial) {
    2758             :   // Normal dipole swap.
    2759           0 :   if (trial.mode == 5) {
    2760             : 
    2761           0 :     for (int i = 0;i < 2; ++i) {
    2762           0 :       ColourDipole* dip = trial.dips[i];
    2763           0 :       if (dip->iCol < 0)
    2764           0 :         for (int j = 0;j < 3; ++j)
    2765           0 :         usedDipoles.push_back(junctions[-(dip->iCol / 10 + 1)].getColDip(j));
    2766           0 :       if (dip->iAcol < 0)
    2767           0 :         for (int j = 0;j < 3; ++j)
    2768           0 :         usedDipoles.push_back(junctions[-(dip->iAcol / 10 + 1)].getColDip(j));
    2769             : 
    2770           0 :       usedDipoles.push_back(dip);
    2771           0 :     }
    2772             : 
    2773           0 :   } else {
    2774             : 
    2775           0 :     for (int i = 0;i < 4; ++i) {
    2776           0 :       if (trial.mode == 3 && i == 3)
    2777             :         continue;
    2778           0 :       usedDipoles.push_back(trial.dips[i]);
    2779           0 :       ColourDipole* dip = trial.dips[i];
    2780             : 
    2781             : 
    2782           0 :       while (findAntiNeighbour(dip) && dip != trial.dips[i])
    2783           0 :         usedDipoles.push_back(dip);
    2784             : 
    2785           0 :       dip = trial.dips[i];
    2786           0 :       while (findColNeighbour(dip) && dip != trial.dips[i])
    2787           0 :         usedDipoles.push_back(dip);
    2788           0 :     }
    2789             :   }
    2790           0 : }
    2791             : 
    2792             : //--------------------------------------------------------------------------
    2793             : 
    2794             : // Calculate the difference between the old and new lambda for dipole swap.
    2795             : 
    2796             : double ColourReconnection::getLambdaDiff(ColourDipole* dip1,
    2797             :   ColourDipole* dip2) {
    2798             : 
    2799             :   // Needed to make sure the same dipoles are compared.
    2800           0 :   vector<ColourDipole*> oldDips, newDips;
    2801             : 
    2802             :   // Calculate old string length.
    2803           0 :   double oldLambda = calculateStringLength(dip1, oldDips)
    2804           0 :     + calculateStringLength( dip2, oldDips);
    2805             : 
    2806             :   // Make test configuration.
    2807           0 :   swapDipoles(dip1,dip2);
    2808             : 
    2809             :  // Calculate new string lengths
    2810           0 :   double newLambda = calculateStringLength(dip1, newDips)
    2811           0 :     +  calculateStringLength(dip2, newDips);
    2812             : 
    2813             :   // Swap back.
    2814           0 :   swapDipoles(dip1, dip2, true);
    2815             : 
    2816             :   // First check if new combination was not useable.
    2817           0 :   if (newLambda >= 0.5E9 || newLambda < 1.) return -1e9;
    2818             : 
    2819             :   // Return the difference.
    2820           0 :   return oldLambda - newLambda;
    2821           0 : }
    2822             : 
    2823             : //--------------------------------------------------------------------------
    2824             : 
    2825             : // Calculate the difference between the old and new lambda.
    2826             : 
    2827             : double ColourReconnection::getLambdaDiff(ColourDipole* dip1,
    2828             :   ColourDipole* dip2, ColourDipole* dip3, ColourDipole* dip4, int mode) {
    2829             : 
    2830             :   // Calculate old lambda measure.
    2831             : 
    2832           0 :   double oldLambda = calculateStringLength(dip1->iCol, dip1->iAcol)
    2833           0 :     + calculateStringLength(dip2->iCol, dip2->iAcol);
    2834           0 :   if (dip3 != dip1)
    2835           0 :     oldLambda += calculateStringLength(dip3->iCol, dip3->iAcol);
    2836           0 :   if (dip4 != 0 && dip4 != dip2)
    2837           0 :     oldLambda += calculateStringLength(dip4->iCol, dip4->iAcol);
    2838             : 
    2839             :   // Calculate new lambda.
    2840             :   double newLambda = 0;
    2841             : 
    2842           0 :   if (mode == 0)
    2843           0 :       newLambda = calculateDoubleJunctionLength(dip1->iCol, dip2->iCol,
    2844           0 :                                                 dip1->iAcol, dip2->iAcol);
    2845           0 :   else if (mode == 1) {
    2846           0 :     if (dip2 == dip4)
    2847           0 :       newLambda = calculateJunctionLength(dip1->iCol, dip2->iCol, dip3->iCol)
    2848           0 :         + calculateJunctionLength(dip1->iAcol, dip2->iAcol, dip3->iAcol);
    2849             :     else
    2850             :       newLambda = calculateJunctionLength(dip1->iCol, dip2->iCol, dip3->iCol)
    2851           0 :         + calculateJunctionLength(dip2->iAcol, dip3->iAcol, dip4->iAcol)
    2852           0 :           + calculateStringLength(dip4->iCol, dip1->iAcol);
    2853             :   }
    2854             : 
    2855           0 :   else if (mode == 2) {
    2856           0 :     if (dip1 == dip3)
    2857           0 :       newLambda = calculateJunctionLength(dip1->iCol, dip2->iCol, dip4->iCol)
    2858           0 :         + calculateJunctionLength(dip1->iAcol, dip2->iAcol, dip4->iAcol);
    2859             :     else
    2860             :       newLambda = calculateJunctionLength(dip1->iCol, dip2->iCol, dip4->iCol)
    2861           0 :           + calculateJunctionLength(dip1->iAcol, dip3->iAcol, dip4->iAcol)
    2862           0 :           + calculateStringLength(dip3->iCol, dip2->iAcol);
    2863             :   }
    2864             : 
    2865             :   // Triple junction connection.
    2866           0 :   else if (mode == 3)
    2867           0 :     newLambda = calculateJunctionLength(dip1->iCol, dip2->iCol, dip3->iCol)
    2868           0 :       + calculateJunctionLength(dip1->iAcol, dip2->iAcol, dip3->iAcol);
    2869             : 
    2870             :   // First check if new combination was not useable.
    2871           0 :   if (newLambda >= 0.5E9 || newLambda < 1.) return -1e9;
    2872             : 
    2873             :   // Returning result.
    2874           0 :   return oldLambda - newLambda;
    2875             : 
    2876           0 : }
    2877             : 
    2878             : //--------------------------------------------------------------------------
    2879             : 
    2880             : // Change colour structure to describe the reconnection in juncTrial.
    2881             : 
    2882             : void ColourReconnection::doDipoleTrial(TrialReconnection& trial) {
    2883             : 
    2884             :   // Store for easier use.
    2885           0 :   ColourDipole* dip1 = trial.dips[0];
    2886           0 :   ColourDipole* dip2 = trial.dips[1];
    2887             : 
    2888             :   // If both acols ends are normal particles.
    2889           0 :   if (dip1->iAcol >= 0 && dip2->iAcol >= 0) {
    2890           0 :     swap(particles[dip1->iAcol].dips[dip1->iAcolLeg].front()->iAcol,
    2891           0 :          particles[dip2->iAcol].dips[dip2->iAcolLeg].front()->iAcol);
    2892           0 :     swap(particles[dip1->iAcol].dips[dip1->iAcolLeg].front(),
    2893           0 :          particles[dip2->iAcol].dips[dip2->iAcolLeg].front());
    2894             :   // If only dip1 has normal acol end.
    2895           0 :   } else if (dip1->iAcol >= 0) {
    2896           0 :     swap(particles[dip1->iAcol].dips[dip1->iAcolLeg].front()->iAcol,
    2897           0 :        junctions[-(dip2->iAcol / 10 + 1)].dipsOrig[-dip2->iAcol % 10]->iAcol);
    2898           0 :     swap(particles[dip1->iAcol].dips[dip1->iAcolLeg].front(),
    2899           0 :          junctions[-(dip2->iAcol / 10 + 1)].dipsOrig[-dip2->iAcol % 10]);
    2900             :   // If only dip2 has normal acol end.
    2901           0 :   } else if (dip2->iAcol >= 0) {
    2902           0 :     swap(particles[dip2->iAcol].dips[dip2->iAcolLeg].front()->iAcol,
    2903           0 :        junctions[-(dip1->iAcol / 10 + 1)].dipsOrig[-dip1->iAcol % 10]->iAcol);
    2904           0 :     swap(particles[dip2->iAcol].dips[dip2->iAcolLeg].front(),
    2905           0 :          junctions[-(dip1->iAcol / 10 + 1)].dipsOrig[-dip1->iAcol % 10]);
    2906             :   // If both ends are junctions.
    2907           0 :   } else {
    2908           0 :     swap(junctions[ -(dip1->iAcol / 10 + 1) ].dipsOrig[
    2909           0 :            -dip1->iAcol % 10 ]->iAcol,
    2910           0 :          junctions[ -(dip2->iAcol / 10 + 1) ].dipsOrig[
    2911           0 :            -dip2->iAcol % 10 ]->iAcol);
    2912           0 :     swap(junctions[ -(dip1->iAcol / 10 + 1) ].dipsOrig[ -dip1->iAcol % 10],
    2913           0 :          junctions[ -(dip2->iAcol / 10 + 1) ].dipsOrig[ -dip2->iAcol % 10] );
    2914             :   }
    2915             : 
    2916             :   // Swap the dipoles.
    2917           0 :   swapDipoles(dip1, dip2);
    2918             : 
    2919             :   // If new particles are below treshhold, form pseudoParticles.
    2920           0 :   if (mDip(dip1) < m0) makePseudoParticle(dip1, 110, true);
    2921           0 :   if (mDip(dip2) < m0) makePseudoParticle(dip2, 110, true);
    2922             : 
    2923             :   // Done.
    2924             : 
    2925           0 : }
    2926             : 
    2927             : //--------------------------------------------------------------------------
    2928             : 
    2929             : // Update the list of dipole trial swaps to account for latest swap.
    2930             : 
    2931             : void ColourReconnection::updateDipoleTrials() {
    2932             : 
    2933             :   // Remove any dipTrials that contains an used dipole.
    2934           0 :   for (int i = 0; i < int(dipTrials.size()); ++i)
    2935           0 :     for (int j = 0;j < 2; ++j) {
    2936           0 :       if (binary_search(usedDipoles.begin(), usedDipoles.end(),
    2937           0 :                        dipTrials[i].dips[j]) ) {
    2938           0 :         dipTrials.erase(dipTrials.begin() + i);
    2939           0 :         i--;
    2940           0 :         break;
    2941             :       }
    2942             :     }
    2943             : 
    2944             :   // Make list of active dipoles.
    2945           0 :   vector<ColourDipole*> activeDipoles;
    2946           0 :   for (int i = 0;i < int(dipoles.size()); ++i)
    2947           0 :     if (dipoles[i]->isActive)
    2948           0 :       activeDipoles.push_back(dipoles[i]);
    2949             : 
    2950             :   // Loop over list of used dipoles and create new trial reconnections.
    2951           0 :   for (int i = 0;i < int(usedDipoles.size()); ++i)
    2952           0 :     if (usedDipoles[i]->isActive)
    2953           0 :       for (int j = 0; j < int(activeDipoles.size()); ++j)
    2954           0 :         singleReconnection(usedDipoles[i], activeDipoles[j]);
    2955             : 
    2956           0 : }
    2957             : 
    2958             : //--------------------------------------------------------------------------
    2959             : 
    2960             : // Update the list of dipole trial swaps to account for latest swap.
    2961             : 
    2962             : void ColourReconnection::updateJunctionTrials() {
    2963             : 
    2964             :  // Remove any junTrials that contains an used dipole.
    2965           0 :   for (int i = 0; i < int(junTrials.size()); ++i)
    2966           0 :     for (int j = 0; j < 4; ++j) {
    2967           0 :       if (binary_search(usedDipoles.begin(), usedDipoles.end(),
    2968           0 :                        junTrials[i].dips[j]) ) {
    2969           0 :         junTrials.erase(junTrials.begin() + i);
    2970           0 :         i--;
    2971           0 :         break;
    2972             :       }
    2973             :     }
    2974             : 
    2975             :   // Make list of active dipoles.
    2976           0 :   vector<ColourDipole*> activeDipoles;
    2977           0 :   for (int i = 0;i < int(dipoles.size()); ++i)
    2978           0 :     if (dipoles[i]->isActive)
    2979           0 :       activeDipoles.push_back(dipoles[i]);
    2980             : 
    2981             :   // Loop over used dipoles and form new junction trials.
    2982           0 :   for (int i = 0;i < int(usedDipoles.size()); ++i)
    2983           0 :     if (usedDipoles[i]->isActive)
    2984           0 :       for (int j = 0; j < int(activeDipoles.size()); ++j)
    2985           0 :         singleJunction(usedDipoles[i], activeDipoles[j]);
    2986             : 
    2987             :   // Loop over used dipoles and form new junction trials.
    2988           0 :   for (int i = 0;i < int(usedDipoles.size()); ++i)
    2989           0 :     if (usedDipoles[i]->isActive)
    2990           0 :       for (int j = 0; j < int(activeDipoles.size()); ++j)
    2991           0 :         for (int k = j + 1; k < int(activeDipoles.size()); ++k)
    2992           0 :           singleJunction(usedDipoles[i], activeDipoles[j], activeDipoles[k]);
    2993             : 
    2994           0 : }
    2995             : 
    2996             : //--------------------------------------------------------------------------
    2997             : 
    2998             : // Change colour structure to describe the reconnection in juncTrial.
    2999             : 
    3000             : void ColourReconnection::doJunctionTrial(Event& event,
    3001             :   TrialReconnection& juncTrial) {
    3002             : 
    3003           0 :   int mode = juncTrial.mode;
    3004             :   // If trial mode is 3 (three dipoles -> 2 junctions) use its own update.
    3005           0 :   if (mode == 3) {
    3006           0 :     doTripleJunctionTrial(event, juncTrial);
    3007           0 :     return;
    3008             :   }
    3009             : 
    3010             :   // Store dipoles and numbers for easier acces.
    3011           0 :   ColourDipole* dip1 = juncTrial.dips[0];
    3012           0 :   ColourDipole* dip2 = juncTrial.dips[1];
    3013           0 :   ColourDipole* dip3 = juncTrial.dips[2];
    3014           0 :   ColourDipole* dip4 = juncTrial.dips[3];
    3015             : 
    3016           0 :   int iCol1 = dip1->iCol;
    3017           0 :   int iCol2 = dip2->iCol;
    3018           0 :   int iCol3 = dip3->iCol;
    3019           0 :   int iCol4 = dip4->iCol;
    3020           0 :   int iAcol1 = dip1->iAcol;
    3021           0 :   int iAcol2 = dip2->iAcol;
    3022           0 :   int iAcol3 = dip3->iAcol;
    3023           0 :   int iAcol4 = dip4->iAcol;
    3024             : 
    3025           0 :   int oldCol1 = dip1->col;
    3026           0 :   int oldCol2 = dip2->col;
    3027           0 :   int oldCol3 = dip3->col;
    3028           0 :   int oldCol4 = dip4->col;
    3029             : 
    3030             :   // New colour tags needed, since three more dipoles will be made.
    3031           0 :   int newCol1 = event.nextColTag();
    3032           0 :   int newCol2 = event.nextColTag();
    3033           0 :   int newCol3 = event.nextColTag();
    3034             : 
    3035             :   // Add new formation times.
    3036           0 :   double mCalc = (particles[iCol1].p() + particles[iAcol1].p() +
    3037           0 :                   particles[iCol2].p() + particles[iAcol2].p() +
    3038           0 :                   particles[iCol3].p() + particles[iAcol3].p() +
    3039           0 :                   particles[iCol4].p() + particles[iAcol4].p()).mCalc();
    3040           0 :   formationTimes[newCol1] = mCalc;
    3041           0 :   formationTimes[newCol2] = mCalc;
    3042           0 :   formationTimes[newCol3] = mCalc;
    3043             : 
    3044             :   // Need to make 3 new real dipoles and 3 active dipoles.
    3045             : 
    3046             :   // First make dipoles between junctions.
    3047             : 
    3048             :   // Find the junction colour.
    3049           0 :   int junCol = 3 * (3 - (dip1->colReconnection / 3)
    3050           0 :              - (dip2->colReconnection / 3) ) + dip1->colReconnection % 3;
    3051             : 
    3052             :   // if other than 9 colours.
    3053           0 :   if (nReconCols != 9) {
    3054           0 :     while (junCol < 0 || junCol % 3 != dip1->colReconnection % 3 ||
    3055           0 :            junCol == dip1->colReconnection || junCol == dip2->colReconnection)
    3056           0 :       junCol = int(nReconCols * rndmPtr->flat());
    3057             :   }
    3058             :   // Need one active and one real dipole.
    3059           0 :   int iJun = junctions.size();
    3060           0 :   int iAntiJun = junctions.size() + 1;
    3061             : 
    3062             :   // Store real dipoles.
    3063           0 :   ColourDipole* dip3real = particles[iCol3].dips[dip3->iColLeg].back();
    3064           0 :   ColourDipole* dip4real = particles[iCol4].dips[dip4->iColLeg].back();
    3065             : 
    3066             :   // If the junction and antijunction are directly connected.
    3067             :   int iActive1 = 0, iReal1 = 0;
    3068           0 :   if (mode == 0) {
    3069           0 :     dipoles.push_back(new ColourDipole(newCol1, -( iAntiJun * 10 + 10 + 2) ,
    3070           0 :       -( iJun * 10 + 10 + 2), junCol, true, true, false, true));
    3071           0 :     iReal1 = dipoles.size() - 1;
    3072           0 :     dipoles.push_back(new ColourDipole(newCol1, -( iAntiJun * 10 + 10 + 2) ,
    3073             :       -( iJun * 10 + 10 + 2), junCol, true, true));
    3074           0 :     iActive1 = dipoles.size() - 1;
    3075           0 :   } else if (mode == 1) {
    3076           0 :     int iCol3real = particles[iCol3].dips[dip3->iColLeg].back()->iCol;
    3077           0 :      dipoles.push_back(new ColourDipole(newCol1, iCol3real ,
    3078           0 :       -( iJun * 10 + 10 + 2), junCol, true, false, false, true));
    3079           0 :     iReal1 = dipoles.size() - 1;
    3080           0 :     particles[iCol3].dips[dip3->iColLeg].back() = dipoles.back();
    3081           0 :     dipoles.push_back(new ColourDipole(newCol1, dip3->iCol,
    3082             :       -( iJun * 10 + 10 + 2), junCol, true, false));
    3083           0 :     iActive1 = dipoles.size() - 1;
    3084           0 :   } else if (mode == 2) {
    3085           0 :     int iCol4real = particles[iCol4].dips[dip4->iColLeg].back()->iCol;
    3086           0 :     dipoles.push_back(new ColourDipole(newCol1, iCol4real,
    3087           0 :       -( iJun * 10 + 10 + 2), junCol, true, false, false, true));
    3088           0 :     iReal1 = dipoles.size() - 1;
    3089           0 :     particles[iCol4].dips[dip4->iColLeg].back() = dipoles.back();
    3090           0 :     dipoles.push_back(new ColourDipole(newCol1, dip4->iCol,
    3091             :       -( iJun * 10 + 10 + 2), junCol, true, false));
    3092           0 :     iActive1 = dipoles.size() - 1;
    3093           0 :   }
    3094             : 
    3095             :   // Now make dipole between anti junction and iAcol1.
    3096             :   // Start by finding real iAcol.
    3097           0 :   int iAcol3real  = particles[iAcol3].dips[dip3->iAcolLeg].front()->iAcol;
    3098           0 :   dipoles.push_back(new ColourDipole(newCol2, -( iAntiJun * 10 + 10),
    3099           0 :     iAcol3real, dip3->colReconnection, false, true, false, true));
    3100           0 :   int iReal2 = dipoles.size() - 1;
    3101           0 :   particles[iAcol3].dips[dip3->iAcolLeg].front() = dipoles.back();
    3102             : 
    3103           0 :   dipoles.push_back(new ColourDipole(newCol2, -( iAntiJun * 10 + 10),
    3104           0 :     iAcol3, dip3->colReconnection, false, true));
    3105           0 :   dipoles.back()->iAcolLeg = dip3->iAcolLeg;
    3106           0 :   int iActive2 = dipoles.size() - 1;
    3107             : 
    3108             :   // Now make dipole between anti junction and iAcol1.
    3109             :   // Start by finding real iAcol.
    3110           0 :   int iAcol4real = particles[iAcol4].dips[dip4->iAcolLeg].front()->iAcol;
    3111           0 :   dipoles.push_back(new ColourDipole(newCol3, -( iAntiJun * 10 + 10 + 1),
    3112           0 :     iAcol4real, dip4->colReconnection, false, true, false, true));
    3113           0 :   int iReal3 = dipoles.size() - 1;
    3114           0 :   particles[iAcol4].dips[dip4->iAcolLeg].front() = dipoles.back();
    3115             : 
    3116           0 :   dipoles.push_back(new ColourDipole(newCol3, -( iAntiJun * 10 + 10 + 1),
    3117           0 :     iAcol4, dip4->colReconnection, false, true));
    3118           0 :   dipoles.back()->iAcolLeg = dip4->iAcolLeg;
    3119           0 :   int iActive3 = dipoles.size() - 1;
    3120             : 
    3121             :   // Update already existing dipoles, start by internal dipoles.
    3122             :   // Now take dipoles connected to the anti junction
    3123             :   // and a possible gluon-gluon connection.
    3124           0 :   if (mode == 1) {
    3125           0 :     if (dip2 == dip4) {
    3126             : 
    3127             :       // Update real dipole.
    3128           0 :       dip3real->iAcol = particles[dip1->iAcol].dips[dip1->iAcolLeg].
    3129           0 :         front()->iAcol;
    3130           0 :       dip3real->iCol  = -( iAntiJun * 10 + 10 + 2);
    3131           0 :       dip3real->isAntiJun = true;
    3132             : 
    3133             :       // Update active dipoles.
    3134           0 :       dip3->iAcol = dip1->iAcol;
    3135           0 :       dip3->iAcolLeg = dip1->iAcolLeg;
    3136           0 :       dip3->isAntiJun = true;
    3137           0 :       dip3->iCol = -( iAntiJun * 10 + 10 + 2);
    3138           0 :       dip3->iColLeg = 0;
    3139             : 
    3140             :       // Store real dipole
    3141           0 :       particles[dip3->iAcol].dips[dip3->iAcolLeg].front() = dip3real;
    3142             : 
    3143           0 :     } else {
    3144             : 
    3145             :       // Update real dipole.
    3146           0 :       dip3real->iAcol = particles[dip2->iAcol].dips[dip2->iAcolLeg].
    3147           0 :         front()->iAcol;
    3148           0 :       dip3real->iCol  = -( iAntiJun * 10 + 10 + 2);
    3149           0 :       dip3real->isAntiJun = true;
    3150           0 :       dip4real->iAcol = particles[dip1->iAcol].dips[dip1->iAcolLeg].
    3151           0 :         front()->iAcol;
    3152             : 
    3153             :       // Change the dipole connected to the antijunction.
    3154           0 :       dip3->iAcol = dip2->iAcol;
    3155           0 :       dip3->iAcolLeg = dip2->iAcolLeg;
    3156           0 :       dip3->isAntiJun = true;
    3157           0 :       dip3->iCol = -( iAntiJun * 10 + 10 + 2);
    3158           0 :       dip3->iColLeg = 0;
    3159             : 
    3160             :       // Change the dipole between the two gluons.
    3161           0 :       dip4->iAcol = dip1->iAcol;
    3162           0 :       dip4->iAcolLeg = dip1->iAcolLeg;
    3163             : 
    3164             :       // Store real dipole
    3165           0 :       particles[dip3->iAcol].dips[dip3->iAcolLeg].front() = dip3real;
    3166           0 :       particles[dip4->iAcol].dips[dip4->iAcolLeg].front() = dip4real;
    3167             : 
    3168             :     }
    3169           0 :   } else if (mode == 2) {
    3170           0 :     if (dip1 == dip3) {
    3171             : 
    3172             :       // Update real dipole.
    3173           0 :       dip4real->iAcol = particles[dip2->iAcol].dips[dip2->iAcolLeg].
    3174           0 :         front()->iAcol;
    3175           0 :       dip4real->iCol  = -( iAntiJun * 10 + 10 + 2);
    3176           0 :       dip4real->isAntiJun = true;
    3177             : 
    3178             :       // Update active dipoles.
    3179           0 :       dip4->iAcol = dip2->iAcol;
    3180           0 :       dip4->iAcolLeg = dip2->iAcolLeg;
    3181           0 :       dip4->isAntiJun = true;
    3182           0 :       dip4->iCol = -( iAntiJun * 10 + 10 + 2);
    3183           0 :       dip4->iColLeg = 0;
    3184             : 
    3185             :       // Store real dipole
    3186           0 :       particles[dip4->iAcol].dips[dip4->iAcolLeg].front() = dip4real;
    3187             : 
    3188           0 :     } else {
    3189             : 
    3190             :       // Update real dipole.
    3191           0 :       dip4real->iAcol = particles[dip1->iAcol].dips[dip1->iAcolLeg].
    3192           0 :         front()->iAcol;
    3193           0 :       dip4real->iCol  = -( iAntiJun * 10 + 10 + 2);
    3194           0 :       dip4real->isAntiJun = true;
    3195           0 :       dip3real->iAcol = particles[dip2->iAcol].dips[dip2->iAcolLeg].
    3196           0 :         front()->iAcol;
    3197             : 
    3198             :       // Change the dipole connected to the antijunction.
    3199           0 :       dip4->iAcol = dip1->iAcol;
    3200           0 :       dip4->iAcolLeg = dip1->iAcolLeg;
    3201           0 :       dip4->isAntiJun = true;
    3202           0 :       dip4->iCol = -( iAntiJun * 10 + 10 + 2);
    3203           0 :       dip4->iColLeg = 0;
    3204             : 
    3205             :       // Change the dipole between the two gluons.
    3206           0 :       dip3->iAcol = dip2->iAcol;
    3207           0 :       dip3->iAcolLeg = dip2->iAcolLeg;
    3208             : 
    3209             :       // Store real dipole
    3210           0 :       particles[dip3->iAcol].dips[dip3->iAcolLeg].front() = dip3real;
    3211           0 :       particles[dip4->iAcol].dips[dip4->iAcolLeg].front() = dip4real;
    3212             :     }
    3213             :   }
    3214             : 
    3215             :   // Dipoles connected to the junction.
    3216             :   // Update real dipoles.
    3217           0 :   particles[iCol1].dips[dip1->iColLeg].back()->iAcol = - (iJun * 10 + 10);
    3218           0 :   particles[iCol2].dips[dip2->iColLeg].back()->iAcol = - (iJun * 10 + 10 + 1);
    3219           0 :   particles[iCol1].dips[dip1->iColLeg].back()->isJun = true;
    3220           0 :   particles[iCol2].dips[dip2->iColLeg].back()->isJun = true;
    3221             : 
    3222             :   // Update active dipoles.
    3223           0 :   dip1->isJun = true;
    3224           0 :   dip2->isJun = true;
    3225           0 :   dip1->iAcol = - (iJun * 10 + 10);
    3226           0 :   dip2->iAcol = - (iJun * 10 + 10 + 1);
    3227           0 :   dip1->iAcolLeg = 0;
    3228           0 :   dip2->iAcolLeg = 0;
    3229             : 
    3230             :   // Update active dipoles for anti particles.
    3231             :   // Normally should only contain active dipoles once,
    3232             :   // only problem is if the two dipole ends are the same particle.
    3233             :   // Start by settings common dipoles.
    3234           0 :   for (int i = 0; i < int(particles[iAcol3].activeDips.size()); ++i)
    3235           0 :     if (particles[iAcol3].activeDips[i] == dip3) {
    3236           0 :       particles[iAcol3].activeDips[i] = dipoles[iActive2];
    3237           0 :       break;
    3238             :     }
    3239             : 
    3240           0 :   for (int i = 0; i < int(particles[iAcol4].activeDips.size()); ++i)
    3241           0 :     if (particles[iAcol4].activeDips[i] == dip4) {
    3242           0 :       particles[iAcol4].activeDips[i] = dipoles[iActive3];
    3243           0 :     break;
    3244             :     }
    3245             : 
    3246             :   // Depending on how the new string is connected, the active dipoles vary.
    3247           0 :   if (mode == 1) {
    3248           0 :     for (int i = 0; i < int(particles[iCol3].activeDips.size()); ++i)
    3249           0 :       if (particles[iCol3].activeDips[i] == dip3) {
    3250           0 :         particles[iCol3].activeDips[i] = dipoles[iActive1];
    3251           0 :         break;
    3252             :       }
    3253             : 
    3254           0 :     if (dip2 == dip4) {
    3255           0 :       for (int i = 0; i < int(particles[iAcol1].activeDips.size()); ++i)
    3256           0 :         if (particles[iAcol1].activeDips[i] == dip1) {
    3257           0 :           particles[iAcol1].activeDips[i] = dip3;
    3258           0 :           break;
    3259             :         }
    3260           0 :     } else {
    3261           0 :       for (int i = 0; i < int(particles[iAcol2].activeDips.size()); ++i)
    3262           0 :         if (particles[iAcol2].activeDips[i] == dip2) {
    3263           0 :           particles[iAcol2].activeDips[i] = dip3;
    3264           0 :           break;
    3265             :         }
    3266             : 
    3267           0 :       for (int i = 0; i < int(particles[iAcol1].activeDips.size()); ++i)
    3268           0 :         if (particles[iAcol1].activeDips[i] == dip1) {
    3269           0 :           particles[iAcol1].activeDips[i] = dip4;
    3270           0 :           break;
    3271             :         }
    3272             :     }
    3273           0 :   } else if (mode == 2) {
    3274           0 :     for (int i = 0; i < int(particles[iCol4].activeDips.size()); ++i)
    3275           0 :       if (particles[iCol4].activeDips[i] == dip4) {
    3276           0 :         particles[iCol4].activeDips[i] = dipoles[iActive1];
    3277           0 :         break;
    3278             :       }
    3279             : 
    3280           0 :     if (dip1 == dip3) {
    3281           0 :       for (int i = 0; i < int(particles[iAcol2].activeDips.size()); ++i)
    3282           0 :         if (particles[iAcol2].activeDips[i] == dip2) {
    3283           0 :           particles[iAcol2].activeDips[i] = dip4;
    3284           0 :           break;
    3285             :         }
    3286           0 :     } else {
    3287           0 :       for (int i = 0; i < int(particles[iAcol1].activeDips.size()); ++i)
    3288           0 :         if (particles[iAcol1].activeDips[i] == dip1) {
    3289           0 :           particles[iAcol1].activeDips[i] = dip4;
    3290           0 :           break;
    3291             :         }
    3292             : 
    3293           0 :       for (int i = 0; i < int(particles[iAcol2].activeDips.size()); ++i)
    3294           0 :         if (particles[iAcol2].activeDips[i] == dip2) {
    3295           0 :           particles[iAcol2].activeDips[i] = dip3;
    3296           0 :           break;
    3297             :         }
    3298             :     }
    3299             :   }
    3300             : 
    3301             :   // Add the junctions to the event.
    3302           0 :   junctions.push_back(Junction(1, oldCol1, oldCol2, newCol1));
    3303           0 :   if (mode == 0) junctions.push_back(Junction(2, newCol2, newCol3, newCol1));
    3304           0 :   else if (mode == 1)
    3305           0 :     junctions.push_back(Junction(2, newCol2, newCol3, oldCol3));
    3306           0 :   else if (mode == 2)
    3307           0 :     junctions.push_back(Junction(2, newCol2, newCol3, oldCol4));
    3308             : 
    3309             :   // Set junction information.
    3310           0 :   junctions[iJun].dipsOrig[0] =
    3311           0 :     particles[iCol1].dips[dip1->iColLeg].back();
    3312           0 :   junctions[iJun].dipsOrig[1] =
    3313           0 :     particles[iCol2].dips[dip2->iColLeg].back();
    3314           0 :   junctions[iJun].dipsOrig[2] = dipoles[iReal1];
    3315           0 :   junctions[iJun].dips[0] = dip1;
    3316           0 :   junctions[iJun].dips[1] = dip2;
    3317           0 :   junctions[iJun].dips[2] = dipoles[iActive1];
    3318             : 
    3319             :   // Set anti junction information.
    3320           0 :   junctions[iAntiJun].dips[0] = dipoles[iActive2];
    3321           0 :   junctions[iAntiJun].dips[1] = dipoles[iActive3];
    3322           0 :   junctions[iAntiJun].dipsOrig[0] = dipoles[iReal2];
    3323           0 :   junctions[iAntiJun].dipsOrig[1] = dipoles[iReal3];
    3324             : 
    3325           0 :   if (mode == 0) {
    3326           0 :     junctions[iAntiJun].dips[2] = dipoles[iActive1];
    3327           0 :     junctions[iAntiJun].dipsOrig[2] = dipoles[iReal1];
    3328           0 :   } else if (mode == 1) {
    3329           0 :     junctions[iAntiJun].dips[2] = dip3;
    3330           0 :     junctions[iAntiJun].dipsOrig[2] =
    3331           0 :       particles[dip3->iAcol].dips[dip3->iAcolLeg].front();
    3332           0 :   } else if (mode == 2) {
    3333           0 :     junctions[iAntiJun].dips[2] = dip4;
    3334           0 :     junctions[iAntiJun].dipsOrig[2] =
    3335           0 :       particles[dip4->iAcol].dips[dip4->iAcolLeg].front();
    3336           0 :   }
    3337             : 
    3338             :   // Make pseudo particles.
    3339           0 :   if (dip1->isActive && mDip(dip1) < m0)
    3340           0 :     makePseudoParticle(dip1, 110, true);
    3341           0 :   if (dip2->isActive && mDip(dip2) < m0)
    3342           0 :     makePseudoParticle(dip2, 110, true);
    3343           0 :   if (dip3->isActive && mDip(dip3) < m0)
    3344           0 :     makePseudoParticle(dip3, 110, true);
    3345           0 :   if (dip4->isActive && mDip(dip4) < m0)
    3346           0 :     makePseudoParticle(dip4, 110, true);
    3347             : 
    3348           0 :   if (dipoles[iActive1]->isActive && mDip(dipoles[iActive1]) < m0)
    3349           0 :     makePseudoParticle(dipoles[iActive1], 110, true);
    3350           0 :   if (dipoles[iActive2]->isActive && mDip(dipoles[iActive2]) < m0)
    3351           0 :     makePseudoParticle(dipoles[iActive2], 110, true);
    3352           0 :   if (dipoles[iActive3]->isActive && mDip(dipoles[iActive3]) < m0)
    3353           0 :     makePseudoParticle(dipoles[iActive3], 110, true);
    3354             : 
    3355             :   // Add new dipoles to usedDipoles.
    3356           0 :   usedDipoles.push_back(dipoles[iActive1]);
    3357           0 :   usedDipoles.push_back(dipoles[iActive2]);
    3358           0 :   usedDipoles.push_back(dipoles[iActive3]);
    3359             : 
    3360             :   // Done.
    3361           0 : }
    3362             : 
    3363             : //--------------------------------------------------------------------------
    3364             : 
    3365             : // Change colour structure if it is three dipoles forming a junction system.
    3366             : 
    3367             : void ColourReconnection::doTripleJunctionTrial(Event& event,
    3368             :   TrialReconnection& juncTrial) {
    3369             : 
    3370             :   // store information for easier acces.
    3371           0 :   ColourDipole* dip1 = juncTrial.dips[0];
    3372           0 :   ColourDipole* dip2 = juncTrial.dips[1];
    3373           0 :   ColourDipole* dip3 = juncTrial.dips[2];
    3374             : 
    3375             :   // Store indices.
    3376           0 :   int iCol1 = dip1->iCol;
    3377           0 :   int iCol2 = dip2->iCol;
    3378           0 :   int iCol3 = dip3->iCol;
    3379           0 :   int iAcol1 = dip1->iAcol;
    3380           0 :   int iAcol2 = dip2->iAcol;
    3381           0 :   int iAcol3 = dip3->iAcol;
    3382             : 
    3383             :   // Store colours
    3384           0 :   int oldCol1 = dip1->col;
    3385           0 :   int oldCol2 = dip2->col;
    3386           0 :   int oldCol3 = dip3->col;
    3387           0 :   int newCol1 = event.nextColTag();
    3388           0 :   int newCol2 = event.nextColTag();
    3389           0 :   int newCol3 = event.nextColTag();
    3390             : 
    3391             :   // Store new junction indices.
    3392           0 :   int iJun = junctions.size();
    3393           0 :   int iAntiJun = junctions.size() + 1;
    3394             : 
    3395             :   // Now make dipole between anti junction and iAcol1.
    3396             :   // Start by finding real iAcol.
    3397             :   int iAcol1real
    3398           0 :     = particles[iAcol1].dips[dip1->iAcolLeg].front()->iAcol;
    3399           0 :   dipoles.push_back(new ColourDipole(newCol1, -( iAntiJun * 10 + 10),
    3400           0 :     iAcol1real, dip1->colReconnection, false, true, false, true));
    3401           0 :   int iReal1 = dipoles.size() - 1;
    3402           0 :   particles[iAcol1].dips[dip1->iAcolLeg].front() = dipoles.back();
    3403             : 
    3404           0 :   dipoles.push_back(new ColourDipole(newCol1, -( iAntiJun * 10 + 10),
    3405           0 :     iAcol1, dip1->colReconnection, false, true));
    3406           0 :   dipoles.back()->iAcolLeg = dip1->iAcolLeg;
    3407           0 :   int iActive1 = dipoles.size() - 1;
    3408             : 
    3409             :   // Now make dipole between anti junction and iAcol2.
    3410             :   // Start by finding real iAcol2.
    3411             :   int iAcol2real
    3412           0 :     = particles[iAcol2].dips[dip2->iAcolLeg].front()->iAcol;
    3413           0 :   dipoles.push_back(new ColourDipole(newCol2, -( iAntiJun * 10 + 10 + 1),
    3414           0 :     iAcol2real, dip2->colReconnection, false, true, false, true));
    3415           0 :   int iReal2 = dipoles.size() - 1;
    3416           0 :   particles[iAcol2].dips[dip2->iAcolLeg].front() = dipoles.back();
    3417             : 
    3418           0 :   dipoles.push_back(new ColourDipole(newCol2, -( iAntiJun * 10 + 10 + 1),
    3419           0 :     iAcol2, dip2->colReconnection, false, true));
    3420           0 :   dipoles.back()->iAcolLeg = dip2->iAcolLeg;
    3421           0 :   int iActive2 = dipoles.size() - 1;
    3422             : 
    3423             :   // Now make dipole between anti junction and iAcol3.
    3424             :   // Start by finding real iAcol3.
    3425             :   int iAcol3real
    3426           0 :     = particles[iAcol3].dips[dip3->iAcolLeg].front()->iAcol;
    3427           0 :   dipoles.push_back(new ColourDipole(newCol3, -( iAntiJun * 10 + 10 + 2),
    3428           0 :     iAcol3real, dip3->colReconnection, false, true, false, true));
    3429           0 :   int iReal3 = dipoles.size() - 1;
    3430           0 :   particles[iAcol3].dips[dip3->iAcolLeg].front() = dipoles.back();
    3431             : 
    3432           0 :   dipoles.push_back(new ColourDipole(newCol3, -( iAntiJun * 10 + 10 + 2),
    3433           0 :     iAcol3, dip3->colReconnection, false, true));
    3434           0 :   dipoles.back()->iAcolLeg = dip3->iAcolLeg;
    3435           0 :   int iActive3 = dipoles.size() - 1;
    3436             : 
    3437             :   // Update already existing dipoles.
    3438             : 
    3439             :   // Update real dipoles.
    3440           0 :   particles[iCol1].dips[dip1->iColLeg].back()->iAcol = - (iJun * 10 + 10);
    3441           0 :   particles[iCol2].dips[dip2->iColLeg].back()->iAcol = - (iJun * 10 + 10 + 1);
    3442           0 :   particles[iCol3].dips[dip3->iColLeg].back()->iAcol = - (iJun * 10 + 10 + 2);
    3443           0 :   particles[iCol1].dips[dip1->iColLeg].back()->isJun = true;
    3444           0 :   particles[iCol2].dips[dip2->iColLeg].back()->isJun = true;
    3445           0 :   particles[iCol3].dips[dip3->iColLeg].back()->isJun = true;
    3446             : 
    3447             :   // Update active dipoles.
    3448           0 :   dip1->isJun = true;
    3449           0 :   dip2->isJun = true;
    3450           0 :   dip3->isJun = true;
    3451           0 :   dip1->iAcol = - (iJun * 10 + 10);
    3452           0 :   dip2->iAcol = - (iJun * 10 + 10 + 1);
    3453           0 :   dip3->iAcol = - (iJun * 10 + 10 + 2);
    3454           0 :   dip1->iAcolLeg = 0;
    3455           0 :   dip2->iAcolLeg = 0;
    3456           0 :   dip3->iAcolLeg = 0;
    3457             : 
    3458             :   // Update active dipoles for anti particles.
    3459           0 :   for (int i = 0; i < int(particles[iAcol1].activeDips.size()); ++i)
    3460           0 :     if (particles[iAcol1].activeDips[i] == dip1)
    3461           0 :       particles[iAcol1].activeDips[i] = dipoles[iActive1];
    3462           0 :   for (int i = 0; i < int(particles[iAcol2].activeDips.size()); ++i)
    3463           0 :     if (particles[iAcol2].activeDips[i] == dip2)
    3464           0 :       particles[iAcol2].activeDips[i] = dipoles[iActive2];
    3465           0 :   for (int i = 0; i < int(particles[iAcol3].activeDips.size()); ++i)
    3466           0 :     if (particles[iAcol3].activeDips[i] == dip3)
    3467           0 :       particles[iAcol3].activeDips[i] = dipoles[iActive3];
    3468             : 
    3469             :   // Add the junctions to the event.
    3470           0 :   junctions.push_back(Junction(1, oldCol1, oldCol2, oldCol3));
    3471           0 :   junctions.push_back(Junction(2, newCol1, newCol3, newCol3));
    3472             : 
    3473             :   // Update junction ends.
    3474           0 :   junctions[iJun].dipsOrig[0] =
    3475           0 :     particles[iCol1].dips[dip1->iColLeg].back();
    3476           0 :   junctions[iJun].dipsOrig[1] =
    3477           0 :     particles[iCol2].dips[dip2->iColLeg].back();
    3478           0 :   junctions[iJun].dipsOrig[2] =
    3479           0 :     particles[iCol3].dips[dip3->iColLeg].back();
    3480           0 :   junctions[iJun].dips[0] = dip1;
    3481           0 :   junctions[iJun].dips[1] = dip2;
    3482           0 :   junctions[iJun].dips[2] = dip3;
    3483             : 
    3484             :   // Update the anti junction.
    3485           0 :   junctions[iAntiJun].dips[0] = dipoles[iActive1];
    3486           0 :   junctions[iAntiJun].dips[1] = dipoles[iActive2];
    3487           0 :   junctions[iAntiJun].dips[2] = dipoles[iActive3];
    3488           0 :   junctions[iAntiJun].dipsOrig[0] = dipoles[iReal1];
    3489           0 :   junctions[iAntiJun].dipsOrig[1] = dipoles[iReal2];
    3490           0 :   junctions[iAntiJun].dipsOrig[2] = dipoles[iReal3];
    3491             : 
    3492             :   // Make pseudo particles if needed.
    3493           0 :   if (dip1->isActive && mDip(dip1) < m0)
    3494           0 :     makePseudoParticle(dip1, 110, true);
    3495           0 :   if (dip2->isActive && mDip(dip2) < m0)
    3496           0 :     makePseudoParticle(dip2, 110, true);
    3497           0 :   if (dip3->isActive && mDip(dip3) < m0)
    3498           0 :     makePseudoParticle(dip3, 110, true);
    3499             : 
    3500           0 :   if (dipoles[iActive1]->isActive && mDip(dipoles[iActive1]) < m0)
    3501           0 :     makePseudoParticle(dipoles[iActive1], 110, true);
    3502           0 :   if (dipoles[iActive2]->isActive && mDip(dipoles[iActive2]) < m0)
    3503           0 :     makePseudoParticle(dipoles[iActive2], 110, true);
    3504           0 :   if (dipoles[iActive3]->isActive && mDip(dipoles[iActive3]) < m0)
    3505           0 :     makePseudoParticle(dipoles[iActive3], 110, true);
    3506             : 
    3507             :   // Add to newly created dipoles to used dipoles.
    3508           0 :   usedDipoles.push_back(dipoles[iActive1]);
    3509           0 :   usedDipoles.push_back(dipoles[iActive2]);
    3510           0 :   usedDipoles.push_back(dipoles[iActive3]);
    3511             : 
    3512             :   // Done.
    3513           0 : }
    3514             : 
    3515             : //--------------------------------------------------------------------------
    3516             : 
    3517             : // Allow colour reconnections by moving gluons from their current location
    3518             : // to another colour line. Also optionally flip two colour chains.
    3519             : 
    3520             : bool ColourReconnection::reconnectMove( Event&  event, int oldSize) {
    3521             : 
    3522             :   // Create or reset arrays to prepare for the new event analysis.
    3523           0 :   vector<int> iGlu;
    3524           0 :   iReduceCol.resize( event.size() );
    3525           0 :   iExpandCol.clear();
    3526           0 :   map<int, int> colMap, acolMap;
    3527           0 :   map<int, int>::iterator colM, acolM;
    3528           0 :   vector<InfoGluonMove> infoGM;
    3529             : 
    3530             :   // Temporary variables.
    3531           0 :   int iNow            = 0;
    3532           0 :   int colNow          = 0;
    3533           0 :   int acolNow         = 0;
    3534             :   int iColNow         = 0;
    3535             :   int iAcolNow        = 0;
    3536           0 :   int col2Now         = 0;
    3537             :   int iCol2Now        = 0;
    3538             :   int iAcol2Now       = 0;
    3539             :   double lambdaRefNow = 0.;
    3540             :   double dLambdaNow   = 0.;
    3541             : 
    3542             :   // Loop over all final particles. Store (fraction of) gluons to move.
    3543           0 :   for (int i = oldSize; i < event.size(); ++i) if (event[i].isFinal()) {
    3544           0 :     if (flipMode < 3 && event[i].id() == 21 && rndmPtr->flat() < fracGluon)
    3545           0 :       iGlu.push_back(i);
    3546             : 
    3547             :     // Store location of all colour and anticolour particles and indices.
    3548           0 :     if (event[i].col() > 0 || event[i].acol() > 0) {
    3549           0 :       iReduceCol[i] = iExpandCol.size();
    3550           0 :       iExpandCol.push_back(i);
    3551           0 :       if (event[i].col() > 0) colMap[event[i].col()] = i;
    3552           0 :       if (event[i].acol() > 0) acolMap[event[i].acol()] = i;
    3553             :     }
    3554             :   }
    3555             : 
    3556             :   // Erase (anti)colours for (anti)junctions and skip adjacent gluons.
    3557           0 :   for (int iJun = 0; iJun < event.sizeJunction(); ++iJun) {
    3558           0 :     if (event.kindJunction(iJun) == 1) {
    3559           0 :       for (int j = 0; j < 3; ++j) {
    3560           0 :         int jCol = event.colJunction( iJun, j);
    3561           0 :         for (colM = colMap.begin(); colM != colMap.end(); ++colM)
    3562           0 :         if (colM->first == jCol) {
    3563           0 :           colMap.erase( colM);
    3564           0 :           break;
    3565             :         }
    3566           0 :         for (int iG = 0; iG < int(iGlu.size()); ++iG)
    3567           0 :         if (event[iGlu[iG]].col() == jCol) {
    3568           0 :           iGlu.erase(iGlu.begin() + iG);
    3569           0 :           break;
    3570             :         }
    3571             :       }
    3572           0 :     } else if (event.kindJunction(iJun) == 2) {
    3573           0 :       for (int j = 0; j < 3; ++j) {
    3574           0 :         int jCol = event.colJunction( iJun, j);
    3575           0 :         for (acolM = acolMap.begin(); acolM != acolMap.end(); ++acolM)
    3576           0 :         if (acolM->first == jCol) {
    3577           0 :           acolMap.erase( acolM);
    3578           0 :           break;
    3579             :         }
    3580           0 :         for (int iG = 0; iG < int(iGlu.size()); ++iG)
    3581           0 :         if (event[iGlu[iG]].acol() == jCol) {
    3582           0 :           iGlu.erase(iGlu.begin() + iG);
    3583           0 :           break;
    3584             :         }
    3585             :       }
    3586           0 :     }
    3587             :   }
    3588             : 
    3589             :   // Error checks.
    3590           0 :   int nGlu = iGlu.size();
    3591           0 :   int nCol = colMap.size();
    3592           0 :   if (int(acolMap.size()) != nCol) {
    3593           0 :     infoPtr->errorMsg("Error in MBReconUserHooks: map sizes do not match");
    3594           0 :     return false;
    3595             :   }
    3596           0 :   colM  = colMap.begin();
    3597           0 :   acolM = acolMap.begin();
    3598           0 :   for (int iCol = 0; iCol < nCol; ++iCol) {
    3599           0 :     if (colM->first != acolM->first) {
    3600           0 :       infoPtr->errorMsg("Error in MBReconUserHooks: map elements"
    3601             :         " do not match");
    3602           0 :       return false;
    3603             :     }
    3604           0 :     ++colM;
    3605           0 :     ++acolM;
    3606             :   }
    3607             : 
    3608             :   // Calculate and tabulate lambda between any pair of coloured partons.
    3609           0 :   nColMove = iExpandCol.size();
    3610           0 :   lambdaijMove.resize( pow2(nColMove) );
    3611           0 :   for (int iAC = 0; iAC < nColMove - 1; ++iAC) {
    3612           0 :     int i = iExpandCol[iAC];
    3613           0 :     for (int jAC = iAC + 1; jAC < nColMove; ++jAC) {
    3614           0 :       int j = iExpandCol[jAC];
    3615           0 :       lambdaijMove[nColMove * iAC + jAC]
    3616           0 :         = log(1. + m2( event[i], event[j]) / m2Lambda);
    3617             :     }
    3618             :   }
    3619             : 
    3620             :   // Set up initial possible gluon moves with lambda gains/losses.
    3621           0 :   for (int iG = 0; iG < nGlu; ++iG) {
    3622             : 
    3623             :     // Gluon and its current neighbours.
    3624           0 :     iNow     = iGlu[iG];
    3625           0 :     colNow   = event[iNow].col();
    3626           0 :     acolNow  = event[iNow].acol();
    3627           0 :     iColNow  = acolMap[colNow];
    3628           0 :     iAcolNow = colMap[acolNow];
    3629             : 
    3630             :     // Addition to Lambda of gluon in current position.
    3631           0 :     lambdaRefNow = lambda123Move( iNow, iColNow, iAcolNow);
    3632             : 
    3633             :     // Loop over all colour lines where gluon could be inserted.
    3634           0 :     for (colM = colMap.begin(); colM != colMap.end(); ++colM) {
    3635           0 :       col2Now   = colM->first;
    3636           0 :       iCol2Now  = colMap[col2Now];
    3637           0 :       iAcol2Now = acolMap[col2Now];
    3638             : 
    3639             :       // Addition to total Lambda if gluon moved to be inserted on line.
    3640           0 :       dLambdaNow = (iCol2Now == iNow || iAcol2Now == iNow
    3641           0 :         || iColNow == iAcolNow) ? 2e4
    3642           0 :         : lambda123Move( iNow, iCol2Now, iAcol2Now) - lambdaRefNow;
    3643             : 
    3644             :       // Add new container for gluon and colour line information.
    3645           0 :       infoGM.push_back( InfoGluonMove( iNow, colNow, acolNow, iColNow,
    3646           0 :         iAcolNow, col2Now, iCol2Now, iAcol2Now, lambdaRefNow, dLambdaNow ));
    3647             :     }
    3648             :   }
    3649           0 :   int nPair = infoGM.size();
    3650             : 
    3651             :   // Keep on looping over moves until no further negative dLambda.
    3652           0 :   for ( int iMove = 0; iMove < nGlu; ++iMove) {
    3653             :     int    iPairMin   = -1;
    3654             :     double dLambdaMin = 1e4;
    3655             : 
    3656             :     // Find lowest dLambda.
    3657           0 :     for (int iPair = 0; iPair < nPair; ++iPair)
    3658           0 :     if (infoGM[iPair].dLambda < dLambdaMin) {
    3659             :       iPairMin   = iPair;
    3660           0 :       dLambdaMin = infoGM[iPair].dLambda;
    3661           0 :     }
    3662             : 
    3663             :     // Break if no shift below upper limit found.
    3664           0 :     if (dLambdaMin > -dLambdaCut) break;
    3665             : 
    3666             :     // Partons and colours involved in move.
    3667           0 :     InfoGluonMove& selSM = infoGM[iPairMin];
    3668           0 :     int i1Sel     = selSM.i1;
    3669           0 :     int iCol1Sel  = selSM.iCol1;
    3670           0 :     int iAcol1Sel = selSM.iAcol1;
    3671           0 :     int iCol2Sel  = selSM.iCol2;
    3672           0 :     int iAcol2Sel = selSM.iAcol2;
    3673           0 :     int iCol2Mod[3]  = { iAcol1Sel , i1Sel     , iCol2Sel    };
    3674           0 :     int col2Mod[3]   = { selSM.col1, selSM.col2, selSM.acol1};
    3675             : 
    3676             :     // Remove gluon from old colour line and insert on new colour line.
    3677           0 :     for (int i = 0; i < 3; ++i) {
    3678           0 :       event[ iCol2Mod[i] ].col( col2Mod[i] );
    3679           0 :       colMap[ col2Mod[i] ] = iCol2Mod[i];
    3680             :     }
    3681             : 
    3682             :     // Update info for partons with new colors.
    3683             :     int  i1Now    = 0;
    3684             :     bool doUpdate = false;
    3685           0 :     for (int iPair = 0; iPair < nPair; ++iPair) {
    3686           0 :       InfoGluonMove& tmpSM = infoGM[iPair];
    3687           0 :       if (tmpSM.i1 != i1Now) {
    3688             :         i1Now = tmpSM.i1;
    3689             :         doUpdate = false;
    3690           0 :         if (i1Now == i1Sel || i1Now == iCol1Sel || i1Now == iAcol1Sel
    3691           0 :           || i1Now == iCol2Sel || i1Now == iAcol2Sel) {
    3692           0 :           colNow       = event[i1Now].col();
    3693           0 :           acolNow      = event[i1Now].acol();
    3694           0 :           iColNow      = acolMap[colNow];
    3695           0 :           iAcolNow     = colMap[acolNow];
    3696           0 :           lambdaRefNow = lambda123Move( i1Now, iColNow, iAcolNow);
    3697             :           doUpdate     = true;
    3698           0 :         }
    3699             :       }
    3700           0 :       if (doUpdate) {
    3701           0 :         tmpSM.col1      = colNow;
    3702           0 :         tmpSM.acol1     = acolNow;
    3703           0 :         tmpSM.iCol1     = iColNow;
    3704           0 :         tmpSM.iAcol1    = iAcolNow;
    3705           0 :         tmpSM.lambdaRef = lambdaRefNow;
    3706           0 :       }
    3707             :     }
    3708             : 
    3709             :     // Update info on dLambda for affected particles and colour lines.
    3710           0 :     for (int iPair = 0; iPair < nPair; ++iPair) {
    3711           0 :       InfoGluonMove& tmpSM = infoGM[iPair];
    3712             :       int iMod = -1;
    3713           0 :       for (int i = 0; i < 3; ++i) if (tmpSM.col2 == col2Mod[i]) iMod = i;
    3714           0 :       if (iMod > -1) tmpSM.iCol2 = iCol2Mod[iMod];
    3715           0 :       if (tmpSM.i1 == i1Sel || tmpSM.i1 == iCol1Sel || tmpSM.i1 == iAcol1Sel
    3716           0 :         || tmpSM.i1 == iCol2Sel || tmpSM.i1 == iAcol2Sel || iMod > -1)
    3717           0 :         tmpSM.dLambda = (tmpSM.iCol2 == tmpSM.i1 || tmpSM.iAcol2 == tmpSM.i1
    3718           0 :           || tmpSM.iCol1 == tmpSM.iAcol1) ? 2e4
    3719           0 :           : lambda123Move( tmpSM.i1, tmpSM.iCol2, tmpSM.iAcol2)
    3720           0 :           - tmpSM.lambdaRef;
    3721             :     }
    3722             : 
    3723             :   // End of loop over gluon shifting.
    3724           0 :   }
    3725             : 
    3726             :   // Done if no flip.
    3727           0 :   if (flipMode == 0) return true;
    3728             : 
    3729             :   // Array with colour lines, and where each line begins and ends.
    3730           0 :   vector<int> iTmpFlip, iVecFlip, iBegFlip, iEndFlip;
    3731             : 
    3732             :   // Variables for minimum search.
    3733             :   int i1c, i1a, i2c, i2a, i1cMin, i1aMin, i2cMin, i2aMin, iSMin;
    3734             :   double dLambdaFlip, dLambdaFlipMin;
    3735           0 :   vector<InfoGluonMove> flipMin;
    3736             : 
    3737             :   // Grab all colour ends.
    3738           0 :   for (int i = oldSize; i < event.size(); ++i)
    3739           0 :   if (event[i].isFinal() && event[i].col() > 0 && event[i].acol() == 0) {
    3740           0 :     iTmpFlip.clear();
    3741           0 :     iTmpFlip.push_back( i);
    3742             : 
    3743             :     // Step through colour neighbours to catch system.
    3744           0 :     iNow = i;
    3745           0 :     acolM = acolMap.find( event[iNow].col() );
    3746             :     bool foundEnd = false;
    3747           0 :     while (acolM != acolMap.end()) {
    3748           0 :       iNow = acolM->second;
    3749           0 :       iTmpFlip.push_back( iNow);
    3750           0 :       if (event[iNow].col() == 0) {
    3751             :         foundEnd = true;
    3752           0 :         break;
    3753             :       }
    3754           0 :       acolM = acolMap.find( event[iNow].col() );
    3755             :     }
    3756             : 
    3757             :     // Store acceptable system, optionally including junction legs.
    3758           0 :     if (foundEnd || flipMode == 2 || flipMode == 4) {
    3759           0 :       iBegFlip.push_back( iVecFlip.size());
    3760           0 :       for (int j = 0; j < int(iTmpFlip.size()); ++j)
    3761           0 :         iVecFlip.push_back( iTmpFlip[j]);
    3762           0 :       iEndFlip.push_back( iVecFlip.size());
    3763             :     }
    3764           0 :   }
    3765             : 
    3766             :   // Optionally search for antijunction legs: grab all anticolour ends.
    3767           0 :   if (flipMode == 2 || flipMode == 4)
    3768           0 :   for (int i = oldSize; i < event.size(); ++i)
    3769           0 :   if (event[i].isFinal() && event[i].acol() > 0 && event[i].col() == 0) {
    3770           0 :     iTmpFlip.clear();
    3771           0 :     iTmpFlip.push_back( i);
    3772             : 
    3773             :     // Step through anticolour neighbours to catch system.
    3774           0 :     iNow = i;
    3775           0 :     colM = colMap.find( event[iNow].acol() );
    3776             :     bool foundEnd = false;
    3777           0 :     while (colM != colMap.end()) {
    3778           0 :       iNow = colM->second;
    3779           0 :       iTmpFlip.push_back( iNow);
    3780           0 :       if (event[iNow].acol() == 0) {
    3781             :         foundEnd = true;
    3782           0 :         break;
    3783             :       }
    3784           0 :       colM = colMap.find( event[iNow].acol() );
    3785             :     }
    3786             : 
    3787             :     // Store acceptable system, but do not doublecount q - (n g) - qbar.
    3788           0 :     if (!foundEnd) {
    3789           0 :       iBegFlip.push_back( iVecFlip.size());
    3790           0 :       for (int j = 0; j < int(iTmpFlip.size()); ++j)
    3791           0 :         iVecFlip.push_back( iTmpFlip[j]);
    3792           0 :       iEndFlip.push_back( iVecFlip.size());
    3793             :     }
    3794           0 :   }
    3795             : 
    3796             :   // Loop through all system pairs.
    3797           0 :   int nSysFlip = iBegFlip.size();
    3798           0 :   for (int iSys1 = 0; iSys1 < nSysFlip - 1; ++iSys1)
    3799           0 :   if (iBegFlip[iSys1] >= 0)
    3800           0 :   for (int iSys2 = iSys1 + 1; iSys2 < nSysFlip; ++iSys2)
    3801           0 :   if (iBegFlip[iSys2] >= 0) {
    3802             :     i1cMin     = 0;
    3803             :     i1aMin     = 0;
    3804             :     i2cMin     = 0;
    3805             :     i2aMin     = 0;
    3806             :     dLambdaFlipMin = 1e4;
    3807             : 
    3808             :     // Loop through all possible flip locations for a pair.
    3809           0 :     for (int j1 = iBegFlip[iSys1]; j1 < iEndFlip[iSys1] - 1; ++j1)
    3810           0 :     for (int j2 = iBegFlip[iSys2]; j2 < iEndFlip[iSys2] - 1; ++j2) {
    3811           0 :       i1c = iVecFlip[j1];
    3812           0 :       i1a = iVecFlip[j1 + 1];
    3813           0 :       i2c = iVecFlip[j2];
    3814           0 :       i2a = iVecFlip[j2 + 1];
    3815           0 :       dLambdaFlip = lambda12Move( i1c, i2a) + lambda12Move( i2c, i1a)
    3816           0 :                   - lambda12Move( i1c, i1a) - lambda12Move( i2c, i2a);
    3817           0 :       if (dLambdaFlip < dLambdaFlipMin) {
    3818             :         i1cMin = i1c;
    3819             :         i1aMin = i1a;
    3820             :         i2cMin = i2c;
    3821             :         i2aMin = i2a;
    3822             :         dLambdaFlipMin = dLambdaFlip;
    3823           0 :       }
    3824             :     }
    3825             : 
    3826             :     // Store possible flips if low enough dLambdaMin.
    3827           0 :     if (dLambdaFlipMin < -dLambdaCut) flipMin.push_back( InfoGluonMove(
    3828           0 :       iSys1, iSys2, i1cMin, i1aMin, i2cMin, i2aMin, dLambdaFlipMin) );
    3829           0 :   }
    3830           0 :   int flipSize = flipMin.size();
    3831             : 
    3832             :   // Search for lowest possible flip among unused systems.
    3833           0 :   for (int iFlip = 0; iFlip < min( nSysFlip / 2, flipSize); ++iFlip) {
    3834             :     iSMin = -1;
    3835             :     dLambdaFlipMin  = 1e4;
    3836           0 :     for (int iSys12 = 0; iSys12 < flipSize; ++iSys12)
    3837           0 :     if (flipMin[iSys12].i1 >= 0 && flipMin[iSys12].dLambda < dLambdaFlipMin) {
    3838             :       iSMin   = iSys12;
    3839           0 :       dLambdaFlipMin = flipMin[iSys12].dLambda;
    3840           0 :     }
    3841             : 
    3842             :     // Do flip. Mark flipped systems.
    3843           0 :     if (iSMin >= 0) {
    3844           0 :       InfoGluonMove& flipNow = flipMin[iSMin];
    3845           0 :       int iS1 = flipNow.i1;
    3846           0 :       int iS2 = flipNow.i2;
    3847           0 :       event[ flipNow.iAcol1 ].acol( event[flipNow.iCol2].col() );
    3848           0 :       event[ flipNow.iAcol2 ].acol( event[flipNow.iCol1].col() );
    3849           0 :        for (int iSys12 = 0; iSys12 < flipSize; ++iSys12)
    3850           0 :       if ( flipMin[iSys12].i1 == iS1 || flipMin[iSys12].i1 == iS2
    3851           0 :         || flipMin[iSys12].i2 == iS1 || flipMin[iSys12].i2 == iS2)
    3852           0 :         flipMin[iSys12].i1 = -1;
    3853             :     }
    3854           0 :     else break;
    3855             :   }
    3856             : 
    3857             :   // Done.
    3858             :   return true;
    3859             : 
    3860           0 : }
    3861             : 
    3862             : //--------------------------------------------------------------------------
    3863             : 
    3864             : // Common code for the SK I and SK II models for WW/ZZ/WZ systems.
    3865             : 
    3866             : bool ColourReconnection::reconnectTypeCommon( Event& event, int ) {
    3867             : 
    3868             :   // Make storage containers. Check that at least two parton systems.
    3869           0 :   vector<vector< ColourDipole> > dips;
    3870           0 :   int iBosons[2];
    3871           0 :   Vec4 decays[2];
    3872           0 :   if (partonSystemsPtr->sizeSys() < 2) {
    3873           0 :     infoPtr->errorMsg("Error in ColourReconnection::reconnectTypeCommon: "
    3874             :                       "expect at least two parton systems");
    3875           0 :     return false;
    3876             :   }
    3877             : 
    3878             :   // Find the dipoles connected to their respective resonance decays.
    3879           0 :   for (int i = 0; i < 2; ++i) {
    3880           0 :     dips.push_back(vector<ColourDipole>());
    3881           0 :     int iSys = partonSystemsPtr->sizeSys() - i - 1;
    3882           0 :     for (int j = 0; j < partonSystemsPtr->sizeOut(iSys); ++j) {
    3883           0 :       int iPar = partonSystemsPtr->getOut(iSys, j);
    3884             : 
    3885             :       // Find decayed boson. Only need to do it once.
    3886           0 :       if (j == 0) {
    3887           0 :         int iMot = event[iPar].mother1();
    3888           0 :         while (iMot != 0 && event[iMot].idAbs() != 23
    3889           0 :           && event[iMot].idAbs() != 24) iMot = event[iMot].mother1();
    3890           0 :         if (iMot == 0) {
    3891           0 :           infoPtr->errorMsg("Error in ColourReconnection::reconnectTypeCommon:"
    3892             :                             " Not a resonance decay of a W/Z");
    3893           0 :           return false;
    3894             :         }
    3895           0 :         iBosons[i] = iMot;
    3896           0 :       }
    3897             : 
    3898             :       // Pick up all dipoles by starting from colour end.
    3899           0 :       int col = event[iPar].col();
    3900           0 :       if (col == 0) continue;
    3901           0 :       for (int k = 0; k <  partonSystemsPtr->sizeOut(iSys); ++k) {
    3902           0 :         int iAntiPar = partonSystemsPtr->getOut(iSys, k);
    3903           0 :         if (event[iAntiPar].acol() == col) {
    3904           0 :           dips.back().push_back(ColourDipole(col, iPar, iAntiPar));
    3905           0 :           break;
    3906             :         }
    3907           0 :       }
    3908           0 :     }
    3909           0 :   }
    3910             : 
    3911             :   // Boost system to W+W- rest frame.
    3912           0 :   Vec4 boost = event[iBosons[0]].p() + event[iBosons[1]].p();
    3913           0 :   for (int i = 1; i < event.size(); ++i) event[i].bstback(boost);
    3914             : 
    3915             :   // Find the time and position of the decay vertices.
    3916           0 :   for (int i = 0; i < 2; ++i) {
    3917           0 :     int iBoson = iBosons[i];
    3918           0 :     double mBoson = particleDataPtr->m0(event[iBoson].idAbs());
    3919           0 :     double gammaBoson = particleDataPtr->mWidth(event[iBoson].idAbs());
    3920           0 :     double mReal = event[iBoson].mCalc();
    3921           0 :     decays[i][0] = -HBAR * log(rndmPtr->flat()) * event[iBoson].e() /
    3922           0 :       sqrt(pow2(pow2(mBoson) - pow2(mReal)) + pow2(gammaBoson * pow2(mReal)
    3923           0 :       / mBoson));
    3924           0 :     for (int j = 1; j < 4; ++j)
    3925           0 :       decays[i][j] = event[iBoson].p()[j]/ event[iBoson].e() * decays[i][0];
    3926           0 :   }
    3927             : 
    3928             :   // Find the possible reconnections, depeding on choice of model.
    3929           0 :   map<double,pair<int,int> > reconnections;
    3930           0 :   if (reconnectMode == 3)
    3931           0 :     reconnections = reconnectTypeI(event, dips, decays);
    3932           0 :   else if (reconnectMode == 4)
    3933           0 :     reconnections = reconnectTypeII(event, dips, decays);
    3934             : 
    3935             :   // Carry out the reconnections.
    3936           0 :   vector<bool> used1(dips[0].size(), false), used2(dips[1].size(), false);
    3937           0 :   for (map<double,pair<int,int> >::iterator it=reconnections.begin();
    3938           0 :     it != reconnections.end(); ++it) {
    3939             : 
    3940             :     // Check if any of the dipoles already reconnected.
    3941           0 :     if (used1[it->second.first] || used2[it->second.second]) continue;
    3942             : 
    3943             :     // Do the reconnection.
    3944           0 :     int iAcol1 = dips[0][it->second.first].iAcol;
    3945           0 :     int iAcol2 = dips[1][it->second.second].iAcol;
    3946           0 :     event.copy(iAcol1, 79);
    3947           0 :     event.back().acol(event[iAcol2].acol());
    3948           0 :     event.copy(iAcol2, 79);
    3949           0 :     event.back().acol(event[iAcol1].acol());
    3950             : 
    3951             :     // Mark dipoles as used.
    3952           0 :     used1[it->second.first] = true;
    3953           0 :     used2[it->second.second] = true;
    3954             : 
    3955             :     // If only a single reconnection is wanted, break the loop.
    3956           0 :     if (singleReconOnly) break;
    3957           0 :   }
    3958             : 
    3959             :   // Boost system back to origianl rest frame.
    3960           0 :   for (int i = 1; i < event.size(); ++i) event[i].bst(boost);
    3961             : 
    3962             :   // Done.
    3963             :   return true;
    3964           0 : }
    3965             : 
    3966             : //--------------------------------------------------------------------------
    3967             : 
    3968             : // The SK I model for WW/ZZ/WZ systems.
    3969             : 
    3970             : map<double,pair<int,int> > ColourReconnection::reconnectTypeI( Event& event,
    3971             :   vector<vector<ColourDipole> > &dips, Vec4 decays[2]) {
    3972             : 
    3973             :   // Make storage containers.
    3974           0 :   multimap<double,pair<int,int> > reconnections;
    3975             : 
    3976             :   // Velocity stored as: vx  vy, vz , gamma (uses Vec4 for easy storage).
    3977           0 :   vector<vector<Vec4> > vel;
    3978             :   // string direction.
    3979           0 :   vector<vector<Vec4> > dir;
    3980             : 
    3981             :   // Calculate velocities.
    3982           0 :   for (int i = 0; i < 2; ++i) {
    3983           0 :     vel.push_back(vector<Vec4>(dips[i].size(),Vec4()));
    3984           0 :     dir.push_back(vector<Vec4>(dips[i].size(),Vec4()));
    3985           0 :     for (int j = 0; j < int(dips[i].size()); ++j) {
    3986             : 
    3987             :       // Calculate sum of momenta.
    3988           0 :       double pSumCol  = event[dips[i][j].iCol].pAbs();
    3989           0 :       double pSumAcol = event[dips[i][j].iAcol].pAbs();
    3990             : 
    3991             :       // Velocities and directions.
    3992           0 :       for (int k = 1; k < 4; ++k) {
    3993           0 :         vel[i][j][k] = 0.5 *(event[dips[i][j].iCol].p()[k] / pSumCol
    3994           0 :           + event[dips[i][j].iAcol].p()[k] / pSumAcol);
    3995           0 :         dir[i][j][k] = event[dips[i][j].iCol].p()[k] / pSumCol
    3996           0 :           - event[dips[i][j].iAcol].p()[k] / pSumAcol;
    3997             :       }
    3998           0 :       vel[i][j][0] = 1/sqrt(1 - vel[i][j].pAbs2());
    3999           0 :       dir[i][j] /= dir[i][j].pAbs();
    4000             : 
    4001             :     }
    4002             :   }
    4003             : 
    4004             :   // Select random point.
    4005             :   int nPoints = 100;
    4006             :   double sumW = 0;
    4007           0 :   for (int i = 0; i < nPoints; ++i) {
    4008           0 :     Vec4 x;
    4009           0 :     double r    = sqrt(- log(rndmPtr->flat()));
    4010           0 :     double phi  = 2 * M_PI * rndmPtr->flat();
    4011           0 :     x[1]        = blowR * rHadron * r * cos(phi);
    4012           0 :     x[2]        = blowR * rHadron * r * sin(phi);
    4013           0 :     r           = sqrt(- log(rndmPtr->flat()));
    4014           0 :     phi         = 2 * M_PI * rndmPtr->flat();
    4015           0 :     x[3]        = blowR * rHadron * r * cos(phi);
    4016           0 :     x[0]        = max(decays[0][0], decays[1][0])
    4017           0 :                 + blowT * sqrt(0.5) * tfrag * r * abs(sin(phi));
    4018           0 :     if (x.m2Calc() < 0) continue;
    4019             : 
    4020             :     // Find weight of trial point.
    4021           0 :     double weightTrial = exp(-x.pAbs2() / pow2(blowR*rHadron))
    4022           0 :       * exp( -2. * pow2(x[0] - max(decays[0][0],decays[1][0]))
    4023           0 :       / pow2(blowT * tfrag) );
    4024             : 
    4025             :     // Find max weight and their indices.
    4026           0 :     double maxWeights[2] = {0,0}; // {1E-10,1E-10};
    4027           0 :     int maxIndices[2] = {-1,-1};
    4028             : 
    4029             :     // Loop over W decays.
    4030           0 :     for (int j = 0;j < 2;++j) {
    4031             : 
    4032             :       // Calculate the difference between decay point and random point.
    4033           0 :       Vec4 xd = x - decays[j];
    4034             : 
    4035             :       // Loop over strings.
    4036           0 :       for (int k = 0; k < int(dips[j].size()); ++k) {
    4037             : 
    4038             :         // Boost to rest frame of string.
    4039           0 :         double     gam = vel[j][k][0];
    4040           0 :         double dotProd = dot3(xd,vel[j][k]);
    4041           0 :         double xBoost  = gam * (gam * dotProd/ (1. + gam) - xd[0]);
    4042           0 :         Vec4 xb = xd + xBoost * vel[j][k];
    4043           0 :         xb[0] = gam * (xd[0] - dotProd);
    4044             : 
    4045             :         // Check that position is reachable.
    4046           0 :         if (xb.m2Calc() < 0) continue;
    4047             : 
    4048             :         // Find and store largest weight.
    4049           0 :         double weight = exp( -(xb.pAbs2() - pow2(dot3(xb,dir[j][k])))
    4050           0 :           / (2 * pow2(rHadron)) )
    4051           0 :           * exp( -(pow2(xb[0]) - pow2(dot3(xb, dir[j][k]))) / pow2(tfrag) );
    4052           0 :         if (weight > maxWeights[j]) {
    4053           0 :           maxWeights[j] = weight;
    4054           0 :           maxIndices[j] = k;
    4055           0 :         }
    4056           0 :       }
    4057           0 :     }
    4058             : 
    4059             :     // Store weight.
    4060           0 :     if (maxIndices[0] != -1 && maxIndices[1] != -1) {
    4061             : 
    4062             :       // Check if the new configuration lowers the lambda measure.
    4063           0 :       if (lowerLambdaOnly) {
    4064           0 :         double oldLambda = stringLength.getStringLength(event,
    4065           0 :           dips[0][maxIndices[0]].iCol, dips[0][maxIndices[0]].iAcol) +
    4066           0 :           stringLength.getStringLength(event, dips[1][maxIndices[1]].iCol,
    4067           0 :           dips[1][maxIndices[1]].iAcol);
    4068           0 :         double newLambda = stringLength.getStringLength(event,
    4069           0 :           dips[0][maxIndices[0]].iCol, dips[1][maxIndices[1]].iAcol) +
    4070           0 :           stringLength.getStringLength(event, dips[1][maxIndices[1]].iCol,
    4071           0 :           dips[0][maxIndices[0]].iAcol);
    4072           0 :         if (oldLambda < newLambda) continue;
    4073           0 :       }
    4074             : 
    4075             :       // Save weights.
    4076           0 :       double weight = maxWeights[0] * maxWeights[1] / weightTrial;
    4077           0 :       reconnections.insert(make_pair(weight,
    4078           0 :         make_pair(maxIndices[0], maxIndices[1])));
    4079           0 :       sumW += weight;
    4080           0 :     }
    4081           0 :   }
    4082             : 
    4083             : 
    4084             :   // check whether to do any reconnections.
    4085           0 :   map<double,pair<int,int> > singleRecon;
    4086           0 :   double result = pow3(blowR) * blowT * sumW/nPoints;
    4087             :   // No reconections.
    4088           0 :   if (1 - exp(-kI * result) < rndmPtr->flat()) {
    4089           0 :     singleRecon.clear();
    4090           0 :     return singleRecon;
    4091             :   // Find reconnection.
    4092             :   } else {
    4093           0 :     double rSum = sumW * rndmPtr->flat();
    4094           0 :     for (map<double,pair<int,int> >::iterator it = reconnections.begin();
    4095           0 :          it != reconnections.end(); ++it) {
    4096           0 :       rSum -= it->first;
    4097           0 :       if (rSum < 0.) {
    4098           0 :         singleRecon.insert(make_pair(1., it->second));
    4099           0 :         return singleRecon;
    4100             :       }
    4101             :     }
    4102             : 
    4103             :     // If no solution was found (shoult not happen) do no reconnections.
    4104           0 :     singleRecon.clear();
    4105           0 :     return singleRecon;
    4106             :   }
    4107           0 : }
    4108             : 
    4109             : //--------------------------------------------------------------------------
    4110             : 
    4111             : // The SK II model for WW/ZZ/WZ systems.
    4112             : 
    4113             : map<double,pair<int,int> > ColourReconnection::reconnectTypeII( Event& event,
    4114             :   vector<vector<ColourDipole> > &dips, Vec4 decays[2]) {
    4115             : 
    4116             :   // Make storage containers.
    4117           0 :   map<double,pair<int,int> > reconnections;
    4118             : 
    4119             :   // Find dipole velocities.
    4120           0 :   for (int i = 0;i < int(dips[0].size()); ++i) {
    4121           0 :     for (int j = 0;j < int(dips[1].size()); ++j) {
    4122           0 :       Vec4 v1,v2,u1,u2;
    4123           0 :       v1 = event[dips[0][i].iCol].p()  / event[dips[0][i].iCol].e();
    4124           0 :       v2 = event[dips[0][i].iAcol].p() / event[dips[0][i].iAcol].e();
    4125           0 :       u1 = event[dips[1][j].iCol].p()  / event[dips[1][j].iCol].e();
    4126           0 :       u2 = event[dips[1][j].iAcol].p() / event[dips[1][j].iAcol].e();
    4127             : 
    4128             :       // Begin setup to solve system of equations.
    4129           0 :       vector<vector<double> > matUpper, matLower;
    4130           0 :       for (int k = 0; k < 3; ++k) {
    4131           0 :         matUpper.push_back(vector<double>(3,0));
    4132           0 :         matLower.push_back(vector<double>(3,0));
    4133             :       }
    4134             : 
    4135             :       // Insert in matrix, beware of different convention in index.
    4136           0 :       for (int k = 0;k < 3; ++k) {
    4137           0 :         matUpper[0][k] = matLower[0][k] = v2[k+1]-v1[k+1];
    4138           0 :         matUpper[1][k] = matLower[1][k] = -(u2[k+1]-u1[k+1]);
    4139           0 :         matUpper[2][k] = decays[0][k+1] - decays[1][k+1]
    4140           0 :           - decays[0][0] * v1[k+1] + decays[1][0] * u1[k+1];
    4141           0 :         matLower[2][k] = v1[k+1] - u1[k+1];
    4142             :       }
    4143           0 :       double t = -determinant3(matUpper) / determinant3(matLower);
    4144             : 
    4145             :       // Find alpha and beta of string crossing.
    4146           0 :       double s11 = matUpper[0][0]*(t - decays[0][0]);
    4147           0 :       double s12 = matUpper[1][0]*(t - decays[1][0]);
    4148           0 :       double s13 = matUpper[2][0] + matLower[2][0]*t;
    4149           0 :       double s21 = matUpper[0][1]*(t - decays[0][0]);
    4150           0 :       double s22 = matUpper[1][1]*(t - decays[1][0]);
    4151           0 :       double s23 = matUpper[2][1] + matLower[2][1]*t;
    4152           0 :       double den = s11*s22 - s12*s21;
    4153           0 :       double alpha = (s12*s23 - s22*s13)/den;
    4154           0 :       double beta  = (s21*s13 - s11*s23)/den;
    4155             : 
    4156             :       // Check if solution is physical.
    4157           0 :       if (alpha < 0 || alpha > 1) continue;
    4158           0 :       if (beta < 0 || beta > 1) continue;
    4159           0 :       if (t < max(decays[0][0], decays[1][0])) continue;
    4160             : 
    4161             :       // Find the crossing points.
    4162           0 :       Vec4 x1,x2;
    4163           0 :       x1 = decays[0] + (alpha * v2 + (1 - alpha) * v1) * (t - decays[0][0]);
    4164           0 :       x2 = decays[1] + (beta * u2 + (1 - beta) * u1) * (t - decays[1][0]);
    4165           0 :       x1[0] = x2[0] = t;
    4166             : 
    4167             :       // Check that both points are the same.
    4168           0 :       if (dot3(x1-x2,x1-x2) > 1E-4 * (x1.pAbs2() + x2.pAbs2())) continue;
    4169             : 
    4170             :       // Find string eigentimes.
    4171           0 :       double tauPlus  = (x1 - decays[0]).mCalc();
    4172           0 :       double tauMinus = (x2 - decays[1]).mCalc();
    4173             : 
    4174             :       // Check if strings already decayed.
    4175           0 :       if (rndmPtr->flat() > exp( -(pow2(tauPlus) + pow2(tauMinus))
    4176           0 :           / pow2(tfrag))) continue;
    4177             : 
    4178             :       // Optionally only accept if reconnection reduces string length.
    4179           0 :       if (lowerLambdaOnly) {
    4180           0 :         double oldLambda = stringLength.getStringLength(event,
    4181           0 :           dips[0][i].iCol, dips[0][i].iAcol) +
    4182           0 :           stringLength.getStringLength(event, dips[1][j].iCol,
    4183           0 :           dips[1][j].iAcol);
    4184           0 :         double newLambda = stringLength.getStringLength(event,
    4185           0 :           dips[0][i].iCol, dips[1][j].iAcol) +
    4186           0 :           stringLength.getStringLength(event, dips[1][j].iCol,
    4187           0 :           dips[0][i].iAcol);
    4188           0 :         if (oldLambda < newLambda) continue;
    4189           0 :       }
    4190             : 
    4191             :       // Store dipole pair.
    4192           0 :       reconnections.insert(make_pair(t,make_pair(i,j)));
    4193           0 :     }
    4194             :   }
    4195             : 
    4196             :   return reconnections;
    4197           0 : }
    4198             : 
    4199             : 
    4200             : //--------------------------------------------------------------------------
    4201             : 
    4202             : // Calculate the determinant of a 3 * 3 matrix.
    4203             : 
    4204             : double ColourReconnection::determinant3(vector<vector< double> >& vec) {
    4205           0 :   return vec[0][0]*vec[1][1]*vec[2][2] + vec[0][1]*vec[1][2]*vec[2][0]
    4206           0 :     + vec[0][2]*vec[1][0]*vec[2][1] - vec[0][0]*vec[2][1]*vec[1][2]
    4207           0 :     - vec[0][1]*vec[1][0]*vec[2][2] - vec[0][2]*vec[1][1]*vec[2][0];
    4208             : }
    4209             : 
    4210             : //==========================================================================
    4211             : 
    4212             : } // end namespace Pythia8

Generated by: LCOV version 1.11