All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GFMaterialEffects.cxx
Go to the documentation of this file.
1 /* Copyright 2008-2009, Technische Universitaet Muenchen,
2  Authors: Christian Hoeppner & Sebastian Neubert
3 
4  This file is part of GENFIT.
5 
6  GENFIT is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  GENFIT is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with GENFIT. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
21 
22 #include <math.h>
23 
25 
26 #include "TDatabasePDG.h"
27 #include "TGeoManager.h"
28 #include "TGeoMaterial.h"
29 #include "TGeoMedium.h"
30 #include "TGeoVolume.h"
31 #include "TMatrixT.h"
32 #include "TMatrixTBase.h"
33 #include "TMatrixTUtils.h"
34 #include "TParticlePDG.h"
35 
37 
38 
39 
41  // for(unsigned int i=0;i<fEnergyLoss.size();++i) delete fEnergyLoss.at(i);
42  //delete geoMatManager;
43 }
44 
45 /*
46 genf::GFMaterialEffects::GFMaterialEffects(){
47  // append all EnergyLoss classes
48  fEnergyLoss.push_back(new GFEnergyLossBetheBloch());
49  fEnergyLoss.push_back(new GFEnergyLossBrems());
50  fEnergyLoss.push_back(new GFEnergyLossCoulomb());
51 
52  //geoMatManager = new GFGeoMatManager(); // handles material parameters and geometry - GFGeoMatManager uses TGeoMaterial and TGeoManager
53 }
54 */
55 
57  fEnergyLossBetheBloch(true), fNoiseBetheBloch(true),
58  fNoiseCoulomb(true),
59  fEnergyLossBrems(true), fNoiseBrems(true),
60  me(0.510998910E-3),
61  fstep(0),
62  fbeta(0),
63  fdedx(0),
64  fgamma(0),
65  fgammaSquare(0),
66  fmatDensity(0),
67  fmatZ(0),
68  fmatA(0),
69  fradiationLength(0),
70  fmEE(0),
71  fpdg(0),
72  fcharge(0),
73  fmass(0) {
74 }
75 
77  if(finstance == NULL) finstance = new GFMaterialEffects();
78  return finstance;
79 }
80 
82  if(finstance != NULL) {
83  delete finstance;
84  finstance = NULL;
85  }
86 }
87 
88 double genf::GFMaterialEffects::effects(const std::vector<TVector3>& points,
89  const std::vector<double>& pointPaths,
90  const double& mom,
91  const int& pdg,
92  const bool& doNoise,
93  TMatrixT<Double_t>* noise,
94  const TMatrixT<Double_t>* jacobian,
95  const TVector3* directionBefore,
96  const TVector3* directionAfter){
97 
98  //assert(points.size()==pointPaths.size());
99  fpdg = pdg;
100 
101  double momLoss=0.;
102 
103  for(unsigned int i=1;i<points.size();++i){
104  // TVector3 p1=points.at(i-1);
105  //TVector3 p2=points.at(i);
106  //TVector3 dir=p2-p1;
107  TVector3 dir=points.at(i)-points.at(i-1);
108  double dist=dir.Mag();
109  double realPath = pointPaths.at(i);
110 
111  if (dist > 1.E-8) { // do material effects only if distance is not too small
112  dir*=1./dist; //normalize dir
113 
114  double X(0.);
115  /*
116  double matDensity, matZ, matA, radiationLength, mEE;
117  double step;
118  */
119 
120  gGeoManager->InitTrack(points.at(i-1).X(),points.at(i-1).Y(),points.at(i-1).Z(),
121  dir.X(),dir.Y(),dir.Z());
122 
123  while(X<dist){
124 
125  getParameters();
126  // geoMatManager->getMaterialParameters(matDensity, matZ, matA, radiationLength, mEE);
127 
128  // step = geoMatManager->stepOrNextBoundary(dist-X);
129  gGeoManager->FindNextBoundaryAndStep(dist-X);
130  fstep = gGeoManager->GetStep();
131 
132  // Loop over EnergyLoss classes
133  if(fmatZ>1.E-3){
134  /*
135  for(unsigned int j=0;j<fEnergyLoss.size();++j){
136  momLoss += realPath/dist*fEnergyLoss.at(j)->energyLoss(step,
137  mom,
138  pdg,
139  matDensity,
140  matZ,
141  matA,
142  radiationLength,
143  mEE,
144  doNoise,
145  noise,
146  jacobian,
147  directionBefore,
148  directionAfter);
149  }
150  */
151  calcBeta(mom);
152 
153  if (fEnergyLossBetheBloch)
154  momLoss += realPath/dist * this->energyLossBetheBloch(mom);
155  if (doNoise && fEnergyLossBetheBloch && fNoiseBetheBloch)
156  this->noiseBetheBloch(mom, noise);
157 
158  if (/*doNoise &&*/ fNoiseCoulomb) // Force it
159  this->noiseCoulomb(mom, noise, jacobian, directionBefore, directionAfter);
160 
161  if (fEnergyLossBrems)
162  momLoss += realPath/dist * this->energyLossBrems(mom);
163  if (doNoise && fEnergyLossBrems && fNoiseBrems)
164  this->noiseBrems(mom, noise);
165 
166 
167 
168  }
169 
170  X += fstep;
171 
172  }
173  }
174  }
175  //std::cout << "GFMaterialEffects::effects(): momLoss " << momLoss << std::endl;
176  return momLoss;
177 }
178 
179 
180 
181 
182 
183 double genf::GFMaterialEffects::stepper(const double& maxDist,
184  const double& posx,
185  const double& posy,
186  const double& posz,
187  const double& dirx,
188  const double& diry,
189  const double& dirz,
190  const double& mom,
191  const int& /* pdg */){
192 
193  static const double maxPloss = .005; // maximum relative momentum loss allowed
194 
195  gGeoManager->InitTrack(posx,posy,posz,dirx,diry,dirz);
196 
197  double X(0.);
198  double dP = 0.;
199  double momLoss = 0.;
200  /*
201  double matDensity, matZ, matA, radiationLength, mEE;
202  double step;
203  */
204 
205  while(X<maxDist){
206 
207  getParameters();
208 
209  gGeoManager->FindNextBoundaryAndStep(maxDist-X);
210  fstep = gGeoManager->GetStep();
211  //
212  // step = geoMatManager->stepOrNextBoundary(maxDist-X);
213 
214  // Loop over EnergyLoss classes
215 
216  if(fmatZ>1.E-3){
217  /*
218  for(unsigned int j=0;j<fEnergyLoss.size();++j){
219  momLoss += fEnergyLoss.at(j)->energyLoss(step,
220  mom,
221  pdg,
222  matDensity,
223  matZ,
224  matA,
225  radiationLength,
226  mEE);
227  }
228  */
229  calcBeta(mom);
230 
231  if (fEnergyLossBetheBloch)
232  momLoss += this->energyLossBetheBloch(mom);
233 
234  if (fEnergyLossBrems)
235  momLoss += this->energyLossBrems(mom);
236 
237  }
238 
239  if(dP + momLoss > mom*maxPloss){
240  double fraction = (mom*maxPloss-dP)/momLoss;
241  if ((fraction <= 0.) || (fraction >= 1.))
242  throw GFException(std::string(__func__) + ": invalid fraction", __LINE__, __FILE__).setFatal();
243  dP+=fraction*momLoss;
244  X+=fraction*fstep;
245  break;
246  }
247 
248  dP += momLoss;
249  X += fstep;
250  }
251 
252  return X;
253 }
254 
256  if (!gGeoManager->GetCurrentVolume()->GetMedium())
257  throw GFException(std::string(__func__) + ": no medium", __LINE__, __FILE__).setFatal();
258  TGeoMaterial * mat = gGeoManager->GetCurrentVolume()->GetMedium()->GetMaterial();
259  fmatDensity = mat->GetDensity();
260  fmatZ = mat->GetZ();
261  fmatA = mat->GetA();
262  fradiationLength = mat->GetRadLen();
263  fmEE = MeanExcEnergy_get(mat);
264 
265  // You know what? F*ck it. Just force this to be LAr.... is what I *could/will* say here ....
266  // See comment in energyLossBetheBloch() for why fmEE is in eV here.
267  fmatDensity = 1.40; fmatZ = 18.0; fmatA = 39.95; fradiationLength=13.947; fmEE=188.0;
268 
269 
270  TParticlePDG * part = TDatabasePDG::Instance()->GetParticle(fpdg);
271  fcharge = part->Charge()/(3.);
272  fmass = part->Mass();
273 }
274 
275 
277  fbeta = mom/sqrt(fmass*fmass+mom*mom);
278 
279  //for numerical stability
280  fgammaSquare = 1.-fbeta*fbeta;
281  if(fgammaSquare>1.E-10) fgammaSquare = 1./fgammaSquare;
282  else fgammaSquare = 1.E10;
283  fgamma = sqrt(fgammaSquare);
284 }
285 
286 
287 
288 //---- Energy-loss and Noise calculations -----------------------------------------
289 
291 
292  // calc fdedx, also needed in noiseBetheBloch!
293  fdedx = 0.307075*fmatZ/fmatA*fmatDensity/(fbeta*fbeta)*fcharge*fcharge;
294  double massRatio = me/fmass;
295  // me=0.000511 here is in GeV. So fmEE must come in here in eV to get converted to MeV.
296  double argument = fgammaSquare*fbeta*fbeta*me*1.E3*2./((1.E-6*fmEE) * sqrt(1+2*sqrt(fgammaSquare)*massRatio + massRatio*massRatio));
297 
298  if (fmass==0.0) return(0.0);
299  if (argument <= exp(fbeta*fbeta))
300  {
301  fdedx = 0.;
302  // so-called Anderson-Ziegler domain ... Let's approximate it with a flat
303  // 100 MeV/cm, looking at the muon dE/dx curve in the PRD Review, or, ahem, wikipedia.
304  // http://pdg.lbl.gov/2011/reviews/rpp2011-rev-passage-particles-matter.pdf
305  // But there's a practical problem: must not reduce momentum to zero for tracking in G3,
306  // so allow only 50% reduction of kinetic energy.
307  // fdedx = 100.0*1.E-3/fstep; // in GeV/cm, hence 1.e-3
308  //if (fdedx > 0.5*0.5*fmass*fbeta*fbeta/fstep) fdedx = 0.5*0.5*fmass*fbeta*fbeta/fstep;
309  }
310  else{
311  fdedx *= (log(argument)-fbeta*fbeta); // Bethe-Bloch [MeV/cm]
312  fdedx *= 1.E-3; // in GeV/cm, hence 1.e-3
313  if (fdedx<0.) fdedx = 0;
314  }
315 
316  double DE = fstep * fdedx; //always positive
317  double momLoss = sqrt(mom*mom+2.*sqrt(mom*mom+fmass*fmass)*DE+DE*DE) - mom; //always positive
318 
319  //in vacuum it can numerically happen that momLoss becomes a small negative number. A cut-off at 0.01 eV for momentum loss seems reasonable
320  if(fabs(momLoss)<1.E-11)momLoss=1.E-11;
321 
322  // if(fabs(momLoss)>mom)momLoss=mom; // For going fwd and ending its life. EC.
323  return momLoss;
324 }
325 
326 
328  TMatrixT<double>* noise) const{
329 
330 
331  // ENERGY LOSS FLUCTUATIONS; calculate sigma^2(E);
332  double sigma2E = 0.;
333  double zeta = 153.4E3 * fcharge*fcharge/(fbeta*fbeta) * fmatZ/fmatA * fmatDensity * fstep; // eV
334  double Emax = 2.E9*me*fbeta*fbeta*fgammaSquare / (1. + 2.*fgamma*me/fmass + (me/fmass)*(me/fmass) ); // eV
335  double kappa = zeta/Emax;
336 
337  if (kappa > 0.01) { // Vavilov-Gaussian regime
338  sigma2E += zeta*Emax*(1.-fbeta*fbeta/2.); // eV^2
339  }
340  else { // Urban/Landau approximation
341  double alpha = 0.996;
342  double sigmaalpha = 15.76;
343  // calculate number of collisions Nc
344  double I = 16. * pow(fmatZ, 0.9); // eV
345  double f2 = 0.;
346  if (fmatZ > 2.) f2 = 2./fmatZ;
347  double f1 = 1. - f2;
348  double e2 = 10.*fmatZ*fmatZ; // eV
349  double e1 = pow( (I/pow(e2,f2)), 1./f1); // eV
350 
351  double mbbgg2 = 2.E9*fmass*fbeta*fbeta*fgammaSquare; // eV
352  double Sigma1 = fdedx*1.0E9 * f1/e1 * (log(mbbgg2 / e1) - fbeta*fbeta) / (log(mbbgg2 / I) - fbeta*fbeta) * 0.6; // 1/cm
353  double Sigma2 = fdedx*1.0E9 * f2/e2 * (log(mbbgg2 / e2) - fbeta*fbeta) / (log(mbbgg2 / I) - fbeta*fbeta) * 0.6; // 1/cm
354  double Sigma3 = fdedx*1.0E9 * Emax / ( I*(Emax+I)*log((Emax+I)/I) ) * 0.4; // 1/cm
355 
356  double Nc = (Sigma1 + Sigma2 + Sigma3)*fstep;
357 
358  if (Nc > 50.) { // truncated Landau distribution
359  // calculate sigmaalpha (see GEANT3 manual W5013)
360  double RLAMED = -0.422784 - fbeta*fbeta - log(zeta/Emax);
361  double RLAMAX = 0.60715 + 1.1934*RLAMED +(0.67794 + 0.052382*RLAMED)*exp(0.94753+0.74442*RLAMED);
362  // from lambda max to sigmaalpha=sigma (empirical polynomial)
363  if(RLAMAX <= 1010.) {
364  sigmaalpha = 1.975560
365  +9.898841e-02 *RLAMAX
366  -2.828670e-04 *RLAMAX*RLAMAX
367  +5.345406e-07 *pow(RLAMAX,3.)
368  -4.942035e-10 *pow(RLAMAX,4.)
369  +1.729807e-13 *pow(RLAMAX,5.);
370  }
371  else { sigmaalpha = 1.871887E+01 + 1.296254E-02 *RLAMAX; }
372  // alpha=54.6 corresponds to a 0.9996 maximum cut
373  if(sigmaalpha > 54.6) sigmaalpha=54.6;
374  sigma2E += sigmaalpha*sigmaalpha * zeta*zeta; // eV^2
375  }
376  else { // Urban model
377  double Ealpha = I / (1.-(alpha*Emax/(Emax+I))); // eV
378  double meanE32 = I*(Emax+I)/Emax * (Ealpha-I); // eV^2
379  sigma2E += fstep * (Sigma1*e1*e1 + Sigma2*e2*e2 + Sigma3*meanE32); // eV^2
380  }
381  }
382 
383  sigma2E*=1.E-18; // eV -> GeV
384 
385  // update noise matrix
386  (*noise)[6][6] += (mom*mom+fmass*fmass)/pow(mom,6.)*sigma2E;
387 }
388 
389 
391  TMatrixT<double>* noise,
392  const TMatrixT<double>* jacobian,
393  const TVector3* directionBefore,
394  const TVector3* directionAfter) const{
395 
396  // MULTIPLE SCATTERING; calculate sigma^2
397  // PANDA report PV/01-07 eq(43); linear in step length
398  double sigma2 = 225.E-6/(fbeta*fbeta*mom*mom) * fstep/fradiationLength * fmatZ/(fmatZ+1) * log(159.*pow(fmatZ,-1./3.))/log(287.*pow(fmatZ,-0.5)); // sigma^2 = 225E-6/mom^2 * XX0/fbeta^2 * Z/(Z+1) * ln(159*Z^(-1/3))/ln(287*Z^(-1/2)
399 
400  // noiseBefore
401  TMatrixT<double> noiseBefore(7,7);
402 
403  // calculate euler angles theta, psi (so that directionBefore' points in z' direction)
404  double psi = 0;
405  if (fabs((*directionBefore)[1]) < 1E-14) { // numerical case: arctan(+-inf)=+-PI/2
406  if ((*directionBefore)[0] >= 0.) psi = M_PI/2.;
407  else psi = 3.*M_PI/2.;
408  }
409  else {
410  if ((*directionBefore)[1] > 0.) psi = M_PI - atan((*directionBefore)[0]/(*directionBefore)[1]);
411  else psi = -atan((*directionBefore)[0]/(*directionBefore)[1]);
412  }
413  // cache sin and cos
414  double sintheta = sqrt(1-(*directionBefore)[2]*(*directionBefore)[2]); // theta = arccos(directionBefore[2])
415  double costheta = (*directionBefore)[2];
416  double sinpsi = sin(psi);
417  double cospsi = cos(psi);
418 
419  // calculate NoiseBefore Matrix R M R^T
420  double noiseBefore34 = sigma2 * cospsi * sinpsi * sintheta*sintheta; // noiseBefore_ij = noiseBefore_ji
421  double noiseBefore35 = -sigma2 * costheta * sinpsi * sintheta;
422  double noiseBefore45 = sigma2 * costheta * cospsi * sintheta;
423 
424  noiseBefore[3][3] = sigma2 * (cospsi*cospsi + costheta*costheta - costheta*costheta * cospsi*cospsi);
425  noiseBefore[4][3] = noiseBefore34;
426  noiseBefore[5][3] = noiseBefore35;
427 
428  noiseBefore[3][4] = noiseBefore34;
429  noiseBefore[4][4] = sigma2 * (sinpsi*sinpsi + costheta*costheta * cospsi*cospsi);
430  noiseBefore[5][4] = noiseBefore45;
431 
432  noiseBefore[3][5] = noiseBefore35;
433  noiseBefore[4][5] = noiseBefore45;
434  noiseBefore[5][5] = sigma2 * sintheta*sintheta;
435 
436  TMatrixT<double> jacobianT(7,7);
437  jacobianT = (*jacobian);
438  jacobianT.T();
439 
440  noiseBefore = jacobianT*noiseBefore*(*jacobian); //propagate
441 
442  // noiseAfter
443  TMatrixT<double> noiseAfter(7,7);
444 
445  // calculate euler angles theta, psi (so that A' points in z' direction)
446  psi = 0;
447  if (fabs((*directionAfter)[1]) < 1E-14) { // numerical case: arctan(+-inf)=+-PI/2
448  if ((*directionAfter)[0] >= 0.) psi = M_PI/2.;
449  else psi = 3.*M_PI/2.;
450  }
451  else {
452  if ((*directionAfter)[1] > 0.) psi = M_PI - atan((*directionAfter)[0]/(*directionAfter)[1]);
453  else psi = -atan((*directionAfter)[0]/(*directionAfter)[1]);
454  }
455  // cache sin and cos
456  sintheta = sqrt(1-(*directionAfter)[2]*(*directionAfter)[2]); // theta = arccos(directionAfter[2])
457  costheta = (*directionAfter)[2];
458  sinpsi = sin(psi);
459  cospsi = cos(psi);
460 
461  // calculate NoiseAfter Matrix R M R^T
462  double noiseAfter34 = sigma2 * cospsi * sinpsi * sintheta*sintheta; // noiseAfter_ij = noiseAfter_ji
463  double noiseAfter35 = -sigma2 * costheta * sinpsi * sintheta;
464  double noiseAfter45 = sigma2 * costheta * cospsi * sintheta;
465 
466  noiseAfter[3][3] = sigma2 * (cospsi*cospsi + costheta*costheta - costheta*costheta * cospsi*cospsi);
467  noiseAfter[4][3] = noiseAfter34;
468  noiseAfter[5][3] = noiseAfter35;
469 
470  noiseAfter[3][4] = noiseAfter34;
471  noiseAfter[4][4] = sigma2 * (sinpsi*sinpsi + costheta*costheta * cospsi*cospsi);
472  noiseAfter[5][4] = noiseAfter45;
473 
474  noiseAfter[3][5] = noiseAfter35;
475  noiseAfter[4][5] = noiseAfter45;
476  noiseAfter[5][5] = sigma2 * sintheta*sintheta;
477 
478  //calculate mean of noiseBefore and noiseAfter and update noise
479  (*noise) += 0.5*noiseBefore + 0.5*noiseAfter;
480 
481 }
482 
483 
484 double genf::GFMaterialEffects::energyLossBrems(const double& mom) const{
485 
486  if (fabs(fpdg)!=11) return 0; // only for electrons and positrons
487 
488  #if !defined(BETHE)
489  static const double C[101]={ 0.0,-0.960613E-01, 0.631029E-01,-0.142819E-01, 0.150437E-02,-0.733286E-04, 0.131404E-05, 0.859343E-01,-0.529023E-01, 0.131899E-01,-0.159201E-02, 0.926958E-04,-0.208439E-05,-0.684096E+01, 0.370364E+01,-0.786752E+00, 0.822670E-01,-0.424710E-02, 0.867980E-04,-0.200856E+01, 0.129573E+01,-0.306533E+00, 0.343682E-01,-0.185931E-02, 0.392432E-04, 0.127538E+01,-0.515705E+00, 0.820644E-01,-0.641997E-02, 0.245913E-03,-0.365789E-05, 0.115792E+00,-0.463143E-01, 0.725442E-02,-0.556266E-03, 0.208049E-04,-0.300895E-06,-0.271082E-01, 0.173949E-01,-0.452531E-02, 0.569405E-03,-0.344856E-04, 0.803964E-06, 0.419855E-02,-0.277188E-02, 0.737658E-03,-0.939463E-04, 0.569748E-05,-0.131737E-06,-0.318752E-03, 0.215144E-03,-0.579787E-04, 0.737972E-05,-0.441485E-06, 0.994726E-08, 0.938233E-05,-0.651642E-05, 0.177303E-05,-0.224680E-06, 0.132080E-07,-0.288593E-09,-0.245667E-03, 0.833406E-04,-0.129217E-04, 0.915099E-06,-0.247179E-07, 0.147696E-03,-0.498793E-04, 0.402375E-05, 0.989281E-07,-0.133378E-07,-0.737702E-02, 0.333057E-02,-0.553141E-03, 0.402464E-04,-0.107977E-05,-0.641533E-02, 0.290113E-02,-0.477641E-03, 0.342008E-04,-0.900582E-06, 0.574303E-05, 0.908521E-04,-0.256900E-04, 0.239921E-05,-0.741271E-07,-0.341260E-04, 0.971711E-05,-0.172031E-06,-0.119455E-06, 0.704166E-08, 0.341740E-05,-0.775867E-06,-0.653231E-07, 0.225605E-07,-0.114860E-08,-0.119391E-06, 0.194885E-07, 0.588959E-08,-0.127589E-08, 0.608247E-10};
490  static const double xi=2.51, beta=0.99, vl=0.00004;
491  #endif
492  #if defined(BETHE) // no MIGDAL corrections
493  static const double C[101]={ 0.0, 0.834459E-02, 0.443979E-02,-0.101420E-02, 0.963240E-04,-0.409769E-05, 0.642589E-07, 0.464473E-02,-0.290378E-02, 0.547457E-03,-0.426949E-04, 0.137760E-05,-0.131050E-07,-0.547866E-02, 0.156218E-02,-0.167352E-03, 0.101026E-04,-0.427518E-06, 0.949555E-08,-0.406862E-02, 0.208317E-02,-0.374766E-03, 0.317610E-04,-0.130533E-05, 0.211051E-07, 0.158941E-02,-0.385362E-03, 0.315564E-04,-0.734968E-06,-0.230387E-07, 0.971174E-09, 0.467219E-03,-0.154047E-03, 0.202400E-04,-0.132438E-05, 0.431474E-07,-0.559750E-09,-0.220958E-02, 0.100698E-02,-0.596464E-04,-0.124653E-04, 0.142999E-05,-0.394378E-07, 0.477447E-03,-0.184952E-03,-0.152614E-04, 0.848418E-05,-0.736136E-06, 0.190192E-07,-0.552930E-04, 0.209858E-04, 0.290001E-05,-0.133254E-05, 0.116971E-06,-0.309716E-08, 0.212117E-05,-0.103884E-05,-0.110912E-06, 0.655143E-07,-0.613013E-08, 0.169207E-09, 0.301125E-04,-0.461920E-04, 0.871485E-05,-0.622331E-06, 0.151800E-07,-0.478023E-04, 0.247530E-04,-0.381763E-05, 0.232819E-06,-0.494487E-08,-0.336230E-04, 0.223822E-04,-0.384583E-05, 0.252867E-06,-0.572599E-08, 0.105335E-04,-0.567074E-06,-0.216564E-06, 0.237268E-07,-0.658131E-09, 0.282025E-05,-0.671965E-06, 0.565858E-07,-0.193843E-08, 0.211839E-10, 0.157544E-04,-0.304104E-05,-0.624410E-06, 0.120124E-06,-0.457445E-08,-0.188222E-05,-0.407118E-06, 0.375106E-06,-0.466881E-07, 0.158312E-08, 0.945037E-07, 0.564718E-07,-0.319231E-07, 0.371926E-08,-0.123111E-09};
494  static const double xi=2.10, fbeta=1.00, vl=0.001;
495  #endif
496 
497  double BCUT=10000.; // energy up to which soft bremsstrahlung energy loss is calculated
498 
499  double THIGH=100., CHIGH=50.;
500  double dedxBrems=0.;
501 
502  if(BCUT>0.){
503  double T, kc;
504 
505  if(BCUT>=mom) BCUT=mom; // confine BCUT to mom
506 
507  // T=mom, confined to THIGH
508  // kc=BCUT, confined to CHIGH ??
509  if(mom>=THIGH) {
510  T=THIGH;
511  if(BCUT>=THIGH) kc=CHIGH;
512  else kc=BCUT;
513  }
514  else {
515  T=mom;
516  kc=BCUT;
517  }
518 
519  double E=T+me; // total electron energy
520  if(BCUT>T) kc=T;
521 
522  double X=log(T/me);
523  double Y=log(kc/(E*vl));
524 
525  double XX;
526  int K;
527  double S=0., YY=1.;
528 
529  for (unsigned int I=1; I<=2; ++I) {
530  XX=1.;
531  for (unsigned int J=1; J<=6; ++J) {
532  K=6*I+J-6;
533  S=S+C[K]*XX*YY;
534  XX=XX*X;
535  }
536  YY=YY*Y;
537  }
538 
539  for (unsigned int I=3; I<=6; ++I) {
540  XX=1.;
541  for (unsigned int J=1; J<=6; ++J) {
542  K=6*I+J-6;
543  if(Y<=0.) S=S+C[K]*XX*YY;
544  else S=S+C[K+24]*XX*YY;
545  XX=XX*X;
546  }
547  YY=YY*Y;
548  }
549 
550  double SS=0.;
551  YY=1.;
552 
553  for (unsigned int I=1; I<=2; ++I) {
554  XX=1.;
555  for (unsigned int J=1; J<=5; ++J) {
556  K=5*I+J+55;
557  SS=SS+C[K]*XX*YY;
558  XX=XX*X;
559  }
560  YY=YY*Y;
561  }
562 
563  for (unsigned int I=3; I<=5; ++I) {
564  XX=1.;
565  for (unsigned int J=1; J<=5; ++J) {
566  K=5*I+J+55;
567  if(Y<=0.) SS=SS+C[K]*XX*YY;
568  else SS=SS+C[K+15]*XX*YY;
569  XX=XX*X;
570  }
571  YY=YY*Y;
572  }
573 
574  S=S+fmatZ*SS;
575 
576  if(S>0.){
577  double CORR=1.;
578  #if !defined(BETHE)
579  CORR=1./(1.+0.805485E-10*fmatDensity*fmatZ*E*E/(fmatA*kc*kc)); // MIGDAL correction factor
580  #endif
581 
582  double FAC=fmatZ*(fmatZ+xi)*E*E * pow((kc*CORR/T),beta) / (E+me);
583  if(FAC<=0.) return 0.;
584  dedxBrems=FAC*S;
585 
586  double RAT;
587 
588  if(mom>THIGH) {
589  if(BCUT<THIGH) {
590  RAT=BCUT/mom;
591  S=(1.-0.5*RAT+2.*RAT*RAT/9.);
592  RAT=BCUT/T;
593  S=S/(1.-0.5*RAT+2.*RAT*RAT/9.);
594  }
595  else {
596  RAT=BCUT/mom;
597  S=BCUT*(1.-0.5*RAT+2.*RAT*RAT/9.);
598  RAT=kc/T;
599  S=S/(kc*(1.-0.5*RAT+2.*RAT*RAT/9.));
600  }
601  dedxBrems=dedxBrems*S; // GeV barn
602  }
603 
604  dedxBrems = 0.60221367*fmatDensity*dedxBrems/fmatA; // energy loss dE/dx [GeV/cm]
605  }
606  }
607 
608  if (dedxBrems<0.) dedxBrems = 0;
609 
610  double factor=1.; // positron correction factor
611 
612  if (fpdg==-11){
613  static const double AA=7522100., A1=0.415, A3=0.0021, A5=0.00054;
614 
615  double ETA=0.;
616  if(fmatZ>0.) {
617  double X=log(AA*mom/fmatZ*fmatZ);
618  if(X>-8.) {
619  if(X>=+9.) ETA=1.;
620  else {
621  double W=A1*X+A3*pow(X,3.)+A5*pow(X,5.);
622  ETA=0.5+atan(W)/M_PI;
623  }
624  }
625  }
626 
627  double E0;
628 
629  if(ETA<0.0001) factor=1.E-10;
630  else if (ETA>0.9999) factor=1.;
631  else {
632  E0=BCUT/mom;
633  if(E0>1.) E0=1.;
634  if(E0<1.E-8) factor=1.;
635  else factor = ETA * ( 1.-pow(1.-E0, 1./ETA) ) / E0;
636  }
637  }
638 
639  double DE = fstep * factor*dedxBrems; //always positive
640  double momLoss = sqrt(mom*mom+2.*sqrt(mom*mom+fmass*fmass)*DE+DE*DE) - mom; //always positive
641 
642  return momLoss;
643 }
644 
645 
646 void genf::GFMaterialEffects::noiseBrems(const double& mom,
647  TMatrixT<double>* noise) const{
648 
649  if (fabs(fpdg)!=11) return; // only for electrons and positrons
650 
651  double LX = 1.442695*fstep/fradiationLength;
652  double S2B = mom*mom * ( 1./pow(3.,LX) - 1./pow(4.,LX) );
653  double DEDXB = pow(fabs(S2B),0.5);
654  DEDXB = 1.2E9*DEDXB; //eV
655  double sigma2E = DEDXB*DEDXB; //eV^2
656  sigma2E*=1.E-18; // eV -> GeV
657 
658  (*noise)[6][6] += (mom*mom+fmass*fmass)/pow(mom,6.)*sigma2E;
659 }
660 
661 
662 /*
663 Reference for elemental mean excitation energies at:
664 http://physics.nist.gov/PhysRefData/XrayMassCoef/tab1.html
665 */
666 
667 const int MeanExcEnergy_NELEMENTS = 93; // 0 = vacuum, 1 = hydrogen, 92 = uranium
668 const float MeanExcEnergy_vals[MeanExcEnergy_NELEMENTS] = {1.e15, 19.2, 41.8, 40.0, 63.7, 76.0, 78., 82.0, 95.0, 115.0, 137.0, 149.0, 156.0, 166.0, 173.0, 173.0, 180.0, 174.0, 188.0, 190.0, 191.0, 216.0, 233.0, 245.0, 257.0, 272.0, 286.0, 297.0, 311.0, 322.0, 330.0, 334.0, 350.0, 347.0, 348.0, 343.0, 352.0, 363.0, 366.0, 379.0, 393.0, 417.0, 424.0, 428.0, 441.0, 449.0, 470.0, 470.0, 469.0, 488.0, 488.0, 487.0, 485.0, 491.0, 482.0, 488.0, 491.0, 501.0, 523.0, 535.0, 546.0, 560.0, 574.0, 580.0, 591.0, 614.0, 628.0, 650.0, 658.0, 674.0, 684.0, 694.0, 705.0, 718.0, 727.0, 736.0, 746.0, 757.0, 790.0, 790.0, 800.0, 810.0, 823.0, 823.0, 830.0, 825.0, 794.0, 827.0, 826.0, 841.0, 847.0, 878.0, 890.0};
669 
671  if ((Z < 0) || (Z > MeanExcEnergy_NELEMENTS))
672  throw GFException(std::string(__func__) + ": unsupported Z", __LINE__, __FILE__).setFatal();
673  return MeanExcEnergy_vals[Z];
674 }
675 
677  if(mat->IsMixture()){
678  double logMEE = 0.;
679  double denom = 0.;
680  TGeoMixture *mix = (TGeoMixture*)mat;
681  for(int i=0;i<mix->GetNelements();++i){
682  int index = int(floor((mix->GetZmixt())[i]));
683  logMEE += 1./(mix->GetAmixt())[i]*(mix->GetWmixt())[i]*(mix->GetZmixt())[i]*log(MeanExcEnergy_get(index));
684  denom += (mix->GetWmixt())[i]*(mix->GetZmixt())[i]*1./(mix->GetAmixt())[i];
685  }
686  logMEE/=denom;
687  return exp(logMEE);
688  }
689  else{ // not a mixture
690  int index = int(floor(mat->GetZ()));
691  return MeanExcEnergy_get(index);
692  }
693 }
694 
695 //ClassImp(GFMaterialEffects)
see a below echo or echo I(indirect symbol).'echo" If the symbol is local (non-external)
float MeanExcEnergy_get(int Z)
see a below echo S(symbol in a section other than those above)
static GFMaterialEffects * getInstance()
var pdg
Definition: selectors.fcl:14
void noiseBrems(const double &mom, TMatrixT< double > *noise) const
calculation of energy loss straggeling
void noiseCoulomb(const double &mom, TMatrixT< double > *noise, const TMatrixT< double > *jacobian, const TVector3 *directionBefore, const TVector3 *directionAfter) const
calculation of multiple scattering
process_name E
double energyLossBrems(const double &mom) const
Returns energy loss.
void noiseBetheBloch(const double &mom, TMatrixT< double > *noise) const
calculation of energy loss straggling
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
const float MeanExcEnergy_vals[MeanExcEnergy_NELEMENTS]
constexpr double kc
Speed of light in vacuum in LArSoft units [cm/ns].
static GFMaterialEffects * finstance
tuple dir
Definition: dropbox.py:28
void calcBeta(double mom)
sets fbeta, fgamma, fgammasquare; must only be used after calling getParameters() ...
Exception class for error handling in GENFIT (provides storage for diagnostic information) ...
Definition: GFException.h:48
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double effects(const std::vector< TVector3 > &points, const std::vector< double > &pointPaths, const double &mom, const int &pdg, const bool &doNoise=false, TMatrixT< Double_t > *noise=NULL, const TMatrixT< Double_t > *jacobian=NULL, const TVector3 *directionBefore=NULL, const TVector3 *directionAfter=NULL)
Calculates energy loss in the travelled path, optional calculation of noise matrix.
GFException & setFatal(bool b=true)
set fatal flag. if this is true, the fit stops for this current track repr.
Definition: GFException.h:78
void getParameters()
contains energy loss classes
const int MeanExcEnergy_NELEMENTS
physics pm2 e1
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
double energyLossBetheBloch(const double &mom)
Returns energy loss.
double stepper(const double &maxDist, const double &posx, const double &posy, const double &posz, const double &dirx, const double &diry, const double &dirz, const double &mom, const int &pdg)
Returns maximum length so that a specified momentum loss will not be exceeded.