]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDGeometryBuilder.cxx
Rotated FMD1 half-rings 90 degrees, so that the 3 sensors on long legs
[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   TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
465   rot->RotateZ(90);
466   TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
467   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
468                    fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
469   top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
470   top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
471
472   return 0;
473 }
474
475 //____________________________________________________________________
476 TGeoVolume*
477 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, 
478                                     TGeoVolume* innerTop, 
479                                     TGeoVolume* innerBot, 
480                                     TGeoVolume* outerTop,
481                                     TGeoVolume* outerBot) 
482 {
483   // Setup the FMD2 geometry.  The FMD2 has no
484   // special support as it is at the momement. 
485   // 
486   // See also AliFMDGeometryBuilder::DetectorGeometry 
487   // 
488   if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
489   Double_t z                = fmd2->GetOuterZ();
490   TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
491                                                           fmd2->GetId(), 'T'));
492   TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
493                                                           fmd2->GetId(), 'B'));
494   
495   DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, 
496                    innerTop, innerBot, outerTop, outerBot);
497
498   // Must be done after filling the assemblies 
499   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
500   TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
501   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
502                    fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
503   top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
504   top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
505
506   return 0;
507 }
508   
509 //____________________________________________________________________
510 TGeoVolume*
511 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
512                                     TGeoVolume* innerTop, 
513                                     TGeoVolume* innerBot, 
514                                     TGeoVolume* outerTop,
515                                     TGeoVolume* outerBot) 
516 {
517   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
518   // structure, as the support will also support the vacuum
519   // beam-pipe. 
520   // 
521   // See also AliFMDGeometryBuilder::DetectorGeometry 
522   // 
523   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
524   Double_t nlen    = fmd3->GetNoseLength();
525   Double_t nz      = fmd3->GetNoseZ();
526   Double_t noser1  = fmd3->GetNoseLowR();
527   Double_t noser2  = fmd3->GetNoseHighR();
528   Double_t conel   = fmd3->GetConeLength();
529   Double_t backl   = fmd3->GetBackLength();
530   Double_t backr1  = fmd3->GetBackLowR();
531   Double_t backr2  = fmd3->GetBackHighR();
532   Double_t zdist   = conel -  backl - nlen;
533   Double_t tdist   = backr2 - noser2;
534   Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
535   Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
536   Double_t flanger = fmd3->GetFlangeR();
537   Double_t z       = fmd3->GetInnerZ(); // fmd3->GetZ();
538   Double_t zi;
539
540   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
541                                                           fmd3->GetId(), 'T'));
542   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
543                                                           fmd3->GetId(), 'B'));
544
545   
546   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z, 
547                    innerTop, innerBot, outerTop, outerBot);
548
549
550   // Nose volume 
551   TGeoTubeSeg* noseShape = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180);
552   TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
553   zi                     = -nz + nlen / 2 + z;
554
555   fmd3TopVolume->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, zi));
556   TGeoMatrix* nmatrix    = new TGeoCombiTrans(0, 0, zi, 0); 
557   nmatrix->RotateZ(180);
558   fmd3BotVolume->AddNode(noseVolume, 1, nmatrix);
559   
560   // Back
561   TGeoTubeSeg* backShape = new TGeoTubeSeg(backr1, backr2, backl / 2, 0, 180);
562   TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC);
563   zi                     = -nz + conel - backl / 2 + z;
564   fmd3TopVolume->AddNode(backVolume, 0, new TGeoTranslation(0, 0, zi));
565   TGeoMatrix* bmatrix    = new TGeoCombiTrans(0, 0, zi, 0);
566   bmatrix->RotateZ(180);
567   fmd3BotVolume->AddNode(backVolume, 1, bmatrix);
568   
569   
570   Int_t n;
571   Double_t r;
572   // The flanges 
573   TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, 
574                                        fmd3->GetBeamWidth() / 2,
575                                        backl / 2);
576   TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC);
577   n                        = fmd3->GetNFlange();
578   r                        = backr2 + (flanger - backr2) / 2;
579   TGeoVolume* mother       = fmd3TopVolume;
580   for (Int_t i = 0; i  < n; i++) {
581     if (i >= n / 2) mother = fmd3BotVolume;
582     Double_t phi       = 360. / n * i + 180. / n;
583     Double_t x         = r * TMath::Cos(TMath::Pi() / 180 * phi);
584     Double_t y         = r * TMath::Sin(TMath::Pi() / 180 * phi);
585     AliFMDDebug(15, ("Placing flange %d in %s at (%f,%f,%f) r=%f, phi=%f", 
586                       i, mother->GetName(), x, y, zi, r, phi));
587     TGeoRotation* rot    = new TGeoRotation;
588     rot->RotateZ(phi);
589     TGeoMatrix* matrix = new TGeoCombiTrans(x, y, zi, rot);
590     mother->AddNode(flangeVolume, i, matrix);
591   }
592
593   // The Beams 
594   TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, 
595                                      fmd3->GetBeamWidth() / 2 - .1,
596                                      beaml / 2);
597   TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC);
598   n                      = fmd3->GetNBeam();
599   r                      = noser2 + tdist / 2;
600   zi                     = - nz + nlen + zdist / 2 + z;
601   mother                 = fmd3TopVolume;
602   for (Int_t i = 0; i  < n; i++) {
603     if (i >= n / 2) mother = fmd3BotVolume;
604     Double_t phi      = 360. / n * i;
605     Double_t x        = r * TMath::Cos(TMath::Pi() / 180 * phi);
606     Double_t y        = r * TMath::Sin(TMath::Pi() / 180 * phi);
607     TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i));
608     // Order is important
609     rot->RotateY(-theta);
610     rot->RotateZ(phi);
611     TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam trans %d", i),
612                                             x, y, zi, rot);
613     mother->AddNode(beamVolume, i, matrix);    
614   }
615   
616   z = fmd3->GetInnerZ();
617   TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
618   rot->RotateY(180);
619   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
620   TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
621   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
622                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
623   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
624   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
625
626   return 0;
627 }
628
629 //____________________________________________________________________
630 void
631 AliFMDGeometryBuilder::Exec(Option_t*) 
632 {
633   // Setup up the FMD geometry. 
634   AliFMDDebug(1, ("\tGeometry options: %s",
635                     (fDetailed  ? "divided into strips" : "one volume")));
636   if (!gGeoManager) {
637     AliFatal("No TGeoManager defined");
638     return;
639   }
640
641   fSi      = gGeoManager->GetMedium("FMD_Si$");
642   fC       = gGeoManager->GetMedium("FMD_Carbon$");
643   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
644   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
645   fAir     = gGeoManager->GetMedium("FMD_Air$");
646   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
647   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
648   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
649
650   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper) {
651     AliError("Failed to get some or all tracking mediums");
652     return;
653   }    
654   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
655   AliFMDRing* inner = fmd->GetInner();
656   AliFMDRing* outer = fmd->GetOuter();
657   RingGeometry(inner);
658   RingGeometry(outer);
659   TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
660                                                      inner->GetId()));
661   TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
662                                                      inner->GetId()));
663   TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
664                                                      outer->GetId()));
665   TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
666                                                      outer->GetId()));
667   
668   FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
669   FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
670   FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
671 #ifndef USE_PRE_MOVE
672   fmd->SetSectorOff(fSectorOff);
673   fmd->SetModuleOff(fModuleOff);
674   fmd->SetRingOff(fRingOff);
675   fmd->SetDetectorOff(fDetectorOff);
676   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
677 #endif
678   // fmd->ExtractGeomInfo();
679   
680 }
681
682
683 //____________________________________________________________________
684 //
685 // EOF
686 //