source: trunk/WuerzburgSoft/Thomas/mphys/MElectron.cc@ 1449

Last change on this file since 1449 was 1449, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 14.4 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Harald Kornmayer 1/2001 (harald@mppmu.mpg.de)
19! Author(s): Thomas Bretz 12/2000 (tbretz@uni-sw.gwdg.de)
20!
21! Copyright: MAGIC Software Development, 2000-2001
22!
23!
24\* ======================================================================== */
25
26//////////////////////////////////////////////////////////////////////////////
27// //
28// //
29//////////////////////////////////////////////////////////////////////////////
30#include "MElectron.h"
31
32#include <math.h> // for aqlphas
33#include <iostream.h>
34
35#include <TF1.h>
36#include <TH1.h>
37#include <TMatrixD.h>
38#include <TVectorD.h>
39
40#include <TRandom.h>
41
42#include <TPad.h>
43#include <TCanvas.h>
44
45#include "MPhoton.h"
46
47ClassImp(MElectron);
48
49Double_t MElectron::Li(Double_t *x, Double_t *k)
50{
51 const Double_t t = x[0];
52 return log(1.-t)/t;
53}
54
55Double_t MElectron::DiSum(Double_t *x, Double_t *k)
56{
57 Double_t t = x[0];
58
59 const Double_t eps = fabs(t*1e-2);
60
61 Double_t disum = t;
62 Double_t add = 0;
63
64 Int_t n = 2;
65 Double_t pow = t*t; // t^2
66
67 do
68 {
69 add = pow/n/n;
70
71 pow *= t; // pow = t^n
72 n++;
73
74 disum += add;
75
76 } while (fabs(add)>eps);
77
78 return disum;
79}
80
81Double_t MElectron::Li2(Double_t *x, Double_t *k)
82{
83 //
84 // Dilog, Li2
85 // ----------
86 //
87 // Integral(0, 1) = konst;
88 // Double_t konst = 1./6*TMath::Pi()*TMath::Pi();
89 //
90 // x[0]: z
91 //
92 const Double_t z = x[0];
93
94 if (fabs(z)<1)
95 return DiSum(x);
96
97 // TF1 IntLi("Li", Li, 0, z, 0);
98 static TF1 IntLi("Li", Li, 0, 0, 0);
99 const Double_t integ = IntLi.Integral(0, z, (Double_t*)NULL, 1e-2);
100 return -integ;
101}
102
103Double_t MElectron::Flim(Double_t *x, Double_t *k) // F(omegap)-F(omegam) mit b-->1 (Maple)
104{
105 const Double_t w = x[0];
106
107 const Double_t w4 = w*4;
108 const Double_t wsqr = w*w;
109
110 const Double_t u1 = (w*wsqr*16 + wsqr*40 + w*17 + 2)*log(w4 + 1);
111 const Double_t u2 = -w4*(wsqr*2 + w*9 + 2);
112 const Double_t d = w4*(w4 + 1);
113
114 Double_t s = -w*2*(1+1); // -2*omega*(1+beta)
115 const Double_t li2 = Li2(&s);
116
117 const Double_t res = (u1+u2)/d + li2;
118
119 return res; //<1e-10? 0 : res;
120}
121
122Double_t MElectron::Compton(Double_t *x, Double_t *k)
123{
124 const Double_t E0 = 511e-6; //[GeV]
125
126 Double_t epsilon = x[0];
127 Double_t z = k[1];
128
129 const Double_t E = k[0];
130
131 Double_t flim;
132 if (epsilon<1e-14)
133 {
134 const Double_t d = E/(E0*E0);
135
136 Double_t omega1 = 1e-13*d;
137 Double_t omega2 = 1e-12*d;
138
139 const Double_t f1 = Flim(&omega1);
140 const Double_t f2 = Flim(&omega2);
141
142 const Double_t m = log10(f2/f1);
143 const Double_t t = pow(f2, 13)/pow(f1, 12);
144
145 flim = pow(epsilon, m) * t;
146 }
147 else
148 {
149 Double_t omega = epsilon*E/(E0*E0);
150 flim = Flim(&omega);
151 }
152
153 const Double_t n = MParticle::Planck(&epsilon, &z)/epsilon/epsilon; // [1]
154 return flim*n;
155}
156
157Double_t MElectron::InteractionLength(Double_t *E, Double_t *k)
158{
159 // E = electron energy, ~ TeV(?) 1e12
160 // e = photon energy, ~ meV(?) 1e-3
161 // mc^2 = electron rest mass energy ~.5keV(?) .5e3
162 //
163 // x^-1 = int( n(epsilon)/2beta * ((mc^2)^2/eE)^2 * int ( omega*sigma(omega), omega=o-..o+), epsilon=0..inf)
164 //
165 // o+/- = omage_0 (1 +- beta)
166 //
167 // omega_0 = eE/(mc^2)^2 ~1e12*1e-3/.25e6=4e3
168 //
169 // --> x^-1 = (alpha*hc)^2/4pibetaE^2 * int(n(epsilon)/epsilon^2 *( F(o+)-F(o-)), epsilon=0..inf)
170 //
171 // F(o) = -o/4 + (9/4 + 1/o + o/2) * ln(1+2o) + 1/8(1+2o) - 3/8 + Li2(-2o)
172 //
173 // Li2(x) = int(ln(1-t)/t, t=0..x)
174 //
175 // F(o+)~F(2o) = -o/2 + (9/4 + 1/2o + o) * ln(1+4o) + 1/8(1+4o) - 3/8 + Li2(-4o)
176 // F(o-)~F(0) = 14/8 = 1.75
177
178 const Double_t E0 = 511e-6; // [GeV]
179 const Double_t E02 = E0*E0; // [GeV^2]
180 const Double_t c = 299792458; // [m/s]
181 const Double_t e = 1.602176462e-19; // [C]
182 const Double_t h = 1e-9/e*6.62606876e-34; // [GeVs]
183 const Double_t hc = h*c; // [GeVm]
184 const Double_t alpha = 1./137.; // [1]
185
186 const Double_t z = k ? k[0] : 0;
187
188 /* -------------- old ----------------
189 Double_t from = 1e-15;
190 Double_t to = 1e-11;
191 eps = [default];
192 -----------------------------------
193 */
194 static TF1 func("Compton", Compton, 0, 0, 2); // [0, inf]
195
196 const Double_t from = 1e-17;
197 const Double_t to = 2e-11;
198
199 Double_t val[3] = { E[0], z }; // E[GeV]
200
201 Double_t integ = func.Integral(from, to, val, 1e-2); // [Gev] [0, inf]
202
203 const Double_t aE = alpha/E[0]; // [1/GeV]
204
205 const Double_t beta = 1;
206
207 const Double_t konst = 2.*E02/hc/beta; // [1 / GeV m]
208 const Double_t ret = konst * (aE*aE) * integ; // [1 / m]
209
210 const Double_t ly = 3600.*24.*365.*c; // [m/ly]
211 const Double_t pc = 1./3.258; // [pc/ly]
212
213 return (1./ret)/ly*pc/1000; // [kpc]
214}
215
216Double_t MElectron::GetInteractionLength(Double_t energy, Double_t z)
217{
218 return InteractionLength(&energy, &z);
219}
220
221Double_t MElectron::GetInteractionLength() const
222{
223 return InteractionLength((Double_t*)&fEnergy, (Double_t*)&fZ);
224}
225
226// --------------------------------------------------------------------------
227
228/*inline*/ Double_t MElectron::p_e(Double_t *x, Double_t *k)
229{
230 Double_t e = pow(10, x[0]);
231 return Compton(&e, k);
232 /*
233 Double_t z = k[1];
234
235 const Double_t E = k[0];
236
237 const Double_t E0 = 511e-6; //[GeV]
238 const Double_t E02 = E0*E0;
239
240 Double_t omega = e*E/E02;
241
242 const Double_t n = Planck(&e, &z);
243
244 const Double_t F = Flim(&omega)/omega/omega;
245
246 return n*F*1e26;
247 */
248}
249
250Double_t MElectron::G_q(Double_t *x, Double_t *k)
251{
252 const Double_t q = x[0];
253 const Double_t Gamma = k[0];
254
255 const Double_t Gq = Gamma*q;
256
257 const Double_t s1 = 2.*q*log(q);
258 const Double_t s2 = (1.+2.*q);
259 const Double_t s3 = (Gq*Gq)/(1.+Gq)/2.;
260
261 return s1+(s2+s3)*(1.-q);
262}
263
264
265Double_t MElectron::EnergyLoss(Double_t *x, Double_t *k, Double_t *ep)
266{
267 const Double_t E = x[0];
268 const Double_t z = k ? k[0] : 0;
269
270 const Double_t E0 = 511e-6; //[GeV]
271
272 const Double_t lolim = -log10(E)/7*4-13.5;
273
274 static TF1 fP("p_e", p_e, lolim, -10.6, 2);
275 static TF1 fQ("G", G_q, 0, 1., 1);
276
277 fP.SetNpx(50);
278 fQ.SetNpx(50);
279
280 fP.SetRange(lolim, -10.6);
281 fP.SetParameter(0, E);
282 fP.SetParameter(1, z);
283
284 const Double_t e = pow(10, fP.GetRandom());
285
286 if (ep)
287 *ep = e;
288
289 const Double_t omega = (e/E0)*(E/E0);
290 const Double_t Gamma = 4.*omega;
291
292 fQ.SetParameter(0, Gamma);
293
294 const Double_t q = fQ.GetRandom();
295 const Double_t Gq = Gamma*q;
296
297 const Double_t e1 = Gq*E/(1.+Gq);
298
299 return e1;
300}
301
302Double_t MElectron::GetEnergyLoss(Double_t E, Double_t z, Double_t *ep)
303{
304 return EnergyLoss(&E, &z);
305}
306
307Double_t MElectron::GetEnergyLoss(Double_t *ep) const
308{
309 return EnergyLoss((Double_t*)&fEnergy, (Double_t*)&fZ, ep);
310}
311
312MPhoton *MElectron::DoInvCompton(Double_t theta)
313{
314 const Double_t E0 = 511e-6; //[GeV]
315
316 Double_t epsilon;
317 const Double_t e = GetEnergyLoss(&epsilon);
318
319 // er: photon energy before interaction, rest frame
320 // e: photon energy after interaction, lab
321
322 const Double_t gamma = fEnergy/E0;
323 // const Double_t beta = sqrt(1.-1./(gamma*gamma));
324 const Double_t gammabeta = sqrt(gamma*gamma-1);
325
326 const Double_t f = fEnergy/e;
327
328 Double_t t=-10;
329 Double_t arg;
330 do
331 {
332 if (t>-10)
333 cout << "~" << flush;
334
335 //
336 // Create an angle uniformly distributed in the range of possible
337 // interaction angles due to the known energies.
338 //
339 // The distibution is a theta-function which is incorrect, but
340 // should be correct in a first order...
341 //
342 t = gRandom->Uniform(TMath::Pi())+TMath::Pi()/2;
343 Double_t er = epsilon*(gamma-gammabeta*cos(t)); // photon energy rest frame
344 Double_t n = sqrt(fEnergy*fEnergy-E0*E0)/e+1;
345 arg = (f - E0/er - 1)/n;
346
347 /* ------------------ some hints ------------------------------
348 -1 < arg < 1
349 -n < f - r/er - 1 < n
350 1-f-n < r/er < 1-f+n
351 r/(1-f+n) < er < r/(1-f-n)
352 r/(1-f+n) < gamma-gammabeta*cos(t) < r/(1-f-n)
353 r/(1-f+n)-gamma < -gammabeta*cos(t) < r/(1-f-n)-gamma
354 gamma-r/(1-f-n) < gammabeta*cos(t) < gamma-r/(1-f+n)
355 (gamma-r/(1-f-n))/gammabeta < cos(t) < (gamma-r/(1-f+n))/gammabeta
356 acos((gamma-r/(1-f+n))/gammabeta) < t < acos((gamma-r/(1-f-n))/gammabeta)
357
358
359 (gamma+E0/(n*arg+1-f)/epsilon)/gammabeta = cos(t);
360 1 = (epsilon/E0*cos(t)*gammabeta-gamma)*(n*arg+1-f);
361
362 arg=1: (gamma+E0/epsilon*(1-f+n))/gammabeta = cos(t);
363 arg=-1 : (gamma+E0/epsilon*(1-f-n))/gammabeta = cos(t);
364
365 (E0/(1-f-n)/epsilon+gamma)/gammabeta < cos(t) < (E0/(1-f+n)/epsilon+gamma)/gammabeta
366 */
367
368 } while (arg<-1 || arg>1);
369
370 const Double_t theta1s = acos(arg);
371 const Double_t thetas = atan(sin(t)/(gamma*cos(t)-gammabeta));
372
373 const Double_t thetastar = thetas-theta1s;
374
375 const Double_t theta1 = atan(sin(thetastar)/(gamma*cos(thetastar)+gammabeta));
376
377 fEnergy -= e;
378
379 const Double_t phi = gRandom->Uniform(TMath::Pi()*2);
380
381 /*
382 MPhoton &p = *new MPhoton(e, fZ);
383 p = *this;
384 */
385 MPhoton &p = *new MPhoton(*this, e);
386 p.SetNewDirection(theta1, phi);
387
388 const Double_t beta2 = sqrt(1.-E0/fEnergy*E0/fEnergy);
389 const Double_t theta2 = asin((epsilon*sin(t)-e*sin(theta1))/fEnergy/beta2);
390
391 SetNewDirection(theta2, phi);
392
393 return &p;
394}
395
396void MElectron::DrawInteractionLength(Double_t z)
397{
398 if (!gPad)
399 new TCanvas("IL_Electron", "Mean Interaction Length Electron");
400 else
401 gPad->GetVirtCanvas()->cd(3);
402
403 TF1 f2("length", MElectron::InteractionLength, 1e3, 1e10, 0);
404 f2.SetParameter(0, z);
405
406 gPad->SetLogx();
407 gPad->SetLogy();
408 gPad->SetGrid();
409 f2.SetLineWidth(1);
410
411 TH1 &h=*f2.DrawCopy()->GetHistogram();
412
413 h.SetTitle("Mean Interaction Length (Electron)");
414 h.SetXTitle("E [GeV]");
415 h.SetYTitle("x [kpc]");
416
417 gPad->Modified();
418 gPad->Update();
419}
420
421void MElectron::DrawInteractionLength() const
422{
423 DrawInteractionLength(fZ);
424}
425
426Bool_t MElectron::SetNewPositionB(Double_t B)
427{
428 if (B==0)
429 return SetNewPosition();
430
431 Double_t x = gRandom->Exp(GetInteractionLength());
432
433 // -----------------------------
434
435 const Double_t E0 = 511e-6; //[GeV]
436
437 Double_t B_theta = gRandom->Uniform(TMath::Pi());
438 Double_t B_phi = gRandom->Uniform(TMath::Pi()*2);
439
440 static TMatrixD M(3,3);
441
442 M(0, 0) = sin(B_theta)*cos(B_phi);
443 M(1, 0) = cos(B_theta)*cos(B_phi);
444 M(2, 0) = -sin(B_phi);
445
446 M(0, 1) = sin(B_theta)*sin(B_phi);
447 M(1, 1) = cos(B_theta)*sin(B_phi);
448 M(2, 1) = cos(B_phi);
449
450 M(0, 2) = cos(B_theta);
451 M(1, 2) = -sin(B_theta);
452 M(2, 2) = 0;
453
454 const Double_t beta = sqrt(1.-E0/fEnergy*E0/fEnergy);
455
456 //
457 // rotate vector of velocity into a system in
458 // which the x-axis is identical with the B-Field
459 //
460 static TVectorD v(3);
461 v(0) = beta*sin(fTheta)*cos(fPsi);
462 v(1) = beta*sin(fTheta)*sin(fPsi);
463 v(2) = beta*cos(fTheta);
464 v *= M;
465
466 //
467 // Now rotate the system so, that the velocity vector
468 // lays in the y-z-plain
469 //
470 Double_t chi = atan(-v(2)/v(1));
471
472 // -----------------------------
473
474 static TMatrixD N(3,3);
475 N(0, 0) = 1;
476 N(1, 0) = 0;
477 N(2, 0) = 0;
478
479 N(0, 1) = 0;
480 N(1, 1) = -cos(chi);
481 N(2, 1) = -sin(chi);
482
483 N(0, 2) = 0;
484 N(1, 2) = sin(chi);
485 N(2, 2) = -cos(chi);
486 v *= N;
487
488 Double_t beta_p = v(0); // beta parallel
489 Double_t beta_o = v(1); // beta orthogonal
490 // v(2) = 0
491 // -----------------------------
492 static TVectorD p(3);
493
494 Double_t rho = 0;
495 if (B>0)
496 {
497 const Double_t c = 299792458; // [m/s]
498 const Double_t ly = 3600.*24.*365.*c; // [m/ly]
499 const Double_t pc = 1./3.258; // [pc/ly]
500
501 Double_t r = (fEnergy*1e9)*beta_o/(c*B)*(pc/ly/1e3); // [kpc]
502
503 rho = beta_o/beta*x/r; // [2pi]
504
505 // -----------------------------
506
507 if (fabs(rho*3437)>5*60) // > 5*60min
508 {
509 cout << "r" << flush;
510 return kFALSE;
511 }
512
513 p(0) = beta_p/beta*x;
514 p(1) = GetPType()==kEElectron?r*sin(rho):-r*sin(rho);
515 p(2) = r*(1.-cos(rho));
516 }
517 else
518 {
519 p(0) = beta_p/beta*x;
520 p(1) = beta_o/beta*x;
521 p(2) = 0;
522 cout << "------------- HEY! --------------" << endl;
523 }
524
525 static TVectorD s(3);
526 s(0) = fR*cos(fPhi);
527 s(1) = fR*sin(fPhi);
528 s(2) = RofZ(&fZ);
529
530 TMatrixD N2(TMatrixD::kTransposed, N);
531 TMatrixD M2(TMatrixD::kTransposed, M);
532 p *= N2;
533 p *= M2;
534
535 if (p(2)<x) // happens sometimes in case B==0
536 {
537 cout << "----- HA: " << B << " " << x << " " << p(2) << " " << x-p(2) << endl;
538 p(2)=x;
539 }
540
541 s -= p;
542
543 fR = sqrt(s(0)*s(0)+s(1)*s(1));
544 fPhi = atan2(s(1), s(0));
545 fZ = ZofR(&s(2));
546 fX += x-p(2);
547
548 // -----------------------------
549
550 static TVectorD w(3);
551 w(0) = beta_p/beta;
552 w(1) = beta_o/beta*cos(rho);
553 w(2) = beta_o/beta*sin(rho);
554
555 w *= N2;
556 w *= M2;
557
558 fPsi = atan2(w(1), w(0));
559 fTheta = asin(sqrt(w(0)*w(0)+w(1)*w(1)));
560
561 // -----------------------------
562
563 return fZ<0 ? kFALSE : kTRUE;
564}
Note: See TracBrowser for help on using the repository browser.