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