1 package org.lcsim.geometry.compact.converter.lcdd;
2
3 import static java.lang.Math.PI;
4 import static java.lang.Math.cos;
5 import static java.lang.Math.sin;
6 import static java.lang.Math.tan;
7
8 import java.util.Iterator;
9
10 import org.jdom.Attribute;
11 import org.jdom.Element;
12 import org.jdom.JDOMException;
13 import org.lcsim.geometry.compact.converter.lcdd.util.Box;
14 import org.lcsim.geometry.compact.converter.lcdd.util.Define;
15 import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
16 import org.lcsim.geometry.compact.converter.lcdd.util.Material;
17 import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
18 import org.lcsim.geometry.compact.converter.lcdd.util.PolyhedraRegular;
19 import org.lcsim.geometry.compact.converter.lcdd.util.Position;
20 import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
21 import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
22 import org.lcsim.geometry.compact.converter.lcdd.util.Solids;
23 import org.lcsim.geometry.compact.converter.lcdd.util.Structure;
24 import org.lcsim.geometry.compact.converter.lcdd.util.Trapezoid;
25 import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
26 import org.lcsim.geometry.layer.Layer;
27 import org.lcsim.geometry.layer.Layering;
28
29
30
31
32
33
34
35 public class PolyhedraBarrelCalorimeter2 extends LCDDSubdetector
36 {
37 private Element node;
38
39 public PolyhedraBarrelCalorimeter2(Element node) throws JDOMException
40 {
41 super(node);
42 this.node = node;
43 }
44
45 public void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
46 {
47
48 Solids solids = lcdd.getSolids();
49 Structure structure = lcdd.getStructure();
50 Volume motherVolume = lcdd.pickMotherVolume(this);
51 Material air = lcdd.getMaterial("Air");
52 Define define = lcdd.getDefine();
53 Material gapMaterial = air;
54 if (node.getAttribute("material") != null)
55 gapMaterial = lcdd.getMaterial(node.getAttribute("material").getValue());
56
57
58 String detName = node.getAttributeValue("name");
59 int id = node.getAttribute("id").getIntValue();
60
61 Element staves = node.getChild("staves");
62
63 double gap = 0.0;
64 if (node.getAttribute("gap") != null)
65 {
66 gap = node.getAttribute("gap").getDoubleValue();
67 }
68
69
70 Element dimensions = node.getChild("dimensions");
71 double detZ = dimensions.getAttribute("z").getDoubleValue();
72 double rmin = dimensions.getAttribute("rmin").getDoubleValue();
73 int numsides = dimensions.getAttribute("numsides").getIntValue();
74
75
76 double zrot = Math.PI / numsides;
77 Rotation rot = new Rotation(detName + "_rotation");
78 rot.setZ(zrot);
79 define.addRotation(rot);
80
81
82 Layering layering = Layering.makeLayering(this.node);
83
84
85 double total_thickness = layering.getLayerStack().getTotalThickness();
86
87 int total_repeat = 0;
88 int total_slices = 0;
89 for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();)
90 {
91 Element layer_element = (Element) i.next();
92 int repeat = (int)layer_element.getAttribute("repeat").getDoubleValue();
93 total_repeat += repeat;
94 total_slices += (layer_element.getChildren("slice").size() * total_repeat);
95 }
96
97
98 PolyhedraRegular polyhedra = new PolyhedraRegular(
99 detName + "_polyhedra",
100 numsides,
101 rmin,
102 rmin + total_thickness,
103 detZ);
104 solids.addSolid(polyhedra);
105
106 Volume envelopeVolume = new Volume(detName + "_envelope");
107 envelopeVolume.setSolid(polyhedra);
108 envelopeVolume.setMaterial(air);
109
110 PhysVol envelopePhysvol = new PhysVol(envelopeVolume);
111 envelopePhysvol.setRotation(rot);
112 envelopePhysvol.addPhysVolID("system", id);
113 envelopePhysvol.addPhysVolID("barrel", 0);
114 motherVolume.addPhysVol(envelopePhysvol);
115
116
117 double innerAngle = Math.PI * 2 / numsides;
118 double halfInnerAngle = innerAngle / 2;
119 double innerFaceLength = rmin * tan(halfInnerAngle) * 2;
120 double rmax = rmin + total_thickness;
121 double outerFaceLength = rmax * tan(halfInnerAngle) * 2;
122 double stave_thickness = total_thickness;
123
124
125 Trapezoid staveTrdOuter = new Trapezoid(detName + "_stave_trapezoid_outer");
126 staveTrdOuter.setY2(detZ/2);
127 staveTrdOuter.setY1(detZ/2);
128 staveTrdOuter.setZ(stave_thickness/2);
129 staveTrdOuter.setX1(innerFaceLength/2);
130 staveTrdOuter.setX2(outerFaceLength/2);
131 solids.addSolid(staveTrdOuter);
132
133
134 Volume staveOuterVolume = new Volume(detName + "_stave_outer");
135 staveOuterVolume.setSolid(staveTrdOuter);
136 staveOuterVolume.setMaterial(gapMaterial);
137
138
139 Trapezoid staveTrdInner = new Trapezoid(detName + "_stave_trapezoid_inner");
140 staveTrdInner.setY2(detZ/2);
141 staveTrdInner.setY1(detZ/2);
142 staveTrdInner.setZ(stave_thickness/2);
143 staveTrdInner.setX1(innerFaceLength/2 - gap);
144 staveTrdInner.setX2(outerFaceLength/2 - gap);
145 solids.addSolid(staveTrdInner);
146
147
148 Volume staveInnerVolume = new Volume(detName + "_stave_inner");
149 staveInnerVolume.setMaterial(air);
150 staveInnerVolume.setSolid(staveTrdInner);
151
152
153 double layerOuterAngle = (PI - innerAngle) / 2;
154 double layerInnerAngle = (PI / 2 - layerOuterAngle);
155 int layer_number = 0;
156 double layer_position_z = -(stave_thickness / 2);
157 double layer_dim_x = innerFaceLength - gap * 2;
158
159 for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();)
160 {
161 Element layer_element = (Element) i.next();
162
163
164 Layer layer = layering.getLayer(layer_number);
165
166
167 int repeat = (int)layer_element.getAttribute("repeat").getDoubleValue();
168
169
170 for (int j = 0; j < repeat; j++)
171 {
172
173 String layer_name = detName + "_stave_layer" + layer_number;
174
175
176 double layer_thickness = layer.getThickness();
177
178 int nslices = layer_element.getChildren("slices").size();
179
180
181 layer_position_z += layer_thickness / 2;
182
183
184 Position layer_position = new Position(layer_name + "_position");
185 layer_position.setZ(layer_position_z);
186 define.addPosition(layer_position);
187
188
189 Box layer_box = new Box(layer_name + "_box");
190 layer_box.setX(layer_dim_x);
191 layer_box.setY(detZ);
192 layer_box.setZ(layer_thickness);
193 solids.addSolid(layer_box);
194
195
196 Volume layer_volume = new Volume(layer_name);
197 layer_volume.setSolid(layer_box);
198 layer_volume.setMaterial(air);
199
200
201 double slice_position_z = -(layer_thickness / 2);
202
203 int slice_number = 0;
204 for (Iterator k = layer_element.getChildren("slice").iterator(); k.hasNext();)
205 {
206 Element slice_element = (Element) k.next();
207
208 String slice_name = layer_name + "_slice" + slice_number;
209
210 Attribute s = slice_element.getAttribute("sensitive");
211 boolean sensitive = s != null && s.getBooleanValue();
212
213 double slice_thickness = slice_element.getAttribute("thickness").getDoubleValue();
214
215 slice_position_z += slice_thickness / 2;
216
217 Material slice_material = lcdd.getMaterial(slice_element.getAttributeValue("material"));
218
219
220 Position slice_position = new Position(slice_name + "_position");
221 slice_position.setZ(slice_position_z);
222 define.addPosition(slice_position);
223
224
225 Box slice_box = new Box(slice_name + "_box");
226 slice_box.setX(layer_dim_x);
227 slice_box.setY(detZ);
228 slice_box.setZ(slice_thickness);
229 solids.addSolid(slice_box);
230
231
232 Volume slice_volume = new Volume(slice_name);
233 slice_volume.setSolid(slice_box);
234 slice_volume.setMaterial(slice_material);
235 if (sensitive)
236 slice_volume.setSensitiveDetector(sens);
237 structure.addVolume(slice_volume);
238
239
240 setRegion(lcdd, slice_element, slice_volume);
241 setLimitSet(lcdd, slice_element, slice_volume);
242 setVisAttributes(lcdd, slice_element, slice_volume);
243
244
245 PhysVol slice_physvol = new PhysVol(slice_volume);
246 slice_physvol.setPosition(slice_position);
247 slice_physvol.addPhysVolID("slice", slice_number);
248 layer_volume.addPhysVol(slice_physvol);
249
250
251 slice_position_z += slice_thickness / 2;
252
253
254 ++slice_number;
255 }
256
257
258 setRegion(lcdd, layer_element, layer_volume);
259 setLimitSet(lcdd, layer_element, layer_volume);
260 setVisAttributes(lcdd, layer_element, layer_volume);
261
262
263 structure.addVolume(layer_volume);
264
265
266 PhysVol layer_physvol = new PhysVol(layer_volume);
267 layer_physvol.setPosition(layer_position);
268 layer_physvol.addPhysVolID("layer", layer_number);
269 staveInnerVolume.addPhysVol(layer_physvol);
270
271
272 layer_dim_x += layer_thickness * tan(layerInnerAngle) * 2;
273
274
275 layer_position_z += layer_thickness / 2;
276
277
278 ++layer_number;
279 }
280 }
281
282
283 PhysVol staveInnerPhysVol = new PhysVol(staveInnerVolume);
284
285
286 staveOuterVolume.addPhysVol(staveInnerPhysVol);
287
288
289 if (staves != null)
290 {
291 if (staves.getAttribute("vis") != null)
292 {
293 setVisAttributes(lcdd,staves,staveOuterVolume);
294 }
295 }
296
297
298 structure.addVolume(staveInnerVolume);
299
300
301 structure.addVolume(staveOuterVolume);
302
303
304 placeStaves(define, detName, rmin, numsides, total_thickness, envelopeVolume, innerAngle, staveOuterVolume);
305
306
307 setAttributes(lcdd, node, envelopeVolume);
308
309
310 structure.addVolume(envelopeVolume);
311 }
312
313 private void placeStaves(Define define, String detName, double rmin, int numsides, double total_thickness, Volume envelopeVolume, double innerAngle, Volume sectVolume)
314 {
315
316 double innerRotation = innerAngle;
317 double offsetRotation= -innerRotation / 2;
318 double sectCenterRadius = rmin + total_thickness / 2;
319 double rotY = -offsetRotation;
320 double rotX = PI / 2;
321 double posX = -sectCenterRadius * sin(rotY);
322 double posY = sectCenterRadius * cos(rotY);
323
324 for (int i = 0; i < numsides; i++)
325 {
326 int moduleNumber = i;
327
328 Position position = new Position(detName + "_stave0_module" + moduleNumber + "_position");
329 position.setX(posX);
330 position.setY(posY);
331
332 Rotation rotation = new Rotation(detName + "_stave0_module" + moduleNumber + "_rotation");
333 rotation.setX(rotX);
334 rotation.setY(rotY);
335
336 define.addPosition(position);
337 define.addRotation(rotation);
338
339 PhysVol sectPhysVol = new PhysVol(sectVolume);
340 sectPhysVol.setPosition(position);
341 sectPhysVol.setRotation(rotation);
342
343 envelopeVolume.addPhysVol(sectPhysVol);
344 sectPhysVol.addPhysVolID("stave", 0);
345 sectPhysVol.addPhysVolID("module", moduleNumber);
346
347 rotY -= innerRotation;
348 posX = -sectCenterRadius * sin(rotY);
349 posY = sectCenterRadius * cos(rotY);
350 }
351 }
352
353 public boolean isCalorimeter()
354 {
355 return true;
356 }
357 }