StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
JunctionSplitting.cc
1 // JunctionSplitting.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 // JunctionSplitting class.
8 
9 // Setup the list of colours, this is needed later for finding colour chains.
10 
11 #include "Pythia8/JunctionSplitting.h"
12 
13 namespace Pythia8 {
14 
15 //==========================================================================
16 
17 // The JunctionSplitting class.
18 
19 //--------------------------------------------------------------------------
20 
21 // Constants: could be changed here if desired, but normally should not.
22 // These are of technical nature, as described for each.
23 
24 // For breaking J-J string, pick a Gamma by taking a step with fictitious mass.
25 const double JunctionSplitting::JJSTRINGM2MAX = 25.;
26 const double JunctionSplitting::JJSTRINGM2FRAC = 0.1;
27 
28 // Iterate junction rest frame boost until convergence or too many tries.
29 const double JunctionSplitting::CONVJNREST = 1e-5;
30 const int JunctionSplitting::NTRYJNREST = 20;
31 
32 // Typical average transvere primary hadron mass <mThad>.
33 const double JunctionSplitting::MTHAD = 0.9;
34 
35 // Minimum angle between two partons, to avoid problems with infinities.
36 const double JunctionSplitting::MINANGLE = 1e-7;
37 
38 //--------------------------------------------------------------------------
39 
40 // Initialize the class and all the created classes.
41 
42 void JunctionSplitting::init() {
43 
44  // Initialize
45  colTrace.init(infoPtr);
46  stringLength.init(infoPtr, *settingsPtr);
47 
48  // Initialize auxiliary fragmentation classes.
49  flavSel.init();
50  pTSel.init();
51  zSel.init();
52 
53  // Initialize string and ministring fragmentation.
54  stringFrag.init(&flavSel, &pTSel, &zSel);
55 
56  // For junction processing.
57  eNormJunction = parm("StringFragmentation:eNormJunction");
58  allowDoubleJunRem = flag("ColourReconnection:allowDoubleJunRem");
59 }
60 
61 //--------------------------------------------------------------------------
62 
63 // Check that all colours are connected in physical way. Also split
64 // junction pairs, such that the hadronization can handle the configuration.
65 
66 bool JunctionSplitting::checkColours( Event& event) {
67 
68  // Not really a colour check, but a check all numbers are valid.
69  for (int i = 0; i < event.size(); ++i)
70  if (abs(event[i].px()) >= 0. && abs(event[i].py()) >= 0.
71  && abs(event[i].pz()) >= 0. && abs(event[i].e()) >= 0.
72  && abs(event[i].m()) >= 0.);
73  else {
74  infoPtr->errorMsg("Warning in JunctionSplitting::CheckColours: "
75  "not-a-number energy/momentum/mass");
76  return false;
77  }
78 
79  // Check if any singlet gluons were made, and if so return false.
80  for (int i = 0; i < event.size(); ++i) {
81  if (event[i].isFinal() && event[i].col() != 0 &&
82  event[i].col() == event[i].acol()) {
83  infoPtr->errorMsg("Warning in JunctionSplitting::CheckColours: "
84  "Made a gluon colour singlet; redoing colours");
85  return false;
86  }
87  }
88 
89  // Need to try and split junction structures.
90  colTrace.setupColList(event);
91  vector<int> iParton;
92  vector<vector <int > > iPartonJun, iPartonAntiJun;
93  getPartonLists(event, iPartonJun, iPartonAntiJun);
94 
95  // Try to split up the junction chains by splitting gluons
96  if (!splitJunGluons(event, iPartonJun, iPartonAntiJun) ) {
97  infoPtr->errorMsg("Warning in JunctionSplitting::CheckColours: "
98  "Not possible to split junctions; making new colours");
99  return false;
100  }
101 
102  // Remove junctions if more than 2 are connected.
103  if (!splitJunChains(event) ) {
104  infoPtr->errorMsg("Warning in JunctionSplitting::CheckColours: "
105  "Not possible to split junctions; making new colours");
106  return false;
107  }
108 
109  // Split up junction pairs.
110  getPartonLists(event, iPartonJun, iPartonAntiJun);
111  if (!splitJunPairs(event, iPartonJun, iPartonAntiJun) ) {
112  infoPtr->errorMsg("Warning in JunctionSplitting::CheckColours: "
113  "Not possible to split junctions; making new colours");
114  return false;
115  }
116 
117  // Done checking.
118  return true;
119 }
120 
121 //--------------------------------------------------------------------------
122 
123 // Split connected junction chains into separated, mainly by splitting gluons
124 // into q-qbar pairs. Other methods are applied if the junctions are directly
125 // connected. (Note: implementation below assumes any intermediate gluons
126 // are bookkept in iPartonJun, not in iPartonAntiJun.)
127 
128 bool JunctionSplitting::splitJunGluons(Event& event,
129  vector<vector< int > >& iPartonJun, vector<vector< int > >& iPartonAntiJun) {
130 
131  // Loop over all junctions and all junction legs.
132  for (int iJun = 0; iJun < int(iPartonJun.size()); ++iJun) {
133 
134  // Fill in vector of the legs content.
135  vector<vector <int> > iJunLegs;
136  iJunLegs.resize(3);
137  int leg = -1;
138  for (int i = 0; i < int(iPartonJun[iJun].size()); ++i) {
139  if ( iPartonJun[iJun][i]/10 == iPartonJun[iJun][0]/10) ++leg;
140  iJunLegs[leg].push_back(iPartonJun[iJun][i]);
141  }
142 
143  // Loop over legs.
144  for (int i = 0;i < int(iJunLegs.size()); ++i) {
145 
146  // If it is not connected to another junction, no need to do anything.
147  if (iJunLegs[i].back() > 0)
148  continue;
149  int identJun = iJunLegs[i][0];
150  // If no gluons in between two junctions, not possible to do anything.
151  if (iJunLegs[i].size() == 2)
152  continue;
153 
154  int identAntiJun = 0, iAntiLeg = -1;
155 
156  // Pick a new quark at random; for simplicity no diquarks.
157  int colQ = 0, acolQ = 0;
158  int idQ = flavSel.pickLightQ();
159 
160  // If a single gluon in between the two junctions, change it to a
161  // quark-anti quark system.
162  if ( iJunLegs[i].size() == 3) {
163 
164  // Verify that intermediate particle is a gluon (not a gluino).
165  if (event[ iJunLegs[i][1] ].idAbs() != 21) continue;
166 
167  // Store the new q qbar pair, sharing gluon colour and momentum.
168  colQ = event[ iJunLegs[i][1] ].col();
169  acolQ = event[ iJunLegs[i][1] ].acol();
170  Vec4 pQ = 0.5 * event[ iJunLegs[i][1] ].p();
171  double mQ = 0.5 * event[ iJunLegs[i][1] ].m();
172  int iQ = event.append( idQ, 75, iJunLegs[i][1], 0, 0, 0, colQ, 0,
173  pQ, mQ );
174  int iQbar = event.append( -idQ, 75, iJunLegs[i][1], 0, 0, 0, 0, acolQ,
175  pQ, mQ );
176 
177  // Mark split gluon.
178  event[ iJunLegs[i][1] ].statusNeg();
179  event[ iJunLegs[i][1] ].daughters( iQ, iQbar);
180 
181  // Update junction and antijunction list.
182  identAntiJun = iJunLegs[i].back();
183  int iOld = iJunLegs[i][1];
184  bool erasing = false;
185  for (int j = 0; j < int(iPartonJun[iJun].size()); ++j) {
186  if (iPartonJun[iJun][j] == iOld)
187  erasing = true;
188  if (iPartonJun[iJun][j] == identAntiJun) {
189  iPartonJun[iJun][j] = iQ;
190  break;
191  }
192  if (erasing) {
193  iPartonJun[iJun].erase(iPartonJun[iJun].begin() + j);
194  --j;
195  }
196  }
197 
198  // Find the connected antijunction from the list of antijunctions.
199  int iAntiJun = -1;
200  for (int j = 0; j < int(iPartonAntiJun.size()); j++)
201  if ( iPartonAntiJun[j][0]/10 == identAntiJun/10) {
202  iAntiJun = j;
203  break;
204  }
205  // If no antijunction found, something went wrong earlier.
206  if (iAntiJun == -1) {
207  infoPtr->errorMsg("Warning in JunctionSplitting::SplitJunChain:"
208  "Something went wrong in finding antijunction");
209  return false;
210  }
211 
212  // Update the antijunction list.
213  erasing = false;
214  for (int j = 0; j < int(iPartonAntiJun[iAntiJun].size()); ++j) {
215  if ( iPartonAntiJun[iAntiJun][j] / 10 == identAntiJun / 10)
216  iAntiLeg++;
217  if ( iPartonAntiJun[iAntiJun][j] == identJun) {
218  iPartonAntiJun[iAntiJun][j] = iQbar;
219  break;
220  }
221  }
222  }
223  // If more than a single gluon, decide depending on mass.
224  else if (iJunLegs[i].size() > 3) {
225 
226  // Evaluate mass-squared for all adjacent gluon pairs.
227  vector<double> m2Pair;
228  double m2Sum = 0.;
229  for (int j = 1; j < int(iJunLegs[i].size()) - 2; ++j) {
230  double m2Now = 0.5 * event[ iJunLegs[i][j] ].p()
231  * event[ iJunLegs[i][j + 1] ].p();
232  m2Pair.push_back(m2Now);
233  m2Sum += m2Now;
234  }
235 
236  // Pick breakup region with probability proportional to mass-squared.
237  double m2Reg = m2Sum * rndmPtr->flat();
238  int iReg = -1;
239  do m2Reg -= m2Pair[++iReg];
240  while (m2Reg > 0. && iReg < int(m2Pair.size()) - 1);
241  m2Reg = m2Pair[iReg];
242 
243  // increase iReg with one, since it should not point towards itself.
244  iReg++;
245 
246  // Pick breaking point of string in chosen region (symmetrically).
247  double m2Temp = min( JJSTRINGM2MAX, JJSTRINGM2FRAC * m2Reg);
248  double xPos = 0.5;
249  double xNeg = 0.5;
250  do {
251  double zTemp = zSel.zFrag( idQ, 0, m2Temp);
252  xPos = 1. - zTemp;
253  xNeg = m2Temp / (zTemp * m2Reg);
254  } while (xNeg > 1.);
255  if (rndmPtr->flat() > 0.5) swap(xPos, xNeg);
256 
257  // Verify that intermediate particles are gluons (not gluinos).
258  if ( event[ iJunLegs[i][iReg] ].idAbs() != 21
259  || event[ iJunLegs[i][iReg + 1] ].idAbs() != 21 ) continue;
260 
261  // Pick up two "mother" gluons of breakup. Mark them decayed.
262  Particle& gJun = event[ iJunLegs[i][iReg] ];
263  Particle& gAnti = event[ iJunLegs[i][iReg + 1] ];
264  gJun.statusNeg();
265  gAnti.statusNeg();
266  int dau1 = event.size();
267  gJun.daughters(dau1, dau1 + 3);
268  gAnti.daughters(dau1, dau1 + 3);
269  int mother1 = min( iJunLegs[i][iReg], iJunLegs[i][iReg + 1]);
270  int mother2 = max( iJunLegs[i][iReg], iJunLegs[i][iReg + 1]);
271 
272  // Need to store variables, since it is not safe to use references
273  // with append.
274  int gJunCol = gJun.col();
275  int gJunAcol = gJun.acol();
276  int gAntiAcol = gAnti.acol();
277  Vec4 gJunP = gJun.p();
278  Vec4 gAntiP = gAnti.p();
279  double gJunM = gJun.m();
280  double gAntiM = gAnti.m();
281 
282  // Can keep one of old colours but need one new so unambiguous.
283  colQ = gJunAcol;
284  acolQ = event.nextColTag();
285 
286  // Store copied gluons with reduced momenta.
287  int iGjun = event.append( 21, 75, mother1, mother2, 0, 0,
288  gJunCol, gJunAcol, (1. - 0.5 * xPos) * gJunP,
289  (1. - 0.5 * xPos) * gJunM);
290  event.append( 21, 75, mother1, mother2, 0, 0,
291  acolQ, gAntiAcol, (1. - 0.5 * xNeg) * gAntiP,
292  (1. - 0.5 * xNeg) * gAntiM);
293 
294  // Store the new q qbar pair with remaining momenta.
295  int iQ = event.append( idQ, 75, mother1, mother2, 0, 0,
296  colQ, 0, 0.5 * xNeg * gAntiP, 0.5 * xNeg * gAntiM );
297  int iQbar = event.append( -idQ, 75, mother1, mother2, 0, 0,
298  0, acolQ, 0.5 * xPos * gJunP, 0.5 * xPos * gJunM );
299 
300  // Update the list of junctions to reflect the splitting.
301  identAntiJun = iJunLegs[i].back();
302  bool erasing = false;
303  for (int j = 0; j < int(iPartonJun[iJun].size()); ++j) {
304  if (iPartonJun[iJun][j] == mother1 ||
305  iPartonJun[iJun][j] == mother2)
306  erasing = true;
307 
308  if ( iPartonJun[iJun][j] == identAntiJun) {
309  iPartonJun[iJun][j] = iQ;
310  iPartonJun[iJun].insert(iPartonJun[iJun].begin() + j, iGjun);
311  break;
312  }
313  if (erasing) {
314  iPartonJun[iJun].erase(iPartonJun[iJun].begin() + j);
315  j--;
316  }
317  }
318 
319  // Find the connected antijunction from the list of antijunctions.
320  int iAntiJun = -1;
321  for (int j = 0; j < int(iPartonAntiJun.size());j++)
322  if ( iPartonAntiJun[j][0]/10 == identAntiJun/10) {
323  iAntiJun = j;
324  break;
325  }
326  // If no antijunction found, something went wrong earlier.
327  if (iAntiJun == -1) {
328  infoPtr->errorMsg("Warning in JunctionSplitting::SplitJunChain:"
329  "Something went wrong in finding antijunction");
330  return false;
331  }
332 
333  // Update the antijunction list to reflect the splitting
334  for (int j = 0; j < int(iPartonAntiJun[iAntiJun].size()); ++j) {
335  if ( iPartonAntiJun[iAntiJun][j] / 10 == identAntiJun / 10)
336  iAntiLeg++;
337  if (iPartonAntiJun[iAntiJun][j] == identJun) {
338  iPartonAntiJun[iAntiJun][j] = iQbar;
339  break;
340  }
341  }
342  }
343 
344  // Update end colours for both g -> q qbar and g g -> g g q qbar.
345  event.endColJunction((-identJun)/10 - 1, i, colQ);
346  event.endColJunction((-identAntiJun)/10 - 1, iAntiLeg, acolQ);
347  }
348  }
349 
350  // Done.
351  return true;
352 }
353 
354 //--------------------------------------------------------------------------
355 
356 // Fix chains that contain more than two junctions.
357 // This is done by removing the minimum needed amount of junctions.
358 // Might need to make choice based on String length, now randomly chosen.
359 
360 bool JunctionSplitting::splitJunChains(Event& event) {
361 
362  // Get junction chains.
363  event.saveJunctionSize();
364  vector<vector<int> > junChains = colTrace.getJunChains(event);
365 
366  // Remove junctions.
367  vector<int> junRem;
368  for (int i = 0; i < int(junChains.size()); ++i) {
369  if (junChains[i].size() < 3)
370  continue;
371 
372  vector<int> cols, acols;
373  for (int j = 0; j < int(junChains[i].size()); ++j) {
374 
375  junRem.push_back(junChains[i][j]);
376  if (event.kindJunction(junChains[i][j]) % 2 == 0)
377  for (int jLeg = 0; jLeg < 3; ++jLeg)
378  acols.push_back(event.colJunction(junChains[i][j],jLeg));
379  else
380  for (int jLeg = 0; jLeg < 3; ++jLeg)
381  cols.push_back(event.colJunction(junChains[i][j],jLeg));
382  }
383 
384  for (int j = 0; j < int(cols.size()); ++j)
385  for (int k = 0; k < int(acols.size()); ++k)
386  if (cols[j] == acols[k]) {
387  cols.erase(cols.begin() + j);
388  acols.erase(acols.begin() + k);
389  j--;
390  break;
391  }
392 
393  // Find junctions if we have more colours than anti colours
394  while (cols.size() > acols.size()) {
395  int i1 = int(rndmPtr->flat() *cols.size());
396  int col1 = cols[i1];
397  cols.erase(cols.begin() + i1);
398  int i2 = int(rndmPtr->flat() *cols.size());
399  int col2 = cols[i2];
400  cols.erase(cols.begin() + i2);
401  int i3 = int(rndmPtr->flat() *cols.size());
402  int col3 = cols[i3];
403  cols.erase(cols.begin() + i3);
404  event.appendJunction(1, col1, col2, col3);
405  }
406 
407  // Find junctions if we have more colours than anti colours
408  while (acols.size() > cols.size()) {
409  int i1 = int(rndmPtr->flat() *acols.size());
410  int acol1 = acols[i1];
411  acols.erase(acols.begin() + i1);
412  int i2 = int(rndmPtr->flat() *acols.size());
413  int acol2 = acols[i2];
414  acols.erase(acols.begin() + i2);
415  int i3 = int(rndmPtr->flat() *acols.size());
416  int acol3 = acols[i3];
417  acols.erase(acols.begin() + i3);
418  event.appendJunction(2,acol1,acol2,acol3);
419  }
420 
421  // If we have more than two colour anti colour pairs
422  // form junction antijunction pair.
423  while (int(acols.size()) > 1) {
424  int i1 = int(rndmPtr->flat() *cols.size());
425  int col1 = cols[i1];
426  cols.erase(cols.begin() + i1);
427  int i2 = int(rndmPtr->flat() *cols.size());
428  int col2 = cols[i2];
429  cols.erase(cols.begin() + i2);
430  int i3 = int(rndmPtr->flat() *acols.size());
431  int acol1 = acols[i3];
432  acols.erase(acols.begin() + i3);
433  int i4 = int(rndmPtr->flat() *acols.size());
434  int acol2 = acols[i4];
435  acols.erase(acols.begin() + i4);
436  int newCol = event.nextColTag();
437  event.appendJunction(1, col1, col2, newCol);
438  event.appendJunction(2, acol1, acol2, newCol);
439  }
440 
441  // If we have one colour and one anti colour, form normal string.
442  if (int(acols.size()) == 1) {
443  int iCol = -1;
444  for (int iPar = 0; iPar < event.size(); ++iPar)
445  if (event[iPar].isFinal() && event[iPar].col() == cols[0])
446  iCol = iPar;
447  if (iCol == -1) {
448  infoPtr->errorMsg("Warning in JunctionSplitting::SplitJunChain:"
449  "Splitting multiple directly connected junctions failed");
450  return false;
451  }
452  int iNew = event.copy(iCol, 76);
453  event[iNew].col(acols[0]);
454  }
455  }
456 
457  // Delete the junctions from the event record.
458  sort(junRem.begin(),junRem.end());
459  reverse(junRem.begin(),junRem.end());
460  for (int i = 0; i < int(junRem.size()); ++i)
461  event.eraseJunction(junRem[i]);
462  event.saveJunctionSize();
463 
464  return true;
465 }
466 
467 //--------------------------------------------------------------------------
468 
469 // Split junction pairs.
470 // If it has 3 connections just ignore junctions.
471 // If it has 2 connections colapse into single string.
472 // If it has 1 connection, depend on the string length.
473 
474 bool JunctionSplitting::splitJunPairs(Event& event,
475  vector<vector< int > >& iPartonJun, vector<vector< int > >& iPartonAntiJun) {
476 
477  // Clear old memory.
478  event.saveJunctionSize();
479  vector<int> junRem;
480 
481  // Get junction chains.
482  vector<vector<int> > junChains = colTrace.getJunChains(event);
483 
484  for (int i = 0; i < int(junChains.size()); ++i) {
485  if (junChains[i].size() == 2) {
486  vector<pair<int,int> > matchedLegs;
487  for (int j = 0; j < 3; ++j)
488  for (int k = 0; k < 3; ++k)
489  if (event.colJunction(junChains[i][0],j) ==
490  event.colJunction(junChains[i][1],k))
491  matchedLegs.push_back(make_pair(j,k));
492 
493  // For three connected legs, just remove the junctions,
494  // since the pair contains no energy/momentum.
495  if (matchedLegs.size() == 3) {
496  junRem.push_back(junChains[i][0]);
497  junRem.push_back(junChains[i][1]);
498 
499  }
500 
501  // Split into string if two legs are combined.
502  else if (matchedLegs.size() == 2) {
503 
504  // Find first leg.
505  int i1 = 0;
506  if (matchedLegs[0].first != 1 && matchedLegs[1].first != 1) i1 = 1;
507  if (matchedLegs[0].first != 2 && matchedLegs[1].first != 2) i1 = 2;
508 
509  // Find second leg.
510  int j1 = 0;
511  if (matchedLegs[0].second != 1 && matchedLegs[1].second != 1) j1 = 1;
512  if (matchedLegs[0].second != 2 && matchedLegs[1].second != 2) j1 = 2;
513 
514  // Find corresponding colours.
515  int col = event.colJunction(junChains[i][0],i1);
516  int acol = event.colJunction(junChains[i][1],j1);
517  if (event.kindJunction(junChains[i][1]) % 2 == 1)
518  swap(col,acol);
519 
520  // Find index of anti particle.
521  int iAcol = -1;
522  for (int j = 0;j < event.size();++j)
523  if (event[j].isFinal() && event[j].acol() == acol) {
524  iAcol = j;
525  break;
526  }
527  if (iAcol == -1) {
528  infoPtr->errorMsg("Warning in JunctionSplitting::SplitJunChain:"
529  "Anti colour not found when combining two junctions to a string");
530  return false;
531  }
532 
533  // Update anti colour of anti particle.
534  int iNew = event.copy(iAcol,66);
535  event[iNew].acol(col);
536 
537  // Remove the junctions from the event record.
538  junRem.push_back(junChains[i][0]);
539  junRem.push_back(junChains[i][1]);
540  }
541 
542  // Split into string if two legs are combined.
543  else if (matchedLegs.size() == 1) {
544 
545  // store junction numbers.
546  int iJun = junChains[i][0];
547  int iAnti = junChains[i][1];
548  int iLeg = matchedLegs[0].first;
549  int iAntiLeg = matchedLegs[0].second;
550  if (event.kindJunction(iAnti) % 2 == 1) {
551  swap(iJun, iAnti);
552  swap(iLeg, iAntiLeg);
553  }
554 
555  // Find the junctions in the parton list.
556  int iJunList = -1, iAntiList = -1;
557  for (int l = 0;l < int(iPartonJun.size()); ++l)
558  if (- iPartonJun[l][0]/10 - 1 == iJun) {
559  iJunList = l;
560  break;
561  }
562  for (int l = 0;l < int(iPartonAntiJun.size()); ++l)
563  if (- iPartonAntiJun[l][0]/10 - 1 == iAnti) {
564  iAntiList = l;
565  break;
566  }
567  if (iJunList == -1 || iAntiList == -1) {
568  infoPtr->errorMsg("Error in JunctionSplitting::SplitJunChain:"
569  " failed to find junctions in the parton list");
570  return false;
571  }
572 
573  // Fill in vector of the legs content.
574  vector<vector <int> > iJunLegs;
575  iJunLegs.resize(3);
576  int leg = -1;
577 
578  for (int l = 0; l < int(iPartonJun[iJunList].size()); ++l) {
579  if ( iPartonJun[iJunList][l]/10 == iPartonJun[iJunList][0]/10) ++leg;
580  iJunLegs[leg].push_back(iPartonJun[iJunList][l]);
581  }
582 
583  // Fill in vector of the legs content.
584  vector<vector <int> > iAntiLegs;
585  iAntiLegs.resize(3);
586  leg = -1;
587  for (int l = 0; l < int(iPartonAntiJun[iAntiList].size()); ++l) {
588  if ( iPartonAntiJun[iAntiList][l]/10
589  == iPartonAntiJun[iAntiList][0]/10) ++leg;
590  iAntiLegs[leg].push_back(iPartonAntiJun[iAntiList][l]);
591  }
592 
593  // Identify the two external legs of either junction.
594  vector<int>& iJunLeg0 = (iLeg == 0) ? iJunLegs[1] : iJunLegs[0];
595  vector<int>& iJunLeg1 = (iLeg == 2) ? iJunLegs[1] : iJunLegs[2];
596  vector<int>& iAntiLeg0 = (iAntiLeg == 0) ? iAntiLegs[1] : iAntiLegs[0];
597  vector<int>& iAntiLeg1 = (iAntiLeg == 2) ? iAntiLegs[1] : iAntiLegs[2];
598 
599  // Check that the anti-leg is not stored as a junction.
600  // This should only happen for gluinos, which are not split.
601  if (iAntiLeg0[1] < 0 || iAntiLeg1[1] < 0) continue;
602 
603  // Simplified procedure: mainly study first parton on each leg.
604  Vec4 pJunLeg0 = event[ iJunLeg0[1] ].p();
605  Vec4 pJunLeg1 = event[ iJunLeg1[1] ].p();
606  Vec4 pAntiLeg0 = event[ iAntiLeg0[1] ].p();
607  Vec4 pAntiLeg1 = event[ iAntiLeg1[1] ].p();
608 
609  // Check that no two legs are parallel.
610  if ( theta(pJunLeg0,pJunLeg1) < MINANGLE
611  || theta(pAntiLeg0,pAntiLeg1) < MINANGLE
612  || theta(pJunLeg0,pAntiLeg0) < MINANGLE
613  || theta(pJunLeg0,pAntiLeg1) < MINANGLE
614  || theta(pJunLeg1,pAntiLeg0) < MINANGLE
615  || theta(pJunLeg1,pAntiLeg1) < MINANGLE) {
616  infoPtr->errorMsg("Warning in JunctionSplitting::SplitJunPairs: "
617  "parallel junction state not allowed.");
618  return false;
619  }
620 
621  // Starting frame hopefully intermediate to two junction directions.
622  Vec4 pStart = pJunLeg0 / pJunLeg0.e() + pJunLeg1 / pJunLeg1.e()
623  + pAntiLeg0 / pAntiLeg0.e() + pAntiLeg1 / pAntiLeg1.e();
624 
625  // Loop over iteration to junction/antijunction rest frames (JRF/ARF).
626  RotBstMatrix MtoJRF, MtoARF;
627  Vec4 pInJRF[3], pInARF[3];
628  for (int iJunLocal = 0; iJunLocal < 2; ++iJunLocal) {
629  int offset = (iJunLocal == 0) ? 0 : 2;
630 
631  // Iterate from system rest frame towards the junction rest frame.
632  RotBstMatrix MtoRF, Mstep;
633  MtoRF.bstback(pStart);
634  Vec4 pInRF[4];
635  int iter = 0;
636  do {
637  ++iter;
638 
639  // Find rest-frame momenta on the three sides of the junction.
640  // Only consider first parton on each leg, for simplicity.
641  pInRF[0 + offset] = pJunLeg0;
642  pInRF[1 + offset] = pJunLeg1;
643  pInRF[2 - offset] = pAntiLeg0;
644  pInRF[3 - offset] = pAntiLeg1;
645  for (int l = 0; l < 4; ++l) pInRF[l].rotbst(MtoRF);
646 
647  // For third side add both legs beyond other junction, weighted.
648  double wt2 = 1. - exp( -pInRF[2].e() / eNormJunction);
649  double wt3 = 1. - exp( -pInRF[3].e() / eNormJunction);
650  pInRF[2] = wt2 * pInRF[2] + wt3 * pInRF[3];
651 
652  // Find new junction rest frame from the set of momenta.
653  Mstep = stringFrag.junctionRestFrame( pInRF[0], pInRF[1], pInRF[2]);
654  MtoRF.rotbst( Mstep );
655  } while (iter < 3 || (Mstep.deviation() > CONVJNREST
656  && iter < NTRYJNREST) );
657 
658  // Store final boost and rest-frame (weighted) momenta.
659  if (iJunLocal == 0) {
660  MtoJRF = MtoRF;
661  for (int l = 0; l < 3; ++l) pInJRF[l] = pInRF[l];
662  } else {
663  MtoARF = MtoRF;
664  for (int l = 0; l < 3; ++l) pInARF[l] = pInRF[l];
665  }
666  }
667 
668  // Opposite operations: boost from JRF/ARF to original system.
669  RotBstMatrix MfromJRF = MtoJRF;
670  MfromJRF.invert();
671  RotBstMatrix MfromARF = MtoARF;
672  MfromARF.invert();
673 
674  // Velocity vectors of junctions and momentum of legs in lab frame.
675  Vec4 vJun(0., 0., 0., 1.);
676  vJun.rotbst(MfromJRF);
677  Vec4 vAnti(0., 0., 0., 1.);
678  vAnti.rotbst(MfromARF);
679  Vec4 pLabJ[3], pLabA[3];
680  for (int l = 0; l < 3; ++l) {
681  pLabJ[l] = pInJRF[l];
682  pLabJ[l].rotbst(MfromJRF);
683  pLabA[l] = pInARF[l];
684  pLabA[l].rotbst(MfromARF);
685  }
686 
687  // Calculate Lambda-measure length of three possible topologies.
688  double vJvA = vJun * vAnti;
689  double vJvAe2y = vJvA + sqrt(vJvA*vJvA - 1.);
690  double lambdaJA = stringLength.getJuncLength(pInJRF[0], pInJRF[1],
691  pInARF[0], pInARF[1]);
692 
693  double lambda00 = stringLength.getStringLength(pLabJ[0], pLabA[0]) +
694  stringLength.getStringLength(pLabJ[1], pLabA[1]);
695 
696  double lambda01 = stringLength.getStringLength(pLabJ[0], pLabA[1]) +
697  stringLength.getStringLength(pLabJ[1], pLabA[0]);
698 
699  // Case when either topology without junctions is the shorter one.
700  if (lambdaJA > min( lambda00, lambda01) && allowDoubleJunRem) {
701 
702  // Find indices of particles.
703  int iCol1 = iJunLeg0[1];
704  int iCol2 = iJunLeg1[1];
705  int iAcol1 = iAntiLeg0[1];
706  int iAcol2 = iAntiLeg1[1];
707  if (lambda00 > lambda01)
708  swap(iAcol1, iAcol2);
709 
710  // Change the colour index and mark junctions to be removed.
711  int iNew1 = event.copy(iAcol1, 66);
712  event[iNew1].acol(event[iCol1].col());
713  int iNew2 = event.copy(iAcol2, 66);
714  event[iNew2].acol(event[iCol2].col());
715  junRem.push_back(junChains[i][0]);
716  junRem.push_back(junChains[i][1]);
717  continue;
718  }
719 
720  // Case where junction and antijunction to be separated.
721  // Shuffle (p+/p-) momentum of order <mThad> between systems,
722  // times 2/3 for 120 degree in JRF, times 1/2 for two legs,
723  // but not more than half of what nearest parton carries.
724 
725  // Only allow to take momentum from non-heavy resonances
726  // (i.e. id 1-5 and 21 and diquarks). If none is available return false.
727  int idJ0Abs = event[ iJunLeg0[1] ].idAbs();
728  bool acceptJ0 = idJ0Abs < 6 || idJ0Abs == 21 ||
729  (idJ0Abs > 1000 && idJ0Abs < 6000 && (idJ0Abs / 10) % 10 == 0);
730  int idJ1Abs = event[ iJunLeg1[1] ].idAbs();
731  bool acceptJ1 = idJ1Abs < 6 || idJ1Abs == 21 ||
732  (idJ1Abs > 1000 && idJ1Abs < 6000 && (idJ1Abs / 10) % 10 == 0);
733  int idA0Abs = event[ iAntiLeg0[1] ].idAbs();
734  bool acceptA0 = idA0Abs < 6 || idA0Abs == 21 ||
735  (idA0Abs > 1000 && idA0Abs < 6000 && (idA0Abs / 10) % 10 == 0);
736  int idA1Abs = event[ iAntiLeg1[1] ].idAbs();
737  bool acceptA1 = idA1Abs < 6 || idA1Abs == 21 ||
738  (idA1Abs > 1000 && idA1Abs < 6000 && (idA1Abs / 10) % 10 == 0);
739 
740  if ( !(acceptJ0 || acceptJ1)) {
741  infoPtr->errorMsg("Warning in JunctionSplitting::SplitJunPairs: "
742  "No light quarks available in junction split.");
743  return false;
744  }
745 
746  if ( !(acceptA0 || acceptA1)) {
747  infoPtr->errorMsg("Warning in JunctionSplitting::SplitJunPairs: "
748  "No light quarks available in junction split.");
749  return false;
750  }
751 
752  double eShift = MTHAD / (3. * sqrt(vJvAe2y));
753  double fracJ0 = 0, fracJ1 = 0, fracA0 = 0, fracA1 = 0;
754  if (acceptJ0)
755  fracJ0 = min(0.5, eShift / pInJRF[0].e());
756  if (acceptJ1)
757  fracJ1 = min(0.5, eShift / pInJRF[1].e());
758  Vec4 pFromJun = fracJ0 * pJunLeg0 + fracJ1 * pJunLeg1;
759  if (acceptA0)
760  fracA0 = min(0.5, eShift / pInARF[0].e());
761  if (acceptA1)
762  fracA1 = min(0.5, eShift / pInARF[1].e());
763  Vec4 pFromAnti = fracA0 * pAntiLeg0 + fracA1 * pAntiLeg1;
764 
765  // Pick a new quark at random; for simplicity no diquarks.
766  int idQ = flavSel.pickLightQ();
767 
768  int junMother1 = min(iJunLeg0[1], iJunLeg1[1]);
769  int junMother2 = max(iJunLeg0[1], iJunLeg1[1]);
770  int antiMother1 = min(iAntiLeg0[1], iAntiLeg1[1]);
771  int antiMother2 = max(iAntiLeg0[1], iAntiLeg1[1]);
772 
773  // Copy junction partons with scaled-down momenta and update legs.
774  int iJunNew1 = event.copy(iJunLeg0[1], 76);
775  event[iJunNew1].rescale5(1. - fracJ0);
776  iJunLeg0[1] = iJunNew1;
777  event[iJunNew1].mothers(junMother2, junMother1);
778 
779  int iJunNew2 = event.copy(iJunLeg1[1], 76);
780  event[iJunNew2].rescale5(1. - fracJ1);
781  iJunLeg1[1] = iJunNew2;
782  event[iJunNew2].mothers(junMother2, junMother1);
783 
784  // Update antijunction anticolour and store antiquark with junction
785  // momentum.
786  int acolQ = event.nextColTag();
787  event.endColJunction(iAnti, iAntiLeg, acolQ);
788  event.colJunction(iAnti, iAntiLeg, acolQ);
789  int iNewA = event.append( -idQ, 76, junMother2, junMother1, 0, 0,
790  0, acolQ, pFromJun, pFromJun.mCalc() );
791 
792  // Copy antijunction partons with scaled-down momenta and update legs.
793  int iAntiNew1 = event.copy(iAntiLeg0[1], 76);
794  event[iAntiNew1].rescale5(1. - fracA0);
795  iAntiLeg0[1] = iAntiNew1;
796  event[iAntiNew1].mothers(antiMother2, antiMother1);
797 
798  int iAntiNew2 = event.copy(iAntiLeg1[1], 76);
799  event[iAntiNew2].rescale5(1. - fracA1);
800  iAntiLeg1[1] = iAntiNew2;
801  event[iAntiNew2].mothers(antiMother2, antiMother1);
802 
803  // Update junction colour and store quark with antijunction momentum.
804  int colQ = event.nextColTag();
805  event.endColJunction(iJun, iLeg, colQ);
806  event.colJunction(iJun, iLeg, colQ);
807  int iNewJ = event.append( idQ, 76, antiMother2, antiMother1, 0, 0,
808  colQ, 0, pFromAnti, pFromAnti.mCalc() );
809 
810  // Set daughters.
811  event[event[iJunNew1].mother1()].daughters( iJunNew1, iNewA);
812  event[event[iJunNew1].mother2()].daughters( iJunNew1, iNewA);
813  event[event[iAntiNew1].mother1()].daughters( iAntiNew1, iNewJ);
814  event[event[iAntiNew1].mother2()].daughters( iAntiNew1, iNewJ);
815 
816  // Done with splitting junction from antijunction.
817  }
818  }
819  }
820 
821  // Delete the junctions from the event record.
822  sort(junRem.begin(),junRem.end());
823  reverse(junRem.begin(),junRem.end());
824  for (int i = 0; i < int(junRem.size()); ++i)
825  event.eraseJunction(junRem[i]);
826  event.saveJunctionSize();
827 
828  // Done.
829  return true;
830 }
831 
832 //--------------------------------------------------------------------------
833 
834 // Create the lists of partons connected to junctions.
835 // Input: event
836 // Output: iPartonJun and iPartonAntiJun (for JJ connections).
837 
838 bool JunctionSplitting::getPartonLists(Event& event,
839  vector<vector< int > > & iPartonJun, vector<vector<int > >& iPartonAntiJun) {
840 
841  // Need to try and split junction structures.
842  colTrace.setupColList(event);
843  vector<int> iParton;
844  iPartonJun.clear();
845  iPartonAntiJun.clear();
846 
847  // Loop over junctions (first junctions, then antijunctions; this ensures
848  // that any gluons between junction-antijunction pairs are bookkept in
849  // iPartonJun rather than in iPartonAntiJun; assumed by subsequent
850  // splitting methods).
851  for (int iLoop = 0; iLoop < 2*event.sizeJunction(); ++iLoop) {
852 
853  int iJun = iLoop % event.sizeJunction();
854  if ( !event.remainsJunction(iJun)) continue;
855 
856  // Do junctions first, then antijunctions
857  int kindJun = event.kindJunction(iJun);
858  if ( iLoop < event.sizeJunction() && kindJun%2 == 0) continue;
859  else if ( iLoop >= event.sizeJunction() && kindJun%2 == 1) continue;
860 
861  iParton.resize(0);
862  // Loop over junction legs
863  // Afterwards (using iJun=0 as example), iParton should look something
864  // like {-10, parton-chain-to-first-colour-end, -11, parton-chain-to-next-
865  // colour-end, -12, parton-chain-to-last-colour-end}
866  // (Note: -10*N indicates leg connected to another junction, with iJun=N-1)
867  for (int iCol = 0; iCol < 3; ++iCol) {
868  int indxCol = event.colJunction(iJun, iCol);
869  iParton.push_back( -(10 + 10 * iJun + iCol) );
870  // Junctions: check that we can find colour ends.
871  if ( kindJun%2 == 1 && !colTrace.traceFromAcol(indxCol,event, iJun,
872  iCol, iParton) ) return false;
873  // Antijunctions: check that we can find anticolour ends.
874  else if ( kindJun%2 == 0 && !colTrace.traceFromCol(indxCol,event, iJun,
875  iCol, iParton) ) return false;
876  }
877 
878  // Save lists for junction-junction systems in iPartonJun, iPartonAntiJun
879  int nNeg = 0;
880  for (int i = 0; i < int(iParton.size()); ++i) if (iParton[i] < 0) ++nNeg;
881  // If 3
882  if (nNeg > 3) {
883  if ( kindJun%2 == 1 ) iPartonJun.push_back(iParton);
884  else iPartonAntiJun.push_back(iParton);
885  }
886 
887  }
888 
889  // Done.
890  return true;
891 
892 }
893 
894 //--------------------------------------------------------------------------
895 
896 // Change the anticolour of the particle that has acol to be col.
897 
898 bool JunctionSplitting::setAcol(Event& event, int col, int acol) {
899 
900  // Update anticolour if it belongs to a particle.
901  for (int j = 0;j < event.size(); ++j)
902  if (event[j].isFinal() && event[j].acol() == acol) {
903  int iNew = event.copy(j,66);
904  event[iNew].acol(col);
905  return true;
906  }
907  // Check if antijunction is connected to a junction.
908  for (int j = 0;j < event.sizeJunction(); ++j)
909  for (int jLeg = 0;jLeg < 3; ++jLeg)
910  if (event.colJunction(j, jLeg) == acol) {
911  event.colJunction(j, jLeg, col);
912  return true;
913  }
914 
915  // If no acol was found something went wrong.
916  infoPtr->errorMsg("Warning in JunctionSplitting::setAcol:"
917  "Anti colour not found when combing two junctions to a string");
918  return false;
919 }
920 
921 //==========================================================================
922 
923 } // end namespace Pythia8
Definition: AgUStep.h:26