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
20
21
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
34 Structure structure = lcdd.getStructure();
35 Volume motherVolume = lcdd.pickMotherVolume(this);
36
37
38 String subdetectorName = node.getAttributeValue("name");
39 int id = node.getAttribute("id").getIntValue();
40
41
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
49 LayerStack layers = Layering.makeLayering(this.node).getLayerStack();
50
51
52 double thickness = layers.getTotalThickness();
53
54
55 double rmin2 = rmin + thickness * Math.tan(innerAngle);
56
57
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
64 Volume envelopeVolume = new Volume(subdetectorName + "_envelope", pc, lcdd.getMaterial("Air"));
65
66
67 double layerZ = -thickness/2;
68
69
70 double layerRmin = rmin;
71
72
73 for (int i=0, l=layers.getNumberOfLayers(); i<l; i++)
74 {
75
76
77
78 double layerThickness = layers.getLayer(i).getThickness();
79
80
81 double layerdy = Math.tan(innerAngle) * layerThickness;
82
83
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
92 Volume layerVolume =
93 new Volume(layerName + "_volume", layerTube, lcdd.getMaterial("Air"));
94
95
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
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
124 lcdd.getStructure().addVolume(layerVolume);
125
126
127 PhysVol layerPhysVol = new PhysVol(layerVolume);
128 layerPhysVol.addPhysVolID("layer", i);
129 layerPhysVol.setZ(layerZ + layerThickness/2);
130 envelopeVolume.addPhysVol(layerPhysVol);
131
132
133 layerZ += layerThickness;
134 }
135
136
137 lcdd.add(envelopeVolume);
138
139
140 Rotation positiveEndcapRotation = new Rotation(subdetectorName + "_positive");
141 lcdd.getDefine().addRotation(positiveEndcapRotation);
142
143
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
152 Rotation negativeEndcapRotation = new Rotation(subdetectorName + "_negative");
153 negativeEndcapRotation.setY(Math.PI);
154 lcdd.getDefine().addRotation(negativeEndcapRotation);
155
156
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 }