View Javadoc

1   package org.lcsim.geometry.compact.converter.lcdd;
2   
3   import org.jdom.Element;
4   import org.jdom.JDOMException;
5   import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
6   import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
7   import org.lcsim.geometry.compact.converter.lcdd.util.Polycone;
8   import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
9   import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
10  import org.lcsim.geometry.compact.converter.lcdd.util.Structure;
11  import org.lcsim.geometry.compact.converter.lcdd.util.Tube;
12  import org.lcsim.geometry.compact.converter.lcdd.util.VisAttributes;
13  import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
14  import org.lcsim.geometry.layer.LayerSlice;
15  import org.lcsim.geometry.layer.LayerStack;
16  import org.lcsim.geometry.layer.Layering;
17  
18  /**
19   * A cylindrical endcap calorimeter that has a tapered interior section.
20   * 
21   * @author jeremym
22   */
23  public class TaperedCylindricalEndcapCalorimeter01 extends LCDDSubdetector
24  {
25      public TaperedCylindricalEndcapCalorimeter01(Element node) throws JDOMException
26      {
27          super(node);
28          this.node = node;
29      }
30  
31      public void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
32      {       
33          // Get important references from LCDD.
34          Structure structure = lcdd.getStructure();
35          Volume motherVolume = lcdd.pickMotherVolume(this);
36                  
37          // Get subdetector name and id.
38          String subdetectorName = node.getAttributeValue("name");
39          int id = node.getAttribute("id").getIntValue();      
40          
41          // Get the basic parameters from the XML.
42          Element dimensions = node.getChild("dimensions");
43          double zmin = dimensions.getAttribute("zmin").getDoubleValue();
44          double rmin = dimensions.getAttribute("rmin").getDoubleValue();
45          double rmax = dimensions.getAttribute("rmax").getDoubleValue();
46          double innerAngle = dimensions.getAttribute("angle").getDoubleValue();
47          
48          // Make layering to get thickness.
49          LayerStack layers = Layering.makeLayering(this.node).getLayerStack();
50          
51          // Get thickness of calorimeter in z dimension determined by layering.
52          double thickness = layers.getTotalThickness();
53                  
54          // Compute radius at last zplane of envelope.
55          double rmin2 = rmin + thickness * Math.tan(innerAngle);
56          
57          // Create Polycone and ZPlanes.
58          Polycone pc = new Polycone(subdetectorName + "_polycone");
59          pc.addZPlane(rmin, rmax, -thickness/2);
60          pc.addZPlane(rmin2, rmax, thickness/2);        
61          lcdd.add(pc);
62          
63          // Create envelope volume.        
64          Volume envelopeVolume = new Volume(subdetectorName + "_envelope", pc, lcdd.getMaterial("Air"));
65          
66          // Set the z coordinate of the layer front face for layer loop.
67          double layerZ = -thickness/2;
68          
69          // The rmin of the layer which will decrease along z.
70          double layerRmin = rmin;
71          
72          // Loop over and build the layers into the detector envelope.               
73          for (int i=0, l=layers.getNumberOfLayers(); i<l; i++)
74          {              
75              //System.out.println(i+" : layerZ="+layerZ);
76              
77              // Get this layer's thickness.
78              double layerThickness = layers.getLayer(i).getThickness();
79              
80              // Compute change in layer inner radius.
81              double layerdy = Math.tan(innerAngle) * layerThickness;
82              
83              // Add dx to inner radius.
84              layerRmin += layerdy;     
85              
86              String layerName = subdetectorName + "_layer" + i;
87              
88              Tube layerTube = new Tube(layerName + "_tube", layerRmin, rmax, layerThickness/2);
89              lcdd.add(layerTube);
90  
91              // Make layer volume.            
92              Volume layerVolume = 
93                  new Volume(layerName + "_volume", layerTube, lcdd.getMaterial("Air"));
94              
95              // Build slices into the layer volume.            
96              double sliceZ = -layerThickness/2;
97              int sliceCount = 0;
98              for (LayerSlice slice : layers.getLayer(i).getSlices())
99              {                
100                 double sliceThickness = slice.getThickness();
101                 
102                 String sliceName = layerName + "_slice" + sliceCount;
103                 
104                 Tube sliceTube = new Tube(sliceName + "_tube", layerRmin, rmax, sliceThickness/2);
105                 lcdd.add(sliceTube);
106                 
107                 Volume sliceVolume = new Volume(sliceName + "volume", sliceTube, lcdd.getMaterial("Air"));
108                 structure.addVolume(sliceVolume);
109                 
110                 // Set slice volume's sensitive detector.
111                 if (slice.isSensitive())
112                     sliceVolume.setSensitiveDetector(sens);
113                 
114                 PhysVol slicePhysVol = new PhysVol(sliceVolume);                
115                 slicePhysVol.setZ(sliceZ + sliceThickness/2);
116                 slicePhysVol.addPhysVolID("slice", sliceCount);
117                 layerVolume.addPhysVol(slicePhysVol);
118                                                
119                 sliceZ += sliceThickness;
120                 ++sliceCount;
121             }            
122             
123             // Add layer volume after slices are built.
124             lcdd.getStructure().addVolume(layerVolume);           
125             
126             // Make layer placement into envelope.
127             PhysVol layerPhysVol = new PhysVol(layerVolume);
128             layerPhysVol.addPhysVolID("layer", i);
129             layerPhysVol.setZ(layerZ + layerThickness/2);
130             envelopeVolume.addPhysVol(layerPhysVol);              
131             
132             // Set z to edge of next layer.
133             layerZ += layerThickness;       
134         }
135 
136         // Add envelope volume after layer construction.
137         lcdd.add(envelopeVolume);
138         
139         // Make rotation for positive endcap.
140         Rotation positiveEndcapRotation = new Rotation(subdetectorName + "_positive");
141         lcdd.getDefine().addRotation(positiveEndcapRotation);
142                 
143         // Positive endcap placement.
144         PhysVol endcapPositivePhysVol = new PhysVol(envelopeVolume);
145         endcapPositivePhysVol.setZ(zmin + thickness/2);
146         endcapPositivePhysVol.addPhysVolID("system",id);
147         endcapPositivePhysVol.addPhysVolID("barrel",1);                     
148         endcapPositivePhysVol.setRotation(positiveEndcapRotation);                       
149         motherVolume.addPhysVol(endcapPositivePhysVol);
150                 
151         // Make rotation for negative endcap.        
152         Rotation negativeEndcapRotation = new Rotation(subdetectorName + "_negative");
153         negativeEndcapRotation.setY(Math.PI);
154         lcdd.getDefine().addRotation(negativeEndcapRotation);
155         
156         // Negative endcap placement.
157         PhysVol endcapNegativePhysVol = new PhysVol(envelopeVolume);
158         endcapNegativePhysVol.setZ(-zmin - thickness/2);
159         endcapNegativePhysVol.addPhysVolID("system",id);
160         endcapNegativePhysVol.addPhysVolID("barrel",2);                     
161         endcapNegativePhysVol.setRotation(negativeEndcapRotation);                       
162         motherVolume.addPhysVol(endcapNegativePhysVol);                            
163     }
164 
165     public boolean isEndcap()
166     {
167         return true;
168     }
169     
170     public boolean isCalorimeter()
171     {
172         return true;
173     }
174 }