View Javadoc

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   * A calculator for dEdX using the Bethe-Bloch formula
19   * from the PDG guide.  
20   *
21   * <a href="http://pdg.lbl.gov/2006/reviews/passagerpp.pdf">Passage of Particles Through Matter</a>
22   *
23   * @author jeremym
24   * @author caroline
25   */
26  public class BetheBlochCalculator
27  {	
28  	/**
29  	 * 
30  	 * Calculate Bethe-Bloch using IMaterial and Particle.
31  	 * 
32  	 * @param material
33  	 * @param particle
34  	 * @param distance
35  	 * @return The energy loss in MeV. 
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  	 * Calculate Bethe-Bloch using an IMaterial.
52  	 * 
53  	 * @param material
54  	 * @param p
55  	 * @param mass
56  	 * @param charge
57  	 * @param distance
58  	 * @return The energy loss in MeV.
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  	 * Calculate Bethe Bloch with numerical parameters.
82  	 * 
83  	 * The pressure and temperature arguments are only used if the
84  	 * state is a gas.
85  	 * 
86  	 * @param Z
87  	 * @param A
88  	 * @param density
89  	 * @param state
90  	 * @param pressure
91  	 * @param temperature
92  	 * @param p
93  	 * @param mass
94  	 * @param charge
95  	 * @param distance
96  	 * @return The energy loss in MeV.
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         // K matches PDG, pg. 238 --> 0.307075 in MeV g-1 cm2 */
115         double K = ((4 * PI) * Avogadro * (classic_electr_radius * classic_electr_radius) * electron_mass_c2);
116         double z2 = charge * charge;
117         
118         // Convert p(GeV) to p(MeV).       
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         //double beta = sqrt(beta2);
129         
130         double coeff1 = K * z2 * (ZoverA) * (1 / beta2);        
131         
132         double gamma = 1 / (sqrt(1 - beta2));
133         double gamma2 = gamma * gamma;
134                 
135         // Compute T_max.
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         // Compute I using lelaps/CEPack/cematerial.cc .
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; // convert I to MeV
158         double I2 = I * I;
159         
160         // Compute plasma E.
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         // Cbar
175         double Cbar = 2.0 * log( I / plasmaE ) + 1.0;
176         
177         // Xa
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         //double ASP = 0.1536 * ZoverA;        
235         //double BSP = log(511.0e9 / I2);
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         //double delta_estimate = log(plasmaE / I) + log((sqrt(beta2) * gamma)) - 0.5;
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 }