Pluto v6.3.0
Loading...
Searching...
No Matches
PGammaConversion.cc
Go to the documentation of this file.
1
2// Fast conversion gamma -> e+e- in material
3//
4//
5// Author:
6// Written: 12/01/2014
7// Revised:
8//
10
11#include "PGammaConversion.h"
12#include "PChannel.h"
13
14#include "TFile.h"
15#include "TH3F.h"
16#include "TSystem.h"
17
19 ConvProb = 0;
20 Z = 41; // Sep08 p+Nb run
21 convpar[0] = 0.4319;
22 convpar[1] = -0.02322;
23 convpar[2] = 0.000359;
24 ep = PParticle("e+");
25 em = PParticle("e-");
26
27 for (Int_t i=0; i<NEFUNCS; i++)
28 Elepton[i] = NULL;
29 RGen = new TRandom3();
30 ulep = new TF1("ulep","x*exp(-0.625*x)*(1+27*exp(-1.25*x))",0,20); // lepton angle w.r.t. photon
31 ulep->SetNpx(300);
32 ulep->SetLineWidth(1);
33
34 nVertex = 0;
35 nbinTheta = 0;
36 nbinR = 0;
37 nbinZ = 0;
38 hdimension = 0;
39 hvertexgeom = 0;
40 x1 = y1 = z1 = 0;
41
42}
43
44PGammaConversion::PGammaConversion(Float_t z, Float_t p, Int_t run = 0) {
45 ConvProb = p;
46 Z = z;
47
48 // following coeffs are fitted to results of a complete GEANT3 simulation: ProbConv(Ephoton, Theta)
49 if(run==0) {
50 convpar[0] = 0.4319; // Sep08 p+Nb run coeffs.
51 convpar[1] = -0.02322;
52 convpar[2] = 0.000359;
53 } else if(run==1) {
54 convpar[0] = 0.649; // Sep05 Ar+KCl run coeffs.
55 convpar[1] = 0.00740;
56 convpar[2] = 3.97e-5;
57 } else if(run==2) {
58 convpar[0] = 0.380904 ; // 12 Au+Au run coeffs.
59 convpar[1] = -0.0777771 ;
60 convpar[2] = 0.00522763;
61 convpar[3] = -1.33942e-4;
62 convpar[4] = 1.49021e-6;
63 convpar[5] = -6.11297e-9;
64 } else {
65 cout<< " no correct run number" <<endl;
66 return;
67 }
68 ep = PParticle("e+");
69 em = PParticle("e-");
70
71 for (Int_t i=0; i<NEFUNCS; i++)
72 Elepton[i] = NULL;
73 RGen = new TRandom3();
74 ulep = new TF1("ulep", "x*exp(-0.625*x)*(1+27*exp(-1.25*x))", 0, 20); // lepton angle w.r.t. photon (GEANT3)
75 ulep->SetNpx(300);
76 ulep->SetLineWidth(1);
77
78 nVertex = 0;
79 nbinTheta = 0;
80 nbinR = 0;
81 nbinZ = 0;
82 hdimension = 0;
83 hvertexgeom = 0;
84 x1 = y1 = z1 = 0;
85
86}
87
88
90 for (Int_t i=0; i<NEFUNCS; i++)
91 if (Elepton[i] != NULL)
92 Elepton[i]->Delete();
93 ulep->Delete();
94 RGen->Delete();
95}
96
97
98Float_t PGammaConversion::ConversionXS(Float_t E) { // return total conversion cross section in mb/atom (Geant3)
99
100 const Float_t EMass = 5.109990615e-4; // electron mass in GeV
101 if ( E<2.*EMass ) return 0; // unphysical region
102 Float_t Eph = (E<10 ? E : 10.);
103
104 // Coefficients from Geant3 routine GPRSGA
105 const Float_t CPar[18] = {0.87842E-3, -0.19625E-2, 0.12949E-2, -0.20028E-3, 0.12575E-4, -0.28333E-6,
106 -0.10342E-4, 0.17692E-4, -0.82391E-5, 0.13063E-5, -0.90815E-7, 0.23586E-8,
107 -0.45263E-3, 0.11161E-2, -0.86749E-3, 0.21773E-3, -0.20467E-4, 0.65372E-6};
108 Float_t CC[3] = {0, 0, 0};
109 Float_t X = log(Eph/EMass);
110
111 // initialising parameters of CC1, CC2, CC3
112 for (Int_t i=0; i<3; i++) {
113 Float_t D = 1;
114 for(int j=0; j<6; j++){
115 Int_t jx = 6*i + j;
116 CC[i] = CC[i] + D*CPar[jx];
117 D = D*X;
118 }
119 }
120
121 // total cross section for element with Z
122 return (Z*(Z+1.0) * (CC[0] + CC[1]*Z + CC[2]/Z));
123}
124
125
126Float_t PGammaConversion::GetConversionProb(Float_t E, Float_t th, Int_t run = 0) {
127 // return conversion prob for photon of energy E [GeV] and polar angle theta [deg]
128 if (th<0. || th>90)
129 return 0; // out of HADES acceptance
130 if (ConvProb >= 1.0)
131 return 1; // convert all
132 if (ConvProb > 0)
133 return ConvProb; // use constant conversion probability
134 else {
135 if (run != 2)
136 return 0.01 * convpar[0] * (1. + convpar[1]*th + convpar[2]*th*th) * ConversionXS(E);
137 if (run == 2)
138 return 0.01 * convpar[0] * (1. + convpar[1]*th + convpar[2]*th*th +
139 convpar[3]*th*th*th+convpar[4]*th*th*th*th) * ConversionXS(E);
140 }
141 return 0.;
142}
143
144Double_t PGammaConversion::dSde(Double_t *x, Double_t *par) { // electron energy distribution (GEANT3)
145 Double_t E = par[0]; // photon energy in GeV
146 Double_t Z = par[1]; // average atomic charge of converter material
147
148 Double_t eps = x[0]/E; // electron fraction of photon energy
149 if (eps<=0 || eps>=1 || Z<1)
150 return 0;
151
152 const Double_t alpha = 1./137.036; // fine structure constant
153 const Double_t me = 0.0005109989; // electron mass in GeV
154
155 Double_t a = pow(alpha*Z,2);
156 Double_t fcZ = alpha*(1/(1+alpha) + 0.20206 - 0.0369*a + 0.0083*a*a - 0.002*a*a*a); // Coulomb correction
157 Double_t FZ = E<0.05 ? 4./3.*log(Z) : 4./3.*log(Z)+4.*fcZ;
158
159 Double_t delta = 136.*me/(pow(Z,1./3.)*E*eps*(1-eps));
160 Double_t phi1, phi2; // screening functions
161 if (delta<=1) {
162 phi1 = 20.867 - 3.242*delta + 0.625*delta*delta;
163 phi2 = 20.209 - 1.930*delta - 0.086*delta*delta;
164 } else {
165 phi1 = phi2 = 21.12 - 4.184*log(delta+0.952);
166 }
167
168 phi1 = max(phi1, FZ); // to avoid negative result for eps close to 0 or 1
169 phi2 = max(phi2, FZ);
170
171 Double_t xiZ = log(1440./pow(Z,2./3.))/(log(183./pow(Z,1./3.)) - fcZ);
172
173 Double_t val = alpha*Z*(1+xiZ)/(E*E) * ((eps*eps+(1-eps)*(1-eps))*(phi1-FZ)
174 + 2./3.*eps*(1-eps)*(phi2-FZ));
175 return val;
176}
177
179
180 if(gSystem->AccessPathName(input.Data())!=0) {
181 Error("readHist()", "File %s not found!", input.Data());
182 return -1;
183 }
184
185 TFile *file = new TFile(input, "READ");
186 Int_t size = -1;
187
188 hvertexgeom = (TH1F*) gDirectory->Get("hvertex");
189
190 if(!hvertexgeom) {
191 Error("readHist()", "hvertex hist for target geom not found! hopeless ....");
192 exit(1);
193 }
194
195 nVertex = hvertexgeom->GetNbinsX();
196 if(file) {
197 for(Int_t binVertex=0; binVertex<nVertex; binVertex++) {
198 TH3F *h = (TH3F*)gDirectory->Get(Form("hVertex_full%i", binVertex+1));
199 if(h) {
200 nbinTheta = h->GetNbinsZ();
201 nbinR = h->GetNbinsY();
202 nbinZ = h->GetNbinsX();
203
204 if(size == -1) {
205 hdimension = h;
206
207 size = nVertex*nbinTheta;
208 for(Int_t i=0; i<size; i++){
209 fhzr.push_back(0);
210 }
211 cout << "Histogram binning : theta " << nbinTheta << " r " <<
212 nbinR << " z " << nbinZ << endl;
213 }
214
215 for(Int_t binTheta=0; binTheta<nbinTheta; binTheta++) {
216 h->GetZaxis()->SetRange(binTheta+1, binTheta+1);
217 fhzr[binVertex*nbinTheta+binTheta] = (TH2F*) h->Project3D("xy");
218 fhzr[binVertex*nbinTheta+binTheta]->SetName(Form("%s_%i_xy", h->GetName(), binTheta));
219 fhzr[binVertex*nbinTheta+binTheta]->SetDirectory(0);
220 }
221
222 } else {
223 Error("readHist()", "hvertex %i not found!", binVertex);
224 }
225
226 }
227 } else {
228 Error("readHist()", "File point NULL!");
229 return -1;
230 }
231 return 0;
232}
233
234Int_t PGammaConversion::findVertexBin(Float_t zVertexEvt) {
235 Int_t bin = -1;
236 if(hvertexgeom) {
237 bin = hvertexgeom->GetXaxis()->FindBin(zVertexEvt);
238 if(bin > hvertexgeom->GetNbinsX())
239 bin = -1;
240 else
241 bin -= 1;
242 return bin;
243 } else return bin;
244}
245
246Int_t PGammaConversion::getThetaBin(Double_t thetadeg) {
247
248 if(hdimension) {
249 Int_t bin = hdimension->GetZaxis()->FindBin(thetadeg);
250 if(thetadeg==0||thetadeg>=nbinTheta)
251 return -1;
252 else
253 return bin;
254 }
255 return -1;
256}
257
258TH2F *PGammaConversion::getHist(Double_t zVertexEvt, Double_t thetadeg)
259{
260 if(hdimension) {
261 Int_t thbin = getThetaBin(thetadeg);
262 if(thbin < 0)
263 return 0;
264
265 Int_t binVertex = findVertexBin(zVertexEvt);
266 if(binVertex < 0)
267 return 0;
268
269 return fhzr[binVertex*nbinTheta+thbin] ;
270 }
271 return 0;
272}
273
274Bool_t PGammaConversion::Modify(PParticle **mstack, int *decay_done, int *num, int stacksize) {
275 // Read the particles from the defined stack and copy this to the official
276 // particle stream
277
278 const Double_t R2D = 57.295780; // rad to deg
279 const Double_t me = 0.0005109989; // electron mass in GeV
280
281 int cur = *num;
282 int gamma_id = makeStaticData()->GetParticleID("g");
283
284 // cout << cur << " " << mstack[0]->ID() << endl;
285
286 for (int i=0; i<cur; i++) {
287
288 if (mstack[i]->HasID(gamma_id) && mstack[i]->IsActive()) { // this is a photon
289
290 if ((*num) == stacksize) {
291 Warning("Modify", "stacksize reached");
292 return kFALSE;
293 }
294
295 //make kinematics here....
296 PParticle *track = mstack[i];
297 TVector3 vertex = track->GetVertex();
298
299 Double_t Ephot = track->E();
300 Double_t thphot = R2D*track->Theta();
301
302 if ( thphot<0. || thphot>90 ) continue;
303 /*
304 Double_t convprob = GetConversionProb(Ephot, thphot); // get conversion probability
305 if ( RGen->Uniform()>convprob ) { // do not convert this one
306 decay_done[i] = 0; // do not suppress unconverted photons from output
307 continue;
308 }
309 */
310 // Int_t mesonId = track->GetParentId();
311
312 if (Ephot < 2*me)
313 return kFALSE;
314 Int_t index = int(Ephot/0.01); // select energy slice of 0.01 GeV/c
315 if (index < 0)
316 return kFALSE;
317 index = min(index, NEFUNCS-1);
318
319 if (Elepton[index] == NULL) { // this slice does not yet exist
320 Char_t funame[11] = "Elepton000";
321 sprintf(funame, "Elepton%03d", index); // create function object
322 Elepton[index] = new TF1(funame, PGammaConversion::dSde, me, double(index)*0.01+0.005, 2);
323 Elepton[index]->SetNpx(200);
324 Elepton[index]->SetParameters(Ephot, Z); // and initialize it
325 }
326
327 // Do energy and angle sampling of the e+/e- pair
328
329 Double_t Eelec = Elepton[index]->GetRandom(); // lepton total energy
330 Eelec *= Ephot/(double(index)*0.01+0.005); // correct for discretization of sampling
331 Double_t Pelec = sqrt(Eelec*Eelec - me*me); // lepton momentum
332 Double_t Thelec = (me/Ephot) * ulep->GetRandom(); // lepton polar angle (w.r.t. photon)
333 Double_t Eposi = Ephot - Eelec; // assume energy conservation
334 Double_t Pposi = sqrt(Eposi*Eposi - me*me);
335 Double_t arg = (Pelec/Pposi) * sin(Thelec); // assume coplanar photon e+ e-
336 if (arg<-1.) arg = -1;
337 if (arg> 1.) arg = 1;
338 Double_t Thposi = TMath::ASin(arg);
339
340 Double_t Phelec = 6.28318531 * RGen->Uniform(); // sample uniform phi angle
341 Double_t Phposi = 6.28318531 - Phelec; // assume that pair momentum is colinear
342 // Double_t close = R2D * (Thelec + Thposi); // opening angle of conversion pair
343 TVector3 Dirphot(track->Vect()); // photon direction
344 Dirphot = Dirphot.Unit(); // normalize photon vector
345
346 TVector3 lep3(Pelec*cos(Phelec)*sin(Thelec), Pelec*sin(Phelec)*sin(Thelec), Pelec*cos(Thelec));
347 TVector3 lep4(Pposi*cos(Phposi)*sin(Thposi), Pposi*sin(Phposi)*sin(Thposi), Pposi*cos(Thposi));
348 lep3.RotateUz(Dirphot); // rotate lepton vectors into lab frame
349 lep4.RotateUz(Dirphot);
350
351 /*
352 Float_t ptot3 = lep3.Mag();
353 Float_t theta3 = R2D*lep3.Theta();
354 Float_t phi3 = R2D*TMath::ACos(lep3.X()/lep3.Perp());
355 if (lep3.Y() < 0.) phi3 = 360.-phi3;
356 Float_t ptot4 = lep4.Mag();
357 Float_t theta4 = R2D*lep4.Theta();
358 Float_t phi4 = R2D*TMath::ACos(lep4.X()/lep4.Perp());
359 if (lep4.Y() < 0.) phi4 = 360.-phi4;
360 */
361
362 Int_t id3, id4;
363 if (RGen->Uniform() < 0.5) { // decide which is e- and which is e+
364 id3 = 3;
365 id4 = 2;
366 } else {
367 id3 = 2;
368 id4 = 3;
369 }
370
371
372 ep.SetVectM(lep3,me);
373 ep.SetID(id3);
374 ep.SetSourceId(track->GetSourceId());
375 ep.SetParentId(1);
376 ep.SetParentIndex(track->GetIndex());
377 ep.SetW(track->W());
378 ep.SetVertex(0, 0, 0, 0);
379 ep.SetActive();
380
381 em.SetVectM(lep4,me);
382 em.SetID(id4);
383 em.SetSourceId(track->GetSourceId());
384 em.SetParentId(1);
385 em.SetParentIndex(track->GetIndex());
386 em.SetW(track->W());
387 em.SetVertex(0, 0, 0, 0);
388 em.SetActive();
389
390
391 if (nVertex > 0) {
392 //----------------------------------
393 // Convert vertex into target num
394 TH2F *hzr = getHist(vertex.Z(), thphot);
395
396 if(!hzr) {
397 Error("Modify()", "hzr at theta %f and vertex %f not found !", thphot, vertex.Z());
398 continue;
399 }
400
401 Double_t z,r;
402 hzr->GetRandom2(z, r);
403
404 if(!TMath::Finite(z) || !TMath::Finite(r)) {
405 ep.SetVertex(0, 0, 10000, 0);
406 em.SetVertex(0, 0, 10000, 0);
407 } else {
408 Double_t phi = gRandom->Rndm()*2*TMath::Pi();
409 Double_t x = cos(phi)*r;
410 Double_t y = sin(phi)*r;;
411 ep.SetVertex(x, y, z, 0);
412 em.SetVertex(x, y, z, 0);
413
414 cout<<" x " << x << " y " << y << " phi " << phi*TMath::RadToDeg() <<
415 " r " << r << " th " << thphot << endl;
416 }
417 } else {
418 ep.SetVertex(x1, y1, z1, 0);
419 em.SetVertex(x1, y1, z1, 0);
420 }
421
422 *(mstack[*num]) = ep;
423 (*num)++;
424 *(mstack[*num]) = em;
425 (*num)++;
426 decay_done[i] = 1;
427 }
428 }
429
430 return kTRUE;
431
432}
433
ClassImp(PBeamLineSimulation) PBeamLineSimulation
#define NEFUNCS
PStaticData * makeStaticData()
PParticle * par[11]
Int_t readHist(TString inputroot)
Float_t GetConversionProb(Float_t E, Float_t theta, Int_t run)
Bool_t Modify(PParticle **stack, int *decay_done, int *num, int stacksize)
TVector3 & GetVertex()
Definition PParticle.h:275
Int_t GetSourceId() const
Definition PParticle.h:230
Int_t GetIndex() const
Definition PParticle.h:257
Double_t W() const
Definition PParticle.h:92
int GetParticleID(const char *id, int warn=1)
PReaction r(c,"eta_dalitz", 3, 0, 0, 0, 1)
PParticle * delta
PParticle * p
Definition dp_mult.C:24
TH1F * phi1
Definition pn_ela.C:17
PUniGenInput * input
Definition unigen_input.C:7