EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gammagammasingle.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file gammagammasingle.cpp
1 
2 //
3 // Copyright 2010
4 //
5 // This file is part of starlight.
6 //
7 // starlight is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // starlight is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with starlight. If not, see <http://www.gnu.org/licenses/>.
19 //
21 //
22 // File and Version Information:
23 // $Rev:: 274 $: revision of last commit
24 // $Author:: butter $: author of last commit
25 // $Date:: 2016-09-11 23:40:25 +0100 #$: date of last commit
26 //
27 // Description:
28 //
29 //
30 //
32 
33 #include <iostream>
34 #include <fstream>
35 #include <cmath>
36 #include <vector>
37 
38 
39 #include "starlightconstants.h"
40 #include "gammagammasingle.h"
41 #include "starlightconfig.h"
42 
43 using namespace std;
44 
45 
46 //______________________________________________________________________________
47 Gammagammasingle::Gammagammasingle(const inputParameters& inputParametersInstance, beamBeamSystem& bbsystem)
48 : eventChannel(inputParametersInstance, bbsystem)
49 #ifdef ENABLE_PYTHIA
50 ,_pyDecayer()
51 #endif
52 {
53 
54 #ifdef ENABLE_PYTHIA
55  _pyDecayer.init();
56 #endif
57 
58  //Storing inputparameters into protected members for use
59  _GGsingInputnumw=inputParametersInstance.nmbWBins();
60  _GGsingInputnumy=inputParametersInstance.nmbRapidityBins();
61  _GGsingInputpidtest=inputParametersInstance.prodParticleType();
62  _GGsingInputGamma_em=inputParametersInstance.beamLorentzGamma();
63  _axionMass=inputParametersInstance.axionMass(); // AXION HACK
64  cout<<"SINGLE MESON pid test: "<<_GGsingInputpidtest<<endl;
65  //reading in luminosity tables
66  read();
67  //Now calculating crosssection
69 }
70 
71 
72 //______________________________________________________________________________
74 { }
75 
76 
77 //______________________________________________________________________________
79 {
80  //This function carries out a delta function cross-section calculation. For reference, see STAR Note 243, Eq. 8
81  //Multiply all _Farray[] by _f_max
82  double _sigmaSum=0.,remainw=0.;//_remainwd=0.;
83  int ivalw =0;//_ivalwd;
84  //calculate the differential cross section and place in the sigma table
85  cout << "MASS " << getMass() << "\n"; // AXION HACK, optional
86  cout << "WIDTH " << getWidth() << "\n";// AXION HACK, optional
87  _wdelta=getMass();
88  for(int i=0;i<_GGsingInputnumw;i++){
89  for(int j=0;j<_GGsingInputnumy;j++){
90  // Eq. 1 of starnote 347
93  }
94  }
95  //find the index, i,for the value of w just less than the mass because we want to use the value from the sigma table that has w=mass
96 
97  for(int i=0;i<_GGsingInputnumw;i++){
98  if(getMass()>_Warray[i]) ivalw=i;
99  }
100 
101  remainw = (getMass()-_Warray[ivalw])/(_Warray[ivalw+1]-_Warray[ivalw]);
102  _ivalwd = ivalw;
103  _remainwd = remainw;
104  //if we are interested rho pairs at threshold, the just set sigma to 100nb
105  switch(_GGsingInputpidtest){
107  _sigmaSum =0.;
108  for(int j=0;j<_GGsingInputnumy-1;j++){
109  _sigmaSum = _sigmaSum +(_Yarray[j+1]-_Yarray[j])*
110  100.0E-9*(.1/getMass())*((1.-remainw)*_f_max*
111  (_Farray[ivalw][j]+_Farray[ivalw][j])/2.+remainw*_f_max*
112  (_Farray[ivalw+1][j]+_Farray[ivalw+1][j+1])/2.);
113  }
114  break;
115  default:
116  //Sum to find the total cross-section
117  _sigmaSum =0.;
118  for(int j =0;j<_GGsingInputnumy-1;j++){
119  _sigmaSum = _sigmaSum+
120  (_Yarray[j+1]-_Yarray[j])*((1.-remainw)*
121  (_sigmax[ivalw][j]+_sigmax[ivalw][j+1])/2.+remainw*
122  (_sigmax[ivalw+1][j]+_sigmax[ivalw+1][j+1])/2.);
123  }
124  }
125  // if(_sigmaSum > 0.1) cout <<"The total cross-section is: "<<_sigmaSum<<" barns."<<endl;
126  // else if(_sigmaSum > 0.0001)cout <<"The total cross-section is: "<<_sigmaSum*1000<<" mb."<<endl;
127  // else cout <<"The total cross-section is: "<<_sigmaSum*1000000<<" ub."<<endl;
128  cout<<endl;
129  if (_sigmaSum > 1.){
130  cout << "Total cross section: "<<_sigmaSum<<" barn."<<endl;
131  } else if (1000.*_sigmaSum > 1.){
132  cout << "Total cross section: "<<1000.*_sigmaSum<<" mb."<<endl;
133  } else if (1000000.*_sigmaSum > 1.){
134  cout << "Total cross section: "<<1000000.*_sigmaSum<<" microbarn."<<endl;
135  } else if (1.E9*_sigmaSum > 1.){
136  cout << "Total cross section: "<<1.E9*_sigmaSum<<" nanobarn."<<endl;
137  } else if (1.E12*_sigmaSum > 1.){
138  cout << "Total cross section: "<<1.E12*_sigmaSum<<" picobarn."<<endl;
139  } else {
140  cout << "Total cross section: "<<1.E15*_sigmaSum<<" femtobarn."<<endl;
141  }
142  cout<<endl;
143  setTotalChannelCrossSection(_sigmaSum);
144 
145  return;
146 }
147 
148 
149 //______________________________________________________________________________
150 void Gammagammasingle::pickw(double &w)
151 {
152  //This function picks a w for the 2-photon calculation.
153  double sgf=0.,signorm=0.,x=0.,remainarea=0.,remainw=0.,a=0.,b=0.,c=0.;
154  int ivalw=0;
155 
156  double * _sigofw;
157  double * sgfint;
158  _sigofw = new double[starlightLimits::MAXWBINS];
159  sgfint = new double[starlightLimits::MAXYBINS];
160 
161  if(_wdelta != 0){
162  w=_wdelta;
163  ivalw=_ivalwd;
164  remainw=_remainwd;
165  }
166  else{
167  //deal with the case where sigma is an array
168  //_sigofw is simga integrated over y using a linear interpolation
169  //sigint is the integral of sgfint, normalized
170 
171  //integrate sigma down to a function of just w
172  for(int i=0;i<_GGsingInputnumw;i++){
173  _sigofw[i]=0.;
174  for(int j=0;j<_GGsingInputnumy-1;j++){
175  _sigofw[i] = _sigofw[i]+(_Yarray[j+1]-_Yarray[j])*(_sigmax[i][j+1]+_sigmax[i][j])/2.;
176  }
177  }
178  //calculate the unnormalized sgfint array
179  sgfint[0]=0.;
180  for(int i=0;i<_GGsingInputnumw-1;i++){
181  sgf=(_sigofw[i+1]+_sigofw[i])*(_Warray[i+1]-_Warray[i])/2.;
182  sgfint[i+1]=sgfint[i]+sgf;
183  }
184  //normalize sgfint array
185  signorm=sgfint[_GGsingInputnumw-1];
186 
187  for(int i=0;i<_GGsingInputnumw;i++){
188  sgfint[i]=sgfint[i]/signorm;
189  }
190  //pick a random number
191  x = _randy.Rndom();
192  //compare x and sgfint to find the ivalue which is just less than the random number x
193  for(int i=0;i<_GGsingInputnumw;i++){
194  if(x > sgfint[i]) ivalw=i;
195  }
196  //remainder above ivalw
197  remainarea = x - sgfint[ivalw];
198 
199  //figure out what point corresponds to the excess area in remainarea
200  c = -remainarea*signorm/(_Warray[ivalw+1]-_Warray[ivalw]);
201  b = _sigofw[ivalw];
202  a = (_sigofw[ivalw+1]-_sigofw[ivalw])/2.;
203  if(a==0.){
204  remainw = -c/b;
205  }
206  else{
207  remainw = (-b+sqrt(b*b-4.*a*c))/(2.*a);
208  }
209  _ivalwd = ivalw;
210  _remainwd = remainw;
211  //calculate the w value
212  w = _Warray[ivalw]+(_Warray[ivalw+1]-_Warray[ivalw])*remainw;
213  }
214 
215  delete[] _sigofw;
216  delete[] sgfint;
217 }
218 
219 
220 //______________________________________________________________________________
222 {
223  double * sigofy;
224  double * sgfint;
225  sigofy = new double[starlightLimits::MAXYBINS];
226  sgfint = new double[starlightLimits::MAXYBINS];
227 
228  double remainw =0.,remainarea=0.,remainy=0.,a=0.,b=0.,c=0.,sgf=0.,signorm=0.,x=0.;
229  int ivalw=0,ivaly=0;
230 
231  ivalw=_ivalwd;
232  remainw=_remainwd;
233  //average over two colums to get y array
234  for(int j=0;j<_GGsingInputnumy;j++){
235  sigofy[j]=_sigmax[ivalw][j]+(_sigmax[ivalw+1][j]-_sigmax[ivalw][j])*remainw;
236  }
237  //calculate the unnormalized sgfint
238 
239  sgfint[0]=0.;
240  for(int j=0;j<_GGsingInputnumy-1;j++){
241  sgf = (sigofy[j+1]+sigofy[j])/2.;
242  sgfint[j+1]=sgfint[j]+sgf*(_Yarray[j+1]-_Yarray[j]);
243  }
244 
245  //normalize the sgfint array
246  signorm = sgfint[_GGsingInputnumy-1];
247 
248  for(int j=0;j<_GGsingInputnumy;j++){
249  sgfint[j]=sgfint[j]/signorm;
250  }
251  //pick a random number
252  x = _randy.Rndom();
253  //compare x and sgfint to find the ivalue which is just less then the random number x
254  for(int i=0;i<_GGsingInputnumy;i++){
255  if(x > sgfint[i])
256  ivaly = i;
257  }
258  //remainder above ivaly
259  remainarea = x - sgfint[ivaly];
260  //figure what point corresponds to the leftover area in remainarea
261  c = -remainarea*signorm/(_Yarray[ivaly+1]-_Yarray[ivaly]);
262  b = sigofy[ivaly];
263  a = (sigofy[ivaly+1]-sigofy[ivaly])/2.;
264  if(a==0.){
265  remainy = -c/b;
266  }
267  else{
268  remainy = (-b + sqrt(b*b-4.*a*c))/(2.*a);
269  }
270  //calculate the y value
271  y = _Yarray[ivaly]+(_Yarray[ivaly+1]-_Yarray[ivaly])*remainy;
272  delete[] sigofy;
273  delete[] sgfint;
274 }
275 
276 
277 //______________________________________________________________________________
278 void Gammagammasingle::parentMomentum(double w,double y,double &E,double &px,double &py,double &pz)
279 {
280  //this function calculates px,py,pz,and E given w and y
281  double anglepp1=0.,anglepp2=0.,ppp1=0.,ppp2=0.,E1=0.,E2=0.,signpx=0.,pt=0.;
282 
283  //E1 and E2 are for the 2 photons in the CM frame
284  E1 = w*exp(y)/2.;
285  E2 = w*exp(-y)/2.;
286  //calculate px and py
287  //to get x and y components-- phi is random between 0 and 2*pi
288  anglepp1 = _randy.Rndom();
289  anglepp2 = _randy.Rndom();
290 
291  ppp1 = pp1(E1);
292  ppp2 = pp2(E2);
293  px = ppp1*cos(2.*starlightConstants::pi*anglepp1)+ppp2*cos(2.*starlightConstants::pi*anglepp2);
294  py = ppp1*sin(2.*starlightConstants::pi*anglepp1)+ppp2*sin(2.*starlightConstants::pi*anglepp2);
295  //Compute vector sum Pt=Pt1+Pt2 to find pt for the produced particle
296  pt = sqrt(px*px+py*py);
297  //W is the mass of the produced particle (not necessarily on-mass-shell).Now compute its energy and pz
298  E = sqrt(w*w+pt*pt)*cosh(y);
299  pz= sqrt(w*w+pt*pt)*sinh(y);
300  signpx = _randy.Rndom();
301  //pick the z direction
302  if(signpx > 0.5)
303  pz = -pz;
304 }
305 
306 
307 //______________________________________________________________________________
308 double Gammagammasingle::pp1(double E)
309 {
310  // First 'copy' of pp, for nucleus 1 form factor. The split was needed to handle asymmetric beams. SRK 4/2015
311  // will probably have to pass in beambeamsys? that way we can do beam1.formFactor(t) or beam2..., careful with the way sergey did it for asymmetry
312  // returns on random draw from pp(E) distribution
313 
314  double ereds =0.,Cm=0.,Coef=0.,x=0.,pp=0.,test=0.,u=0.;
315  double singleformfactorCm=0.,singleformfactorpp1=0.,singleformfactorpp2=0.;
316  int satisfy =0;
317 
319  Cm = sqrt(3.)*E/_GGsingInputGamma_em;
320  //the amplitude of the p_t spectrum at the maximum
321  singleformfactorCm=_bbs.electronBeam().formFactor(Cm*Cm+ereds);
322  //Doing this once and then storing it as a double, for the beam 1 form factor.
323  Coef = 3.0*(singleformfactorCm*singleformfactorCm*Cm*Cm*Cm)/((2.*(starlightConstants::pi)*(ereds+Cm*Cm))*(2.*(starlightConstants::pi)*(ereds+Cm*Cm)));
324 
325  //pick a test value pp, and find the amplitude there
326  x = _randy.Rndom();
327  pp = x*5.*starlightConstants::hbarc/_bbs.electronBeam().nuclearRadius(); //Will use nucleus #1, there should be two for symmetry//nextline
328  singleformfactorpp1=_bbs.electronBeam().formFactor(pp*pp+ereds);
329  test = (singleformfactorpp1*singleformfactorpp1)*pp*pp*pp/((2.*starlightConstants::pi*(ereds+pp*pp))*(2.*starlightConstants::pi*(ereds+pp*pp)));
330 
331  while(satisfy==0){
332  u = _randy.Rndom();
333  if(u*Coef <= test){
334  satisfy =1;
335  }
336  else{
337  x =_randy.Rndom();
339  singleformfactorpp2=_bbs.electronBeam().formFactor(pp*pp+ereds);//Symmetry
340  test = (singleformfactorpp2*singleformfactorpp2)*pp*pp*pp/(2.*starlightConstants::pi*(ereds+pp*pp)*2.*starlightConstants::pi*(ereds+pp*pp));
341  }
342  }
343  return pp;
344 }
345 
346 //______________________________________________________________________________
347 double Gammagammasingle::pp2(double E)
348 {
349  // Second 'copy' of pp, for nucleus 1 form factor. The split was needed to handle asymmetric beams. SRK 4/2015
350  // will probably have to pass in beambeamsys? that way we can do electronBeam.formFactor(t) or beam2..., careful with the way sergey did it for asymmetry
351  // returns on random draw from pp(E) distribution
352 
353  double ereds =0.,Cm=0.,Coef=0.,x=0.,pp=0.,test=0.,u=0.;
354  double singleformfactorCm=0.,singleformfactorpp1=0.,singleformfactorpp2=0.;
355  int satisfy =0;
356 
358  Cm = sqrt(3.)*E/_GGsingInputGamma_em;
359  //the amplitude of the p_t spectrum at the maximum
360  singleformfactorCm=_bbs.targetBeam().formFactor(Cm*Cm+ereds);
361  //Doing this once and then storing it as a double, which we square later...SYMMETRY?using electronBeam for now.
362  Coef = 3.0*(singleformfactorCm*singleformfactorCm*Cm*Cm*Cm)/((2.*(starlightConstants::pi)*(ereds+Cm*Cm))*(2.*(starlightConstants::pi)*(ereds+Cm*Cm)));
363 
364  //pick a test value pp, and find the amplitude there
365  x = _randy.Rndom();
366  pp = x*5.*starlightConstants::hbarc/_bbs.targetBeam().nuclearRadius(); //Will use nucleus #1, there should be two for symmetry//nextline
367  singleformfactorpp1=_bbs.targetBeam().formFactor(pp*pp+ereds);
368  test = (singleformfactorpp1*singleformfactorpp1)*pp*pp*pp/((2.*starlightConstants::pi*(ereds+pp*pp))*(2.*starlightConstants::pi*(ereds+pp*pp)));
369 
370  while(satisfy==0){
371  u = _randy.Rndom();
372  if(u*Coef <= test){
373  satisfy =1;
374  }
375  else{
376  x =_randy.Rndom();
378  singleformfactorpp2=_bbs.targetBeam().formFactor(pp*pp+ereds);//Symmetry
379  test = (singleformfactorpp2*singleformfactorpp2)*pp*pp*pp/(2.*starlightConstants::pi*(ereds+pp*pp)*2.*starlightConstants::pi*(ereds+pp*pp));
380  }
381  }
382  return pp;
383 }
384 
385 
386 //______________________________________________________________________________
387 void Gammagammasingle::twoBodyDecay(starlightConstants::particleTypeEnum &ipid,double W,double px0,double py0,double pz0,double &px1,double &py1,double &pz1,double &px2,double &py2,double &pz2,int &iFbadevent)
388 {
389  // This routine decays a particle into two particles of mass mdec,
390  // taking spin into account
391 
392  double mdec=0.,E1=0.,E2=0.;
393  double pmag,ytest=0.;
394  double phi,theta,xtest,dndtheta,Ecm;
395  double betax,betay,betaz;
396 
397  // set the mass of the daughter particles
398  switch(_GGsingInputpidtest){
402  break;
403  case starlightConstants::AXION: // AXION HACK
404  mdec = 0;//axion decays to two photons, set mass of decay products to zero
405  break;
407  // decays 50% to K+/K-, 50% to K_0's
408  ytest = _randy.Rndom();
409  if(ytest >= 0.5){
411  }
412  else{
413  mdec = 0.493677;
414  }
415  break;
416  default :
417  cout<<"No default mass selected for single photon-photon particle, expect errant results"<<endl;
418  }
419 
420  //Calculating the momentum's magnitude
421  if(W < 2*mdec){
422  cout<<" ERROR: W="<<W<<endl;
423  iFbadevent = 1;
424  return;
425  }
426  pmag = sqrt(W*W/4. - mdec*mdec);
427 // }
428  // pick an orientation, based on the spin
429  // phi has a flat distribution in 2*pi
431 
432  // find theta, the angle between one of the outgoing particles and
433  // the beamline, in the frame of the two photons
434  //this will depend on spin, F2,F2' and z/z03 all have spin 2, all other photonphoton-single mesons are handled by jetset/pythia
435  //Applies to spin2 mesons.
436  L300td:
438  xtest = _randy.Rndom();
439  dndtheta = sin(theta)*sin(theta)*sin(theta)*sin(theta)*sin(theta);
440  if(xtest > dndtheta)
441  goto L300td;
442 
443  // compute unboosted momenta
444  px1 = sin(theta)*cos(phi)*pmag;
445  py1 = sin(theta)*sin(phi)*pmag;
446  pz1 = cos(theta)*pmag;
447  px2 = -px1;
448  py2 = -py1;
449  pz2 = -pz1;
450  // compute energies
451  //Changed mass to W 11/9/2000 SRK
452  Ecm = sqrt(W*W+px0*px0+py0*py0+pz0*pz0);
453  E1 = sqrt(mdec*mdec+px1*px1+py1*py1+pz1*pz1);
454  E2 = sqrt(mdec*mdec+px2*px2+py2*py2+pz2*pz2);
455 
456  // Lorentz transform into the lab frame
457  // betax,betay,betaz are the boost of the complete system
458  betax = -(px0/Ecm);
459  betay = -(py0/Ecm);
460  betaz = -(pz0/Ecm);
461 
462  transform (betax,betay,betaz,E1,px1,py1,pz1,iFbadevent);
463  transform (betax,betay,betaz,E2,px2,py2,pz2,iFbadevent);
464 
465 
466  if(iFbadevent == 1)
467  return;
468 
469  // change particle id from that of parent to that of daughters
470 
471  switch(_GGsingInputpidtest){
472  //These decay into a pi+ pi- pair
476  break;
477  case starlightConstants::AXION:// AXION HACK
478  ipid=starlightConstants::PHOTON; // AXION HACK
479  break; // AXION HACK
481  if( ytest >= 0.5 )
482  {
483  //Decays 50/50 into k+ k- or k_s k_l
485  }
486  else
487  {
489  }
490  break;
491  default:
492  cout<<"Rethink the daughter particles"<<endl;
493  }
494 }
495 
496 
497 //______________________________________________________________________________
499 {
500  // Not in use anymore, default event struct returned
501  return starlightConstants::event();
502 }
503 
504 
505 //______________________________________________________________________________
507 {
508  using namespace starlightConstants;
509  double singlemass=0.;
510  switch(_GGsingInputpidtest){
512  singlemass = starlightConstants::etaMass;
513  break;
516  break;
518  singlemass = starlightConstants::etaCMass;
519  break;
521  singlemass = starlightConstants::f0Mass;
522  break;
524  singlemass = starlightConstants::f2Mass;
525  break;
527  singlemass = starlightConstants::a2Mass;
528  break;
530  singlemass = starlightConstants::f2PrimeMass;
531  break;
534  break;
535  case starlightConstants::AXION: // AXION HACK
536  singlemass = _axionMass; // AXION HACK
537  break; // AXION HACK
538  default:
539  cout<<"Not a recognized single particle, Gammagammasingle::getmass(), mass = 0."<<endl;
540  }
541  return singlemass;
542 }
543 
544 
545 //______________________________________________________________________________
547 {
548 
549  /* Partial widths(GAMMA(gammgamma)) taken from PDG 2014- Chinese Physics C 38, no 9, Sept. 2014.*/
550  double singlewidth=0.;
551  switch(_GGsingInputpidtest){
554  break;
557  break;
560  break;
563  break;
566  break;
569  break;
572  break;
575  break;
576  case starlightConstants::AXION: // AXION HACK
577  singlewidth = 1/(64*starlightConstants::pi)*_axionMass*_axionMass*_axionMass/(1000*1000);//Fix Lambda=1000 GeV,rescaling is trivial. // AXION HACK
578  break;
579  default:
580  cout<<"Not a recognized single particle, Gammagammasingle::getwidth(), width = 0."<<endl;
581  }
582  return singlewidth;
583 }
584 
585 
586 //______________________________________________________________________________
588 {
589  double singlespin=0.5;
590  switch(_GGsingInputpidtest){
592  singlespin = starlightConstants::etaSpin;
593  break;
596  break;
598  singlespin = starlightConstants::etaCSpin;
599  break;
601  singlespin = starlightConstants::f0Spin;
602  break;
604  singlespin = starlightConstants::f2Spin;
605  break;
607  singlespin = starlightConstants::a2Spin;
608  break;
610  singlespin = starlightConstants::f2PrimeSpin;
611  break;
614  break;
615  case starlightConstants::AXION:// AXION HACK
616  singlespin = starlightConstants::axionSpin;// AXION HACK
617  break;// AXION HACK
618  default:
619  cout<<"Not a recognized single particle, Gammagammasingle::getspin(), spin = 0."<<endl;
620  }
621  return singlespin;
622 }
624 {
625  eXEvent event;
626  cout<< " Gamma+Gamma -> single particle is not implemente in current eSTARlight build. REturning empty event"<<endl;
627  return event;
628 }
629 
630