stablejet is hosted by Hepforge, IPPP Durham
StableJet
PythiaJetGun.cc
1 #include <cassert>
2 #include <cmath>
3 #include <cfloat>
4 
5 #include "PythiaJetGun.hh"
6 #include "generator/pythia6.h"
7 #include "geners/GenericIO.hh"
8 #include "geners/IOException.hh"
9 
10 #include "rk/rkIO.hh"
11 
12 using namespace geom3;
13 using namespace gs;
14 
15 namespace PythiaJetGun
16 {
17  bool Particle::operator==(const Particle& r) const
18  {
19  return code_ == r.code_ &&
20  p4_.momentum() == r.p4_.momentum() &&
21  p4_.m() == r.p4_.m();
22  }
23 
24  double Particle::charge() const
25  {
26  return pychge(code_)/3.0;
27  }
28 
29  double Particle::gyrationRadius(const double B) const
30  {
31  const double qB = charge()*B;
32  if (qB == 0.0)
33  return DBL_MAX;
34  else
35  {
36  const double c = 299792458.0;
37  return 1.e9/c*p4_.pt()/qB;
38  }
39  }
40 
41  bool Particle::write(std::ostream& of) const
42  {
43  write_item(of, p4_, false);
44  write_pod(of, code_);
45  return !of.fail();
46  }
47 
48  void Particle::restore(const gs::ClassId& id, std::istream& in,
49  Particle* ptr)
50  {
51  static const ClassId myClassId(ClassId::makeId<Particle>());
52  myClassId.ensureSameId(id);
53 
54  assert(ptr);
55  restore_item(in, &ptr->p4_, false);
56  read_pod(in, &ptr->code_);
57 
58  if (in.fail()) throw IOReadFailure("In Particle::restore: "
59  "input stream failure");
60  }
61 
62  double pyrandom()
63  {
64  return pyr();
65  }
66 
67  void pythiacmd(const char* cmd)
68  {
69  pygive(cmd);
70  }
71 
72  double gaussRandom(const double mean, const double sigma)
73  {
74  double r;
75  do {
76  r = 1.0 - pyrandom();
77  } while (r <= 0.0 || r > 1.0);
78  return mean + sigma*sqrt(-2.0*log(r))*cos(2.0*M_PI*pyrandom());
79  }
80 
81  void shoot1(const int code, const double pt, const double eta,
82  const double phi, Particle* partonptr,
83  std::vector<Particle>* output)
84  {
85  assert(pt > 0.0);
86  assert(code >= 1 && code <= 500);
87  int zcode = code;
88  if (pyrandom() < 0.5)
89  zcode = -code;
90 
91  rk::P4 parton(Vector3(pt*cos(phi), pt*sin(phi),
92  pt*sinh(eta)), pymass(zcode));
93 
94  // Generate the hadronization, shooting either particle
95  // or antiparticle in the given direction
96  py1ent(0, zcode, parton.e(), parton.theta(), phi);
97 
98  // Clear all decayed particles (this also removes neutrinos)
99  pyedit(2);
100 
101  // Pick up all particles
102  const int nparticles = pyjets_.n;
103  if (nparticles > 0)
104  {
105  output->clear();
106  output->reserve(nparticles);
107  for (int i=0; i<nparticles; ++i)
108  {
109  Vector3 p(pyjets_.p[0][i],pyjets_.p[1][i],pyjets_.p[2][i]);
110  output->push_back(Particle(pyjets_.k[1][i],
111  rk::P4(p, pyjets_.p[4][i])));
112  }
113  *partonptr = Particle(zcode, parton);
114  }
115  else
116  {
117  /* Hmm... Seems like something did not get generated. Retry. */
118  shoot1(code, pt, eta, phi, partonptr, output);
119  }
120  }
121 
122  void shoot2(const int code, const double pt, const double eta,
123  const double phi, Particle* partonptr,
124  std::vector<Particle>* output, bool runPyexec)
125  {
126  assert(pt > 0.0);
127  assert(code >= 1 && code <= 500);
128  int zcode = code;
129  if (pyrandom() < 0.5)
130  zcode = -code;
131 
132  rk::P4 parton(Vector3(pt*cos(phi), pt*sin(phi),
133  pt*sinh(eta)), pymass(zcode));
134  const UnitVector3 pdir(parton.momentum().direction());
135 
136  // Generate the hadronization, shooting either particle
137  // or antiparticle in the Z direction
138  // py2ent(0, zcode, -zcode, 2.0*parton.e());
139  py2ent(-1, zcode, -zcode, 2.0*parton.e());
140  pyshow(1, 2, 2.0*parton.e());
141  if (runPyexec)
142  pyexec();
143 
144  // Clear all decayed particles (this also removes neutrinos)
145  pyedit(2);
146 
147  // Create the rotation to the lab
148  const UnitVector3 axis(
149  UnitVector3::zAxis().cross(pdir).direction());
150  const double angle = UnitVector3::zAxis().angle(pdir);
151  Rotation3 rot(axis, angle);
152 
153  // Also, rotate the jet randomly around its own axis
154  rot *= Rotation3(pdir, pyrandom()*2.0*M_PI);
155 
156  // Pick up only the particles going into positive Z direction
157  const int nparticles = pyjets_.n;
158  unsigned count = 0;
159  for (int i=0; i<nparticles; ++i)
160  if (pyjets_.p[2][i] > 0.0)
161  ++count;
162 
163  if (count > 0)
164  {
165  output->clear();
166  output->reserve(count);
167  for (int i=0; i<nparticles; ++i)
168  if (pyjets_.p[2][i] > 0.0)
169  {
170  Vector3 p(pyjets_.p[0][i],pyjets_.p[1][i],pyjets_.p[2][i]);
171  output->push_back(Particle(pyjets_.k[1][i],
172  rk::P4(rot.rotate(p), pyjets_.p[4][i])));
173  }
174  *partonptr = Particle(zcode, parton);
175  }
176  else
177  {
178  /* Hmm... Seems like something did not get generated. Retry. */
179  shoot2(code, pt, eta, phi, partonptr, output);
180  }
181  }
182 }