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.Define;
14 import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
15 import org.lcsim.geometry.compact.converter.lcdd.util.Material;
16 import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
17 import org.lcsim.geometry.compact.converter.lcdd.util.Position;
18 import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
19 import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
20 import org.lcsim.geometry.compact.converter.lcdd.util.Solids;
21 import org.lcsim.geometry.compact.converter.lcdd.util.Structure;
22 import org.lcsim.geometry.compact.converter.lcdd.util.Trapezoid;
23 import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
24 import org.lcsim.geometry.layer.LayerStack;
25 import org.lcsim.geometry.layer.Layering;
26
27
28
29
30
31
32
33 public class PolyhedraEndcapCalorimeter extends LCDDSubdetector
34 {
35 private Element node;
36
37
38
39 private final double STAVE_ENVELOPE_TOLERANCE=0.0;
40
41
42
43 private final double LAYER_ENVELOPE_TOLERANCE=0.0;
44
45
46
47 private final double SLICE_ENVELOPE_TOLERANCE=0.0;
48
49
50
51 private final double INTER_LAYER_GAP=0.0;
52
53
54
55 private final double SLICE_TOLERANCE=0.0;
56
57 public PolyhedraEndcapCalorimeter(Element node) throws JDOMException
58 {
59 super(node);
60 this.node = node;
61 }
62
63 public void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
64 {
65 if ( sens == null)
66 {
67 throw new IllegalArgumentException("PolyhedraBarrelCalorimeter <" + getName() + " has null SD.");
68 }
69
70
71 Solids solids = lcdd.getSolids();
72 Structure structure = lcdd.getStructure();
73 Volume motherVolume = lcdd.pickMotherVolume(this);
74 Material air = lcdd.getMaterial("Air");
75 Define define = lcdd.getDefine();
76 Element staves = node.getChild("staves");
77
78
79 String detName = node.getAttributeValue("name");
80 int id = node.getAttribute("id").getIntValue();
81
82
83 Element dimensions = node.getChild("dimensions");
84 double zmin = dimensions.getAttribute("zmin").getDoubleValue();
85 double rmin = dimensions.getAttribute("rmin").getDoubleValue();
86 double rmax = dimensions.getAttribute("rmax").getDoubleValue();
87
88 int numsides = dimensions.getAttribute("numsides").getIntValue();
89
90
91
92 rmax = rmax*Math.cos(Math.PI/numsides);
93
94 LayerStack layers = Layering.makeLayering(this.node).getLayerStack();
95
96 rmax = rmin + layers.getTotalThickness();
97
98
99 double subdetectorThickness = org.lcsim.geometry.layer.LayerFromCompactCnv.computeDetectorTotalThickness(node);
100
101
102 subdetectorThickness += layers.getNumberOfLayers() * INTER_LAYER_GAP;
103
104
105 double radialThickness = rmax - rmin;
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 double innerAngle = Math.PI * 2 / numsides;
123 double halfInnerAngle = innerAngle/2;
124 double innerFaceLength = (rmin * tan(halfInnerAngle)) * 2;
125 double outerFaceLength = (rmax * tan(halfInnerAngle)) * 2;
126
127
128 radialThickness -= STAVE_ENVELOPE_TOLERANCE;
129 innerFaceLength -= STAVE_ENVELOPE_TOLERANCE;
130 outerFaceLength -= STAVE_ENVELOPE_TOLERANCE;
131
132
133
134
135 Trapezoid sectTrd = new Trapezoid(detName + "_stave_trapezoid");
136 sectTrd.setY2(subdetectorThickness/2);
137 sectTrd.setY1(subdetectorThickness/2);
138 sectTrd.setZ(radialThickness/2);
139 sectTrd.setX1(innerFaceLength/2);
140 sectTrd.setX2(outerFaceLength/2);
141
142 solids.addSolid(sectTrd);
143 Volume sectVolume = new Volume(detName + "_stave");
144 sectVolume.setMaterial(air);
145 sectVolume.setSolid(sectTrd);
146
147
148 int layer_number = 0;
149 double layerPositionY = subdetectorThickness / 2;
150
151
152 layerPositionY -= INTER_LAYER_GAP;
153 for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();)
154 {
155 Element layerElement = (Element) i.next();
156
157 int repeat = (int)layerElement.getAttribute("repeat").getDoubleValue();
158
159 for ( int j=0; j<repeat; j++)
160 {
161 String layerName = detName + "_stave_layer" + layer_number;;
162
163 double layerThickness = layers.getLayer(layer_number).getThickness();
164
165 layerPositionY -= layerThickness / 2;
166
167
168 Position layerPosition = new Position(layerName + "_position");
169 layerPosition.setY(layerPositionY);
170 define.addPosition(layerPosition);
171
172
173 Trapezoid layerTrd = new Trapezoid(layerName + "_trapezoid");
174
175 double layerInnerFaceLength=innerFaceLength-LAYER_ENVELOPE_TOLERANCE;
176 double layerOuterFaceLength=outerFaceLength-LAYER_ENVELOPE_TOLERANCE;
177 double layerRadialThickness=radialThickness-LAYER_ENVELOPE_TOLERANCE;
178
179 layerTrd.setX1(layerInnerFaceLength/2);
180 layerTrd.setX2(layerOuterFaceLength/2);
181 layerTrd.setY1(layerThickness/2);
182 layerTrd.setY2(layerThickness/2);
183 layerTrd.setZ(layerRadialThickness/2);
184
185 solids.addSolid(layerTrd);
186
187 Volume layerVolume = new Volume(layerName);
188 layerVolume.setSolid(layerTrd);
189 layerVolume.setMaterial(lcdd.getMaterial("Air"));
190
191 int slice_number = 0;
192 double slice_position_y = layerThickness / 2;
193 for ( Iterator k = layerElement.getChildren("slice").iterator(); k.hasNext();)
194 {
195 Element sliceElement = (Element)k.next();
196
197 String sliceName = layerName + "_slice" + slice_number;
198
199 Attribute s = sliceElement.getAttribute("sensitive");
200 boolean sensitive = s != null && s.getBooleanValue();
201
202 double slice_thickness = sliceElement.getAttribute("thickness").getDoubleValue();
203
204
205
206
207 slice_position_y -= slice_thickness / 2;
208
209 Position slicePosition = new Position(sliceName + "_position");
210 slicePosition.setY(slice_position_y);
211 define.addPosition(slicePosition);
212
213 Trapezoid sliceTrd = new Trapezoid(sliceName + "_trapezoid");
214
215 double sliceInnerFaceLength = layerInnerFaceLength - SLICE_ENVELOPE_TOLERANCE;
216 double sliceOuterFaceLength = layerOuterFaceLength - SLICE_ENVELOPE_TOLERANCE;
217 double sliceRadialThickness = layerRadialThickness - SLICE_ENVELOPE_TOLERANCE;
218
219 sliceTrd.setX1(sliceInnerFaceLength/2);
220 sliceTrd.setX2(sliceOuterFaceLength/2);
221 sliceTrd.setY1((slice_thickness-SLICE_TOLERANCE)/2);
222 sliceTrd.setY2((slice_thickness-SLICE_TOLERANCE)/2);
223 sliceTrd.setZ(sliceRadialThickness/2);
224
225 solids.addSolid(sliceTrd);
226
227 Volume sliceVolume = new Volume(sliceName);
228 sliceVolume.setSolid(sliceTrd);
229 sliceVolume.setMaterial(lcdd.getMaterial(sliceElement.getAttributeValue("material")));
230
231 if ( sensitive ) sliceVolume.setSensitiveDetector(sens);
232
233 if (sliceElement.getAttribute("vis") != null)
234 {
235 sliceVolume.setVisAttributes(lcdd.getVisAttributes(sliceElement.getAttributeValue("vis")));
236 }
237
238 setRegion(lcdd, sliceElement, sliceVolume);
239 setLimitSet(lcdd, sliceElement, sliceVolume);
240
241
242 structure.addVolume(sliceVolume);
243
244 PhysVol slicePhysVol = new PhysVol(sliceVolume);
245 slicePhysVol.setPosition(slicePosition);
246 slicePhysVol.addPhysVolID("slice", slice_number);
247 layerVolume.addPhysVol(slicePhysVol);
248
249
250
251
252 slice_position_y -= slice_thickness / 2;
253
254
255 ++slice_number;
256 }
257
258 lcdd.add(layerVolume);
259
260 setRegion(lcdd, layerElement, layerVolume);
261 setLimitSet(lcdd, layerElement, layerVolume);
262 if (layerElement.getAttribute("vis") != null)
263 {
264 layerVolume.setVisAttributes(lcdd.getVisAttributes(layerElement.getAttributeValue("vis")));
265 }
266
267
268 PhysVol layer_physvol = new PhysVol(layerVolume);
269 layer_physvol.setPosition(layerPosition);
270 layer_physvol.addPhysVolID("layer", layer_number);
271 sectVolume.addPhysVol(layer_physvol);
272
273 layerPositionY -= layerThickness / 2;
274
275
276
277 ++layer_number;
278 }
279
280
281 }
282
283
284 if (staves != null)
285 {
286 if (staves.getAttribute("vis") != null)
287 {
288 setVisAttributes(lcdd,staves,sectVolume);
289 }
290 }
291
292
293
294
295
296
297
298 structure.addVolume(sectVolume);
299
300
301 double innerRotation = innerAngle;
302
303
304
305
306
307 double sectCenterRadius = rmin + radialThickness / 2;
308
309
310 double rotY = 0.;
311
312 double rotX = PI / 2;
313
314 double posX = -sectCenterRadius * sin(rotY);
315 double sectPosY = sectCenterRadius * cos(rotY);
316
317
318 for ( int i=0; i < numsides; i++)
319 {
320 int moduleNumber=i;
321
322
323
324
325
326 Position position = new Position(detName + "_stave0_module" + moduleNumber + "_position");
327 position.setX(posX);
328 position.setY(sectPosY);
329 position.setZ(zmin + subdetectorThickness/2);
330
331 Rotation rotation = new Rotation(detName + "_stave0_module" + moduleNumber + "_rotation");
332 rotation.setX(rotX);
333 rotation.setY(rotY);
334
335 define.addPosition(position);
336 define.addRotation(rotation);
337
338 PhysVol sectPhysVol = new PhysVol(sectVolume);
339 sectPhysVol.setPosition(position);
340 sectPhysVol.setRotation(rotation);
341
342
343 motherVolume.addPhysVol(sectPhysVol);
344 sectPhysVol.addPhysVolID("system",id);
345 sectPhysVol.addPhysVolID("barrel",1);
346 sectPhysVol.addPhysVolID("stave",0);
347 sectPhysVol.addPhysVolID("module",moduleNumber);
348
349
350 boolean reflect = true;
351 if (node.getAttribute("reflect") != null)
352 reflect = node.getAttribute("reflect").getBooleanValue();
353 if (reflect)
354 {
355 Rotation envelopeRotationReflect = new Rotation(detName + "_stave0_module" + moduleNumber + "_reflect_rotation");
356
357
358
359
360
361 envelopeRotationReflect.setX(Math.PI / 2);
362 envelopeRotationReflect.setY(rotY);
363 envelopeRotationReflect.setZ(Math.PI);
364
365
366
367 define.addRotation(envelopeRotationReflect);
368
369 Position reflect_position = new Position(detName + "_stave0_module" + moduleNumber + "_reflect_position");
370 reflect_position.setX(posX);
371 reflect_position.setY(sectPosY);
372 reflect_position.setZ(-zmin-subdetectorThickness/2);
373 define.addPosition(reflect_position);
374
375 PhysVol physvol2 = new PhysVol(sectVolume);
376 physvol2.setPosition(reflect_position);
377 physvol2.setRotation(envelopeRotationReflect);
378 physvol2.addPhysVolID("system",id);
379 physvol2.addPhysVolID("barrel",2);
380 physvol2.addPhysVolID("stave",0);
381 physvol2.addPhysVolID("module",moduleNumber);
382 motherVolume.addPhysVol(physvol2);
383 }
384
385 rotY -= innerRotation;
386 posX = -sectCenterRadius * sin(rotY);
387 sectPosY = sectCenterRadius * cos(rotY);
388
389
390
391
392
393
394 }
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427 }
428
429 public boolean isCalorimeter()
430 {
431 return true;
432 }
433 }