StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HiddenValleyFragmentation.cc
1 // HiddenValleyFragmentation.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 // HiddenValleyFragmentation class and its helper classes.
8 
9 #include "Pythia8/HiddenValleyFragmentation.h"
10 
11 namespace Pythia8 {
12 
13 //==========================================================================
14 
15 // The HVStringFlav class is used to select HV-quark and HV-hadron flavours.
16 
17 //--------------------------------------------------------------------------
18 
19 // Initialize data members of the flavour generation.
20 
21 void HVStringFlav::init() {
22 
23  // Read in data from Settings.
24  nFlav = mode("HiddenValley:nFlav");
25  probVector = parm("HiddenValley:probVector");
26  thermalModel = false;
27  useWidthPre = false;
28  closePacking = false;
29  mT2suppression = false;
30 
31 }
32 
33 //--------------------------------------------------------------------------
34 
35 // Pick a new HV-flavour given an incoming one.
36 
37 FlavContainer HVStringFlav::pick(FlavContainer& flavOld, double, double,
38  bool) {
39 
40  // Initial values for new flavour.
41  FlavContainer flavNew;
42  flavNew.rank = flavOld.rank + 1;
43 
44  // Pick new HV-flavour at random; keep track of sign.
45  flavNew.id = 4900100 + min( 1 + int(nFlav * rndmPtr->flat()), nFlav);
46  if (flavOld.id > 0) flavNew.id = -flavNew.id;
47 
48  // Done.
49  return flavNew;
50 
51 }
52 
53 //--------------------------------------------------------------------------
54 
55 // Combine two HV-flavours to produce an HV-hadron.
56 // This is simplified procedure, assuming only two HV mesons defined.
57 
58 int HVStringFlav::combine(FlavContainer& flav1, FlavContainer& flav2) {
59 
60  // Positive and negative flavour. Note that with kinetic mixing
61  // the Fv are really intended to represent qv, so remap.
62  int idMeson = 0;
63  int idPos = max( flav1.id, flav2.id) - 4900000;
64  int idNeg = -min( flav1.id, flav2.id) - 4900000;
65  if (idPos < 20) idPos = 101;
66  if (idNeg < 20) idNeg = 101;
67 
68  // Pick HV-meson code, spin either 0 or 1.
69  if (idNeg == idPos) idMeson = 4900111;
70  else if (idPos > idNeg) idMeson = 4900211;
71  else idMeson = -4900211;
72  if (rndmPtr->flat() < probVector) idMeson += ((idMeson > 0) ? 2 : -2);
73 
74  // Done.
75  return idMeson;
76 
77 }
78 
79 //==========================================================================
80 
81 // The HVStringPT class is used to select pT in HV fragmentation.
82 
83 //--------------------------------------------------------------------------
84 
85 // Initialize data members of the string pT selection.
86 
87 void HVStringPT::init() {
88 
89  // Parameter of the pT width. No enhancement, since this is finetuning.
90  double sigmamqv = parm("HiddenValley:sigmamqv");
91  double sigma = sigmamqv * particleDataPtr->m0( 4900101);
92  sigmaQ = sigma / sqrt(2.);
93  enhancedFraction = 0.;
94  enhancedWidth = 0.;
95 
96  // Parameter for pT suppression in MiniStringFragmentation.
97  sigma2Had = 2. * pow2( max( SIGMAMIN, sigma) );
98  thermalModel = false;
99  useWidthPre = false;
100  closePacking = false;
101 
102 }
103 
104 //==========================================================================
105 
106 // The HVStringZ class is used to select z in HV fragmentation.
107 
108 //--------------------------------------------------------------------------
109 
110 // Initialize data members of the string z selection.
111 
112 void HVStringZ::init() {
113 
114  // Paramaters of Lund/Bowler symmetric fragmentation function.
115  aLund = parm("HiddenValley:aLund");
116  bmqv2 = parm("HiddenValley:bmqv2");
117  rFactqv = parm("HiddenValley:rFactqv");
118 
119  // Use qv mass to set scale of bEff = b * m^2;
120  mqv2 = pow2( particleDataPtr->m0( 4900101) );
121  bLund = bmqv2 / mqv2;
122 
123  // Mass of qv meson used to set stop scale for fragmentation iteration.
124  mhvMeson = particleDataPtr->m0( 4900111);
125 
126 }
127 
128 //--------------------------------------------------------------------------
129 
130 // Generate the fraction z that the next hadron will take using Lund/Bowler.
131 
132 double HVStringZ::zFrag( int , int , double mT2) {
133 
134  // Shape parameters of Lund symmetric fragmentation function.
135  double bShape = bLund * mT2;
136  double cShape = 1. + rFactqv * bmqv2;
137  return zLund( aLund, bShape, cShape);
138 
139 }
140 
141 //==========================================================================
142 
143 // The HiddenValleyFragmentation class.
144 
145 //--------------------------------------------------------------------------
146 
147 // Initialize and save pointers.
148 
149 bool HiddenValleyFragmentation::init() {
150 
151  // Check whether Hidden Valley fragmentation switched on, and SU(N).
152  doHVfrag = flag("HiddenValley:fragment");
153  if (mode("HiddenValley:Ngauge") < 2) doHVfrag = false;
154  if (!doHVfrag) return false;
155 
156  // Several copies of qv may be needed. Taken to have same mass.
157  nFlav = mode("HiddenValley:nFlav");
158  if (nFlav > 1) {
159  int spinType = particleDataPtr->spinType(4900101);
160  double m0 = particleDataPtr->m0(4900101);
161  for (int iFlav = 2; iFlav <= nFlav; ++iFlav)
162  particleDataPtr->addParticle( 4900100 + iFlav, "qv", "qvbar",
163  spinType, 0, 0, m0);
164  }
165 
166  // Hidden Valley meson mass used to choose hadronization mode.
167  mhvMeson = particleDataPtr->m0(4900111);
168 
169  // Initialize the hvEvent instance of an event record.
170  hvEvent.init( "(Hidden Valley fragmentation)", particleDataPtr);
171 
172  // Create HVStringFlav instance for HV-flavour selection.
173  hvFlavSel.init();
174 
175  // Create HVStringPT instance for pT selection in HV fragmentation.
176  hvPTSel.init();
177 
178  // Create HVStringZ instance for z selection in HV fragmentation.
179  hvZSel.init();
180 
181  // Initialize auxiliary administrative class.
182  hvColConfig.init(infoPtr, &hvFlavSel);
183 
184  // Initialize HV-string and HV-ministring fragmentation.
185  hvStringFrag.init(&hvFlavSel, &hvPTSel, &hvZSel);
186  hvMinistringFrag.init(&hvFlavSel, &hvPTSel, &hvZSel);
187 
188  // Done.
189  return true;
190 
191 }
192 
193 //--------------------------------------------------------------------------
194 
195 // Perform the fragmentation.
196 
197 bool HiddenValleyFragmentation::fragment(Event& event) {
198 
199  // Reset containers for next event.
200  hvEvent.reset();
201  hvColConfig.clear();
202  ihvParton.resize(0);
203 
204  // Extract HV-particles from event to hvEvent. Assign HV-colours.
205  // Done if no HV-particles found.
206  if (!extractHVevent(event)) return true;
207 
208  // Store found string system. Analyze its properties.
209  if (!hvColConfig.insert(ihvParton, hvEvent)) return false;
210 
211  // Collect sequentially all partons in the HV subsystem.
212  // Copy also if already in order, or else history tracing may fail.
213  hvColConfig.collect(0, hvEvent, false);
214 
215  // Mass used to decide how to fragment system.
216  mSys = hvColConfig[0].mass;
217 
218  // HV-string fragmentation when enough mass to produce >= 3 HV-mesons.
219  if (mSys > 3.5 * mhvMeson) {
220  if (!hvStringFrag.fragment( 0, hvColConfig, hvEvent)) return false;
221 
222  // HV-ministring fragmentation when enough mass to produce 2 HV-mesons.
223  } else if (mSys > 2.1 * mhvMeson) {
224  if (!hvMinistringFrag.fragment( 0, hvColConfig, hvEvent, true))
225  return false;
226 
227  // If only enough mass for one HV-meson assume HV-glueballs emitted.
228  } else if (!collapseToMeson()) return false;
229 
230  // Insert HV particles from hvEvent to event.
231  insertHVevent(event);
232 
233  // Done.
234  return true;
235 
236 }
237 
238 //--------------------------------------------------------------------------
239 
240 // Extract HV-particles from event to hvEvent. Assign HV-colours.
241 
242 bool HiddenValleyFragmentation::extractHVevent(Event& event) {
243 
244  // Copy Hidden-Valley particles to special event record.
245  for (int i = 0; i < event.size(); ++i) {
246  int idAbs = event[i].idAbs();
247  bool isHV = (idAbs > 4900000 && idAbs < 4900007)
248  || (idAbs > 4900010 && idAbs < 4900017)
249  || idAbs == 4900021
250  || (idAbs > 4900100 && idAbs < 4900109);
251  if (isHV) {
252  int iHV = hvEvent.append( event[i]);
253  // Convert HV-gluons into normal ones so as to use normal machinery.
254  if (event[i].id() == 4900021) hvEvent[iHV].id(21);
255  // Second mother points back to position in complete event;
256  // otherwise construct the HV history inside hvEvent.
257  hvEvent[iHV].mothers( 0, i);
258  hvEvent[iHV].daughters( 0, 0);
259  int iMother = event[i].mother1();
260  for (int iHVM = 1; iHVM < hvEvent.size(); ++iHVM)
261  if (hvEvent[iHVM].mother2() == iMother) {
262  hvEvent[iHV].mother1( iHVM);
263  if (hvEvent[iHVM].daughter1() == 0) hvEvent[iHVM].daughter1(iHV);
264  else hvEvent[iHVM].daughter2(iHV);
265  }
266  }
267  }
268 
269  // Done if no HV particles found.
270  hvOldSize = hvEvent.size();
271  if (hvOldSize == 1) return false;
272 
273  // Initial colour - anticolour parton pair.
274  int colBeg = hvEvent.nextColTag();
275  for (int iHV = 1; iHV < hvOldSize; ++iHV)
276  if (hvEvent[iHV].mother1() == 0) {
277  if (hvEvent[iHV].id() > 0) hvEvent[iHV].col( colBeg);
278  else hvEvent[iHV].acol( colBeg);
279  }
280 
281  // Then trace colours down to daughters; new colour if two daughters.
282  for (int iHV = 1; iHV < hvOldSize; ++iHV) {
283  int dau1 = hvEvent[iHV].daughter1();
284  int dau2 = hvEvent[iHV].daughter2();
285  if (dau1 > 0 && dau2 == 0)
286  hvEvent[dau1].cols( hvEvent[iHV].col(), hvEvent[iHV].acol());
287  else if (dau2 > 0) {
288  int colHV = hvEvent[iHV].col();
289  int acolHV = hvEvent[iHV].acol();
290  int colNew = hvEvent.nextColTag();
291  if (acolHV == 0) {
292  hvEvent[dau1].cols( colNew, 0);
293  hvEvent[dau2].cols( colHV, colNew);
294  } else if (colHV == 0) {
295  hvEvent[dau1].cols( 0, colNew);
296  hvEvent[dau2].cols( colNew, acolHV);
297  // Temporary: should seek recoiling dipole end!??
298  } else if (rndmPtr->flat() > 0.5) {
299  hvEvent[dau1].cols( colHV, colNew);
300  hvEvent[dau2].cols( colNew, acolHV);
301  } else {
302  hvEvent[dau1].cols( colNew, acolHV);
303  hvEvent[dau2].cols( colHV, colNew);
304  }
305  }
306  }
307 
308  // Pick up the colour end.
309  int colNow = 0;
310  for (int iHV = 1; iHV < hvOldSize; ++iHV)
311  if (hvEvent[iHV].isFinal() && hvEvent[iHV].acol() == 0) {
312  ihvParton.push_back( iHV);
313  colNow = hvEvent[iHV].col();
314  }
315 
316  // Trace colour by colour until reached anticolour end.
317  while (colNow > 0) {
318  for (int iHV = 1; iHV < hvOldSize; ++iHV)
319  if (hvEvent[iHV].isFinal() && hvEvent[iHV].acol() == colNow) {
320  ihvParton.push_back( iHV);
321  colNow = hvEvent[iHV].col();
322  break;
323  }
324  }
325 
326  // Done.
327  return true;
328 
329 }
330 
331 //--------------------------------------------------------------------------
332 
333 // Collapse of light system to one HV-meson, by the emission of HV-glueballs.
334 
335 bool HiddenValleyFragmentation::collapseToMeson() {
336 
337  // If too low mass then cannot do anything. Should not happen.
338  if (mSys < 1.001 * mhvMeson) {
339  infoPtr->errorMsg("Error in HiddenValleyFragmentation::collapseToMeson:"
340  " too low mass to do anything");
341  return false;
342  }
343 
344  // Choose mass of collective HV-glueball states flat between limits.
345  double mhvGlue = (0.001 + 0.998 * rndmPtr->flat()) * (mSys - mhvMeson);
346 
347  // Find momentum in rest frame, with isotropic "decay" angles.
348  double pAbs = 0.5 * sqrtpos( pow2(mSys*mSys - mhvMeson*mhvMeson
349  - mhvGlue*mhvGlue) - pow2(2. * mhvMeson * mhvGlue) ) / mSys;
350  double pz = (2 * rndmPtr->flat() - 1.) * pAbs;
351  double pT = sqrtpos( pAbs*pAbs - pz*pz);
352  double phi = 2. * M_PI * rndmPtr->flat();
353  double px = pT * cos(phi);
354  double py = pT * sin(phi);
355 
356  // Construct four-vectors and boost them to event frame.
357  Vec4 phvMeson( px, py, pz, sqrt(mhvMeson*mhvMeson + pAbs*pAbs) );
358  Vec4 phvGlue( -px, -py, -pz, sqrt(mhvGlue*mhvGlue + pAbs*pAbs) );
359  phvMeson.bst( hvColConfig[0].pSum );
360  phvGlue.bst( hvColConfig[0].pSum );
361 
362  // Add produced particles to the event record.
363  vector<int> iParton = hvColConfig[0].iParton;
364  int iFirst = hvEvent.append( 4900111, 82, iParton.front(),
365  iParton.back(), 0, 0, 0, 0, phvMeson, mhvMeson);
366  int iLast = hvEvent.append( 4900991, 82, iParton.front(),
367  iParton.back(), 0, 0, 0, 0, phvGlue, mhvGlue);
368 
369  // Mark original partons as hadronized and set their daughter range.
370  for (int i = 0; i < int(iParton.size()); ++i) {
371  hvEvent[ iParton[i] ].statusNeg();
372  hvEvent[ iParton[i] ].daughters(iFirst, iLast);
373  }
374 
375  // Done.
376  return true;
377 
378 }
379 
380 //--------------------------------------------------------------------------
381 
382 // Insert HV-particles from hvEvent to event.
383 
384 bool HiddenValleyFragmentation::insertHVevent(Event& event) {
385 
386  // Offset for mother/daughter indices.
387  hvNewSize = hvEvent.size();
388  int nOffset = event.size() - hvOldSize;
389 
390  // Copy back HV-particles.
391  int iNew, iMot1, iMot2, iDau1, iDau2;
392  for (int iHV = hvOldSize; iHV < hvNewSize; ++iHV) {
393  iNew = event.append( hvEvent[iHV]);
394 
395  // Restore HV-gluon codes. Do not keep HV-colours, to avoid confusion.
396  if (hvEvent[iHV].id() == 21) event[iNew].id(4900021);
397  event[iNew].cols( 0, 0);
398 
399  // Begin history construction.
400  iMot1 = hvEvent[iHV].mother1();
401  iMot2 = hvEvent[iHV].mother2();
402  iDau1 = hvEvent[iHV].daughter1();
403  iDau2 = hvEvent[iHV].daughter2();
404  // Special mother for partons copied from event, else simple offset.
405  // Also set daughters of mothers in original record.
406  if (iMot1 > 0 && iMot1 < hvOldSize) {
407  iMot1 = hvEvent[iMot1].mother2();
408  event[iMot1].statusNeg();
409  event[iMot1].daughter1(iNew);
410  } else if (iMot1 > 0) iMot1 += nOffset;
411  if (iMot2 > 0 && iMot2 < hvOldSize) {
412  iMot2 = hvEvent[iMot2].mother2();
413  event[iMot2].statusNeg();
414  if (event[iMot2].daughter1() == 0) event[iMot2].daughter1(iNew);
415  else event[iMot2].daughter2(iNew);
416  } else if (iMot2 > 0) iMot2 += nOffset;
417  if (iDau1 > 0) iDau1 += nOffset;
418  if (iDau2 > 0) iDau2 += nOffset;
419  event[iNew].mothers( iMot1, iMot2);
420  event[iNew].daughters( iDau1, iDau2);
421  }
422 
423  // Done.
424  return true;
425 
426 }
427 
428 //==========================================================================
429 
430 } // end namespace Pythia8
Definition: AgUStep.h:26