]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDGeometryBuilder.cxx
Additiona TOF data members (S.Arcelli)
[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 // 
26 #include "AliFMDGeometryBuilder.h"      // ALIFMDGEOSIMULATOR_H
27 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
28 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
29 #include "AliFMDRing.h"         // ALIFMDRING_H
30 #include "AliFMD1.h"            // ALIFMD1_H
31 #include "AliFMD2.h"            // ALIFMD2_H
32 #include "AliFMD3.h"            // ALIFMD3_H
33 #include "AliFMD.h"             // ALIFMD_H
34 #include "AliLog.h"             // ALILOG_H
35 #include <TGeoVolume.h>         // ROOT_TGeoVolume
36 #include <TGeoTube.h>           // ROOT_TGeoTube
37 #include <TGeoPcon.h>           // ROOT_TGeoPcon
38 #include <TGeoMaterial.h>       // ROOT_TGeoMaterial
39 #include <TGeoMedium.h>         // ROOT_TGeoMedium
40 #include <TGeoXtru.h>           // ROOT_TGeoXtru
41 #include <TGeoPolygon.h>        // ROOT_TGeoPolygon
42 #include <TGeoTube.h>           // ROOT_TGeoTube
43 #include <TGeoManager.h>        // ROOT_TGeoManager
44 #include <TVector2.h>           // ROOT_TVector2
45 #include <TArrayD.h>            // ROOT_TArrayD
46
47 //====================================================================
48 ClassImp(AliFMDGeometryBuilder)
49 #if 0
50   ; // This is here to keep Emacs for indenting the next line
51 #endif
52
53 //____________________________________________________________________
54 const Char_t* AliFMDGeometryBuilder::fgkActiveName      = "F%cAC";
55 const Char_t* AliFMDGeometryBuilder::fgkSectorName      = "F%cSC";
56 const Char_t* AliFMDGeometryBuilder::fgkStripName       = "F%cST";
57 const Char_t* AliFMDGeometryBuilder::fgkSensorName      = "F%cSE";
58 const Char_t* AliFMDGeometryBuilder::fgkPCBName         = "F%cPB";
59 const Char_t* AliFMDGeometryBuilder::fgkCuName          = "F%cCU";
60 const Char_t* AliFMDGeometryBuilder::fgkChipName        = "F%cCH";
61 const Char_t* AliFMDGeometryBuilder::fgkLongLegName     = "F%cLL";
62 const Char_t* AliFMDGeometryBuilder::fgkShortLegName    = "F%cSL";
63 const Char_t* AliFMDGeometryBuilder::fgkFrontVName      = "F%cFH";
64 const Char_t* AliFMDGeometryBuilder::fgkBackVName       = "F%cBH";
65 const Char_t* AliFMDGeometryBuilder::fgkRingTopName     = "F%cTV";
66 const Char_t* AliFMDGeometryBuilder::fgkRingBotName     = "F%cBV";
67 const Char_t* AliFMDGeometryBuilder::fgkHCName          = "F%dH%c";
68 const Char_t* AliFMDGeometryBuilder::fgkIHCName         = "F%dI%c";
69 const Char_t* AliFMDGeometryBuilder::fgkNoseName        = "F3SN";
70 const Char_t* AliFMDGeometryBuilder::fgkBackName        = "F3SB";
71 const Char_t* AliFMDGeometryBuilder::fgkBeamName        = "F3SL";
72 const Char_t* AliFMDGeometryBuilder::fgkFlangeName      = "F3SF";
73 const Char_t* AliFMDGeometryBuilder::fgkFMDName         = "F%dM%c";
74
75 //____________________________________________________________________
76 AliFMDGeometryBuilder::AliFMDGeometryBuilder() 
77   : fDetailed(kTRUE),
78     fUseAssembly(kTRUE),
79     fSi(0),
80     fC(0),
81     fAl(0),
82     fPCB(0),
83     fChip(0),
84     fPlastic(0)
85 {
86   // Default constructor
87   fActiveId.Set(2);
88 }
89
90 //____________________________________________________________________
91 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
92   : TTask("FMD", "Geometry builder"),
93     fDetailed(detailed),
94     fUseAssembly(kTRUE),
95     fSi(0),
96     fC(0),
97     fAl(0),
98     fPCB(0),
99     fChip(0),
100     fPlastic(0)
101 {
102   // Normal constructor
103   // 
104   // Parameters: 
105   // 
106   //      fmd           Pointer to AliFMD object 
107   //      detailed      Whether to make a detailed simulation or not 
108   // 
109   fActiveId.Set(2);
110 }
111
112
113 //____________________________________________________________________
114 TGeoVolume*
115 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) 
116 {
117   // Setup the geometry of a ring.    The defined TGeoVolume is
118   // returned, and should be used when setting up the rest of the
119   // volumes. 
120   // 
121   // 
122   // Parameters:
123   //
124   //     r              Pointer to ring geometry object 
125   // 
126   // Returns:
127   //    pointer to ring volume 
128   //
129   if (!r) { 
130     AliError("Didn't get a ring object");
131     return 0;
132   }
133   Char_t      id       = r->GetId();
134   Double_t    siThick  = r->GetSiThickness();
135   const Int_t nv       = r->GetNVerticies();
136   TVector2*   a        = r->GetVertex(5);
137   TVector2*   b        = r->GetVertex(3);
138   TVector2*   c        = r->GetVertex(4);
139   Double_t    theta    = r->GetTheta();
140   Double_t    off      = (TMath::Tan(TMath::Pi() * theta / 180) 
141                           * r->GetBondingWidth());
142   Double_t    rmax     = b->Mod();
143   Double_t    rmin     = r->GetLowR();
144   Double_t    pcbThick = r->GetPrintboardThickness();
145   Double_t    cuThick  = r->GetCopperThickness();
146   Double_t    chipThick= r->GetChipThickness();
147   Double_t    modSpace = r->GetModuleSpacing();
148   Double_t    legr     = r->GetLegRadius();
149   Double_t    legl     = r->GetLegLength();
150   Double_t    legoff   = r->GetLegOffset();
151   Int_t       ns       = r->GetNStrips();
152   Double_t    stripoff = a->Mod();
153   Double_t    dstrip   = (rmax - stripoff) / ns;
154   Double_t    space    = r->GetSpacing();
155   TArrayD xs(nv);
156   TArrayD ys(nv);
157   for (Int_t i = 0; i < nv; i++) {
158     // Reverse the order 
159     TVector2* vv = r->GetVertex(nv - 1 - i);
160     if (!vv) {
161       AliError(Form("Failed to get vertex # %d", nv - 1 - i));
162       continue;
163     }
164     xs[i] = vv->X();
165     ys[i] = vv->Y();
166   }
167   
168   // Shape of actual sensor 
169   TGeoXtru* sensorShape = new TGeoXtru(2);
170   sensorShape->DefinePolygon(nv, xs.fArray, ys.fArray);
171   sensorShape->DefineSection(0, - siThick/2);
172   sensorShape->DefineSection(1, siThick/2);
173   TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id), 
174                                             sensorShape, fSi);
175   sensorVolume->VisibleDaughters(kFALSE);
176   Int_t sid = sensorVolume->GetNumber();
177   fSectorOff   = -1;
178   fModuleOff   = 1;
179   fRingOff     = 2;
180   fDetectorOff = 3;
181   if (fDetailed) {
182     fSectorOff   = 1;
183     fModuleOff   = 3;
184     fRingOff     = 4;
185     fDetectorOff = 5;
186     // Virtual volume shape to divide - This volume is only defined if
187     // the geometry is set to be detailed. 
188     TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2, 
189                                                - theta, theta);
190     TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
191                                               activeShape,fSi);
192     TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), 
193                                                       2, 2, -theta,0,0,"N");
194     TGeoVolume* stripVolume  = sectorVolume->Divide(Form(fgkStripName, id), 
195                                                     1, ns, stripoff, dstrip, 
196                                                     0, "SX");
197     sid = stripVolume->GetNumber();
198     sensorVolume->AddNodeOverlap(activeVolume, 0);
199   }
200   
201   switch (id) {
202   case 'i': case 'I': fActiveId[0] = sid; break;
203   case 'o': case 'O': fActiveId[1] = sid; break;
204   }
205
206   // Shape of Printed circuit Board 
207   for (Int_t i = 0;      i < nv / 2; i++) ys[i] -= off;
208   for (Int_t i = nv / 2; i < nv;     i++) ys[i] += off;
209   TGeoXtru* pcbShape         = new TGeoXtru(2);
210   pcbShape->DefinePolygon(nv, xs.fArray, ys.fArray);
211   pcbShape->DefineSection(0, - pcbThick/2);
212   pcbShape->DefineSection(1, pcbThick/2);
213   TGeoVolume* pcbVolume      = new TGeoVolume(Form(fgkPCBName, id), 
214                                               pcbShape, fPCB);
215
216   // Copper layer
217   TGeoXtru* cuShape       = new TGeoXtru(2);
218   cuShape->DefinePolygon(6, xs.fArray, ys.fArray);
219   cuShape->DefineSection(0, - cuThick/2);
220   cuShape->DefineSection(1, cuThick/2);
221   TGeoVolume* cuVolume    = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper);
222
223   // Chip layer
224   TGeoXtru*   chipShape   = new TGeoXtru(2);
225   chipShape->DefinePolygon(6, xs.fArray, ys.fArray);
226   chipShape->DefineSection(0, - chipThick/2);
227   chipShape->DefineSection(1, chipThick/2);
228   TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id),
229                                           chipShape,fChip);
230
231   // Short leg shape 
232   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, legl / 2);
233   TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), 
234                                               shortLegShape, fPlastic);
235
236   // Long leg shape
237   TGeoTube*   longLegShape   = new TGeoTube(0, legr, (legl + modSpace) / 2);
238   TGeoVolume* longLegVolume  = new TGeoVolume(Form(fgkLongLegName, id), 
239                                               longLegShape, fPlastic);
240   
241   
242   // Back container volume 
243   TGeoVolume* backVolume     = new TGeoVolumeAssembly(Form(fgkBackVName, id));
244   Double_t x = 0;
245   Double_t y = 0;
246   Double_t z = pcbThick / 2;
247   backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
248   z          += (pcbThick + cuThick) / 2;
249   backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
250   z          += (cuThick + chipThick) / 2;
251   backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
252   x          =  a->X() + legoff + legr;
253   y          =  0;
254   z          += pcbThick / 2 + legl / 2;
255   backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z));
256   x          =  c->X();
257   y          =  c->Y() - legoff - legr - off;
258   backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z));
259   y          =  -y;
260   backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z));
261
262   // Front container volume 
263   TGeoVolume* frontVolume    = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
264   x         =  0;
265   y         =  0;
266   z         =  pcbThick / 2;
267   frontVolume->AddNode(pcbVolume, 1, new TGeoTranslation(x,y,z));
268   z          += (pcbThick + cuThick) / 2;
269   frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
270   z          += (cuThick + chipThick) / 2;
271   frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
272   x         =  a->X() + legoff + legr;
273   y         =  0;
274   z         += pcbThick / 2 + (legl + modSpace)/ 2;
275   frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z));
276   x         =  c->X();
277   y         =  c->Y() - legoff - legr - off;
278   frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z));
279   y         =  -y;
280   frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z));
281   
282   // Half ring mother volumes. 
283   TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
284   TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
285   TGeoVolume* halfRing      = ringTopVolume;
286
287   // Adding modules to half-rings
288   Int_t    nmod =  r->GetNModules();
289   AliDebug(10, Form("making %d modules in ring %c", nmod, id));
290   for (Int_t i = 0; i < nmod; i++) {
291     if (i == nmod / 2) halfRing = ringBotVolume;
292     Bool_t      front =  (i % 2 == 0);
293     Double_t    z1    =  siThick / 2 + (i % 2) * modSpace;
294     Double_t    z2    =  z1 + siThick / 2 + space;
295     Double_t    th    =  (2 * i + 1) * theta;
296     TGeoVolume* vol   =  (front ? frontVolume : backVolume);
297     AliDebug(20, Form("Placing copy %d of %s and %s in %s at z=%f and %f, "
298                       "and theta=%f", i, sensorVolume->GetName(), 
299                       vol->GetName(), halfRing->GetName(), z1, z2, th));
300     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
301     mat1->RotateZ(th);
302     halfRing->AddNode(sensorVolume, i, mat1);
303     TGeoMatrix* mat2  =  new TGeoCombiTrans(0,0,z2,0); 
304     mat2->RotateZ(th);
305     halfRing->AddNode(vol, i, mat2);
306   }
307
308   return 0;
309 }
310
311 //____________________________________________________________________
312 TGeoVolume*
313 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, 
314                                         TGeoVolume* topMother, 
315                                         TGeoVolume* botMother, 
316                                         Double_t    zMother, 
317                                         TGeoVolume* innerTop, 
318                                         TGeoVolume* innerBot, 
319                                         TGeoVolume* outerTop, 
320                                         TGeoVolume* outerBot) 
321 {
322   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
323   // This includes putting the Honeycomb support plates and the rings
324   // into the mother volumes.   
325   // 
326   // Parameeters:
327   //    d         The detector geometry to use 
328   //    mother    The mother volume of the detector 
329   //    zmother   The midpoint in global coordinates of detector vol.
330   //    inner     Pointer to inner ring volume 
331   //    outer     Pointer to outer ring volume
332   //
333   // Returns:
334   //    Pointer to mother (detector volume) 
335   // 
336   if (!d) return 0;
337   // Loop over the defined rings 
338   for (int i = 0; i < 2; i++) {
339     AliFMDRing* r     = 0;
340     Double_t    lowr  = 0;
341     Double_t    highr = 0;
342     Double_t    rz    = 0;
343     TGeoVolume* tvol  = 0;
344     TGeoVolume* bvol  = 0;
345     switch (i) {
346     case 0: 
347       r      = d->GetInner();
348       lowr   = d->GetInnerHoneyLowR();
349       highr  = d->GetInnerHoneyHighR();
350       rz     = d->GetInnerZ();
351       tvol   = innerTop;
352       bvol   = innerBot;
353       break;
354     case 1: 
355       r      = d->GetOuter();
356       lowr   = d->GetOuterHoneyLowR();
357       highr  = d->GetOuterHoneyHighR();
358       rz     = d->GetOuterZ();
359       tvol   = outerTop;
360       bvol   = outerBot;
361       break;
362     }
363     if (!r) continue;
364     Char_t   c       = r->GetId();
365     Int_t    id      = d->GetId();
366     Double_t hcThick = d->GetHoneycombThickness();
367     Double_t alThick = d->GetAlThickness();
368     Double_t z       = TMath::Abs(rz - zMother);
369
370     // Place ring in mother volume
371     // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
372     AliDebug(5, Form("Placing volumes %s and %s in %s and %s at z=%f", 
373                      tvol->GetName(), bvol->GetName(), 
374                      topMother->GetName(), botMother->GetName(), z));
375     topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
376     botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
377
378     // Top of Honeycomb
379     TGeoTubeSeg* hcSha = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180);
380     TGeoVolume*  hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
381     // Air in top of honeycomb
382     TGeoTubeSeg* ihcSha = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
383                                              (hcThick-alThick)/2, 0, 180);
384     TGeoVolume*  ihcVol = new TGeoVolume(Form(fgkIHCName,id,c),ihcSha,fAir);
385     hcVol->AddNode(ihcVol, 0);
386     hcVol->VisibleDaughters(kFALSE);    
387     hcVol->SetVisibility(kTRUE);
388
389     z += (r->GetSiThickness() + 
390           r->GetSpacing() + 
391           r->GetPrintboardThickness() + 
392           r->GetCopperThickness() + 
393           r->GetChipThickness() + 
394           r->GetModuleSpacing() +
395           r->GetLegLength() + 
396           hcThick / 2); 
397
398     AliDebug(15, Form("Placing a copy of %s in %s and %s at z=%f", 
399                       hcVol->GetName(), topMother->GetName(), 
400                       botMother->GetName(), z));
401     // Add to top 
402     topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
403
404     // Add to bottom
405     TGeoMatrix*   bhcMatrix = new TGeoCombiTrans(0,0,z,0);
406     bhcMatrix->RotateZ(180);
407     botMother->AddNode(hcVol, 1, bhcMatrix);
408   }
409   return 0;
410 }
411
412 //____________________________________________________________________
413 TGeoVolume*
414 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, 
415                                     TGeoVolume* innerTop, 
416                                     TGeoVolume* innerBot) 
417 {
418   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
419   // special support as it is at the momement. 
420   // 
421   // See also AliFMDGeometryBuilder::DetectorGeometry 
422   // 
423   if (!fmd1 || !innerTop || !innerBot) return 0;
424   Double_t    z             = fmd1->GetInnerZ();  
425   TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
426                                                           fmd1->GetId(), 'T'));
427   TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
428                                                           fmd1->GetId(), 'B'));
429   
430   // Basic detector geometry 
431   DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, 
432                    innerTop, innerBot, 0, 0);
433
434   // Must add this after filling the assembly.
435   TGeoVolume* top    = gGeoManager->GetVolume("ALIC");
436   TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
437   AliDebug(5, Form("Placing volumes %s and %s in ALIC at z=%f", 
438                    fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
439   top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
440   top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
441
442   return 0;
443 }
444
445 //____________________________________________________________________
446 TGeoVolume*
447 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, 
448                                     TGeoVolume* innerTop, 
449                                     TGeoVolume* innerBot, 
450                                     TGeoVolume* outerTop,
451                                     TGeoVolume* outerBot) 
452 {
453   // Setup the FMD2 geometry.  The FMD2 has no
454   // special support as it is at the momement. 
455   // 
456   // See also AliFMDGeometryBuilder::DetectorGeometry 
457   // 
458   if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
459   Double_t z                = fmd2->GetOuterZ();
460   TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
461                                                           fmd2->GetId(), 'T'));
462   TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
463                                                           fmd2->GetId(), 'B'));
464   
465   DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, 
466                    innerTop, innerBot, outerTop, outerBot);
467
468   // Must be done after filling the assemblies 
469   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
470   TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
471   AliDebug(5, Form("Placing volumes %s and %s in ALIC at z=%f", 
472                    fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
473   top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
474   top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
475
476   return 0;
477 }
478   
479 //____________________________________________________________________
480 TGeoVolume*
481 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
482                                     TGeoVolume* innerTop, 
483                                     TGeoVolume* innerBot, 
484                                     TGeoVolume* outerTop,
485                                     TGeoVolume* outerBot) 
486 {
487   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
488   // structure, as the support will also support the vacuum
489   // beam-pipe. 
490   // 
491   // See also AliFMDGeometryBuilder::DetectorGeometry 
492   // 
493   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
494   Double_t nlen    = fmd3->GetNoseLength();
495   Double_t nz      = fmd3->GetNoseZ();
496   Double_t noser1  = fmd3->GetNoseLowR();
497   Double_t noser2  = fmd3->GetNoseHighR();
498   Double_t conel   = fmd3->GetConeLength();
499   Double_t backl   = fmd3->GetBackLength();
500   Double_t backr1  = fmd3->GetBackLowR();
501   Double_t backr2  = fmd3->GetBackHighR();
502   Double_t zdist   = conel -  backl - nlen;
503   Double_t tdist   = backr2 - noser2;
504   Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
505   Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
506   Double_t flanger = fmd3->GetFlangeR();
507   Double_t z       = fmd3->GetInnerZ(); // fmd3->GetZ();
508   Double_t zi;
509
510   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
511                                                           fmd3->GetId(), 'T'));
512   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
513                                                           fmd3->GetId(), 'B'));
514
515   
516   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z, 
517                    innerTop, innerBot, outerTop, outerBot);
518
519
520   // Nose volume 
521   TGeoTubeSeg* noseShape = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180);
522   TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
523   zi                     = -nz + nlen / 2 + z;
524
525   fmd3TopVolume->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, zi));
526   TGeoMatrix* nmatrix    = new TGeoCombiTrans(0, 0, zi, 0); 
527   nmatrix->RotateZ(180);
528   fmd3BotVolume->AddNode(noseVolume, 1, nmatrix);
529   
530   // Back
531   TGeoTubeSeg* backShape = new TGeoTubeSeg(backr1, backr2, backl / 2, 0, 180);
532   TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC);
533   zi                     = -nz + conel - backl / 2 + z;
534   fmd3TopVolume->AddNode(backVolume, 0, new TGeoTranslation(0, 0, zi));
535   TGeoMatrix* bmatrix    = new TGeoCombiTrans(0, 0, zi, 0);
536   bmatrix->RotateZ(180);
537   fmd3BotVolume->AddNode(backVolume, 1, bmatrix);
538   
539   
540   Int_t n;
541   Double_t r;
542   // The flanges 
543   TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, 
544                                        fmd3->GetBeamWidth() / 2,
545                                        backl / 2);
546   TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC);
547   n                        = fmd3->GetNFlange();
548   r                        = backr2 + (flanger - backr2) / 2;
549   TGeoVolume* mother       = fmd3TopVolume;
550   for (Int_t i = 0; i  < n; i++) {
551     if (i >= n / 2) mother = fmd3BotVolume;
552     Double_t phi       = 360. / n * i + 180. / n;
553     Double_t x         = r * TMath::Cos(TMath::Pi() / 180 * phi);
554     Double_t y         = r * TMath::Sin(TMath::Pi() / 180 * phi);
555     AliDebug(15, Form("Placing flange %d in %s at (%f,%f,%f) r=%f, phi=%f", 
556                       i, mother->GetName(), x, y, zi, r, phi));
557     TGeoRotation* rot    = new TGeoRotation;
558     rot->RotateZ(phi);
559     TGeoMatrix* matrix = new TGeoCombiTrans(x, y, zi, rot);
560     mother->AddNode(flangeVolume, i, matrix);
561   }
562
563   // The Beams 
564   TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, 
565                                      fmd3->GetBeamWidth() / 2 - .1,
566                                      beaml / 2);
567   TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC);
568   n                      = fmd3->GetNBeam();
569   r                      = noser2 + tdist / 2;
570   zi                     = - nz + nlen + zdist / 2 + z;
571   mother                 = fmd3TopVolume;
572   for (Int_t i = 0; i  < n; i++) {
573     if (i >= n / 2) mother = fmd3BotVolume;
574     Double_t phi      = 360. / n * i;
575     Double_t x        = r * TMath::Cos(TMath::Pi() / 180 * phi);
576     Double_t y        = r * TMath::Sin(TMath::Pi() / 180 * phi);
577     TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i));
578     // Order is important
579     rot->RotateY(-theta);
580     rot->RotateZ(phi);
581     TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam trans %d", i),
582                                             x, y, zi, rot);
583     mother->AddNode(beamVolume, i, matrix);    
584   }
585   
586   z = fmd3->GetInnerZ();
587   TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
588   rot->RotateY(180);
589   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
590   TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
591   AliDebug(5, Form("Placing volumes %s and %s in ALIC at z=%f", 
592                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
593   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
594   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
595
596   return 0;
597 }
598
599 //____________________________________________________________________
600 void
601 AliFMDGeometryBuilder::Exec(Option_t*) 
602 {
603   // Setup up the FMD geometry. 
604   AliDebug(1,  Form("\tGeometry options: %s",
605                     (fDetailed  ? "divided into strips" : "one volume")));
606   if (!gGeoManager) {
607     AliFatal("No TGeoManager defined");
608     return;
609   }
610
611   fSi      = gGeoManager->GetMedium("FMD_Si$");
612   fC       = gGeoManager->GetMedium("FMD_Carbon$");
613   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
614   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
615   fAir     = gGeoManager->GetMedium("FMD_Air$");
616   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
617   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
618   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
619
620   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper) {
621     AliError("Failed to get some or all tracking mediums");
622     return;
623   }    
624   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
625   AliFMDRing* inner = fmd->GetInner();
626   AliFMDRing* outer = fmd->GetOuter();
627   RingGeometry(inner);
628   RingGeometry(outer);
629   TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
630                                                      inner->GetId()));
631   TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
632                                                      inner->GetId()));
633   TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
634                                                      outer->GetId()));
635   TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
636                                                      outer->GetId()));
637   
638   FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
639   FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
640   FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
641 #ifndef USE_PRE_MOVE
642   fmd->SetSectorOff(fSectorOff);
643   fmd->SetModuleOff(fModuleOff);
644   fmd->SetRingOff(fRingOff);
645   fmd->SetDetectorOff(fDetectorOff);
646   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
647 #endif
648   // fmd->ExtractGeomInfo();
649   
650 }
651
652
653 //____________________________________________________________________
654 //
655 // EOF
656 //