]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDGeometryBuilder.cxx
Added new method DisIntegrate(AliMUONHit&, TList& digits) to replace the one in
[u/mrichter/AliRoot.git] / FMD / AliFMDGeometryBuilder.cxx
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 |<>-----| AliFMDGeometryBuilder |
33 //      +--------+       +-----------------+
34 //                               ^              
35 //                               |
36 //                 +-------------+-------------+
37 //                 |                           |              
38 //        +--------------------+   +-------------------+
39 //        | AliFMDGeometryBuilder |   | AliFMDG3Simulator | 
40 //        +--------------------+   +---------+---------+
41 //                                           ^
42 //                                           |
43 //                                +--------------------+
44 //                                | AliFMDOldSimulator |
45 //                                +--------------------+
46 //      
47 // *  AliFMD 
48 //    This defines the interface for the various parts of AliROOT that
49 //    uses the FMD, like AliFMDGeometryBuilder, AliFMDDigitizer, 
50 //    AliFMDReconstructor, and so on. 
51 //
52 // *  AliFMDGeometryBuilder
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 // *  AliFMDGeometryBuilder
58 //    This is a concrete implementation of the AliFMDGeometryBuilder 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 AliFMDGeometryBuilder 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 //
71 // *  AliFMDOldSimulator
72 //    This is a concrete implementation of AliFMDGeometryBuilder.   It
73 //    approximates the of the rings as segmented disks. 
74 // 
75 #include "AliFMDGeometryBuilder.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(AliFMDGeometryBuilder)
98 #if 0
99   ; // This is here to keep Emacs for indenting the next line
100 #endif
101
102 //____________________________________________________________________
103 const Char_t* AliFMDGeometryBuilder::fgkActiveName      = "F%cAC";
104 const Char_t* AliFMDGeometryBuilder::fgkSectorName      = "F%cSE";
105 const Char_t* AliFMDGeometryBuilder::fgkStripName       = "F%cST";
106 const Char_t* AliFMDGeometryBuilder::fgkModuleName      = "F%cMO";
107 const Char_t* AliFMDGeometryBuilder::fgkPCBName         = "F%cP%c";
108 const Char_t* AliFMDGeometryBuilder::fgkLongLegName     = "F%cLL";
109 const Char_t* AliFMDGeometryBuilder::fgkShortLegName    = "F%cSL";
110 const Char_t* AliFMDGeometryBuilder::fgkFrontVName      = "F%cFV";
111 const Char_t* AliFMDGeometryBuilder::fgkBackVName       = "F%cBV";
112 const Char_t* AliFMDGeometryBuilder::fgkRingName        = "FMD%c";
113 const Char_t* AliFMDGeometryBuilder::fgkTopHCName       = "F%d%cI";
114 const Char_t* AliFMDGeometryBuilder::fgkBotHCName       = "F%d%cJ";
115 const Char_t* AliFMDGeometryBuilder::fgkTopIHCName      = "F%d%cK";
116 const Char_t* AliFMDGeometryBuilder::fgkBotIHCName      = "F%d%cL";
117 const Char_t* AliFMDGeometryBuilder::fgkNoseName        = "F3SN";
118 const Char_t* AliFMDGeometryBuilder::fgkBackName        = "F3SB";
119 const Char_t* AliFMDGeometryBuilder::fgkBeamName        = "F3SL";
120 const Char_t* AliFMDGeometryBuilder::fgkFlangeName      = "F3SF";
121
122 //____________________________________________________________________
123 AliFMDGeometryBuilder::AliFMDGeometryBuilder() 
124   : fDetailed(kTRUE),
125     fUseAssembly(kTRUE),
126     fSi(0),
127     fC(0),
128     fAl(0),
129     fPCB(0),
130     fChip(0),
131     fPlastic(0)
132 {
133   // Default constructor
134   fActiveId.Set(2);
135 }
136
137 //____________________________________________________________________
138 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
139   : TTask("FMD", "Geometry builder"),
140     fDetailed(detailed),
141     fUseAssembly(kTRUE),
142     fSi(0),
143     fC(0),
144     fAl(0),
145     fPCB(0),
146     fChip(0),
147     fPlastic(0)
148 {
149   // Normal constructor
150   // 
151   // Parameters: 
152   // 
153   //      fmd           Pointer to AliFMD object 
154   //      detailed      Whether to make a detailed simulation or not 
155   // 
156   fActiveId.Set(2);
157 }
158
159
160 //____________________________________________________________________
161 TGeoVolume*
162 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) 
163 {
164   // Setup the geometry of a ring.    The defined TGeoVolume is
165   // returned, and should be used when setting up the rest of the
166   // volumes. 
167   // 
168   // 
169   // Parameters:
170   //
171   //     r              Pointer to ring geometry object 
172   // 
173   // Returns:
174   //    pointer to ring volume 
175   //
176   if (!r) { 
177     AliError("Didn't get a ring object");
178     return 0;
179   }
180   Char_t      id       = r->GetId();
181   Double_t    siThick  = r->GetSiThickness();
182   const Int_t nv       = r->GetNVerticies();
183   TVector2*   a        = r->GetVertex(5);
184   TVector2*   b        = r->GetVertex(3);
185   TVector2*   c        = r->GetVertex(4);
186   Double_t    theta    = r->GetTheta();
187   Double_t    off      = (TMath::Tan(TMath::Pi() * theta / 180) 
188                           * r->GetBondingWidth());
189   Double_t    rmax     = b->Mod();
190   Double_t    rmin     = r->GetLowR();
191   Double_t    pcbThick = r->GetPrintboardThickness();
192   Double_t    modSpace = r->GetModuleSpacing();
193   Double_t    legr     = r->GetLegRadius();
194   Double_t    legl     = r->GetLegLength();
195   Double_t    legoff   = r->GetLegOffset();
196   Int_t       ns       = r->GetNStrips();
197   Double_t    stripoff = a->Mod();
198   Double_t    dstrip   = (rmax - stripoff) / ns;
199   Double_t    space    = r->GetSpacing();
200   TArrayD xs(nv);
201   TArrayD ys(nv);
202   for (Int_t i = 0; i < nv; i++) {
203     // Reverse the order 
204     TVector2* vv = r->GetVertex(nv - 1 - i);
205     if (!vv) {
206       AliError(Form("Failed to get vertex # %d", nv - 1 - i));
207       continue;
208     }
209     xs[i] = vv->X();
210     ys[i] = vv->Y();
211   }
212   
213   // Shape of actual sensor 
214   TGeoXtru* moduleShape = new TGeoXtru(2);
215   moduleShape->DefinePolygon(nv, xs.fArray, ys.fArray);
216   moduleShape->DefineSection(0, - siThick/2);
217   moduleShape->DefineSection(1, siThick/2);
218   TGeoVolume* moduleVolume = new TGeoVolume(Form(fgkModuleName, id), 
219                                             moduleShape, fSi);
220   Int_t sid = moduleVolume->GetNumber();
221   fSectorOff   = -1;
222   fModuleOff   = 1;
223   fRingOff     = 2;
224   fDetectorOff = 3;
225   if (fDetailed) {
226     fSectorOff   = 1;
227     fModuleOff   = 4;
228     fRingOff     = 5;
229     fDetectorOff = 6;
230     // Virtual volume shape to divide - This volume is only defined if
231     // the geometry is set to be detailed. 
232     TGeoTubeSeg* activeShape = 
233       new TGeoTubeSeg(rmin, rmax, siThick/2, - theta, theta);
234     TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
235                                               activeShape,fSi);
236     TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), 
237                                                       2, 2, -theta,0,0,"N");
238     TGeoVolume* stripVolume  = sectorVolume->Divide(Form(fgkStripName, id), 
239                                                     1, ns, stripoff, dstrip, 
240                                                     0, "SX");
241     sid = stripVolume->GetNumber();
242     moduleVolume->AddNodeOverlap(activeVolume, 0);
243   }
244   
245   switch (id) {
246   case 'i':
247   case 'I': fActiveId[0] = sid; break;
248   case 'o':
249   case 'O': fActiveId[1] = sid; break;
250   }
251
252   // Shape of Printed circuit Board 
253   TGeoXtru* pcbShape = new TGeoXtru(2);
254   for (Int_t i = 0;      i < nv / 2; i++) ys[i] -= off;
255   for (Int_t i = nv / 2; i < nv;     i++) ys[i] += off;
256   pcbShape->DefinePolygon(nv, xs.fArray, ys.fArray);
257   pcbShape->DefineSection(0, - pcbThick/2);
258   pcbShape->DefineSection(1, pcbThick/2);
259   TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id, 'B'), 
260                                          pcbShape, fPCB);
261
262   // Short leg shape 
263   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, legl / 2);
264   TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), 
265                                               shortLegShape, fPlastic);
266
267   // Long leg shape
268   TGeoTube*   longLegShape   = new TGeoTube(0, legr, (legl + modSpace) / 2);
269   TGeoVolume* longLegVolume  = new TGeoVolume(Form(fgkLongLegName, id), 
270                                               longLegShape, fPlastic);
271   
272   TGeoMatrix* matrix = 0;
273   // Back container volume 
274   Double_t contThick     = siThick + pcbThick + legl + space;
275   TGeoTubeSeg* backShape = new TGeoTubeSeg(rmin, rmax, contThick/2, 
276                                            - theta, theta);
277   TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackVName, id), 
278                                           backShape, fAir);
279   Double_t x = 0;
280   Double_t y = 0;
281   Double_t z = -contThick / 2 + siThick / 2;
282   matrix     = new TGeoTranslation(Form("FMD Ring  %c mod 1 transform", id), 
283                                    x, y, z);
284   backVolume->AddNode(moduleVolume, 0, matrix);
285   z          += siThick / 2 + space + pcbThick / 2;
286   matrix     =  new TGeoTranslation(Form("FMD Ring %c pcb 1 transfrom", id), 
287                                     x, y, z);
288   backVolume->AddNode(pcbVolume, 0, matrix);
289   x          =  a->X() + legoff + legr;
290   y          =  0;
291   z          += pcbThick / 2 + legl / 2;
292   matrix     = new TGeoTranslation(Form("FMD Ring %c leg 1 transfrom", id), 
293                                    x, y, z);
294   backVolume->AddNode(shortLegVolume, 0, matrix);
295   x          =  c->X();
296   y          =  c->Y() - legoff - legr - off;
297   matrix     =  new TGeoTranslation(Form("FMD Ring %c leg 2 transfrom", id), 
298                                     x, y, z);
299   backVolume->AddNode(shortLegVolume, 1, matrix);
300   y          =  -y;
301   matrix     =  new TGeoTranslation(Form("FMD Ring %c leg 3 transfrom", id), 
302                                     x, y, z);
303   backVolume->AddNode(shortLegVolume, 2, matrix);
304   // backVolume->SetVisibility(kFALSE);
305   // backVolume->VisibleDaughters(kTRUE);
306
307   // Front container volume 
308   contThick += modSpace;
309   TGeoTubeSeg* frontShape = new TGeoTubeSeg(rmin, rmax, contThick/2, 
310                                             -theta, theta);
311   TGeoVolume* frontVolume = new TGeoVolume(Form(fgkFrontVName, id),
312                                            frontShape, fAir);
313   x         =  0;
314   y         =  0;
315   z         =  -contThick / 2 + siThick / 2 ;
316   matrix    = new TGeoTranslation(Form("FMD Ring %c mod 2 transfrom", id), 
317                                   0, 0, z);
318   frontVolume->AddNode(moduleVolume, 1, matrix);
319   z         += siThick / 2 + space + pcbThick / 2;
320   matrix    =  new TGeoTranslation(Form("FMD Ring %c pcb 2 transfrom", id), 
321                                    x, y, z);
322   frontVolume->AddNode(pcbVolume, 1, matrix);
323   x         =  a->X() + legoff + legr;
324   y         =  0;
325   z         += pcbThick / 2 + (legl + modSpace)/ 2;
326   matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
327                                    x, y, z);
328   frontVolume->AddNode(longLegVolume, 0, matrix);
329   x         =  c->X();
330   y         =  c->Y() - legoff - legr - off;
331   matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
332                                    x, y, z);
333   frontVolume->AddNode(longLegVolume, 1, matrix);
334   y         =  -y;
335   matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
336                                    x, y, z);
337   frontVolume->AddNode(longLegVolume, 2, matrix);
338   // frontVolume->SetVisibility(kFALSE);
339   // frontVolume->VisibleDaughters(kTRUE);
340   
341   // Ring mother volume 
342   TGeoTube*   ringShape  = new TGeoTube(rmin, rmax, contThick / 2);
343   TGeoVolume* ringVolume = new TGeoVolume(Form(fgkRingName,id),
344                                           ringShape,fAir);
345
346   Int_t nmod = r->GetNModules();
347   AliDebug(10, Form("making %d modules in ring %c", nmod, id));
348   for (Int_t i = 0; i < nmod; i++) {
349     Bool_t isFront    = (i % 2 == 0);
350     TGeoVolume* vol   = (isFront ? frontVolume : backVolume);
351     TGeoRotation* rot =new TGeoRotation(Form("FMD Ring %c rotation %d",id,i));
352     rot->RotateZ((i + .5) * 2 * theta);
353     Double_t z = (isFront ? 0 : modSpace) / 2;
354     matrix     = new TGeoCombiTrans(Form("FMD Ring %c transform %d", id, i), 
355                                     0, 0, z, rot);
356     ringVolume->AddNode(vol, i, matrix);
357   }
358
359   ringVolume->SetVisibility(kFALSE);
360   ringVolume->VisibleDaughters(kTRUE);
361   return ringVolume;
362 }
363
364 //____________________________________________________________________
365 TGeoVolume*
366 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, 
367                                         TGeoVolume* mother, 
368                                         Double_t    zmother, 
369                                         TGeoVolume* inner, 
370                                         TGeoVolume* outer) 
371 {
372   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
373   // This includes putting the Honeycomb support plates and the rings
374   // into the mother volumes.   
375   // 
376   // Parameeters:
377   //    d         The detector geometry to use 
378   //    mother    The mother volume of the detector 
379   //    zmother   The midpoint in global coordinates of detector vol.
380   //    inner     Pointer to inner ring volume 
381   //    outer     Pointer to outer ring volume
382   //
383   // Returns:
384   //    Pointer to mother (detector volume) 
385   // 
386   if (!d) return 0;
387   // Loop over the defined rings 
388   for (int i = 0; i < 2; i++) {
389     AliFMDRing* r     = 0;
390     Double_t    lowr  = 0;
391     Double_t    highr = 0;
392     Double_t    rz    = 0;
393     TGeoVolume* rvol  = 0;
394     switch (i) {
395     case 0: 
396       r      = d->GetInner();
397       lowr   = d->GetInnerHoneyLowR();
398       highr  = d->GetInnerHoneyHighR();
399       rz     = d->GetInnerZ();
400       rvol   = inner;
401       break;
402     case 1: 
403       r      = d->GetOuter();
404       lowr   = d->GetOuterHoneyLowR();
405       highr  = d->GetOuterHoneyHighR();
406       rz     = d->GetOuterZ();
407       rvol   = outer;
408       break;
409     }
410     if (!r) continue;
411     Char_t   c       = r->GetId();
412     Int_t    id      = d->GetId();
413     Double_t hcThick = d->GetHoneycombThickness();
414     Double_t alThick = d->GetAlThickness();
415     Double_t z;
416     if (zmother > 0) z = rz - zmother + r->GetRingDepth() / 2;
417     else             z = zmother - rz + r->GetRingDepth() / 2;
418     // Place ring in mother volume
419     mother->AddNode(rvol, Int_t(c), 
420                     new TGeoTranslation(Form("FMD%d%c transform", id, c), 
421                                         0, 0, z));
422
423     z += r->GetRingDepth() / 2 + hcThick / 2;
424     // Top of Honeycomb
425     TGeoTubeSeg* topHCShape  = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180);
426     TGeoVolume*  topHCVolume = new TGeoVolume(Form(fgkTopHCName, id, c), 
427                                               topHCShape, fAl);
428     TGeoMatrix*  topHCMatrix = 
429       new TGeoTranslation(Form("FMD%d%c top HC transform", id, c), 0, 0, z);
430     mother->AddNode(topHCVolume, 0, topHCMatrix);
431
432     // Air in top of honeycomb
433     TGeoTubeSeg* topIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
434                                                (hcThick-alThick)/2, 0, 180);
435     TGeoVolume*  topIHCVolume = new TGeoVolume(Form(fgkTopIHCName, id, c), 
436                                                topIHCShape, fAir);
437     topHCVolume->AddNode(topIHCVolume, 0);
438     topHCVolume->VisibleDaughters(kFALSE);    
439     topHCVolume->SetVisibility(kTRUE);
440
441
442     // Bottom of Honeycomb
443     TGeoTubeSeg* botHCShape = new TGeoTubeSeg(lowr, highr, hcThick/2, 
444                                               180, 360);
445     TGeoVolume*  botHCVolume = new TGeoVolume(Form(fgkBotHCName, id, c), 
446                                               botHCShape, fAl);
447     TGeoMatrix*  botHCMatrix = 
448       new TGeoTranslation(Form("FMD%d%c bottom HC transform", id, c), 0, 0, z);
449     mother->AddNode(botHCVolume, 0, botHCMatrix);
450
451     // Air in bot of honeycomb
452     TGeoTubeSeg* botIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
453                                                (hcThick-alThick)/2, 180, 360);
454     TGeoVolume*  botIHCVolume = new TGeoVolume(Form(fgkBotIHCName, id, c), 
455                                                botIHCShape, fAir);
456     botHCVolume->AddNode(botIHCVolume, 0);
457     botHCVolume->VisibleDaughters(kFALSE);    
458     botHCVolume->SetVisibility(kTRUE);    
459   }
460   mother->SetVisibility(kFALSE);
461   mother->VisibleDaughters(kTRUE);
462   return mother;
463 }
464
465 //____________________________________________________________________
466 TGeoVolume*
467 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, TGeoVolume* inner) 
468 {
469   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
470   // special support as it is at the momement. 
471   // 
472   // See also AliFMDGeometryBuilder::DetectorGeometry 
473   // 
474   if (!fmd1 || !inner) return 0;
475   Double_t rmin    = fmd1->GetInner()->GetLowR();
476   Double_t rmax    = fmd1->GetInnerHoneyHighR();
477   Double_t hcThick = fmd1->GetHoneycombThickness();
478   Double_t w       = fmd1->GetInner()->GetRingDepth() + hcThick;
479   Double_t z       = fmd1->GetInnerZ() + w / 2;
480
481   TGeoVolume* fmd1Volume = 0;
482   if (!fUseAssembly) {
483     TGeoTube* fmd1Shape = new TGeoTube(rmin, rmax, w / 2);
484     fmd1Volume = new TGeoVolume(fmd1->GetName(), fmd1Shape, fAir);
485   }
486   else
487     fmd1Volume = new TGeoVolumeAssembly(fmd1->GetName());
488   
489   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
490   TGeoMatrix* matrix = new TGeoTranslation("FMD1 transform", 0, 0, z);
491   top->AddNode(fmd1Volume, fmd1->GetId(), matrix);
492
493   return DetectorGeometry(fmd1, fmd1Volume, z, inner, 0);
494 }
495
496 //____________________________________________________________________
497 TGeoVolume*
498 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, 
499                                  TGeoVolume* inner, 
500                                  TGeoVolume* outer) 
501 {
502   // Setup the FMD2 geometry.  The FMD2 has no
503   // special support as it is at the momement. 
504   // 
505   // See also AliFMDGeometryBuilder::DetectorGeometry 
506   // 
507   if (!fmd2 || !inner || !outer) return 0;
508   Double_t rmin     = fmd2->GetInner()->GetLowR();
509   Double_t rmax     = fmd2->GetOuterHoneyHighR();
510   Double_t hcThick  = fmd2->GetHoneycombThickness();
511   Double_t ow       = fmd2->GetInner()->GetRingDepth();
512   Double_t iz       = fmd2->GetInnerZ();
513   Double_t oz       = fmd2->GetOuterZ();
514   Double_t w        = TMath::Abs(oz - iz) + ow + hcThick;
515   Double_t z        = oz + w / 2;
516   
517   TGeoVolume* fmd2Volume = 0;
518   if (!fUseAssembly) {
519     TGeoTube* fmd2Shape = new TGeoTube(rmin, rmax, w / 2);
520     fmd2Volume = new TGeoVolume(fmd2->GetName(), fmd2Shape, fAir);
521   }
522   else 
523     fmd2Volume = new TGeoVolumeAssembly(fmd2->GetName());
524   
525   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
526   TGeoMatrix* matrix = new TGeoTranslation("FMD2 transform", 0, 0, z);
527   top->AddNode(fmd2Volume, fmd2->GetId(), matrix);
528
529   return DetectorGeometry(fmd2, fmd2Volume, z, inner, outer);
530 }
531   
532 //____________________________________________________________________
533 TGeoVolume*
534 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
535                                  TGeoVolume* inner, 
536                                  TGeoVolume* outer) 
537 {
538   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
539   // structure, as the support will also support the vacuum
540   // beam-pipe. 
541   // 
542   // See also AliFMDGeometryBuilder::DetectorGeometry 
543   // 
544   if (!fmd3 || !inner || !outer) return 0;
545   Double_t nlen    = fmd3->GetNoseLength();
546   Double_t nz      = fmd3->GetNoseZ();
547   Double_t noser1  = fmd3->GetNoseLowR();
548   Double_t noser2  = fmd3->GetNoseHighR();
549   Double_t conel   = fmd3->GetConeLength();
550   Double_t backl   = fmd3->GetBackLength();
551   Double_t backr1  = fmd3->GetBackLowR();
552   Double_t backr2  = fmd3->GetBackHighR();
553   Double_t zdist   = conel -  backl - nlen;
554   Double_t tdist   = backr2 - noser2;
555   Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
556   Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
557   Double_t innerZ  = fmd3->GetInnerZ();
558   Double_t innerZh = (innerZ - fmd3->GetInner()->GetRingDepth() 
559                       - fmd3->GetHoneycombThickness());
560   Double_t outerZ  = fmd3->GetOuterZ();
561   Double_t outerZh = (outerZ - fmd3->GetOuter()->GetRingDepth() 
562                       - fmd3->GetHoneycombThickness());
563   Double_t innerr1 = fmd3->GetInner()->GetLowR();
564   // Double_t innerr2 = fmd3->GetInner()->GetHighR();
565   Double_t outerr1 = fmd3->GetOuter()->GetLowR();
566   // Double_t outerr2 = fmd3->GetOuter()->GetHighR();
567   Double_t flanger = fmd3->GetFlangeR();
568   Double_t minZ    = TMath::Min(nz - conel, outerZh);
569   Double_t z       = fmd3->GetZ();
570   Double_t zi;
571
572   // FMD3 volume 
573   TGeoVolume* fmd3Volume = 0;
574   if (!fUseAssembly) {
575     TGeoPcon* fmd3Shape = new TGeoPcon(0, 360, 8);
576     zi = z - nz;
577     fmd3Shape->DefineSection(0, zi,  noser1,   noser2);
578     zi = z - (nz - nlen);
579     fmd3Shape->DefineSection(1, zi,  noser1,   fmd3->ConeR(z - zi)+.15);
580     zi = z - innerZ;
581     fmd3Shape->DefineSection(2, zi,  innerr1,  fmd3->ConeR(z - zi)+.15);
582     zi = z - innerZh;
583     fmd3Shape->DefineSection(3, zi,  innerr1,  fmd3->ConeR(z - zi)+.15);
584     fmd3Shape->DefineSection(4, zi,  outerr1,  fmd3->ConeR(z - zi)+.15);
585     zi = z - nz + zdist + nlen;
586     fmd3Shape->DefineSection(5, zi,  outerr1,  fmd3->ConeR(z - zi)+.15);
587     zi = z - nz + nlen + zdist;
588     fmd3Shape->DefineSection(6, zi,  outerr1,  flanger+1.5);
589     zi = z - minZ;
590     fmd3Shape->DefineSection(7, zi,  outerr1,  flanger+1.5);
591     fmd3Volume = new TGeoVolume(fmd3->GetName(), fmd3Shape, fAir);
592   }
593   else 
594     fmd3Volume = new TGeoVolumeAssembly(fmd3->GetName());
595   
596   TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
597   rot->RotateY(180);
598   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
599   TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 transform", 0, 0, z, rot);
600   top->AddNode(fmd3Volume, fmd3->GetId(), mmatrix);
601   
602   // Nose volume 
603   TGeoTube* noseShape = new TGeoTube(noser1, noser2, nlen / 2);
604   TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
605   zi = z - nz + nlen / 2;
606   TGeoMatrix* nmatrix = new TGeoTranslation("FMD3 Nose translation", 0, 0, zi);
607   // fmd3Volume->AddNodeOverlap(noseVolume, 0, nmatrix);
608   fmd3Volume->AddNode(noseVolume, 0, nmatrix);
609   
610   // Back
611   TGeoTube* backShape = new TGeoTube(backr1, backr2, backl / 2);
612   TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC);
613   zi = z - nz + conel - backl / 2;
614   TGeoMatrix* bmatrix = new TGeoTranslation("FMD3 Back translation", 0, 0, zi);
615   fmd3Volume->AddNode(backVolume, 0, bmatrix);
616   
617   Int_t n;
618   Double_t r;
619   // The flanges 
620   TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, 
621                                        fmd3->GetBeamWidth() / 2,
622                                        backl / 2);
623   TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC);
624   n = fmd3->GetNFlange();
625   r = backr2 + (flanger - backr2) / 2;
626   for (Int_t i = 0; i  < n; i++) {
627     Double_t phi = 360. / n * i + 180. / n;
628     Double_t x   = r * TMath::Cos(TMath::Pi() / 180 * phi);
629     Double_t y   = r * TMath::Sin(TMath::Pi() / 180 * phi);
630     TGeoRotation* rot = new TGeoRotation(Form("FMD3 Flange rotation %d", i));
631     rot->RotateZ(phi);
632     TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 flange transform %d", 
633                                                  i), x, y, zi, rot);
634     // fmd3Volume->AddNodeOverlap(flangeVolume, i, matrix);
635     fmd3Volume->AddNode(flangeVolume, i, matrix);
636     
637   }
638
639   // The Beams 
640   TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, 
641                                      fmd3->GetBeamWidth() / 2 - .1,
642                                      beaml / 2);
643   TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC);
644   n = fmd3->GetNBeam();
645   r = noser2 + tdist / 2;
646   zi = z - nz + nlen + zdist / 2;
647   for (Int_t i = 0; i  < n; i++) {
648     Double_t phi = 360. / n * i;
649     Double_t x   = r * TMath::Cos(TMath::Pi() / 180 * phi);
650     Double_t y   = r * TMath::Sin(TMath::Pi() / 180 * phi);
651     TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i));
652     // Order is important
653     rot->RotateY(-theta);
654     rot->RotateZ(phi);
655     TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam transform %d", i),
656                                             x, y, zi, rot);
657     fmd3Volume->AddNode(beamVolume, i, matrix);    
658   }
659   
660   
661   return DetectorGeometry(fmd3, fmd3Volume, z, inner, outer);
662 }
663
664 //____________________________________________________________________
665 void
666 AliFMDGeometryBuilder::Exec(Option_t*) 
667 {
668   // Setup up the FMD geometry. 
669   AliDebug(1,  Form("\tGeometry options: %s, %s",
670                     (fDetailed  ? "divided into strips" : "one volume"), 
671                     (fUseAssembly ? "within assemblies" : "in real volumes")));
672   if (!gGeoManager) {
673     AliFatal("No TGeoManager defined");
674     return;
675   }
676
677   fSi      = gGeoManager->GetMedium("FMD_Si$");
678   fC       = gGeoManager->GetMedium("FMD_Carbon$");
679   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
680   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
681   fAir     = gGeoManager->GetMedium("FMD_Air$");
682   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
683   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
684   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
685
686   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper) {
687     AliError("Failed to get some or all tracking mediums");
688     return;
689   }    
690   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
691   TGeoVolume* inner = RingGeometry(fmd->GetInner());
692   TGeoVolume* outer = RingGeometry(fmd->GetOuter());
693   if (!inner || !outer) {
694     AliError("Failed to create one of the ring volumes");
695     return;
696   }
697   FMD1Geometry(fmd->GetFMD1(), inner);
698   FMD2Geometry(fmd->GetFMD2(), inner, outer);
699   FMD3Geometry(fmd->GetFMD3(), inner, outer);
700 #ifndef USE_PRE_MOVE
701   fmd->SetSectorOff(fSectorOff);
702   fmd->SetModuleOff(fModuleOff);
703   fmd->SetRingOff(fRingOff);
704   fmd->SetDetectorOff(fDetectorOff);
705   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
706 #endif
707   // fmd->ExtractGeomInfo();
708   
709 }
710
711
712 //____________________________________________________________________
713 //
714 // EOF
715 //