]>
Commit | Line | Data |
---|---|---|
1a1fdef7 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
16 | /* $Id$ */ | |
17 | ||
18 | //____________________________________________________________________ | |
19 | // | |
20 | // Forward Multiplicity Detector based on Silicon wafers. This class | |
21 | // contains the base procedures for the Forward Multiplicity detector | |
22 | // Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of | |
23 | // which has 1 or 2 rings of silicon sensors. | |
24 | // | |
25 | // This is the base class for all FMD manager classes. | |
26 | // | |
27 | // The actual code is done by various separate classes. Below is | |
28 | // diagram showing the relationship between the various FMD classes | |
29 | // that handles the simulation | |
30 | // | |
31 | // +--------+ 1 +-----------------+ | |
32 | // | AliFMD |<>-----| AliFMDSimulator | | |
33 | // +--------+ +-----------------+ | |
34 | // ^ | |
35 | // | | |
36 | // +-------------+-------------+ | |
37 | // | | | |
38 | // +--------------------+ +-------------------+ | |
39 | // | AliFMDGeoSimulator | | AliFMDG3Simulator | | |
40 | // +--------------------+ +---------+---------+ | |
4ac75127 | 41 | // ^ |
42 | // | | |
43 | // +--------------------+ | |
44 | // | AliFMDOldSimulator | | |
45 | // +--------------------+ | |
1a1fdef7 | 46 | // |
1a1fdef7 | 47 | // * AliFMD |
48 | // This defines the interface for the various parts of AliROOT that | |
49 | // uses the FMD, like AliFMDSimulator, AliFMDDigitizer, | |
50 | // AliFMDReconstructor, and so on. | |
51 | // | |
52 | // * AliFMDSimulator | |
53 | // This is the base class for the FMD simulation tasks. The | |
54 | // simulator tasks are responsible to implment the geoemtry, and | |
55 | // process hits. | |
56 | // | |
57 | // * AliFMDGeoSimulator | |
58 | // This is a concrete implementation of the AliFMDSimulator that | |
59 | // uses the TGeo classes directly only. This defines the active | |
60 | // volume as an ONLY XTRU shape with a divided MANY TUBS shape | |
61 | // inside to implement the particular shape of the silicon | |
62 | // sensors. | |
63 | // | |
64 | // * AliFMDG3Simulator | |
65 | // This is a concrete implementation of the AliFMDSimulator that | |
66 | // uses the TVirtualMC interface with GEANT 3.21-like messages. | |
67 | // This implements the active volume as a divided TUBS shape. Hits | |
68 | // in the corners should be cut away at run time (but currently | |
69 | // isn't). | |
70 | // | |
4ac75127 | 71 | // * AliFMDOldSimulator |
72 | // This is a concrete implementation of AliFMDSimulator. It | |
73 | // approximates the of the rings as segmented disks. | |
74 | // | |
1a1fdef7 | 75 | #include "AliFMDGeoSimulator.h" // ALIFMDGEOSIMULATOR_H |
76 | #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H | |
77 | #include "AliFMDDetector.h" // ALIFMDDETECTOR_H | |
78 | #include "AliFMDRing.h" // ALIFMDRING_H | |
79 | #include "AliFMD1.h" // ALIFMD1_H | |
80 | #include "AliFMD2.h" // ALIFMD2_H | |
81 | #include "AliFMD3.h" // ALIFMD3_H | |
82 | #include "AliFMD.h" // ALIFMD_H | |
83 | #include "AliLog.h" // ALILOG_H | |
84 | #include <TGeoVolume.h> // ROOT_TGeoVolume | |
85 | #include <TGeoTube.h> // ROOT_TGeoTube | |
86 | #include <TGeoPcon.h> // ROOT_TGeoPcon | |
87 | #include <TGeoMaterial.h> // ROOT_TGeoMaterial | |
88 | #include <TGeoMedium.h> // ROOT_TGeoMedium | |
89 | #include <TGeoXtru.h> // ROOT_TGeoXtru | |
90 | #include <TGeoPolygon.h> // ROOT_TGeoPolygon | |
91 | #include <TGeoTube.h> // ROOT_TGeoTube | |
92 | #include <TGeoManager.h> // ROOT_TGeoManager | |
93 | #include <TVector2.h> // ROOT_TVector2 | |
94 | #include <TArrayD.h> // ROOT_TArrayD | |
95 | ||
96 | //==================================================================== | |
97 | ClassImp(AliFMDGeoSimulator) | |
98 | #if 0 | |
99 | ; // This is here to keep Emacs for indenting the next line | |
100 | #endif | |
101 | ||
102 | //____________________________________________________________________ | |
103 | AliFMDGeoSimulator::AliFMDGeoSimulator() | |
104 | : fSi(0), | |
105 | fC(0), | |
106 | fAl(0), | |
107 | fPCB(0), | |
108 | fChip(0), | |
109 | fPlastic(0) | |
110 | { | |
111 | // Default constructor | |
112 | fSectorOff = 1; | |
113 | fModuleOff = 4; | |
114 | fRingOff = 5; | |
115 | fDetectorOff = 6; | |
116 | } | |
117 | ||
118 | //____________________________________________________________________ | |
119 | AliFMDGeoSimulator::AliFMDGeoSimulator(AliFMD* fmd, Bool_t detailed) | |
120 | : AliFMDSimulator(fmd, detailed), | |
121 | fSi(0), | |
122 | fC(0), | |
123 | fAl(0), | |
124 | fPCB(0), | |
125 | fChip(0), | |
126 | fPlastic(0) | |
127 | { | |
128 | // Normal constructor | |
129 | // | |
130 | // Parameters: | |
131 | // | |
132 | // fmd Pointer to AliFMD object | |
133 | // detailed Whether to make a detailed simulation or not | |
134 | // | |
135 | fSectorOff = 1; | |
136 | fModuleOff = 4; | |
137 | fRingOff = 5; | |
138 | fDetectorOff = 6; | |
139 | } | |
140 | ||
141 | //____________________________________________________________________ | |
142 | void | |
143 | AliFMDGeoSimulator::DefineMaterials() | |
144 | { | |
145 | // Define the materials and tracking mediums needed by the FMD | |
146 | // simulation. These mediums are made by sending the messages | |
147 | // AliMaterial, AliMixture, and AliMedium to the passed AliModule | |
148 | // object module. The defined mediums are | |
149 | // | |
150 | // FMD Si$ Silicon (active medium in sensors) | |
151 | // FMD C$ Carbon fibre (support cone for FMD3 and vacuum pipe) | |
152 | // FMD Al$ Aluminium (honeycomb support plates) | |
153 | // FMD PCB$ Printed Circuit Board (FEE board with VA1_ALICE) | |
154 | // FMD Chip$ Electronics chips (currently not used) | |
155 | // FMD Air$ Air (Air in the FMD) | |
156 | // FMD Plastic$ Plastic (Support legs for the hybrid cards) | |
157 | // | |
158 | // Pointers to TGeoMedium objects are retrived from the TGeoManager | |
159 | // singleton. These pointers are later used when setting up the | |
160 | // geometry | |
161 | AliDebug(10, "\tCreating materials"); | |
162 | ||
163 | if (!gGeoManager) { | |
164 | AliFatal("No TGeoManager defined"); | |
165 | return; | |
166 | } | |
167 | AliFMDSimulator::DefineMaterials(); | |
4a9de4af | 168 | fSi = gGeoManager->GetMedium("FMD_Si$"); |
169 | fC = gGeoManager->GetMedium("FMD_Carbon$"); | |
170 | fAl = gGeoManager->GetMedium("FMD_Aluminum$"); | |
4ac75127 | 171 | fChip = gGeoManager->GetMedium("FMD_Si Chip$"); |
4a9de4af | 172 | fAir = gGeoManager->GetMedium("FMD_Air$"); |
173 | fPCB = gGeoManager->GetMedium("FMD_PCB$"); | |
174 | fPlastic = gGeoManager->GetMedium("FMD_Plastic$"); | |
4ac75127 | 175 | fCopper = gGeoManager->GetMedium("FMD_Copper$"); |
1a1fdef7 | 176 | } |
177 | ||
178 | //____________________________________________________________________ | |
179 | TGeoVolume* | |
180 | AliFMDGeoSimulator::RingGeometry(AliFMDRing* r) | |
181 | { | |
182 | // Setup the geometry of a ring. The defined TGeoVolume is | |
183 | // returned, and should be used when setting up the rest of the | |
184 | // volumes. | |
185 | // | |
186 | // | |
187 | // Parameters: | |
188 | // | |
189 | // r Pointer to ring geometry object | |
190 | // | |
191 | // Returns: | |
192 | // pointer to ring volume | |
193 | // | |
194 | if (!r) { | |
195 | AliError("Didn't get a ring object"); | |
196 | return 0; | |
197 | } | |
198 | Char_t id = r->GetId(); | |
199 | Double_t siThick = r->GetSiThickness(); | |
200 | const Int_t nv = r->GetNVerticies(); | |
201 | TVector2* a = r->GetVertex(5); | |
202 | TVector2* b = r->GetVertex(3); | |
203 | TVector2* c = r->GetVertex(4); | |
204 | Double_t theta = r->GetTheta(); | |
205 | Double_t off = (TMath::Tan(TMath::Pi() * theta / 180) | |
206 | * r->GetBondingWidth()); | |
207 | Double_t rmax = b->Mod(); | |
208 | Double_t rmin = r->GetLowR(); | |
209 | Double_t pcbThick = r->GetPrintboardThickness(); | |
210 | Double_t modSpace = r->GetModuleSpacing(); | |
211 | Double_t legr = r->GetLegRadius(); | |
212 | Double_t legl = r->GetLegLength(); | |
213 | Double_t legoff = r->GetLegOffset(); | |
214 | Int_t ns = r->GetNStrips(); | |
215 | Double_t stripoff = a->Mod(); | |
216 | Double_t dstrip = (rmax - stripoff) / ns; | |
4ac75127 | 217 | Double_t space = r->GetSpacing(); |
1a1fdef7 | 218 | TArrayD xs(nv); |
219 | TArrayD ys(nv); | |
220 | for (Int_t i = 0; i < nv; i++) { | |
221 | // Reverse the order | |
222 | TVector2* vv = r->GetVertex(nv - 1 - i); | |
223 | if (!vv) { | |
224 | AliError(Form("Failed to get vertex # %d", nv - 1 - i)); | |
225 | continue; | |
226 | } | |
227 | xs[i] = vv->X(); | |
228 | ys[i] = vv->Y(); | |
229 | } | |
230 | ||
1a1fdef7 | 231 | // Shape of actual sensor |
232 | TGeoXtru* moduleShape = new TGeoXtru(2); | |
233 | moduleShape->DefinePolygon(nv, xs.fArray, ys.fArray); | |
234 | moduleShape->DefineSection(0, - siThick/2); | |
235 | moduleShape->DefineSection(1, siThick/2); | |
236 | TGeoVolume* moduleVolume = new TGeoVolume(Form(fgkModuleName, id), | |
237 | moduleShape, fSi); | |
4ac75127 | 238 | Int_t sid = moduleVolume->GetNumber(); |
239 | fSectorOff = -1; | |
240 | fModuleOff = 1; | |
241 | fRingOff = 2; | |
242 | fDetectorOff = 3; | |
243 | if (fUseDivided) { | |
244 | fSectorOff = 1; | |
245 | fModuleOff = 4; | |
246 | fRingOff = 5; | |
247 | fDetectorOff = 6; | |
248 | // Virtual volume shape to divide - This volume is only defined if | |
249 | // the geometry is set to be detailed. | |
250 | TGeoVolume* activeVolume = 0; | |
251 | if (fDetailed) { | |
252 | TGeoTubeSeg* activeShape = | |
253 | new TGeoTubeSeg(rmin, rmax, siThick/2, - theta, theta); | |
54240c8d | 254 | activeVolume = new TGeoVolume(Form(fgkActiveName, id),activeShape,fSi); |
255 | TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), | |
256 | 2, 2, -theta,0,0,"N"); | |
4ac75127 | 257 | TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id), |
258 | 1, ns, stripoff, dstrip, | |
259 | 0, "SX"); | |
260 | sid = stripVolume->GetNumber(); | |
261 | } | |
262 | // Add divived MANY volume to the true shape of the module, but only | |
263 | // if a detailed simulation is reguested. | |
264 | if (activeVolume) moduleVolume->AddNodeOverlap(activeVolume, 0); | |
265 | } | |
1a1fdef7 | 266 | |
267 | switch (id) { | |
268 | case 'i': | |
4ac75127 | 269 | case 'I': fActiveId[0] = sid; break; |
1a1fdef7 | 270 | case 'o': |
4ac75127 | 271 | case 'O': fActiveId[2] = sid; break; |
1a1fdef7 | 272 | } |
273 | ||
274 | // Shape of Printed circuit Board | |
275 | TGeoXtru* pcbShape = new TGeoXtru(2); | |
276 | for (Int_t i = 0; i < nv / 2; i++) ys[i] -= off; | |
277 | for (Int_t i = nv / 2; i < nv; i++) ys[i] += off; | |
278 | pcbShape->DefinePolygon(nv, xs.fArray, ys.fArray); | |
279 | pcbShape->DefineSection(0, - pcbThick/2); | |
280 | pcbShape->DefineSection(1, pcbThick/2); | |
281 | TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id, 'B'), | |
282 | pcbShape, fPCB); | |
283 | ||
284 | // Short leg shape | |
4ac75127 | 285 | TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2); |
1a1fdef7 | 286 | TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), |
287 | shortLegShape, fPlastic); | |
288 | ||
289 | // Long leg shape | |
4ac75127 | 290 | TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2); |
1a1fdef7 | 291 | TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id), |
292 | longLegShape, fPlastic); | |
293 | ||
294 | TGeoMatrix* matrix = 0; | |
295 | // Back container volume | |
54240c8d | 296 | Double_t contThick = siThick + pcbThick + legl + space; |
1a1fdef7 | 297 | TGeoTubeSeg* backShape = new TGeoTubeSeg(rmin, rmax, contThick/2, |
298 | - theta, theta); | |
299 | TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackVName, id), | |
300 | backShape, fAir); | |
301 | Double_t x = 0; | |
302 | Double_t y = 0; | |
303 | Double_t z = -contThick / 2 + siThick / 2; | |
304 | matrix = new TGeoTranslation(Form("FMD Ring %c mod 1 transform", id), | |
305 | x, y, z); | |
306 | backVolume->AddNode(moduleVolume, 0, matrix); | |
4ac75127 | 307 | z += siThick / 2 + space + pcbThick / 2; |
1a1fdef7 | 308 | matrix = new TGeoTranslation(Form("FMD Ring %c pcb 1 transfrom", id), |
309 | x, y, z); | |
310 | backVolume->AddNode(pcbVolume, 0, matrix); | |
311 | x = a->X() + legoff + legr; | |
312 | y = 0; | |
313 | z += pcbThick / 2 + legl / 2; | |
314 | matrix = new TGeoTranslation(Form("FMD Ring %c leg 1 transfrom", id), | |
315 | x, y, z); | |
316 | backVolume->AddNode(shortLegVolume, 0, matrix); | |
317 | x = c->X(); | |
318 | y = c->Y() - legoff - legr - off; | |
319 | matrix = new TGeoTranslation(Form("FMD Ring %c leg 2 transfrom", id), | |
320 | x, y, z); | |
321 | backVolume->AddNode(shortLegVolume, 1, matrix); | |
322 | y = -y; | |
323 | matrix = new TGeoTranslation(Form("FMD Ring %c leg 3 transfrom", id), | |
324 | x, y, z); | |
325 | backVolume->AddNode(shortLegVolume, 2, matrix); | |
326 | // backVolume->SetVisibility(kFALSE); | |
327 | // backVolume->VisibleDaughters(kTRUE); | |
328 | ||
329 | // Front container volume | |
330 | contThick += modSpace; | |
331 | TGeoTubeSeg* frontShape = new TGeoTubeSeg(rmin, rmax, contThick/2, | |
332 | -theta, theta); | |
333 | TGeoVolume* frontVolume = new TGeoVolume(Form(fgkFrontVName, id), | |
334 | frontShape, fAir); | |
335 | x = 0; | |
336 | y = 0; | |
337 | z = -contThick / 2 + siThick / 2 ; | |
338 | matrix = new TGeoTranslation(Form("FMD Ring %c mod 2 transfrom", id), | |
339 | 0, 0, z); | |
340 | frontVolume->AddNode(moduleVolume, 1, matrix); | |
4ac75127 | 341 | z += siThick / 2 + space + pcbThick / 2; |
1a1fdef7 | 342 | matrix = new TGeoTranslation(Form("FMD Ring %c pcb 2 transfrom", id), |
343 | x, y, z); | |
344 | frontVolume->AddNode(pcbVolume, 1, matrix); | |
345 | x = a->X() + legoff + legr; | |
346 | y = 0; | |
347 | z += pcbThick / 2 + (legl + modSpace)/ 2; | |
348 | matrix = new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), | |
349 | x, y, z); | |
350 | frontVolume->AddNode(longLegVolume, 0, matrix); | |
351 | x = c->X(); | |
352 | y = c->Y() - legoff - legr - off; | |
353 | matrix = new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), | |
354 | x, y, z); | |
355 | frontVolume->AddNode(longLegVolume, 1, matrix); | |
356 | y = -y; | |
357 | matrix = new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), | |
358 | x, y, z); | |
359 | frontVolume->AddNode(longLegVolume, 2, matrix); | |
360 | // frontVolume->SetVisibility(kFALSE); | |
361 | // frontVolume->VisibleDaughters(kTRUE); | |
362 | ||
363 | // Ring mother volume | |
54240c8d | 364 | TGeoTube* ringShape = new TGeoTube(rmin, rmax, contThick / 2); |
365 | TGeoVolume* ringVolume = new TGeoVolume(Form(fgkRingName,id), | |
366 | ringShape,fAir); | |
1a1fdef7 | 367 | |
368 | Int_t nmod = r->GetNModules(); | |
369 | AliDebug(10, Form("making %d modules in ring %c", nmod, id)); | |
370 | for (Int_t i = 0; i < nmod; i++) { | |
371 | Bool_t isFront = (i % 2 == 0); | |
372 | TGeoVolume* vol = (isFront ? frontVolume : backVolume); | |
54240c8d | 373 | TGeoRotation* rot =new TGeoRotation(Form("FMD Ring %c rotation %d",id,i)); |
1a1fdef7 | 374 | rot->RotateZ((i + .5) * 2 * theta); |
375 | Double_t z = (isFront ? 0 : modSpace) / 2; | |
376 | matrix = new TGeoCombiTrans(Form("FMD Ring %c transform %d", id, i), | |
377 | 0, 0, z, rot); | |
378 | ringVolume->AddNode(vol, i, matrix); | |
379 | } | |
380 | ||
381 | ringVolume->SetVisibility(kFALSE); | |
382 | ringVolume->VisibleDaughters(kTRUE); | |
383 | return ringVolume; | |
384 | } | |
385 | ||
386 | //____________________________________________________________________ | |
387 | TGeoVolume* | |
388 | AliFMDGeoSimulator::DetectorGeometry(AliFMDDetector* d, | |
389 | TGeoVolume* mother, | |
390 | Double_t zmother, | |
391 | TGeoVolume* inner, | |
392 | TGeoVolume* outer) | |
393 | { | |
394 | // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries. | |
395 | // This includes putting the Honeycomb support plates and the rings | |
396 | // into the mother volumes. | |
397 | // | |
398 | // Parameeters: | |
399 | // d The detector geometry to use | |
400 | // mother The mother volume of the detector | |
401 | // zmother The midpoint in global coordinates of detector vol. | |
402 | // inner Pointer to inner ring volume | |
403 | // outer Pointer to outer ring volume | |
404 | // | |
405 | // Returns: | |
406 | // Pointer to mother (detector volume) | |
407 | // | |
408 | if (!d) return 0; | |
409 | // Loop over the defined rings | |
410 | for (int i = 0; i < 2; i++) { | |
411 | AliFMDRing* r = 0; | |
412 | Double_t lowr = 0; | |
413 | Double_t highr = 0; | |
414 | Double_t rz = 0; | |
415 | TGeoVolume* rvol = 0; | |
416 | switch (i) { | |
417 | case 0: | |
418 | r = d->GetInner(); | |
419 | lowr = d->GetInnerHoneyLowR(); | |
420 | highr = d->GetInnerHoneyHighR(); | |
421 | rz = d->GetInnerZ(); | |
422 | rvol = inner; | |
423 | break; | |
424 | case 1: | |
425 | r = d->GetOuter(); | |
426 | lowr = d->GetOuterHoneyLowR(); | |
427 | highr = d->GetOuterHoneyHighR(); | |
428 | rz = d->GetOuterZ(); | |
429 | rvol = outer; | |
430 | break; | |
431 | } | |
432 | if (!r) continue; | |
433 | Char_t c = r->GetId(); | |
434 | Int_t id = d->GetId(); | |
435 | Double_t hcThick = d->GetHoneycombThickness(); | |
436 | Double_t alThick = d->GetAlThickness(); | |
437 | Double_t z; | |
438 | if (zmother > 0) z = rz - zmother + r->GetRingDepth() / 2; | |
439 | else z = zmother - rz + r->GetRingDepth() / 2; | |
440 | // Place ring in mother volume | |
441 | mother->AddNode(rvol, Int_t(c), | |
442 | new TGeoTranslation(Form("FMD%d%c transform", id, c), | |
443 | 0, 0, z)); | |
444 | ||
445 | z += r->GetRingDepth() / 2 + hcThick / 2; | |
446 | // Top of Honeycomb | |
447 | TGeoTubeSeg* topHCShape = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180); | |
448 | TGeoVolume* topHCVolume = new TGeoVolume(Form(fgkTopHCName, id, c), | |
449 | topHCShape, fAl); | |
450 | TGeoMatrix* topHCMatrix = | |
451 | new TGeoTranslation(Form("FMD%d%c top HC transform", id, c), 0, 0, z); | |
452 | mother->AddNode(topHCVolume, 0, topHCMatrix); | |
453 | ||
454 | // Air in top of honeycomb | |
455 | TGeoTubeSeg* topIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, | |
456 | (hcThick-alThick)/2, 0, 180); | |
457 | TGeoVolume* topIHCVolume = new TGeoVolume(Form(fgkTopIHCName, id, c), | |
458 | topIHCShape, fAir); | |
459 | topHCVolume->AddNode(topIHCVolume, 0); | |
460 | topHCVolume->VisibleDaughters(kFALSE); | |
461 | topHCVolume->SetVisibility(kTRUE); | |
462 | ||
463 | ||
464 | // Bottom of Honeycomb | |
465 | TGeoTubeSeg* botHCShape = new TGeoTubeSeg(lowr, highr, hcThick/2, | |
466 | 180, 360); | |
467 | TGeoVolume* botHCVolume = new TGeoVolume(Form(fgkBotHCName, id, c), | |
468 | botHCShape, fAl); | |
469 | TGeoMatrix* botHCMatrix = | |
470 | new TGeoTranslation(Form("FMD%d%c bottom HC transform", id, c), 0, 0, z); | |
471 | mother->AddNode(botHCVolume, 0, botHCMatrix); | |
472 | ||
473 | // Air in bot of honeycomb | |
474 | TGeoTubeSeg* botIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, | |
475 | (hcThick-alThick)/2, 180, 360); | |
476 | TGeoVolume* botIHCVolume = new TGeoVolume(Form(fgkBotIHCName, id, c), | |
477 | botIHCShape, fAir); | |
478 | botHCVolume->AddNode(botIHCVolume, 0); | |
479 | botHCVolume->VisibleDaughters(kFALSE); | |
480 | botHCVolume->SetVisibility(kTRUE); | |
481 | } | |
482 | mother->SetVisibility(kFALSE); | |
483 | mother->VisibleDaughters(kTRUE); | |
484 | return mother; | |
485 | } | |
486 | ||
487 | //____________________________________________________________________ | |
488 | TGeoVolume* | |
489 | AliFMDGeoSimulator::FMD1Geometry(AliFMD1* fmd1, TGeoVolume* inner) | |
490 | { | |
491 | // Setup the FMD1 geometry. The FMD1 only has one ring, and no | |
492 | // special support as it is at the momement. | |
493 | // | |
494 | // See also AliFMDGeoSimulator::DetectorGeometry | |
495 | // | |
496 | if (!fmd1 || !inner) return 0; | |
497 | Double_t rmin = fmd1->GetInner()->GetLowR(); | |
498 | Double_t rmax = fmd1->GetInnerHoneyHighR(); | |
499 | Double_t hcThick = fmd1->GetHoneycombThickness(); | |
500 | Double_t w = fmd1->GetInner()->GetRingDepth() + hcThick; | |
501 | Double_t z = fmd1->GetInnerZ() + w / 2; | |
4ac75127 | 502 | |
503 | TGeoVolume* fmd1Volume = 0; | |
504 | if (!fUseAssembly) { | |
505 | TGeoTube* fmd1Shape = new TGeoTube(rmin, rmax, w / 2); | |
506 | fmd1Volume = new TGeoVolume(fmd1->GetName(), fmd1Shape, fAir); | |
507 | } | |
508 | else | |
509 | fmd1Volume = new TGeoVolumeAssembly(fmd1->GetName()); | |
1a1fdef7 | 510 | |
511 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
512 | TGeoMatrix* matrix = new TGeoTranslation("FMD1 transform", 0, 0, z); | |
513 | top->AddNode(fmd1Volume, fmd1->GetId(), matrix); | |
514 | ||
515 | return DetectorGeometry(fmd1, fmd1Volume, z, inner, 0); | |
516 | } | |
517 | ||
518 | //____________________________________________________________________ | |
519 | TGeoVolume* | |
520 | AliFMDGeoSimulator::FMD2Geometry(AliFMD2* fmd2, | |
521 | TGeoVolume* inner, | |
522 | TGeoVolume* outer) | |
523 | { | |
524 | // Setup the FMD2 geometry. The FMD2 has no | |
525 | // special support as it is at the momement. | |
526 | // | |
527 | // See also AliFMDGeoSimulator::DetectorGeometry | |
528 | // | |
529 | if (!fmd2 || !inner || !outer) return 0; | |
530 | Double_t rmin = fmd2->GetInner()->GetLowR(); | |
531 | Double_t rmax = fmd2->GetOuterHoneyHighR(); | |
532 | Double_t hcThick = fmd2->GetHoneycombThickness(); | |
533 | Double_t ow = fmd2->GetInner()->GetRingDepth(); | |
534 | Double_t iz = fmd2->GetInnerZ(); | |
535 | Double_t oz = fmd2->GetOuterZ(); | |
536 | Double_t w = TMath::Abs(oz - iz) + ow + hcThick; | |
537 | Double_t z = oz + w / 2; | |
538 | ||
4ac75127 | 539 | TGeoVolume* fmd2Volume = 0; |
540 | if (!fUseAssembly) { | |
541 | TGeoTube* fmd2Shape = new TGeoTube(rmin, rmax, w / 2); | |
542 | fmd2Volume = new TGeoVolume(fmd2->GetName(), fmd2Shape, fAir); | |
543 | } | |
544 | else | |
545 | fmd2Volume = new TGeoVolumeAssembly(fmd2->GetName()); | |
1a1fdef7 | 546 | |
547 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
548 | TGeoMatrix* matrix = new TGeoTranslation("FMD2 transform", 0, 0, z); | |
549 | top->AddNode(fmd2Volume, fmd2->GetId(), matrix); | |
550 | ||
551 | return DetectorGeometry(fmd2, fmd2Volume, z, inner, outer); | |
552 | } | |
553 | ||
554 | //____________________________________________________________________ | |
555 | TGeoVolume* | |
556 | AliFMDGeoSimulator::FMD3Geometry(AliFMD3* fmd3, | |
557 | TGeoVolume* inner, | |
558 | TGeoVolume* outer) | |
559 | { | |
560 | // Setup the FMD3 geometry. The FMD2 has a rather elaborate support | |
561 | // structure, as the support will also support the vacuum | |
562 | // beam-pipe. | |
563 | // | |
564 | // See also AliFMDGeoSimulator::DetectorGeometry | |
565 | // | |
566 | if (!fmd3 || !inner || !outer) return 0; | |
567 | Double_t nlen = fmd3->GetNoseLength(); | |
568 | Double_t nz = fmd3->GetNoseZ(); | |
569 | Double_t noser1 = fmd3->GetNoseLowR(); | |
570 | Double_t noser2 = fmd3->GetNoseHighR(); | |
571 | Double_t conel = fmd3->GetConeLength(); | |
572 | Double_t backl = fmd3->GetBackLength(); | |
573 | Double_t backr1 = fmd3->GetBackLowR(); | |
574 | Double_t backr2 = fmd3->GetBackHighR(); | |
575 | Double_t zdist = conel - backl - nlen; | |
576 | Double_t tdist = backr2 - noser2; | |
577 | Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist); | |
578 | Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi(); | |
579 | Double_t innerZ = fmd3->GetInnerZ(); | |
580 | Double_t innerZh = (innerZ - fmd3->GetInner()->GetRingDepth() | |
581 | - fmd3->GetHoneycombThickness()); | |
582 | Double_t outerZ = fmd3->GetOuterZ(); | |
583 | Double_t outerZh = (outerZ - fmd3->GetOuter()->GetRingDepth() | |
584 | - fmd3->GetHoneycombThickness()); | |
585 | Double_t innerr1 = fmd3->GetInner()->GetLowR(); | |
586 | // Double_t innerr2 = fmd3->GetInner()->GetHighR(); | |
587 | Double_t outerr1 = fmd3->GetOuter()->GetLowR(); | |
588 | // Double_t outerr2 = fmd3->GetOuter()->GetHighR(); | |
589 | Double_t flanger = fmd3->GetFlangeR(); | |
590 | Double_t minZ = TMath::Min(nz - conel, outerZh); | |
591 | Double_t z = fmd3->GetZ(); | |
592 | Double_t zi; | |
593 | ||
594 | // FMD3 volume | |
4ac75127 | 595 | TGeoVolume* fmd3Volume = 0; |
596 | if (!fUseAssembly) { | |
597 | TGeoPcon* fmd3Shape = new TGeoPcon(0, 360, 8); | |
598 | zi = z - nz; | |
599 | fmd3Shape->DefineSection(0, zi, noser1, noser2); | |
600 | zi = z - (nz - nlen); | |
601 | fmd3Shape->DefineSection(1, zi, noser1, fmd3->ConeR(z - zi)+.15); | |
602 | zi = z - innerZ; | |
603 | fmd3Shape->DefineSection(2, zi, innerr1, fmd3->ConeR(z - zi)+.15); | |
604 | zi = z - innerZh; | |
605 | fmd3Shape->DefineSection(3, zi, innerr1, fmd3->ConeR(z - zi)+.15); | |
606 | fmd3Shape->DefineSection(4, zi, outerr1, fmd3->ConeR(z - zi)+.15); | |
607 | zi = z - nz + zdist + nlen; | |
608 | fmd3Shape->DefineSection(5, zi, outerr1, fmd3->ConeR(z - zi)+.15); | |
609 | zi = z - nz + nlen + zdist; | |
610 | fmd3Shape->DefineSection(6, zi, outerr1, flanger+1.5); | |
611 | zi = z - minZ; | |
612 | fmd3Shape->DefineSection(7, zi, outerr1, flanger+1.5); | |
613 | fmd3Volume = new TGeoVolume(fmd3->GetName(), fmd3Shape, fAir); | |
614 | } | |
615 | else | |
616 | fmd3Volume = new TGeoVolumeAssembly(fmd3->GetName()); | |
1a1fdef7 | 617 | |
618 | TGeoRotation* rot = new TGeoRotation("FMD3 rotatation"); | |
619 | rot->RotateY(180); | |
620 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
621 | TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 transform", 0, 0, z, rot); | |
622 | top->AddNode(fmd3Volume, fmd3->GetId(), mmatrix); | |
623 | ||
624 | // Nose volume | |
625 | TGeoTube* noseShape = new TGeoTube(noser1, noser2, nlen / 2); | |
626 | TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC); | |
627 | zi = z - nz + nlen / 2; | |
628 | TGeoMatrix* nmatrix = new TGeoTranslation("FMD3 Nose translation", 0, 0, zi); | |
4ac75127 | 629 | // fmd3Volume->AddNodeOverlap(noseVolume, 0, nmatrix); |
630 | fmd3Volume->AddNode(noseVolume, 0, nmatrix); | |
1a1fdef7 | 631 | |
632 | // Back | |
633 | TGeoTube* backShape = new TGeoTube(backr1, backr2, backl / 2); | |
634 | TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC); | |
635 | zi = z - nz + conel - backl / 2; | |
636 | TGeoMatrix* bmatrix = new TGeoTranslation("FMD3 Back translation", 0, 0, zi); | |
637 | fmd3Volume->AddNode(backVolume, 0, bmatrix); | |
638 | ||
639 | Int_t n; | |
640 | Double_t r; | |
641 | // The flanges | |
642 | TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, | |
643 | fmd3->GetBeamWidth() / 2, | |
644 | backl / 2); | |
645 | TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC); | |
646 | n = fmd3->GetNFlange(); | |
647 | r = backr2 + (flanger - backr2) / 2; | |
648 | for (Int_t i = 0; i < n; i++) { | |
649 | Double_t phi = 360. / n * i + 180. / n; | |
650 | Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi); | |
651 | Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi); | |
652 | TGeoRotation* rot = new TGeoRotation(Form("FMD3 Flange rotation %d", i)); | |
653 | rot->RotateZ(phi); | |
654 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 flange transform %d", | |
655 | i), x, y, zi, rot); | |
4ac75127 | 656 | // fmd3Volume->AddNodeOverlap(flangeVolume, i, matrix); |
657 | fmd3Volume->AddNode(flangeVolume, i, matrix); | |
1a1fdef7 | 658 | |
659 | } | |
660 | ||
661 | // The Beams | |
662 | TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, | |
4ac75127 | 663 | fmd3->GetBeamWidth() / 2 - .1, |
1a1fdef7 | 664 | beaml / 2); |
665 | TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC); | |
666 | n = fmd3->GetNBeam(); | |
667 | r = noser2 + tdist / 2; | |
668 | zi = z - nz + nlen + zdist / 2; | |
669 | for (Int_t i = 0; i < n; i++) { | |
670 | Double_t phi = 360. / n * i; | |
671 | Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi); | |
672 | Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi); | |
673 | TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i)); | |
4ac75127 | 674 | // Order is important |
1a1fdef7 | 675 | rot->RotateY(-theta); |
4ac75127 | 676 | rot->RotateZ(phi); |
1a1fdef7 | 677 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam transform %d", i), |
678 | x, y, zi, rot); | |
679 | fmd3Volume->AddNode(beamVolume, i, matrix); | |
680 | } | |
681 | ||
682 | ||
683 | return DetectorGeometry(fmd3, fmd3Volume, z, inner, outer); | |
684 | } | |
685 | ||
686 | //____________________________________________________________________ | |
687 | void | |
688 | AliFMDGeoSimulator::DefineGeometry() | |
689 | { | |
690 | // Setup up the FMD geometry. | |
f4ee3d57 | 691 | AliDebug(1, "Setting up volumes, with "); |
1a1fdef7 | 692 | |
693 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
694 | TGeoVolume* inner = RingGeometry(fmd->GetInner()); | |
695 | TGeoVolume* outer = RingGeometry(fmd->GetOuter()); | |
696 | ||
697 | if (!inner || !outer) { | |
698 | AliError("Failed to create one of the ring volumes"); | |
699 | return; | |
700 | } | |
701 | FMD1Geometry(fmd->GetFMD1(), inner); | |
702 | FMD2Geometry(fmd->GetFMD2(), inner, outer); | |
703 | FMD3Geometry(fmd->GetFMD3(), inner, outer); | |
704 | } | |
705 | ||
706 | ||
707 | //____________________________________________________________________ | |
708 | // | |
709 | // EOF | |
710 | // |