thepeg is hosted by Hepforge, IPPP Durham
ThePEG  2.2.1
HelicityFunctions.h
1 // -*- C++ -*-
2 //
3 // HelicityFunctions.h is a part of ThePEG - Toolkit for HEP Event Generation
4 // Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad
5 //
6 // ThePEG is licenced under version 3 of the GPL, see COPYING for details.
7 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
8 //
9 #ifndef ThePEG_HelicityFunctions_H
10 #define ThePEG_HelicityFunctions_H
11 //
12 // This is the declaration of the HelicityFunctions header for common functions
13 // used in helicity calculations to avoid duplication of code
14 
16 #include "LorentzSpinor.h"
17 #include "LorentzSpinorBar.h"
18 
19 namespace ThePEG {
20 namespace Helicity {
21 namespace HelicityFunctions {
22 
23 inline LorentzPolarizationVector polarizationVector(const Lorentz5Momentum & p,
24  unsigned int ihel,
25  Direction dir,
27  // check the direction
28  assert(dir!=intermediate);
29  // special helicity combination for gauge invariance tests
30  if(ihel==10) return p*UnitRemoval::InvE;
31  // check a valid helicity combination
32  assert(ihel==0 || ihel == 2 || ((ihel==1 || ihel==3) && p.mass()>ZERO ));
33  // convert the helicitty from 0,1,2 to -1,0,1
34  int jhel=ihel-1;
35  // extract the momentum components
36  double fact = dir==outgoing ? -1 : 1;
37  Energy ppx=fact*p.x(),ppy=fact*p.y(),ppz=fact*p.z(),pee=fact*p.e(),pmm=p.mass();
38  // calculate some kinematic quantites
39  Energy2 pt2 = ppx*ppx+ppy*ppy;
40  Energy pabs = sqrt(pt2+ppz*ppz);
41  Energy pt = sqrt(pt2);
42  // zero subtracted
43  if(ihel==3) {
44  InvEnergy pre = pmm/pabs/(pee+pabs);
45  return LorentzPolarizationVector(double(pre*ppx),double(pre*ppy),double(pre*ppz),-double(pre*pabs));
46  }
47  // overall phase of the vector
48  Complex phase(1.);
49  if(vphase==vector_phase) {
50  if(pt==ZERO || ihel==1) phase = 1.;
51  else if(ihel==0) phase = Complex(ppx/pt,-fact*ppy/pt);
52  else phase = Complex(ppx/pt, fact*ppy/pt);
53  }
54  if(ihel!=1) phase = phase/sqrt(2.);
55  // first the +/-1 helicity states
56  if(ihel!=1) {
57  // first the zero pt case
58  if(pt==ZERO) {
59  double sgnz = ppz<ZERO ? -1. : 1.;
60  return LorentzPolarizationVector(-complex<double>(jhel)*phase,
61  sgnz*phase*complex<double>(0,-fact),
62  0.,0.);
63  }
64  else {
65  InvEnergy opabs=1./pabs;
66  InvEnergy opt =1./pt;
67  return LorentzPolarizationVector(phase*complex<double>(-jhel*ppz*ppx*opabs*opt, fact*ppy*opt),
68  phase*complex<double>(-jhel*ppz*ppy*opabs*opt,-fact*ppx*opt),
69  double(jhel*pt*opabs)*phase,0.);
70  }
71  }
72  // 0 component for massive vectors
73  else {
74  if(pabs==ZERO) {
75  return LorentzPolarizationVector(0.,0.,1.,0.);
76  }
77  else {
78  InvEnergy empabs=pee/pmm/pabs;
79  return LorentzPolarizationVector(double(empabs*ppx),double(empabs*ppy),
80  double(empabs*ppz),double(pabs/pmm));
81  }
82  }
83 }
84 
85 
86 inline LorentzSpinor<SqrtEnergy> dimensionedSpinor(const Lorentz5Momentum & p,
87  unsigned int ihel,
88  Direction dir) {
89  // check direction and helicity
90  assert(dir!=intermediate);
91  assert(ihel<=1);
92  // extract the momentum components
93  double fact = dir==incoming ? 1 : -1.;
94  Energy ppx=fact*p.x(),ppy=fact*p.y(),ppz=fact*p.z(),pee=fact*p.e(),pmm=p.mass();
95  // define and calculate some kinematic quantities
96  Energy2 ptran2 = ppx*ppx+ppy*ppy;
97  Energy pabs = sqrt(ptran2+ppz*ppz);
98  Energy ptran = sqrt(ptran2);
99  // first need to evalulate the 2-component helicity spinors
100  // this is the same regardless of which definition of the spinors
101  // we are using
102  complex <double> hel_wf[2];
103  // compute the + spinor for + helicty particles and - helicity antiparticles
104  if((dir==incoming && ihel== 1) || (dir==outgoing && ihel==0)) {
105  // no transverse momentum
106  if(ptran==ZERO) {
107  if(ppz>=ZERO) {
108  hel_wf[0] = 1;
109  hel_wf[1] = 0;
110  }
111  else {
112  hel_wf[0] = 0;
113  hel_wf[1] = 1;
114  }
115  }
116  else {
117  InvSqrtEnergy denominator = 1./sqrt(2.*pabs);
118  SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz);
119  hel_wf[0] = denominator*rtppluspz;
120  hel_wf[1] = Complex(denominator/rtppluspz*complex<Energy>(ppx,ppy));
121  }
122  }
123  // compute the - spinor for - helicty particles and + helicity antiparticles
124  else {
125  // no transverse momentum
126  if(ptran==ZERO) {
127  if(ppz>=ZERO) {
128  hel_wf[0] = 0;
129  hel_wf[1] = 1;
130  }
131  // transverse momentum
132  else {
133  hel_wf[0] = -1;
134  hel_wf[1] = 0;
135  }
136  }
137  else {
138  InvSqrtEnergy denominator = 1./sqrt(2.*pabs);
139  SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz);
140  hel_wf[0] = Complex(denominator/rtppluspz*complex<Energy>(-ppx,ppy));
141  hel_wf[1] = denominator*rtppluspz;
142  }
143  }
144 
145  SqrtEnergy upper,lower;
146  SqrtEnergy eplusp = sqrt(max(pee+pabs,ZERO));
147  SqrtEnergy eminusp = ( pmm != ZERO ) ? pmm/eplusp : ZERO;
148  // set up the coefficients for the different cases
149  if(dir==incoming) {
150  if(ihel==1) {
151  upper = eminusp;
152  lower = eplusp;
153  }
154  else {
155  upper = eplusp;
156  lower = eminusp;
157  }
158  }
159  else {
160  if(ihel==1) {
161  upper = -eplusp;
162  lower = eminusp;
163  }
164  else {
165  upper = eminusp;
166  lower =-eplusp;
167  }
168  }
169  return LorentzSpinor<SqrtEnergy>(upper*hel_wf[0],upper*hel_wf[1],
170  lower*hel_wf[0],lower*hel_wf[1],
172 }
173 
174 inline LorentzSpinor<double> spinor(const Lorentz5Momentum & p,
175  unsigned int ihel,
176  Direction dir) {
177  LorentzSpinor<SqrtEnergy> temp = dimensionedSpinor(p,ihel,dir);
178  return LorentzSpinor<double>(temp.s1()*UnitRemoval::InvSqrtE,
179  temp.s2()*UnitRemoval::InvSqrtE,
180  temp.s3()*UnitRemoval::InvSqrtE,
181  temp.s4()*UnitRemoval::InvSqrtE,temp.Type());
182 }
183 
184 inline LorentzSpinorBar<SqrtEnergy> dimensionedSpinorBar(const Lorentz5Momentum & p,
185  unsigned int ihel,
186  Direction dir) {
187  // check direction and helicity
188  assert(dir!=intermediate);
189  assert(ihel<=1);
190  // extract the momentum components
191  double fact = dir==incoming ? 1. : -1.;
192  Energy ppx=fact*p.x(),ppy=fact*p.y(),ppz=fact*p.z(),pee=fact*p.e(),pmm=p.mass();
193  // define and calculate some kinematic quantities
194  Energy2 ptran2 = ppx*ppx+ppy*ppy;
195  Energy pabs = sqrt(ptran2+ppz*ppz);
196  Energy ptran = sqrt(ptran2);
197  // first need to evalulate the 2-component helicity spinors
198  Complex hel_wf[2];
199  // compute the + spinor for + helicty particles and - helicity antiparticles
200  if((dir==outgoing && ihel== 1) || (dir==incoming && ihel==0)) {
201  // no transverse momentum
202  if(ptran==ZERO) {
203  if(ppz>=ZERO) {
204  hel_wf[0] = 1;
205  hel_wf[1] = 0;
206  }
207  else {
208  hel_wf[0] = 0;
209  hel_wf[1] = 1;
210  }
211  }
212  else {
213  InvSqrtEnergy denominator = 1./sqrt(2.*pabs);
214  SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz);
215  hel_wf[0] = denominator*rtppluspz;
216  hel_wf[1] = Complex(denominator/rtppluspz*complex<Energy>(ppx,-ppy));
217  }
218  }
219  // compute the - spinor for - helicty particles and + helicity antiparticles
220  else {
221  // no transverse momentum
222  if(ptran==ZERO) {
223  if(ppz>=ZERO) {
224  hel_wf[0] = 0;
225  hel_wf[1] = 1;
226  }
227  // transverse momentum
228  else {
229  hel_wf[0] = -1;
230  hel_wf[1] = 0;
231  }
232  }
233  else {
234  InvSqrtEnergy denominator = 1./sqrt(2.*pabs);
235  SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz);
236  hel_wf[0] = Complex(denominator/rtppluspz*complex<Energy>(-ppx,-ppy));
237  hel_wf[1] = denominator*rtppluspz;
238  }
239  }
240  SqrtEnergy upper, lower;
241  SqrtEnergy eplusp = sqrt(max(pee+pabs,ZERO));
242  SqrtEnergy eminusp = ( pmm!=ZERO ) ? pmm/eplusp : ZERO;
243  // set up the coefficients for the different cases
244  if(dir==outgoing) {
245  if(ihel==1) {
246  upper = eplusp;
247  lower = eminusp;
248  }
249  else {
250  upper = eminusp;
251  lower = eplusp;
252  }
253  }
254  else {
255  if(ihel==1) {
256  upper = eminusp;
257  lower = -eplusp;
258  }
259  else {
260  upper =-eplusp;
261  lower = eminusp;
262  }
263  }
264  // now finally we can construct the spinors
265  return LorentzSpinorBar<SqrtEnergy>(upper*hel_wf[0],
266  upper*hel_wf[1],
267  lower*hel_wf[0],
268  lower*hel_wf[1],
270 }
271 
272 inline LorentzSpinorBar<double> spinorBar(const Lorentz5Momentum & p,
273  unsigned int ihel,
274  Direction dir) {
275  LorentzSpinorBar<SqrtEnergy> temp = dimensionedSpinorBar(p,ihel,dir);
276  return LorentzSpinorBar<double>(temp.s1()*UnitRemoval::InvSqrtE,
277  temp.s2()*UnitRemoval::InvSqrtE,
278  temp.s3()*UnitRemoval::InvSqrtE,
279  temp.s4()*UnitRemoval::InvSqrtE,temp.Type());
280 }
281 }
282 }
283 }
284 
285 #endif /* ThePEG_HelicityFunctions_H */
Qty< 0, 1, 0 > Energy
Energy.
Definition: Unitsystem.h:42
std::complex< double > Complex
ThePEG code should use Complex for all complex scalars.
Definition: Complex.h:23
An incoming particle.
This is the main namespace within which all identifiers in ThePEG are declared.
Definition: FactoryBase.h:28
An intermediate particle.
An outgoing particle.
Include the phase factor.
VectorPhase
Definition of the enumerated values of the phase to include in the calculation of the polarization ve...
contains the LorentzVector class.
Direction
Definition of the enumerated values used for the direction of the particles in the calculation of the...
LorentzVector< complex< double > > LorentzPolarizationVector
Convenience typedef.
constexpr ZeroUnit ZERO
ZERO can be used as zero for any unitful quantity.
Definition: PhysicalQty.h:35