1 package org.lcsim.geometry.compact.converter.lcdd;
2
3 import static java.lang.Math.PI;
4 import static java.lang.Math.acos;
5 import static java.lang.Math.cos;
6 import static java.lang.Math.sin;
7 import static java.lang.Math.sqrt;
8 import static java.lang.Math.tan;
9 import static java.lang.Math.toDegrees;
10
11 import java.util.Iterator;
12
13 import org.jdom.Attribute;
14 import org.jdom.Element;
15 import org.jdom.JDOMException;
16 import org.lcsim.geometry.compact.converter.lcdd.util.Box;
17 import org.lcsim.geometry.compact.converter.lcdd.util.Define;
18 import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
19 import org.lcsim.geometry.compact.converter.lcdd.util.LCDDFactory;
20 import org.lcsim.geometry.compact.converter.lcdd.util.Material;
21 import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
22 import org.lcsim.geometry.compact.converter.lcdd.util.PolyhedraRegular;
23 import org.lcsim.geometry.compact.converter.lcdd.util.Position;
24 import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
25 import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
26 import org.lcsim.geometry.compact.converter.lcdd.util.Trapezoid;
27 import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
28 import org.lcsim.geometry.layer.LayerFromCompactCnv;
29 import org.lcsim.geometry.layer.LayerStack;
30 import org.lcsim.geometry.layer.Layering;
31
32
33
34
35
36
37
38
39
40 public class EcalBarrel extends LCDDSubdetector
41 {
42
43 private boolean _debug = false;
44
45
46
47
48
49
50
51
52 private double tolerance=0.0;
53
54 EcalBarrel(Element node) throws JDOMException
55 {
56 super(node);
57 }
58
59
60 public void addToLCDD(LCDD lcdd, SensitiveDetector sens)
61 throws JDOMException
62 {
63
64 Define define = lcdd.getDefine();
65
66
67 String name = node.getAttributeValue("name");
68
69
70 int id = node.getAttribute("id").getIntValue();
71
72
73 Element dimensions = node.getChild("dimensions");
74
75
76 Element staves = node.getChild("staves");
77
78
79 assert (dimensions != null);
80 assert (dimensions.getAttribute("numsides") != null);
81 assert (dimensions.getAttribute("rmin") != null);
82 assert (dimensions.getAttribute("z") != null);
83
84
85 int nsides = dimensions.getAttribute("numsides").getIntValue();
86
87
88 double inner_radius = dimensions.getAttribute("rmin")
89 .getDoubleValue();
90
91
92 double module_y1 = dimensions.getAttribute("z").getDoubleValue();
93 double module_y2 = module_y1;
94
95
96 double dphi = PI * 2.0 / nsides;
97 double hphi = dphi / 2;
98
99
100 double module_z = LayerFromCompactCnv
101 .computeDetectorTotalThickness(node);
102
103
104 double module_y_offset = inner_radius + module_z / 2;
105
106
107 Volume motherVolume = lcdd.pickMotherVolume(this);
108
109 double totalThickness = org.lcsim.geometry.layer.LayerFromCompactCnv.computeDetectorTotalThickness(node);
110
111
112 PolyhedraRegular polyhedra = new PolyhedraRegular(
113 name + "_polyhedra",
114 nsides, inner_radius, inner_radius+totalThickness+tolerance*2.0, module_y1);
115 lcdd.getSolids().addSolid(polyhedra);
116
117
118 Volume envelopeVolume = new Volume(name + "_envelope");
119 envelopeVolume.setSolid(polyhedra);
120 Material air = lcdd.getMaterial("Air");
121 envelopeVolume.setMaterial(air);
122
123
124 double zrot = Math.PI / nsides;
125 Rotation rot = new Rotation(name + "_rotation");
126 rot.setZ(zrot);
127 define.addRotation(rot);
128
129
130 PhysVol envelopePhysvol = new PhysVol(envelopeVolume);
131 envelopePhysvol.setRotation(rot);
132 envelopePhysvol.addPhysVolID("system",id);
133 envelopePhysvol.addPhysVolID("barrel",0);
134 motherVolume.addPhysVol(envelopePhysvol);
135
136
137 double outer_radius = inner_radius + module_z;
138
139
140 double bo = tan(hphi) * outer_radius;
141 double bi = tan(hphi) * inner_radius;
142
143
144
145 double gamma = (PI * 2) / nsides;
146 double dx = module_z / sin(gamma);
147
148
149 double module_x_offset = dx / 2.0;
150
151
152 double module_x2 = 2 * bo - dx;
153 double module_x1 = 2 * bi + dx;
154
155
156 Trapezoid module_trd = LCDDFactory.createTrapezoid(
157 name + "_module_trd",
158 module_x1/2-tolerance,
159 module_x2/2-tolerance,
160 module_y1/2-tolerance,
161 module_y2/2-tolerance,
162 module_z/2-tolerance);
163 lcdd.add(module_trd);
164
165
166 Volume module_volume = LCDDFactory.createVolume(name + "_module", lcdd
167 .getMaterial("Air"), module_trd);
168
169
170 if (_debug)
171 {
172 System.out.println("name=" + name);
173 System.out.println("nsides=" + nsides);
174 System.out.println("inner_radius=" + inner_radius);
175 System.out.println("module_y1=" + module_y1);
176 System.out.println("module_y2=" + module_y2);
177 System.out.println("module_z=" + module_z);
178 System.out.println("module_y_offset=" + module_y_offset);
179 System.out.println("module_x_offset=" + module_x_offset);
180 System.out.println("gamma=" + gamma);
181 System.out.println("dx=" + dx);
182 System.out.println("bi=" + bi);
183 System.out.println("bo=" + bo);
184 System.out.println("");
185 }
186
187
188 try
189 {
190 buildBarrelStave(lcdd, sens, module_volume);
191 }
192 catch (Exception e)
193 {
194 throw new RuntimeException("Failed to build layers into "
195 + module_volume.getVolumeName(), e);
196 }
197
198
199 if (staves != null)
200 {
201 if (staves.getAttribute("vis") != null)
202 {
203 module_volume.setVisAttributes(lcdd.getVisAttributes(staves.getAttributeValue("vis")));
204 }
205 }
206
207
208 lcdd.add(module_volume);
209
210
211 double phi = ((PI) / nsides);
212
213
214 for (int i = 0; i < nsides; i++)
215 {
216
217 int module_number = i;
218
219
220 Rotation rotation = LCDDFactory.createRotation(name + "_module"
221 + module_number + "_rotation", PI * 0.5, phi, 0);
222 lcdd.add(rotation);
223
224
225
226 double module_position_x = module_x_offset * cos(phi) - module_y_offset * sin(phi);
227 double module_position_y = module_x_offset * sin(phi) + module_y_offset * cos(phi);
228 double module_position_z = 0;
229
230 Position position = LCDDFactory.createPosition(
231 name + "_module" + module_number + "_position",
232 module_position_x, module_position_y, module_position_z);
233 lcdd.add(position);
234
235
236 PhysVol pv = LCDDFactory.createPhysVol(module_volume, position,
237 rotation, null);
238 pv.addPhysVolID("module", module_number);
239
240
241 pv.addPhysVolID("system", node.getAttribute("id").getIntValue());
242 pv.addPhysVolID("barrel", 0);
243
244 envelopeVolume.addPhysVol(pv);
245
246
247 phi -= dphi;
248 }
249
250
251 setAttributes(lcdd, node, envelopeVolume);
252
253 lcdd.getStructure().addVolume(envelopeVolume);
254 }
255
256
257
258
259
260
261
262
263 private void buildBarrelStave(LCDD lcdd,
264 SensitiveDetector sensitiveDetector, Volume container)
265 throws Exception
266 {
267 Trapezoid trd = (Trapezoid) lcdd.getSolid(container.getSolidRef());
268
269 Element node = getElement();
270
271 if (trd == null)
272 {
273 throw new IllegalArgumentException("Volume " + container.getName()
274 + " is not a trapezoid.");
275 }
276
277 double nsides = getElement().getChild("dimensions")
278 .getAttribute("numsides").getDoubleValue();
279
280 Rotation irot = lcdd.getDefine().getRotation("identity_rot");
281
282 double z = trd.y1();
283 double trd_z = trd.z();
284
285
286
287
288
289
290
291 double adj = (trd.x1() - trd.x2()) / 2;
292
293
294 double hyp = sqrt(trd_z * trd_z + adj * adj);
295
296
297 double beta = acos(adj / hyp);
298
299
300 double tan_beta = tan(beta);
301
302 double subdetector_thickness = LayerFromCompactCnv
303 .computeDetectorTotalThickness(node);
304
305 double layer_position_z = -(subdetector_thickness / 2);
306
307 String subdetector_name = getName();
308
309
310 double dphi = PI * 2.0 / nsides;
311
312
313 double hphi = dphi / 2;
314
315
316 double layer_dim_x = trd.x1();
317
318 if (_debug)
319 {
320 System.out.println("slice start posZ=" + layer_position_z);
321 System.out.println("dphi=" + toDegrees(dphi));
322 System.out.println("hphi=" + toDegrees(hphi));
323 System.out.println("starting slice X=" + layer_dim_x);
324 System.out.println("adj=" + adj);
325 System.out.println("beta=" + toDegrees(beta));
326 System.out.println("");
327 }
328
329 Layering layering = Layering.makeLayering(node);
330
331 LayerStack layers = layering.getLayerStack();
332
333
334 int layer_number = 0;
335 for (Iterator i = getElement().getChildren("layer")
336 .iterator(); i.hasNext();)
337 {
338 Element layer_element = (Element) i.next();
339 int repeat = (int)layer_element.getAttribute("repeat").getDoubleValue();
340
341
342 for (int j=0; j<repeat; j++)
343 {
344
345 double layer_thickness = layers.getLayer(layer_number).getThickness();
346
347
348 layer_position_z += layer_thickness / 2;
349
350
351 String layer_name = subdetector_name + "_layer" + layer_number;
352
353
354 Position layer_position = LCDDFactory.createPosition(
355 layer_name + "_position", 0, 0, layer_position_z);
356 lcdd.add(layer_position);
357
358
359 double xcut = (layer_thickness / tan_beta);
360 layer_dim_x -= xcut;
361
362
363 Box layer_box = LCDDFactory.createBox(layer_name + "_box",
364 layer_dim_x*2 - tolerance,
365 z*2 - tolerance,
366 layer_thickness - tolerance);
367 lcdd.add(layer_box);
368
369
370 Volume layer_volume = LCDDFactory.createVolume(layer_name,
371 lcdd.getMaterial("Air"), layer_box);
372
373
374 int slice_number = 0;
375 double slice_position_z = -(layer_thickness / 2);
376 for (Iterator k = layer_element.getChildren("slice").iterator(); k.hasNext();)
377 {
378
379 Element slice_element = (Element) k.next();
380
381
382 String slice_name = layer_name + "_slice" + slice_number;
383
384
385 Attribute s = slice_element.getAttribute("sensitive");
386 boolean sensitive = s != null && s.getBooleanValue();
387
388
389 double slice_thickness = slice_element.getAttribute("thickness").getDoubleValue();
390
391
392 slice_position_z += slice_thickness / 2;
393
394
395 Position slice_position = LCDDFactory.createPosition(
396 slice_name + "_position", 0, 0, slice_position_z);
397 lcdd.add(slice_position);
398
399
400 Box slice_box = LCDDFactory.createBox(slice_name + "_box",
401 layer_dim_x*2 - tolerance,
402 z*2 - tolerance,
403 slice_thickness - tolerance);
404
405 lcdd.add(slice_box);
406
407
408 Material sliceMaterial = lcdd.getMaterial(slice_element
409 .getAttributeValue("material"));
410
411
412 Volume slice_volume = LCDDFactory.createVolume(slice_name,
413 sliceMaterial, slice_box);
414 if (sensitive)
415 {
416 slice_volume.setSensitiveDetector(sensitiveDetector);
417 }
418
419 setRegion(lcdd, slice_element, slice_volume);
420 setLimitSet(lcdd, slice_element, slice_volume);
421 setVisAttributes(lcdd, slice_element, slice_volume);
422
423
424 lcdd.add(slice_volume);
425
426
427 PhysVol slice_physvol = LCDDFactory.createPhysVol(
428 slice_volume, slice_position, irot);
429 slice_physvol.addPhysVolID("layer", layer_number);
430 slice_physvol.addPhysVolID("slice", slice_number);
431 layer_volume.addPhysVol(slice_physvol);
432
433
434 slice_position_z += slice_thickness / 2;
435
436
437 ++slice_number;
438 }
439
440
441 setRegion(lcdd, layer_element, layer_volume);
442 setLimitSet(lcdd, layer_element, layer_volume);
443 setVisAttributes(lcdd, layer_element, layer_volume);
444
445 lcdd.add(layer_volume);
446
447
448 PhysVol layer_physvol = LCDDFactory.createPhysVol(
449 layer_volume, layer_position, irot);
450 layer_physvol.addPhysVolID("layer", layer_number);
451 container.addPhysVol(layer_physvol);
452
453
454 layer_position_z += layer_thickness / 2;
455
456
457 ++layer_number;
458 }
459 }
460
461 }
462
463 public boolean isCalorimeter()
464 {
465 return true;
466 }
467
468 }
469
470
471
472
473
474
475
476
477
478
479
480