View Javadoc

1   package org.lcsim.detector.material;
2   
3   import static java.lang.Math.log;
4   import static java.lang.Math.pow;
5   import static org.lcsim.units.clhep.PhysicalConstants.fine_structure_const;
6   
7   /**
8    * This class is a Material that represents a chemical element.
9    * 
10   * It uses the CLHEP values for Avogadro, fine structure constant, and electron
11   * radius. Radiation lengths are computed using the Tsai formula, ported from
12   * Lelaps. Nuclear interaction length is computed with a simple fit, ported from
13   * Lelaps.
14   * 
15   * @author Jeremy McCormick <jeremym@slac.stanford.edu>
16   * @version $Id: MaterialElement.java,v 1.5 2010/04/14 18:24:53 jeremy Exp $
17   */
18  public class MaterialElement implements IMaterial
19  {
20      // From constructor.
21      protected String name;
22      protected double Z;
23      protected double A;
24      protected double density;
25      protected double temperature;
26      protected double pressure;
27  
28      // Set by the detailed constructor.  Otherwise, use defaults.
29      protected State state = defaultState;
30  
31      // Derived quantities.
32      protected double N;
33      protected double nuclearInteractionLength;
34      protected double nuclearInteractionLengthWithDensity;
35      protected double radiationLength;
36      protected double radiationLengthWithDensity;
37      protected double criticalEnergy;
38      protected double moliereRadius;
39  
40      /**
41       * Constructor for sub-classes.
42       */
43      protected MaterialElement()
44      {
45          MaterialStore.getInstance().add(this);
46      }
47  
48      /**
49       * Construct a MaterialElement.
50       * 
51       * @param name The name of the material, which must be globally unique.
52       * @param Z The atomic mass.
53       * @param A The atomic number.
54       * @param density The density in g/cm3.
55       * @param state The material's state.
56       * @param temperature The temperature in Kelvin.
57       * @param pressure The pressure in atmospheres.
58       */
59      public MaterialElement(String name, double Z, double A, double density, State state, double temperature, double pressure)
60      {
61          // Set parameters.
62          this.name = name;
63          this.Z = Z;
64          this.A = A;
65          this.density = density;
66          this.density = density;
67          this.state = state;
68          this.temperature = temperature;
69          this.pressure = pressure;
70  
71          // Compute derived quantities.
72          computeDerivedQuantities();
73  
74          // Add to global static materials store.
75          MaterialStore.getInstance().add(this);
76      }
77  
78      /**
79       * Construct a MaterialElement.
80       * 
81       * @param name The name of the material, which must be globally unique.
82       * @param Z The atomic mass.
83       * @param A The atomic number.
84       * @param density The density in g/cm3.
85       */
86      public MaterialElement(String name, double Z, double A, double density)
87      {
88          // Set parameters.
89          this.name = name;
90          this.Z = Z;
91          this.A = A;
92          this.density = density;
93          this.density = density;
94          this.state = Unknown;
95          this.temperature = defaultTemperature;
96          this.pressure = defaultPressure;
97  
98          // Compute derived quantities.
99          computeDerivedQuantities();
100 
101         // Add to global static materials store.
102         MaterialStore.getInstance().add(this);
103     }
104 
105     private void computeDerivedQuantities()
106     {
107         computeRadiationLength();
108         computeNuclearInteractionLength();
109         computeCriticalEnergy();
110         computeMoliereRadius();
111     }
112 
113     protected void computeCriticalEnergy()
114     {
115         criticalEnergy = 2.66 * pow(getRadiationLength() * getZ() / getA(), 1.1);
116     }
117 
118     protected void computeMoliereRadius()
119     {
120         moliereRadius = getRadiationLengthWithDensity() * 21.2052 / criticalEnergy;
121     }
122 
123     protected void computeRadiationLength()
124     {
125         radiationLength = computeRadiationLengthTsai(A, Z);
126         radiationLengthWithDensity = radiationLength / getDensity();
127     }
128 
129     protected void computeNuclearInteractionLength()
130     {
131         nuclearInteractionLength = computeNuclearInteractionLength(A, Z);
132         nuclearInteractionLengthWithDensity = nuclearInteractionLength / getDensity();
133     }
134 
135     public double getA()
136     {
137         return A;
138     }
139 
140     public double getDensity()
141     {
142         return density;
143     }
144 
145     public String getName()
146     {
147         return name;
148     }
149 
150     public double getNuclearInteractionLength()
151     {
152         return nuclearInteractionLength;
153     }
154 
155     public double getRadiationLength()
156     {
157         return radiationLength;
158     }
159 
160     public State getState()
161     {
162         return state;
163     }
164 
165     public double getZ()
166     {
167         return Z;
168     }
169 
170     public double getEffectiveNumberOfNucleons()
171     {
172         return N;
173     }
174 
175     public double getMoliereRadius()
176     {
177         return moliereRadius;
178     }
179 
180     public double getNuclearInteractionLengthWithDensity()
181     {
182         return nuclearInteractionLengthWithDensity;
183     }
184 
185     public double getRadiationLengthWithDensity()
186     {
187         return radiationLengthWithDensity;
188     }
189 
190     public static double computeRadiationLengthTsai(double A, double Z)
191     {
192         double azsq = fine_structure_const * Z;
193         azsq *= azsq;
194         double f = azsq * (1.0 / (1.0 + azsq) + 0.20206 - 0.0369 * azsq + 0.0083 * azsq * azsq - 0.002 * azsq * azsq * azsq);
195 
196         double Lrad, LradP;
197         if (Z == 1)
198         {
199             Lrad = 5.31;
200             LradP = 6.144;
201         }
202         else if (Z == 2)
203         {
204             Lrad = 4.79;
205             LradP = 5.621;
206         }
207         else if (Z == 3)
208         {
209             Lrad = 4.74;
210             LradP = 5.805;
211         }
212         else if (Z == 4)
213         {
214             Lrad = 4.71;
215             LradP = 5.924;
216         }
217         else
218         {
219             Lrad = log(184.15 / pow(Z, 0.333333333));
220             LradP = log(1194.0 / pow(Z, 0.666666667));
221         }
222         double rlen = 716.408 * A / ((Z * Z * (Lrad - f) + Z * LradP));
223         return rlen;
224     }
225 
226     public static double computeNuclearInteractionLength(double A, double Z)
227     {
228         double NIL = 0;
229         if (Z == 1)
230         {
231             if (A < 1.5)
232             {
233                 NIL = 50.8;
234             }
235             else
236             {
237                 NIL = 54.7;
238             }
239         }
240         else if (Z == 2)
241         {
242             NIL = 65.2;
243         }
244         else
245         {
246             NIL = 40.8 * pow(A, 0.289);
247         }
248 
249         return NIL;
250     }
251 
252     public double getTemperature()
253     {
254         return temperature;
255     }
256 
257     public double getPressure()
258     {
259         return pressure;
260     }
261 
262     public String toString()
263     {
264         StringBuffer sb = new StringBuffer();
265         sb.append(getName() + '\n');
266         sb.append("D = " + getDensity() + " {g/cm3} ; ");
267         sb.append("A = " + getA() + "; ");
268         sb.append("Z = " + getZ());
269         sb.append('\n');
270         sb.append("LamdaT = " + getNuclearInteractionLength() + " {g/cm2}; ");
271         sb.append("LamdaT = " + getNuclearInteractionLengthWithDensity() + " {cm}; ");
272         sb.append("X0 = " + getRadiationLength() + " {g/cm2}; ");
273         sb.append("X0 = " + getRadiationLengthWithDensity() + " {cm}; ");
274         sb.append("Rm = " + getMoliereRadius() + " {cm} ");
275         sb.append('\n');
276 
277         return sb.toString();
278     }
279 }