1
2
3
4
5
6
7 package org.lcsim.geometry.compact.converter.lcdd;
8
9 import org.jdom.JDOMException;
10 import org.jdom.Element;
11 import org.jdom.Attribute;
12 import org.lcsim.geometry.compact.converter.lcdd.util.Define;
13 import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
14 import org.lcsim.geometry.compact.converter.lcdd.util.Material;
15 import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
16 import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
17 import org.lcsim.geometry.compact.converter.lcdd.util.Solids;
18 import org.lcsim.geometry.compact.converter.lcdd.util.Structure;
19 import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
20 import org.lcsim.geometry.compact.converter.lcdd.util.SubtractionSolid;
21 import org.lcsim.geometry.compact.converter.lcdd.util.Tube;
22 import org.lcsim.geometry.compact.converter.lcdd.util.Position;
23 import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
24 import org.lcsim.geometry.layer.LayerFromCompactCnv;
25
26
27
28
29
30 public class ForwardDetector extends LCDDSubdetector
31 {
32
33
34 public ForwardDetector(Element node) throws JDOMException
35 {
36 super(node);
37 }
38
39
40 public void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
41 {
42 int id = -1;
43 if (node.getAttribute("id") != null)
44 id = node.getAttribute("id").getIntValue();
45 String detectorName = node.getAttributeValue("name");
46
47 Material air = lcdd.getMaterial("Air");
48 Solids solids = lcdd.getSolids();
49 Structure structure = lcdd.getStructure();
50 Volume motherVolume = lcdd.pickMotherVolume(this);
51
52 Define defines = lcdd.getDefine();
53 Rotation reflection = lcdd.getDefine().getRotation("reflect_rot");
54
55 boolean reflect = node.getAttribute("reflect").getBooleanValue();
56
57
58 Element dimensions = node.getChild("dimensions");
59 double zinner = dimensions.getAttribute("inner_z").getDoubleValue();
60 double rmax = dimensions.getAttribute("outer_r").getDoubleValue();
61 double rmin = dimensions.getAttribute("inner_r").getDoubleValue();
62
63
64 Element beam = node.getChild("beampipe");
65 double outgoingR = beam.getAttribute("outgoing_r").getDoubleValue();
66 double incomingR = beam.getAttribute("incoming_r").getDoubleValue();
67 double xangle = beam.getAttribute("crossing_angle").getDoubleValue();
68 double xangleHalf = xangle / 2;
69
70
71 double thickness = layers.getLayerStack().getTotalThickness();
72 double zpos = zinner + (thickness / 2);
73 double zouter = zinner + thickness;
74
75
76 double beamPosX = Math.tan(xangleHalf) * zpos;
77
78
79
80
81
82
83 Tube envelopeTube = new Tube(detectorName + "_tube");
84 envelopeTube.setRMax(rmax);
85 envelopeTube.setRMin(rmin);
86 envelopeTube.setZ(thickness);
87 solids.addSolid(envelopeTube);
88
89
90 Tube beamInTube = new Tube(detectorName + "_beampipe_incoming_tube");
91 beamInTube.setZ(thickness * 2);
92 beamInTube.setRMin(0);
93 beamInTube.setRMax(outgoingR);
94 solids.addSolid(beamInTube);
95
96
97 Tube beamOutTube = new Tube(detectorName + "_beampipe_outgoing_tube");
98 beamOutTube.setZ(thickness * 2);
99 beamOutTube.setRMin(0);
100 beamOutTube.setRMax(incomingR);
101 solids.addSolid(beamOutTube);
102
103
104 SubtractionSolid envelopeSubtraction1 =
105 new SubtractionSolid(detectorName + "_subtraction1_tube");
106 envelopeSubtraction1.setFirstSolid(envelopeTube);
107 envelopeSubtraction1.setSecondSolid(beamInTube);
108 solids.addSolid(envelopeSubtraction1);
109
110
111 Position beamInPos = new Position(detectorName + "_subtraction1_tube_pos");
112 defines.addPosition(beamInPos);
113 beamInPos.setX(beamPosX);
114 envelopeSubtraction1.setPosition(beamInPos);
115
116
117 Rotation beamInRot = new Rotation(detectorName + "_subtraction1_tube_rot");
118 defines.addRotation(beamInRot);
119 beamInRot.setY(xangleHalf);
120 envelopeSubtraction1.setRotation(beamInRot);
121
122
123 SubtractionSolid envelopeSubtraction2 =
124 new SubtractionSolid(detectorName + "_subtraction2_tube");
125 envelopeSubtraction2.setFirstSolid(envelopeSubtraction1);
126 envelopeSubtraction2.setSecondSolid(beamOutTube);
127 solids.addSolid(envelopeSubtraction2);
128
129
130 Position beamOutPos = new Position(detectorName + "_subtraction2_tube_pos");
131 defines.addPosition(beamOutPos);
132 beamOutPos.setX(-beamPosX);
133 envelopeSubtraction2.setPosition(beamOutPos);
134
135
136 Rotation beamOutRot = new Rotation(detectorName + "_subtraction2_tube_rot");
137 defines.addRotation(beamOutRot);
138 beamOutRot.setY(-xangleHalf);
139 envelopeSubtraction2.setRotation(beamOutRot);
140
141
142 Volume envelopeVolume = new Volume(detectorName + "_envelope_volume");
143 envelopeVolume.setSolid(envelopeSubtraction2);
144 envelopeVolume.setMaterial(air);
145
146
147 double layerPosZ = -thickness / 2;
148 double layerDisplZ = 0;
149 for (Object o : node.getChildren("layer") )
150 {
151 Element layerElem = (Element) o;
152
153 int repeat = layerElem.getAttribute("repeat").getIntValue();
154
155 double layerThickness = LayerFromCompactCnv.computeSingleLayerThickness(layerElem);
156
157
158
159
160
161 Tube layerTube = new Tube(detectorName + "_layer_tube");
162 layerTube.setRMin(rmin);
163 layerTube.setRMax(rmax);
164 layerTube.setZ(layerThickness);
165 solids.addSolid(layerTube);
166
167
168 for (int i=0; i < repeat; i++)
169 {
170
171
172 String layerBasename = detectorName + "_layer" + i;
173
174
175 layerDisplZ += layerThickness / 2;
176 layerPosZ += layerThickness / 2;
177
178
179
180
181 SubtractionSolid layerSubtraction1 =
182 new SubtractionSolid(layerBasename + "_subtraction1");
183 layerSubtraction1.setFirstSolid(layerTube);
184 layerSubtraction1.setSecondSolid(beamInTube);
185 solids.addSolid(layerSubtraction1);
186
187 Position layerSubtraction1Pos = new Position(layerBasename + "_subtraction1_pos");
188
189 double layerGlobalZ = zinner + layerDisplZ;
190
191 double layerPosX = Math.tan(xangleHalf) * layerGlobalZ;
192
193 layerSubtraction1Pos.setX(layerPosX);
194 defines.addPosition(layerSubtraction1Pos);
195
196 layerSubtraction1.setPosition(layerSubtraction1Pos);
197 layerSubtraction1.setRotation(beamInRot);
198
199
200 SubtractionSolid layerSubtraction2 =
201 new SubtractionSolid(layerBasename + "_subtraction2");
202 layerSubtraction2.setFirstSolid(layerSubtraction1);
203 layerSubtraction2.setSecondSolid(beamOutTube);
204 solids.addSolid(layerSubtraction2);
205
206 Position layerSubtraction2Pos = new Position(layerBasename + "_subtraction2_pos");
207 layerSubtraction2Pos.setX(-layerPosX);
208 defines.addPosition(layerSubtraction2Pos);
209
210 layerSubtraction2.setPosition(layerSubtraction2Pos);
211 layerSubtraction2.setRotation(beamOutRot);
212
213
214 Volume layerVolume = new Volume(layerBasename + "_volume");
215 layerVolume.setMaterial(air);
216 layerVolume.setSolid(layerSubtraction2);
217
218
219 double slicePosZ = -layerThickness / 2;
220 double sliceDisplZ = 0;
221 int sliceCount = 0;
222 for ( Object oo : layerElem.getChildren("slice"))
223 {
224 Element sliceElem = (Element) oo;
225
226 String sliceBasename = layerBasename + "_slice" + sliceCount;
227
228
229 double sliceThickness = sliceElem.getAttribute("thickness").getDoubleValue();
230 Attribute s = sliceElem.getAttribute("sensitive");
231 boolean sensitive = ( s != null && s.getBooleanValue() );
232 String materialName = sliceElem.getAttributeValue("material");
233
234
235 sliceDisplZ += sliceThickness / 2;
236 slicePosZ += sliceThickness / 2;
237
238
239
240
241 Tube sliceTube = new Tube(sliceBasename + "_tube");
242 sliceTube.setRMin(rmin);
243 sliceTube.setRMax(rmax);
244 sliceTube.setZ(sliceThickness);
245 solids.addSolid(sliceTube);
246
247
248 SubtractionSolid sliceSubtraction1 =
249 new SubtractionSolid(sliceBasename + "_subtraction1");
250 sliceSubtraction1.setFirstSolid(sliceTube);
251 sliceSubtraction1.setSecondSolid(beamInTube);
252 solids.addSolid(sliceSubtraction1);
253
254 Position sliceSubtraction1Pos = new Position(sliceBasename + "_subtraction1_pos");
255 double sliceGlobalZ = zinner + (layerDisplZ - layerThickness / 2) + sliceDisplZ;
256
257
258
259 double slicePosX = Math.tan(xangleHalf) * sliceGlobalZ;
260
261
262
263 sliceSubtraction1Pos.setX(slicePosX);
264 defines.addPosition(sliceSubtraction1Pos);
265
266 sliceSubtraction1.setPosition(sliceSubtraction1Pos);
267 sliceSubtraction1.setRotation(beamInRot);
268
269
270 SubtractionSolid sliceSubtraction2 =
271 new SubtractionSolid(sliceBasename + "_subtraction2");
272 sliceSubtraction2.setFirstSolid(sliceSubtraction1);
273 sliceSubtraction2.setSecondSolid(beamOutTube);
274 solids.addSolid(sliceSubtraction2);
275
276 Position sliceSubtraction2Pos = new Position(sliceBasename + "_subtraction2_pos");
277 sliceSubtraction2Pos.setX(-slicePosX);
278 defines.addPosition(sliceSubtraction2Pos);
279
280 sliceSubtraction2.setPosition(sliceSubtraction2Pos);
281 sliceSubtraction2.setRotation(beamOutRot);
282
283
284 Volume sliceVolume = new Volume(sliceBasename + "_volume");
285 sliceVolume.setMaterial(lcdd.getMaterial(sliceElem.getAttributeValue("material")));
286 sliceVolume.setSolid(sliceSubtraction2);
287
288 if ( sensitive )
289 {
290 sliceVolume.setSensitiveDetector(sens);
291 }
292
293
294 setRegion(lcdd, sliceElem, sliceVolume);
295 setLimitSet(lcdd, sliceElem, sliceVolume);
296
297 setVisAttributes(lcdd, node, sliceVolume);
298
299 structure.addVolume(sliceVolume);
300
301
302 PhysVol slicePV = new PhysVol(sliceVolume);
303 slicePV.setZ(slicePosZ);
304 layerVolume.addPhysVol(slicePV);
305
306
307 sliceDisplZ += sliceThickness / 2;
308 slicePosZ += sliceThickness / 2;
309 ++sliceCount;
310 }
311
312 setVisAttributes(lcdd, node, layerVolume);
313
314 structure.addVolume(layerVolume);
315
316
317 PhysVol layerPV = new PhysVol(layerVolume);
318 layerPV.setZ(layerPosZ);
319 layerPV.addPhysVolID("layer", i);
320 envelopeVolume.addPhysVol(layerPV);
321
322
323 layerDisplZ += layerThickness / 2;
324 layerPosZ += layerThickness / 2;
325 }
326 }
327
328 setVisAttributes(lcdd, node, envelopeVolume);
329
330
331 structure.addVolume(envelopeVolume);
332
333
334 PhysVol envelopePV = new PhysVol(envelopeVolume);
335 envelopePV.setZ(zpos);
336 envelopePV.addPhysVolID("system", id);
337 envelopePV.addPhysVolID("barrel", 1);
338 motherVolume.addPhysVol(envelopePV);
339
340
341 if ( reflect )
342 {
343 PhysVol envelopePV2 = new PhysVol(envelopeVolume);
344 envelopePV2.setZ(-zpos);
345 envelopePV2.setRotation(reflection);
346 envelopePV2.addPhysVolID("system", id);
347 envelopePV2.addPhysVolID("barrel", 2);
348 motherVolume.addPhysVol(envelopePV2);
349 }
350 }
351
352 public boolean isCalorimeter()
353 {
354 return true;
355 }
356 }