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