LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
GFEnergyLossCoulomb.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 
22 #include <math.h>
23 #include <string>
24 
26 
27 double genf::GFEnergyLossCoulomb::energyLoss(const double& step,
28  const double& mom,
29  const int& pdg,
30  const double& /* matDensity */,
31  const double& matZ,
32  const double& /* matA */,
33  const double& radiationLength,
34  const double& /* meanExcitationEnergy */,
35  const bool& doNoise,
36  TMatrixT<Double_t>* noise,
37  const TMatrixT<Double_t>* jacobian,
38  const TVector3* directionBefore,
39  const TVector3* directionAfter)
40 {
41 
42  double charge, mass;
43  getParticleParameters(pdg, charge, mass);
44 
45  const double beta = mom / sqrt(mass * mass + mom * mom);
46 
47  if (doNoise) {
48  if (!noise)
49  throw GFException(std::string(__func__) + ": no noise given!", __LINE__, __FILE__).setFatal();
50  if (!jacobian)
51  throw GFException(std::string(__func__) + ": no jacobian given!", __LINE__, __FILE__)
52  .setFatal();
53  if (!directionBefore)
54  throw GFException(std::string(__func__) + ": no directionBefore given!", __LINE__, __FILE__)
55  .setFatal();
56  if (!directionAfter)
57  throw GFException(std::string(__func__) + ": no directionAfter given!", __LINE__, __FILE__)
58  .setFatal();
59 
60  // MULTIPLE SCATTERING; calculate sigma^2
61  // PANDA report PV/01-07 eq(43); linear in step length
62  double sigma2 =
63  225.E-6 / (beta * beta * mom * mom) * step / radiationLength * matZ / (matZ + 1) *
64  log(159. * pow(matZ, -1. / 3.)) /
65  log(
66  287. /
67  sqrt(
68  matZ)); // sigma^2 = 225E-6/mom^2 * XX0/beta^2 * Z/(Z+1) * ln(159*Z^(-1/3))/ln(287*Z^(-1/2)
69 
70  // noiseBefore
71  TMatrixT<Double_t> noiseBefore(7, 7);
72 
73  // calculate euler angles theta, psi (so that directionBefore' points in z' direction)
74  double psi = 0;
75  if (fabs((*directionBefore)[1]) < 1E-14) { // numerical case: arctan(+-inf)=+-PI/2
76  if ((*directionBefore)[0] >= 0.)
77  psi = M_PI / 2.;
78  else
79  psi = 3. * M_PI / 2.;
80  }
81  else {
82  if ((*directionBefore)[1] > 0.)
83  psi = M_PI - atan((*directionBefore)[0] / (*directionBefore)[1]);
84  else
85  psi = -atan((*directionBefore)[0] / (*directionBefore)[1]);
86  }
87  // cache sin and cos
88  double sintheta =
89  sqrt(1 - (*directionBefore)[2] * (*directionBefore)[2]); // theta = arccos(directionBefore[2])
90  double costheta = (*directionBefore)[2];
91  double sinpsi = sin(psi);
92  double cospsi = cos(psi);
93 
94  // calculate NoiseBefore Matrix R M R^T
95  double noiseBefore34 =
96  sigma2 * cospsi * sinpsi * sintheta * sintheta; // noiseBefore_ij = noiseBefore_ji
97  double noiseBefore35 = -sigma2 * costheta * sinpsi * sintheta;
98  double noiseBefore45 = sigma2 * costheta * cospsi * sintheta;
99 
100  noiseBefore[3][3] =
101  sigma2 * (cospsi * cospsi + costheta * costheta - costheta * costheta * cospsi * cospsi);
102  noiseBefore[4][3] = noiseBefore34;
103  noiseBefore[5][3] = noiseBefore35;
104 
105  noiseBefore[3][4] = noiseBefore34;
106  noiseBefore[4][4] = sigma2 * (sinpsi * sinpsi + costheta * costheta * cospsi * cospsi);
107  noiseBefore[5][4] = noiseBefore45;
108 
109  noiseBefore[3][5] = noiseBefore35;
110  noiseBefore[4][5] = noiseBefore45;
111  noiseBefore[5][5] = sigma2 * sintheta * sintheta;
112 
113  TMatrixT<Double_t> jacobianT(7, 7);
114  jacobianT = (*jacobian);
115  jacobianT.T();
116 
117  noiseBefore = jacobianT * noiseBefore * (*jacobian); //propagate
118 
119  // noiseAfter
120  TMatrixT<Double_t> noiseAfter(7, 7);
121 
122  // calculate euler angles theta, psi (so that A' points in z' direction)
123  psi = 0;
124  if (fabs((*directionAfter)[1]) < 1E-14) { // numerical case: arctan(+-inf)=+-PI/2
125  if ((*directionAfter)[0] >= 0.)
126  psi = M_PI / 2.;
127  else
128  psi = 3. * M_PI / 2.;
129  }
130  else {
131  if ((*directionAfter)[1] > 0.)
132  psi = M_PI - atan((*directionAfter)[0] / (*directionAfter)[1]);
133  else
134  psi = -atan((*directionAfter)[0] / (*directionAfter)[1]);
135  }
136  // cache sin and cos
137  sintheta =
138  sqrt(1 - (*directionAfter)[2] * (*directionAfter)[2]); // theta = arccos(directionAfter[2])
139  costheta = (*directionAfter)[2];
140  sinpsi = sin(psi);
141  cospsi = cos(psi);
142 
143  // calculate NoiseAfter Matrix R M R^T
144  double noiseAfter34 =
145  sigma2 * cospsi * sinpsi * sintheta * sintheta; // noiseAfter_ij = noiseAfter_ji
146  double noiseAfter35 = -sigma2 * costheta * sinpsi * sintheta;
147  double noiseAfter45 = sigma2 * costheta * cospsi * sintheta;
148 
149  noiseAfter[3][3] =
150  sigma2 * (cospsi * cospsi + costheta * costheta - costheta * costheta * cospsi * cospsi);
151  noiseAfter[4][3] = noiseAfter34;
152  noiseAfter[5][3] = noiseAfter35;
153 
154  noiseAfter[3][4] = noiseAfter34;
155  noiseAfter[4][4] = sigma2 * (sinpsi * sinpsi + costheta * costheta * cospsi * cospsi);
156  noiseAfter[5][4] = noiseAfter45;
157 
158  noiseAfter[3][5] = noiseAfter35;
159  noiseAfter[4][5] = noiseAfter45;
160  noiseAfter[5][5] = sigma2 * sintheta * sintheta;
161 
162  //calculate mean of noiseBefore and noiseAfter and update noise
163  (*noise) += 0.5 * noiseBefore + 0.5 * noiseAfter;
164  }
165 
166  return 0.;
167 }
168 
169 //ClassImp(GFEnergyLossCoulomb)
double energyLoss(const double &step, const double &mom, const int &pdg, const double &matDensity, const double &matZ, const double &matA, const double &radiationLength, const double &meanExcitationEnergy, const bool &doNoise=false, TMatrixT< Double_t > *noise=NULL, const TMatrixT< Double_t > *jacobian=NULL, const TVector3 *directionBefore=NULL, const TVector3 *directionAfter=NULL)
Optional calculation of multiple scattering.
unsigned int noise()
Definition: chem4.cc:261
Float_t E
Definition: plot.C:20
void getParticleParameters(const int &pdg, double &charge, double &mass)
Gets particle charge and mass (in GeV)
Exception class for error handling in GENFIT (provides storage for diagnostic information) ...
Definition: GFException.h:47
GFException & setFatal(bool b=true)
set fatal flag. if this is true, the fit stops for this current track repr.
Definition: GFException.h:75