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