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