1 package org.lcsim.detector.material;
2
3 import static java.lang.Math.PI;
4 import static java.lang.Math.log;
5 import static java.lang.Math.log10;
6 import static java.lang.Math.pow;
7 import static java.lang.Math.sqrt;
8 import static org.lcsim.units.clhep.PhysicalConstants.Avogadro;
9 import static org.lcsim.units.clhep.PhysicalConstants.classic_electr_radius;
10 import static org.lcsim.units.clhep.PhysicalConstants.electron_mass_c2;
11 import hep.physics.particle.Particle;
12 import hep.physics.vec.Hep3Vector;
13
14 import org.lcsim.detector.material.IMaterial.State;
15
16
17
18
19
20
21
22
23
24
25
26 public class BetheBlochCalculator
27 {
28
29
30
31
32
33
34
35
36
37 public static double computeBetheBloch(
38 IMaterial material,
39 Particle particle,
40 double distance)
41 {
42 return computeBetheBloch(
43 material,
44 particle.getMomentum(),
45 particle.getMass(),
46 particle.getCharge(),
47 distance);
48 }
49
50
51
52
53
54
55
56
57
58
59
60 public static double computeBetheBloch(
61 IMaterial material,
62 Hep3Vector p,
63 double mass,
64 double charge,
65 double distance)
66 {
67 return computeBetheBloch(
68 material.getZ(),
69 material.getA(),
70 material.getDensity(),
71 material.getState(),
72 material.getPressure(),
73 material.getTemperature(),
74 p,
75 mass,
76 charge,
77 distance);
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 public static double computeBetheBloch(
99 double Z,
100 double A,
101 double density,
102 State state,
103 double pressure,
104 double temperature,
105 Hep3Vector p,
106 double mass,
107 double charge,
108 double distance)
109 {
110 double zeff = Z;
111 double aeff = A;
112 double ZoverA = zeff / aeff;
113
114
115 double K = ((4 * PI) * Avogadro * (classic_electr_radius * classic_electr_radius) * electron_mass_c2);
116 double z2 = charge * charge;
117
118
119 double[] pmev = new double[3];
120 for (int i = 0; i < 3; i++)
121 {
122 pmev[i] = p.v()[i] * 1e+3;
123 }
124
125 double mag2 = pmev[0] * pmev[0] + pmev[1] * pmev[1] + pmev[2] * pmev[2];
126
127 double beta2 = mag2 / (mass * mass + mag2);
128
129
130 double coeff1 = K * z2 * (ZoverA) * (1 / beta2);
131
132 double gamma = 1 / (sqrt(1 - beta2));
133 double gamma2 = gamma * gamma;
134
135
136 double numer_T_max = 2 * electron_mass_c2 * beta2 * gamma2;
137 double denom_T_max = 1 + (2 * gamma * electron_mass_c2 / mass) + pow((electron_mass_c2 / mass), 2);
138 double T_max = numer_T_max / denom_T_max;
139
140
141 double I = 0.0;
142 if (zeff > 12)
143 {
144 I = zeff * (9.76 + 58.8 * pow(zeff, -1.19));
145 }
146 else
147 {
148 if (zeff == 1)
149 {
150 I = 18.7;
151 }
152 else
153 {
154 I = 13.0 * zeff;
155 }
156 }
157 I *= 1e-6;
158 double I2 = I * I;
159
160
161 double eta = 1.0;
162 double rho_STP = density;
163 double rho = density;
164
165 if (state == IMaterial.Gas)
166 {
167 eta = pressure * (273.15 / temperature);
168 rho_STP = rho / eta;
169 }
170
171 double plasmaE = 28.816 * sqrt(rho_STP * ZoverA);
172 plasmaE *= 1e-6;
173
174
175 double Cbar = 2.0 * log( I / plasmaE ) + 1.0;
176
177
178 double Xa = Cbar / 4.6052;
179
180 double X1;
181 if (state == IMaterial.Gas)
182 {
183 if (Cbar < 12.25)
184 {
185 X1 = 4.0;
186 }
187 else
188 {
189 X1 = 5.0;
190 }
191 }
192 else
193 {
194 if ( I < 100.0)
195 {
196 X1 = 2.0;
197 }
198 else
199 {
200 X1 = 3.0;
201 }
202 }
203
204 double m = 3.0;
205
206 double X0 = 0;
207 if (state == IMaterial.Gas)
208 {
209 if (Cbar < 10.0) X0 = 1.6;
210 else if (Cbar < 10.5) X0 = 1.7;
211 else if (Cbar < 11.0) X0 = 1.8;
212 else if (Cbar < 11.5) X0 = 1.9;
213 else if (Cbar < 13.804) X0 = 2.0;
214 else X0 = 0.326 * Cbar - 2.5;
215 }
216 else
217 {
218 if (I < 100.0)
219 {
220 if (Cbar < 3.681) X0 = 0.2;
221 else X0 = 0.326 * Cbar - 1.0;
222 X1 = 2.0;
223 }
224 else
225 {
226 if (Cbar < 5.215) X0 = 0.2;
227 else X0 = 0.326 * Cbar - 1.5;
228 X1 = 3.0;
229 }
230 }
231
232 double a = 4.6052 * (Xa - X0) / pow(X1 - X0, m);
233
234
235
236
237 if (state == IMaterial.Gas)
238 {
239 double eta_corr_1 = 0.5 * log10(eta);
240 double eta_corr_2 = 4.6052 * eta_corr_1;
241
242 Cbar -= eta_corr_2;
243 X1 -= eta_corr_1;
244 X0 -= eta_corr_1;
245 }
246
247
248
249 double delta = 0;
250 double X = log10(sqrt(mag2) / (mass));
251
252 if ( X0 < X && X < X1 )
253 {
254 delta = 4.6052 * X - Cbar + a * (X1 - X);
255 }
256 else if ( X > X1 )
257 {
258 delta = 4.6052 * X - Cbar;
259 }
260 else if ( X < X0 )
261 {
262 delta = 0;
263 }
264
265 double coeff2 = 0.5 * (log((2 * electron_mass_c2 * beta2 * gamma2 * T_max) / I2));
266
267 coeff2 -= beta2;
268 coeff2 -= delta;
269
270 double result = coeff1 * coeff2;
271
272 result = result * density;
273 result = result * distance;
274
275 return result;
276 }
277 }