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