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