]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDGeometryBuilder.cxx
Put middle plane of FMD1 to z = 320 cm.
[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 <TGeoTrd1.h>           // ROOT_TGeoTrd1
40 #include <TGeoCone.h>           // ROOT_TGeoTrd1
41 #include <TGeoVolume.h>         // ROOT_TGeoVolume
42 #include <TGeoXtru.h>           // ROOT_TGeoXtru
43 #include <TGeoCompositeShape.h>
44 #include <TMath.h>
45 #include <TVector2.h>           // ROOT_TVector2
46 //#include <TGeoMaterial.h>     // ROOT_TGeoMaterial
47 //#include <TGeoMedium.h>               // ROOT_TGeoMedium
48 //#include <TGeoPcon.h>         // ROOT_TGeoPcon
49 //#include <TGeoPolygon.h>      // ROOT_TGeoPolygon
50
51 #include "AliFMDGeometryBuilder.h"      // ALIFMDGEOSIMULATOR_H
52 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
53 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
54 #include "AliFMDRing.h"         // ALIFMDRING_H
55 #include "AliFMD1.h"            // ALIFMD1_H
56 #include "AliFMD2.h"            // ALIFMD2_H
57 #include "AliFMD3.h"            // ALIFMD3_H
58 // #include "AliFMD.h"          // ALIFMD_H
59 #include "AliFMDDebug.h"                // ALILOG_H
60
61 //====================================================================
62 ClassImp(AliFMDGeometryBuilder)
63 #if 0
64   ; // This is here to keep Emacs for indenting the next line
65 #endif
66
67 //____________________________________________________________________
68 const Char_t* AliFMDGeometryBuilder::fgkActiveName      = "F%cAC";
69 const Char_t* AliFMDGeometryBuilder::fgkSectorName      = "F%cSC";
70 const Char_t* AliFMDGeometryBuilder::fgkStripName       = "F%cST";
71 const Char_t* AliFMDGeometryBuilder::fgkSensorName      = "F%cSE";
72 const Char_t* AliFMDGeometryBuilder::fgkPCBName         = "F%cPB";
73 const Char_t* AliFMDGeometryBuilder::fgkCuName          = "F%cCU";
74 const Char_t* AliFMDGeometryBuilder::fgkChipName        = "F%cCH";
75 const Char_t* AliFMDGeometryBuilder::fgkLongLegName     = "F%cLL";
76 const Char_t* AliFMDGeometryBuilder::fgkShortLegName    = "F%cSL";
77 const Char_t* AliFMDGeometryBuilder::fgkFrontVName      = "F%cFH";
78 const Char_t* AliFMDGeometryBuilder::fgkBackVName       = "F%cBH";
79 const Char_t* AliFMDGeometryBuilder::fgkRingTopName     = "F%cTV";
80 const Char_t* AliFMDGeometryBuilder::fgkRingBotName     = "F%cBV";
81 const Char_t* AliFMDGeometryBuilder::fgkHCName          = "F%dH%c";
82 const Char_t* AliFMDGeometryBuilder::fgkIHCName         = "F%dI%c";
83 const Char_t* AliFMDGeometryBuilder::fgkNoseName        = "F3SN";
84 const Char_t* AliFMDGeometryBuilder::fgkBackName        = "F%dSB";
85 const Char_t* AliFMDGeometryBuilder::fgkTopName         = "F%dSU";
86 const Char_t* AliFMDGeometryBuilder::fgkBeamName        = "F%dSL";
87 const Char_t* AliFMDGeometryBuilder::fgkFlangeName      = "F%dSF";
88 const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName      = "F%cDC";
89 const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName     = "F%cDP";
90 const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName    = "F%cDI";
91 const Char_t* AliFMDGeometryBuilder::fgkFMDDName        = "F%cDD";
92 const Char_t* AliFMDGeometryBuilder::fgkFMDName         = "F%dM%c";
93
94 //____________________________________________________________________
95 AliFMDGeometryBuilder::AliFMDGeometryBuilder() 
96   : TTask("FMD", "Geomtry builder"),
97     fActiveId(0),
98     fDetailed(kTRUE),
99     fUseAssembly(kTRUE),
100     fSectorOff(0),
101     fModuleOff(0),
102     fRingOff(0),
103     fDetectorOff(0),
104     fSi(0),
105     fC(0),
106     fAl(0),
107     fPCB(0),
108     fChip(0),
109     fAir(0),
110     fPlastic(0),
111     fCopper(0),
112     fSteel(0)
113 {
114   // Default constructor
115   fActiveId.Set(2);
116 }
117
118 //____________________________________________________________________
119 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
120   : TTask("FMD", "Geometry builder"),
121     fActiveId(0),
122     fDetailed(detailed),
123     fUseAssembly(kTRUE),
124     fSectorOff(0),
125     fModuleOff(0),
126     fRingOff(0),
127     fDetectorOff(0),
128     fSi(0),
129     fC(0),
130     fAl(0),
131     fPCB(0),
132     fChip(0),
133     fAir(0),
134     fPlastic(0),
135     fCopper(0),
136     fSteel(0)
137 {
138   // Normal constructor
139   // 
140   // Parameters: 
141   // 
142   //      fmd           Pointer to AliFMD object 
143   //      detailed      Whether to make a detailed simulation or not 
144   // 
145   fActiveId.Set(2);
146 }
147
148
149 //____________________________________________________________________
150 TGeoVolume*
151 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) 
152 {
153   // Setup the geometry of a ring.    The defined TGeoVolume is
154   // returned, and should be used when setting up the rest of the
155   // volumes. 
156   // 
157   // 
158   // Parameters:
159   //
160   //     r              Pointer to ring geometry object 
161   // 
162   // Returns:
163   //    pointer to ring volume 
164   //
165   if (!r) { 
166     AliError("Didn't get a ring object");
167     return 0;
168   }
169   Char_t        id       = r->GetId();
170   const Char_t* lName    = (id == 'i' || id == 'I' ? "inner" : "outer");
171   Double_t      siThick  = r->GetSiThickness();
172   const Int_t   knv      = r->GetNVerticies();
173   TVector2*     a        = r->GetVertex(5);
174   TVector2*     b        = r->GetVertex(3);
175   TVector2*     c        = r->GetVertex(4);
176   Double_t      theta    = r->GetTheta();
177   Double_t      off      = (TMath::Tan(TMath::Pi() * theta / 180) 
178                             * r->GetBondingWidth());
179   Double_t      rmax     = b->Mod();
180   Double_t      rmin     = r->GetLowR();
181   Double_t      pcbThick = r->GetPrintboardThickness();
182   Double_t      cuThick  = r->GetCopperThickness();
183   Double_t      chipThick= r->GetChipThickness();
184   Double_t      modSpace = r->GetModuleSpacing();
185   Double_t      legr     = r->GetLegRadius();
186   Double_t      legl     = r->GetLegLength();
187   Double_t      legoff   = r->GetLegOffset();
188   Int_t         ns       = r->GetNStrips();
189   Double_t      stripoff = a->Mod();
190   Double_t      dstrip   = (rmax - stripoff) / ns;
191   Double_t      space    = r->GetSpacing();
192   TArrayD       xs(knv);
193   TArrayD       ys(knv);
194   for (Int_t i = 0; i < knv; i++) {
195     // Reverse the order 
196     TVector2* vv = r->GetVertex(knv - 1 - i);
197     if (!vv) {
198       AliError(Form("Failed to get vertex # %d", knv - 1 - i));
199       continue;
200     }
201     xs[i] = vv->X();
202     ys[i] = vv->Y();
203   }
204   
205   // Shape of actual sensor 
206   TGeoXtru* sensorShape = new TGeoXtru(2);
207   sensorShape->DefinePolygon(knv, xs.fArray, ys.fArray);
208   sensorShape->DefineSection(0, - siThick/2);
209   sensorShape->DefineSection(1, siThick/2);
210   sensorShape->SetName(Form(fgkSensorName, id));
211   sensorShape->SetTitle(Form("FMD %s Sensor", lName));
212   TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id), 
213                                             sensorShape, fSi);
214   sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
215   sensorVolume->VisibleDaughters(kFALSE);
216   Int_t sid = sensorVolume->GetNumber();
217   fSectorOff   = -1;
218   fModuleOff   = 1;
219   fRingOff     = 2;
220   fDetectorOff = 3;
221   if (fDetailed) {
222     fSectorOff   = 1;
223     fModuleOff   = 4;
224     fRingOff     = 5;
225     fDetectorOff = 6;
226     // Virtual volume shape to divide - This volume is only defined if
227     // the geometry is set to be detailed. 
228     TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2, 
229                                                - theta, theta);
230     activeShape->SetName(Form(fgkActiveName, id));
231     activeShape->SetTitle(Form("FMD %s active area", lName));
232     TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
233                                               activeShape,fSi);
234     activeVolume->SetTitle(Form("FMD %s active area", lName));
235     TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), 
236                                                       2, 2, -theta,0,0,"N");
237     sectorVolume->SetTitle(Form("FMD %s sector", lName));
238     TGeoVolume* stripVolume  = sectorVolume->Divide(Form(fgkStripName, id), 
239                                                     1, ns, stripoff, dstrip, 
240                                                     0, "SX");
241     stripVolume->SetTitle(Form("FMD %s strip", lName));
242     sid = stripVolume->GetNumber();
243     sensorVolume->AddNodeOverlap(activeVolume, 0);
244   }
245   
246   switch (id) {
247   case 'i': case 'I': fActiveId[0] = sid; break;
248   case 'o': case 'O': fActiveId[1] = sid; break;
249   }
250
251   // Shape of Printed circuit Board 
252   for (Int_t i = 0;       i < knv / 2; i++) ys[i] -= off;
253   for (Int_t i = knv / 2; i < knv;     i++) ys[i] += off;
254   TGeoXtru* pcbShape         = new TGeoXtru(2);
255   pcbShape->DefinePolygon(knv, xs.fArray, ys.fArray);
256   pcbShape->DefineSection(0, - pcbThick/2);
257   pcbShape->DefineSection(1, pcbThick/2);
258   pcbShape->SetName(Form(fgkPCBName, id));
259   pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
260   TGeoVolume* pcbVolume      = new TGeoVolume(Form(fgkPCBName, id), 
261                                               pcbShape, fPCB);
262   pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
263
264   // Copper layer
265   TGeoXtru* cuShape       = new TGeoXtru(2);
266   cuShape->DefinePolygon(6, xs.fArray, ys.fArray);
267   cuShape->DefineSection(0, - cuThick/2);
268   cuShape->DefineSection(1, cuThick/2);
269   cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
270   TGeoVolume* cuVolume    = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper);
271   cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
272
273   // Chip layer
274   TGeoXtru*   chipShape   = new TGeoXtru(2);
275   chipShape->DefinePolygon(6, xs.fArray, ys.fArray);
276   chipShape->DefineSection(0, - chipThick/2);
277   chipShape->DefineSection(1, chipThick/2);
278   chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
279   TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id),
280                                           chipShape,fChip);
281   chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
282
283   // Short leg shape 
284   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, legl / 2);
285   shortLegShape->SetName(Form(fgkShortLegName, id));
286   shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
287   TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), 
288                                               shortLegShape, fCopper);
289   shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
290   // Long leg shape
291   TGeoTube*   longLegShape   = new TGeoTube(0, legr, (legl + modSpace) / 2);
292   longLegShape->SetName(Form(fgkLongLegName, id));
293   longLegShape->SetTitle(Form("FMD %s long support foot", lName));
294   TGeoVolume* longLegVolume  = new TGeoVolume(Form(fgkLongLegName, id), 
295                                               longLegShape, fCopper);
296   longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
297   
298   
299   // Back container volume 
300   TGeoVolume* backVolume     = new TGeoVolumeAssembly(Form(fgkBackVName, id));
301   backVolume->SetTitle(Form("FMD %s back module", lName));
302   Double_t x = 0;
303   Double_t y = 0;
304   Double_t z = siThick / 2;
305   backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
306   z          += siThick / 2 + space + pcbThick / 2;
307   backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
308   z          += (pcbThick + cuThick) / 2;
309   backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
310   z          += (cuThick + chipThick) / 2;
311   backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
312   x          =  a->X() + legoff + legr;
313   y          =  0;
314   z          += pcbThick / 2 + legl / 2;
315   backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z));
316   x          =  c->X();
317   y          =  c->Y() - legoff - legr - off;
318   backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z));
319   y          =  -y;
320   backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z));
321
322   // Front container volume 
323   TGeoVolume* frontVolume    = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
324   frontVolume->SetTitle(Form("FMD %s front module", lName));
325   x         =  0;
326   y         =  0;
327   z         = siThick / 2;
328   frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
329   z          += siThick / 2 + space + pcbThick / 2;
330   frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
331   z          += (pcbThick + cuThick) / 2;
332   frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
333   z          += (cuThick + chipThick) / 2;
334   frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
335   x         =  a->X() + legoff + legr;
336   y         =  0;
337   z         += pcbThick / 2 + (legl + modSpace)/ 2;
338   frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z));
339   x         =  c->X();
340   y         =  c->Y() - legoff - legr - off;
341   frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z));
342   y         =  -y;
343   frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z));
344
345
346   // FMDD 
347   Double_t ddlr = r->GetFMDDLowR();
348   Double_t ddhr = r->GetFMDDHighR();
349   Double_t ddpt = r->GetFMDDPrintboardThickness();
350   Double_t ddct = r->GetFMDDCopperThickness();
351   Double_t ddit = r->GetFMDDChipThickness();
352   Double_t ddt  = ddpt + ddct + ddit;
353   
354   TGeoShape* fmddPcbShape  = new TGeoTubeSeg(ddlr, ddhr, ddpt/2,0,180);
355   TGeoShape* fmddCuShape   = new TGeoTubeSeg(ddlr, ddhr, ddct/2,0,180);
356   TGeoShape* fmddChipShape = new TGeoTubeSeg(ddlr, ddhr, ddit/2,0,180);
357   fmddPcbShape->SetName(Form(fgkFMDDPCBName, id));
358   fmddCuShape->SetName(Form(fgkFMDDCuName, id));
359   fmddChipShape->SetName(Form(fgkFMDDChipName, id));
360   if (id == 'O' || id == 'o') { 
361     TString pcbName(fmddPcbShape->GetName());
362     TString cuName(fmddCuShape->GetName());
363     TString chipName(fmddChipShape->GetName());
364     
365     fmddPcbShape->SetName(Form("%s_inner",  pcbName.Data()));
366     fmddCuShape->SetName(Form("%s_inner",   cuName.Data()));
367     fmddChipShape->SetName(Form("%s_inner", chipName.Data()));
368     new TGeoBBox(Form("%s_clip",  pcbName.Data()), ddlr+3, ddhr/2, ddpt);
369     new TGeoBBox(Form("%s_clip",  cuName.Data()),  ddlr+3, ddhr/2, ddpt);
370     new TGeoBBox(Form("%s_clip",  chipName.Data()),ddlr+3, ddhr/2, ddpt);
371     TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
372                                                       pcbName.Data()), 
373                                                  0, ddhr/2, 0);
374     trans->RegisterYourself();
375     fmddPcbShape = new TGeoCompositeShape(pcbName.Data(), 
376                                           Form("%s_inner*%s_clip:%s_trans",
377                                                pcbName.Data(), 
378                                                pcbName.Data(), 
379                                                pcbName.Data())); 
380     fmddCuShape = new TGeoCompositeShape(cuName.Data(), 
381                                          Form("%s_inner*%s_clip:%s_trans",
382                                               cuName.Data(), 
383                                               cuName.Data(), 
384                                               pcbName.Data()));
385     fmddChipShape = new TGeoCompositeShape(chipName.Data(), 
386                                            Form("%s_inner*%s_clip:%s_trans",
387                                                 chipName.Data(), 
388                                                 chipName.Data(), 
389                                                 pcbName.Data()));
390   }
391   fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
392   fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
393   fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
394
395   TGeoVolume*  fmddPcbVolume = new TGeoVolume(Form(fgkFMDDPCBName, id),
396                                               fmddPcbShape, fPCB);
397   TGeoVolume*  fmddCuVolume  = new TGeoVolume(Form(fgkFMDDCuName, id),
398                                               fmddCuShape, fCopper);
399   TGeoVolume*  fmddChipVolume= new TGeoVolume(Form(fgkFMDDChipName, id),
400                                               fmddChipShape, fChip);
401   fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
402   fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
403   fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
404
405   // Half ring mother volumes. 
406   TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
407   TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
408   TGeoVolume* halfRing      = ringTopVolume;
409   ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
410   ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
411   
412   // Adding modules to half-rings
413   Int_t    nmod =  r->GetNModules();
414   AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
415   for (Int_t i = 0; i < nmod; i++) {
416     if (i == nmod / 2) halfRing = ringBotVolume;
417     Bool_t      front =  (i % 2 == 0);
418     TGeoVolume* vol   =  (front ? frontVolume : backVolume);
419     // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
420     Double_t    z1    =  (i % 2) * modSpace;
421     Double_t    th    =  (2 * i + 1) * theta;
422     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
423     mat1->RotateZ(th);
424     mat1->SetName(Form("FMD%c_module_%02d", id, i));
425     mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
426     halfRing->AddNode(vol, i, mat1);
427 #if 0
428     Double_t    z2    =  z1 + siThick / 2 + space;
429     Double_t    th    =  (2 * i + 1) * theta;
430     AliFMDDebug(20, ("Placing copy %d of %s and %s in %s at z=%f and %f, "
431                       "and theta=%f", i, sensorVolume->GetName(), 
432                       vol->GetName(), halfRing->GetName(), z1, z2, th));
433     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
434     mat1->RotateZ(th);
435     halfRing->AddNode(sensorVolume, i, mat1);
436     TGeoMatrix* mat2  =  new TGeoCombiTrans(0,0,z2,0); 
437     mat2->RotateZ(th);
438     halfRing->AddNode(vol, i, mat2);
439 #endif
440   }
441
442   // Add the FMDD 
443   Double_t zi = r->GetFullDepth() - ddt;
444   Int_t    n  = 2;
445   for (Int_t i = 0; i  < n; i++) {
446     halfRing             = (i == 0 ? ringTopVolume : ringBotVolume);
447     Double_t      phi    = 360. / n * i;
448     TGeoRotation* rot    = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
449     rot->RotateZ(phi);
450     rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
451     z         =  zi + ddpt / 2;
452     halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
453     z          += (ddpt + ddct) / 2;
454     halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
455     z          += (ddct + ddit) / 2;
456     halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
457   }
458   
459
460   return 0;
461 }
462
463 //____________________________________________________________________
464 TGeoVolume*
465 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, 
466                                         TGeoVolume* topMother, 
467                                         TGeoVolume* botMother, 
468                                         Double_t    zMother, 
469                                         TGeoVolume* innerTop, 
470                                         TGeoVolume* innerBot, 
471                                         TGeoVolume* outerTop, 
472                                         TGeoVolume* outerBot) 
473 {
474   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
475   // This includes putting the Honeycomb support plates and the rings
476   // into the mother volumes.   
477   // 
478   // Parameeters:
479   //    d         The detector geometry to use 
480   //    mother    The mother volume of the detector 
481   //    zmother   The midpoint in global coordinates of detector vol.
482   //    inner     Pointer to inner ring volume 
483   //    outer     Pointer to outer ring volume
484   //
485   // Returns:
486   //    Pointer to mother (detector volume) 
487   // 
488   if (!d) return 0;
489   // Loop over the defined rings 
490   for (int i = 0; i < 2; i++) {
491     AliFMDRing* r     = 0;
492     Double_t    lowr  = 0;
493     Double_t    highr = 0;
494     Double_t    rz    = 0;
495     TGeoVolume* tvol  = 0;
496     TGeoVolume* bvol  = 0;
497     switch (i) {
498     case 0: 
499       r      = d->GetInner();
500       lowr   = d->GetInnerHoneyLowR();
501       highr  = d->GetInnerHoneyHighR();
502       rz     = d->GetInnerZ();
503       tvol   = innerTop;
504       bvol   = innerBot;
505       break;
506     case 1: 
507       r      = d->GetOuter();
508       lowr   = d->GetOuterHoneyLowR();
509       highr  = d->GetOuterHoneyHighR();
510       rz     = d->GetOuterZ();
511       tvol   = outerTop;
512       bvol   = outerBot;
513       break;
514     }
515     if (!r) continue;
516     Char_t   c       = r->GetId();
517     Int_t    id      = d->GetId();
518     Double_t hcThick = r->GetHoneycombThickness();
519     Double_t alThick = r->GetAlThickness();
520     Double_t z       = TMath::Abs(rz - zMother);
521
522     // Place ring in mother volume
523     // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
524     AliFMDDebug(1, ("Placing volumes %s and %s in %s and %s at z=%f", 
525                      tvol->GetName(), bvol->GetName(), 
526                      topMother->GetName(), botMother->GetName(), z));
527     topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
528     botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
529
530     // Top of Honeycomb
531     TGeoTubeSeg* hcSha = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180);
532     hcSha->SetName(Form(fgkHCName,id,c));
533     hcSha->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
534     TGeoVolume*  hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
535     hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
536     // Air in top of honeycomb
537     TGeoTubeSeg* ihcSha = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
538                                              (hcThick-alThick)/2, 0, 180);
539     ihcSha->SetName(Form(fgkIHCName,id,c));
540     ihcSha->SetTitle(Form("FMD%d%c honeycomb internal", id, c));
541     TGeoVolume*  ihcVol = new TGeoVolume(Form(fgkIHCName,id,c),ihcSha,fAir);
542     ihcVol->SetTitle(Form("FMD%d%c honeycomb internal", id, c));
543     hcVol->AddNode(ihcVol, 0);
544     hcVol->VisibleDaughters(kFALSE);    
545     hcVol->SetVisibility(kTRUE);
546     
547     z += (r->GetSiThickness() + 
548           r->GetSpacing() + 
549           r->GetPrintboardThickness() + 
550           r->GetCopperThickness() + 
551           r->GetChipThickness() + 
552           r->GetModuleSpacing() +
553           r->GetLegLength() + 
554           r->GetHoneycombThickness() + 
555           r->GetFMDDPrintboardThickness() - 
556           hcThick / 2); 
557
558     AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f", 
559                       hcVol->GetName(), topMother->GetName(), 
560                       botMother->GetName(), z));
561     // Add to top 
562     topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
563
564     // Add to bottom
565     TGeoMatrix*   bhcMatrix = new TGeoCombiTrans(0,0,z,0);
566     bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
567     bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
568     bhcMatrix->RotateZ(180);
569     botMother->AddNode(hcVol, 1, bhcMatrix);
570   }
571   return 0;
572 }
573
574 //____________________________________________________________________
575 TGeoVolume*
576 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, 
577                                     TGeoVolume* innerTop, 
578                                     TGeoVolume* innerBot) 
579 {
580   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
581   // special support as it is at the momement. 
582   // 
583   // See also AliFMDGeometryBuilder::DetectorGeometry 
584   // 
585   if (!fmd1 || !innerTop || !innerBot) return 0;
586   AliFMDRing* r             = fmd1->GetInner();
587   Double_t    z             = fmd1->GetInnerZ();  
588   Double_t    disce         = 2;
589   Double_t    backlr        = fmd1->GetInnerHoneyHighR();
590   Double_t    backhr        = fmd1->GetInnerHoneyHighR()+5;
591   Double_t    backth        = 0.2;
592   Double_t    toplr         = r->GetLowR();
593   Double_t    tophr         = fmd1->GetInnerHoneyHighR()+disce;
594   Double_t    wallbh        = (r->GetFullDepth() + disce);
595   Double_t    wallth        = wallbh+0.1;
596   
597   TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
598                                                           fmd1->GetId(), 'T'));
599   fmd1TopVolume->SetTitle("FMD1 top half");
600   TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
601                                                           fmd1->GetId(), 'B'));
602   fmd1BotVolume->SetTitle("FMD1 bottom half");
603   
604   // Basic detector geometry 
605   DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, 
606                    innerTop, innerBot, 0, 0);
607
608
609   // Back
610   TGeoTubeSeg* backShape  = new TGeoTubeSeg(backlr, backhr, backth / 2, 0, 180);
611   TGeoTubeSeg* wallbShape = new TGeoTubeSeg(backlr, backlr + backth, 
612                                             wallbh/2, 0, 180);
613   TGeoTubeSeg* topShape   = new TGeoTubeSeg(toplr, tophr, backth / 2, 0, 180);
614   TGeoTubeSeg* walltShape = new TGeoTubeSeg(tophr, tophr + backth, 
615                                             wallth/2, 0, 180);
616   TGeoVolume*  backVolume = new TGeoVolume(Form(fgkBackName, fmd1->GetId()), 
617                                            backShape, fC);
618   TGeoVolume*  wallbVolume= new TGeoVolume(Form(fgkFlangeName, fmd1->GetId()), 
619                                            wallbShape, fC);
620   TGeoVolume*  topVolume  = new TGeoVolume(Form(fgkTopName, fmd1->GetId()), 
621                                            topShape, fC);
622   TGeoVolume*  walltVolume= new TGeoVolume(Form(fgkBeamName, fmd1->GetId()), 
623                                            walltShape, fC);
624   backShape->SetName(Form(fgkBackName, fmd1->GetId()));
625   wallbShape->SetName(Form(fgkFlangeName, fmd1->GetId()));
626   topShape->SetName(Form(fgkTopName, fmd1->GetId()));
627   walltShape->SetName(Form(fgkBeamName, fmd1->GetId()));
628   backShape->SetTitle("FMD1 back saucer rim");
629   wallbShape->SetTitle("FMD1 back saucer wall");
630   topShape->SetTitle("FMD1 top lid");
631   walltShape->SetTitle("FMD1 top lid wall");
632   backVolume->SetFillColor(kGray);
633   topVolume->SetFillColor(kGray);
634   wallbVolume->SetFillColor(kGray);
635   walltVolume->SetFillColor(kGray);
636   backVolume->SetTitle("FMD1 back saucer rim");
637   wallbVolume->SetTitle("FMD1 back saucer wall");
638   topVolume->SetTitle("FMD1 top lid");
639   walltVolume->SetTitle("FMD1 top lid wall");
640   
641   // Place volumes
642   Double_t zb = TMath::Abs(fmd1->GetInnerZ() - z);
643   Double_t zi = zb;
644   Int_t    n  = 2;
645   
646   // Place top cover
647   zi -= disce / 2 + backth / 2;
648   zb =  zi;
649   for (Int_t i = 0; i  < 2; i++) {
650     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
651     Double_t      phi    = 360. / n * i;
652     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 top rotation %d",i));
653     rot->RotateZ(phi);
654     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1 top wall trans %d", i),
655                                               0, 0, zi, rot);
656     mother->AddNode(topVolume, i, matrix);    
657   }
658   // Place outer wall
659   zi += wallth / 2 + backth / 2;
660   for (Int_t i = 0; i  < 2; i++) {
661     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
662     Double_t      phi    = 360. / n * i;
663     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 outer wall rotation %d",
664                                                  i));
665     rot->RotateZ(phi);
666     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1 outer wall trans %d",
667                                                    i), 0, 0, zi, rot);
668     mother->AddNode(walltVolume, i, matrix);    
669   }
670   // Place back
671   zi += wallth / 2 + backth / 2; // + disce / 2;
672   for (Int_t i = 0; i  < 2; i++) {
673     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
674     Double_t      phi    = 360. / n * i;
675     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 back rotation %d", i));
676     rot->RotateZ(phi);
677     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1 back trans %d", i),
678                                              0, 0, zi, rot);
679     mother->AddNode(backVolume, i, matrix);    
680   }
681   // Place inner wall
682   zi -= wallbh / 2 + backth / 2; // + disce / 2;
683   for (Int_t i = 0; i  < 2; i++) {
684     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
685     Double_t      phi    = 360. / n * i;
686     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 inner wall rotation %d",
687                                                  i)); 
688     rot->RotateZ(phi);
689     TGeoMatrix*   matrix = new TGeoCombiTrans(Form("FMD1 inner wall trans %d", 
690                                                    i), 0, 0, zi, rot);
691     mother->AddNode(wallbVolume, i, matrix);    
692   }
693
694
695   // Must add this after filling the assembly.
696   TGeoVolume* top    = gGeoManager->GetVolume("ALIC");
697   // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
698   TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
699   rot->RotateZ(-90);
700   TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
701   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
702                    fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
703   top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
704   top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
705
706   return 0;
707 }
708
709 //____________________________________________________________________
710 TGeoVolume*
711 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, 
712                                     TGeoVolume* innerTop, 
713                                     TGeoVolume* innerBot, 
714                                     TGeoVolume* outerTop,
715                                     TGeoVolume* outerBot) 
716 {
717   // Setup the FMD2 geometry.  The FMD2 has no
718   // special support as it is at the momement. 
719   // 
720   // See also AliFMDGeometryBuilder::DetectorGeometry 
721   // 
722   if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
723   AliFMDRing* r             = fmd2->GetOuter();
724   Double_t    z             = fmd2->GetOuterZ();  
725   Double_t    framelr       = fmd2->GetOuterHoneyHighR()+0.5;
726   Double_t    framehr       = fmd2->GetOuterHoneyHighR()+1.8;
727   Double_t    framelz       = -1;
728   Double_t    framehz       = (fmd2->GetInnerZ()-z) + r->GetFullDepth() + 1;
729   Double_t    framel        = framehz - framelz;
730   Double_t    coverlr       = fmd2->GetInner()->GetLowR()+1;
731   Double_t    backth        = 0.05;
732
733   TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
734                                                           fmd2->GetId(), 'T'));
735   TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
736                                                           fmd2->GetId(), 'B'));
737   fmd2TopVolume->SetTitle("FMD2 top half");
738   fmd2BotVolume->SetTitle("FMD2 bottom half");
739   
740   DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, 
741                    innerTop, innerBot, outerTop, outerBot);
742
743   TGeoShape*  cylinderShape   = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
744   TGeoVolume* cylinderVolume  = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
745                                                cylinderShape, fC);
746   TGeoShape*  coverShape      = new TGeoTubeSeg(coverlr,framehr,backth/2,0,180);
747   TGeoVolume* coverVolume     = new TGeoVolume(Form(fgkTopName, fmd2->GetId()), 
748                                                coverShape, fC);
749   cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
750   cylinderShape->SetTitle("FMD2 cylinder");
751   cylinderVolume->SetTitle("FMD2 cylinder");
752   cylinderVolume->SetTransparency(63);
753   coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
754   coverShape->SetTitle("FMD2 cover");
755   coverVolume->SetTitle("FMD2 cover");
756   coverVolume->SetTransparency(63);
757   
758   for (Int_t i = 0; i  < 2; i++) {
759     TGeoVolume*   mother = (i == 0 ? fmd2TopVolume : fmd2BotVolume);
760     
761     Double_t      phi    = 360. / 2 * i;
762     TGeoRotation* rot    = new TGeoRotation(Form("FMD2 support rot %d",i)); 
763     rot->RotateZ(phi);
764     TGeoMatrix*   matrix = new TGeoCombiTrans(Form("FMD2 cyl trans %d", i),
765                                               0, 0, framelz+framel/2, rot);
766     mother->AddNode(cylinderVolume, i, matrix);    
767     matrix               = new TGeoCombiTrans(Form("FMD2 fcov trans %d", i),
768                                               0, 0, framelz-backth/2, rot);
769     mother->AddNode(coverVolume, 2*i+0, matrix);    
770     matrix               = new TGeoCombiTrans(Form("FMD2 bcov trans %d", i),
771                                               0, 0, framelz+framel+backth/2, 
772                                               rot);
773     mother->AddNode(coverVolume, 2*i+1, matrix);    
774   }
775
776
777   Double_t    f1l           = 10;
778   Double_t    f1w           = 6;
779   Double_t    f1d           = 1.2;
780   
781   TGeoBBox*   flange1Shape  = new TGeoBBox(f1l/2, f1w/2, f1d/2);
782   TGeoVolume* flange1Volume = new TGeoVolume(Form(fgkFlangeName, fmd2->GetId()),
783                                              flange1Shape, fAl);
784   TGeoBBox*   flange2Shape  = new TGeoBBox(f1w/2, f1d/2, (framel+backth)/2);
785   TGeoVolume* flange2Volume = new TGeoVolume(Form("F%dSG", fmd2->GetId()),
786                                              flange2Shape, fAl);
787   flange1Shape->SetName(Form(fgkFlangeName, fmd2->GetId()));
788   flange1Shape->SetTitle("FMD2 vertical flange");
789   flange1Volume->SetTitle("FMD2 vertical flange");
790   flange2Shape->SetName(Form("F%dSG", fmd2->GetId()));
791   flange2Shape->SetTitle("FMD2 horizontal flange");
792   flange2Volume->SetTitle("FMD2 horizontal flange ");
793   
794   flange1Volume->SetTransparency(42);
795   for (Int_t i = 0; i  < 4; i++) {
796     TGeoVolume*   mother = (i < 2 ? fmd2TopVolume : fmd2BotVolume);
797     
798     Double_t      phi    = 360. / 4 * i - 45;
799     Double_t      rphi   = TMath::Pi()*phi/180;
800     Double_t      x      = (framelr + f1l/2) * TMath::Sin(rphi);
801     Double_t      y      = (framelr + f1l/2) * TMath::Cos(rphi);
802     TGeoRotation* rot    = new TGeoRotation(Form("FMD2 support rot %d",i)); 
803     rot->RotateZ(phi);
804     TGeoMatrix*   matrix = new TGeoCombiTrans(Form("FMD2 flange 1 trans %d", i),
805                                               x,y, framelz-backth-f1d/2, rot);
806     mother->AddNode(flange1Volume, 2*i+0, matrix);    
807     matrix               = new TGeoCombiTrans(Form("FMD2 flange 2 trans %d", i),
808                                               x,y,framelz+framel+backth+f1d/2, 
809                                               rot);
810     mother->AddNode(flange1Volume, 2*i+1, matrix);    
811     Double_t x1 = x - (f1w-f1d) / 2 * TMath::Cos(rphi); 
812     Double_t y1 = y + (f1w-f1d) / 2 * TMath::Sin(rphi);
813     matrix               = new TGeoCombiTrans(Form("FMD2 flange 3 trans %d", i),
814                                               x1,y1,framelz+framel/2, rot);
815     mother->AddNode(flange2Volume, 2*i+0, matrix);    
816     Double_t x2 = x + (f1w-f1d) / 2 * TMath::Cos(rphi); 
817     Double_t y2 = y - (f1w-f1d) / 2 * TMath::Sin(rphi);
818     matrix               = new TGeoCombiTrans(Form("FMD2 flange 4 trans %d", i),
819                                               x2,y2,framelz+framel/2, rot);
820     mother->AddNode(flange2Volume, 2*i+1, matrix);    
821   }
822   
823   // Must be done after filling the assemblies 
824   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
825   TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
826   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
827                    fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
828   top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
829   top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
830
831
832   return 0;
833 }
834   
835 //____________________________________________________________________
836 TGeoVolume*
837 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
838                                     TGeoVolume* innerTop, 
839                                     TGeoVolume* innerBot, 
840                                     TGeoVolume* outerTop,
841                                     TGeoVolume* outerBot) 
842 {
843   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
844   // structure, as the support will also support the vacuum
845   // beam-pipe. 
846   // 
847   // See also AliFMDGeometryBuilder::DetectorGeometry 
848   // 
849   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
850   Double_t nlen    = fmd3->GetNoseLength();
851   Double_t nz      = fmd3->GetNoseZ();
852   Double_t noser1  = fmd3->GetNoseLowR();
853   Double_t noser2  = fmd3->GetNoseHighR();
854   Double_t conet   = fmd3->GetBeamThickness();
855   Double_t conel   = fmd3->GetConeLength();
856   Double_t backl   = fmd3->GetBackLength();
857   // Double_t backr1  = fmd3->GetBackLowR();
858   Double_t backr2  = fmd3->GetBackHighR();
859   Double_t zdist   = conel -  backl - nlen;
860   Double_t tdist   = backr2 - noser2;
861   // Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
862   Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
863   Double_t flanger = fmd3->GetFlangeR();
864   Double_t z       = fmd3->GetInnerZ(); // fmd3->GetZ();
865
866   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
867                                                           fmd3->GetId(), 'T'));
868   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
869                                                           fmd3->GetId(), 'B'));
870   fmd3TopVolume->SetTitle("FMD3 top half");
871   fmd3BotVolume->SetTitle("FMD3 bottom half");
872   
873   
874   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z, 
875                    innerTop, innerBot, outerTop, outerBot);
876
877   
878   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
879   support->SetTitle("FMD3 support");
880   
881   // Nose volume 
882   TGeoTubeSeg* noseShape  = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180);
883   TGeoVolume*  noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
884   support->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, nlen/2));
885   noseShape->SetName(fgkNoseName);
886   noseShape->SetTitle("FMD3 nose");
887   noseVolume->SetTitle("FMD3 nose");
888   
889   // Steel bolts 
890   TGeoTube*       boltShape  = new TGeoTube("F3SB", 0, 0.3, conet / 2);
891   TGeoVolume*     boltVolume = new TGeoVolume("F3SB", boltShape, fSteel);
892   Double_t        z1         = -10;
893   Double_t        x1         = (fmd3->ConeR(nz+z1));
894   TGeoRotation*   r1         = new TGeoRotation();
895   r1->RotateY(theta);
896   TGeoCombiTrans* t          = new TGeoCombiTrans("F3SB1",x1,0,-z1,r1);
897   support->AddNode(boltVolume, 1, t);
898   z1                         = -20;
899   x1                         = (fmd3->ConeR(nz+z1));
900   t                          = new TGeoCombiTrans("F3SB2",x1,0,-z1,r1);
901   support->AddNode(boltVolume, 2, t);
902   boltShape->SetTitle("FMD3 steering bolt");
903   boltVolume->SetTitle("FMD3 steering bolt");
904
905   // Cooling plates
906   TGeoTrd1*   plateShape  = new TGeoTrd1(2, 8, 0.1, (conel-2-2)/2-.1);
907   TGeoVolume* plateVolume = new TGeoVolume("F3CO", plateShape, fAl);
908   plateShape->SetName("F3C0");
909   plateShape->SetTitle("FMD3 cooling plate");
910   plateVolume->SetTitle("FMD3 cooling plate");
911
912   // Shape for carbon half-cone
913   TGeoConeSeg*    innerCone = new TGeoConeSeg("F3SC_inner", conel/2,
914                                               noser2-conet, noser2, 
915                                               backr2-conet, backr2, 0., 180.);
916   innerCone->SetTitle("FMD3 cone inner");
917   TGeoTrd1*       coneHole  = new TGeoTrd1("F3SC_hole",2,8,conet*3,
918                                            (conel-2-2)/2);
919   coneHole->SetTitle("FMD3 cone hole");
920   Double_t        holeAng   = TMath::ATan2(backr2 - noser2, conel);
921   Double_t        holeX     = ((conel-2) / 2 * TMath::Sin(holeAng) +
922                                conet     * TMath::Cos(holeAng) +
923                                noser2);
924   TGeoRotation*   holeRot   = new TGeoRotation();
925   holeRot->SetName("FMD3 cone hole rotation");
926   holeRot->RotateZ(90);
927   holeRot->RotateY(holeAng*180./TMath::Pi());
928   TGeoCombiTrans* holeTrans = new TGeoCombiTrans(holeX, 0, -2, holeRot);
929   holeRot->SetName("FMD3 cone hole");
930
931   // Build-up the composite shape for the cone, and add cooling plates
932   // at the same time. 
933   TString coneExp("F3SC_inner-(");
934   for (int i = 0; i < 4; i++) { 
935     Double_t        thisAng   = 360. / 8 * (i + .5);
936     TGeoCombiTrans* thisTrans = new TGeoCombiTrans(*holeTrans);
937     thisTrans->RotateZ(thisAng);
938     thisTrans->SetName(Form("F3SC_rot%d", i));
939     thisTrans->RegisterYourself();
940     coneExp.Append(Form("F3SC_hole:F3SC_rot%d+", i));
941
942     const Double_t* tt         = thisTrans->GetTranslation();
943     Double_t        x          = tt[0]+1*TMath::Cos(thisAng*TMath::Pi()/180);
944     Double_t        y          = tt[1]+1*TMath::Sin(thisAng*TMath::Pi()/180);
945     TGeoCombiTrans* plateTrans = new TGeoCombiTrans(x,y,tt[2]-1+nlen+conel/2,
946                                                     thisTrans->GetRotation());
947     support->AddNode(plateVolume, i, plateTrans);
948   }
949   // Remove bolt holes 
950   coneExp.Append("F3SB:F3SB1+F3SB:F3SB2)");
951
952   // Finalize the half-cone shape and add volume
953   TGeoCompositeShape* coneShape  = new TGeoCompositeShape(coneExp.Data());
954   TGeoVolume*         coneVolume = new TGeoVolume("F3SC", coneShape, fC);
955   coneShape->SetName("F3SC");
956   coneShape->SetTitle("FMD3 cone");
957   coneVolume->SetTitle("FMD3 cone");
958   support->AddNode(coneVolume,1,new TGeoTranslation(0,0,nlen+conel/2));
959   
960   // The flanges 
961   TGeoBBox* flangeShape    = new TGeoBBox((flanger - backr2) / 2, 
962                                           fmd3->GetBeamWidth() / 2,
963                                           backl / 2);
964   TGeoVolume* flangeVolume = new TGeoVolume(Form(fgkFlangeName, fmd3->GetId()),
965                                             flangeShape, fC);
966   flangeShape->SetName(Form(fgkFlangeName, fmd3->GetId()));
967   flangeShape->SetTitle("FMD3 flange");
968   flangeVolume->SetTitle("FMD3 flange");
969   
970   Int_t    n               = fmd3->GetNFlange();
971   Double_t r               = backr2 + (flanger - backr2) / 2;
972   for (Int_t i = 0; i  < n/2; i++) {
973     Double_t phi       = 360. / n * i + 180. / n;
974     Double_t x         = r * TMath::Cos(TMath::Pi() / 180 * phi);
975     Double_t y         = r * TMath::Sin(TMath::Pi() / 180 * phi);
976     TGeoRotation* rot  = new TGeoRotation;
977     rot->RotateZ(phi);
978     TGeoMatrix* matrix = new TGeoCombiTrans(x, y, nlen+conel-backl/2, rot);
979     matrix->SetName(Form("FMD3_flange_%02d", i));
980     matrix->SetTitle(Form("FMD3_flange_%2d", i));
981     support->AddNode(flangeVolume, i, matrix);
982   }
983
984   // Place support volumes in half-detector volumes 
985   z                          = fmd3->GetInnerZ();
986   z1                         = z-nz;
987   fmd3TopVolume->AddNode(support, 1, new TGeoTranslation(0,0,z1));
988   r1                         = new TGeoRotation();
989   r1->RotateZ(180);
990   t                          = new TGeoCombiTrans(0,0,z1,r1);
991   fmd3BotVolume->AddNode(support, 2, t);
992
993   TGeoRotation*   rot        = new TGeoRotation("FMD3 rotatation");
994   rot->RotateY(180);
995   TGeoVolume*     top        = gGeoManager->GetVolume("ALIC");
996   TGeoMatrix* mmatrix        = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
997   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
998                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
999   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1000   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1001
1002   return 0;
1003 }
1004
1005 //____________________________________________________________________
1006 void
1007 AliFMDGeometryBuilder::Exec(Option_t*) 
1008 {
1009   // Setup up the FMD geometry. 
1010   AliFMDDebug(1, ("\tGeometry options: %s",
1011                     (fDetailed  ? "divided into strips" : "one volume")));
1012   if (!gGeoManager) {
1013     AliFatal("No TGeoManager defined");
1014     return;
1015   }
1016
1017   fSi      = gGeoManager->GetMedium("FMD_Si$");
1018   fC       = gGeoManager->GetMedium("FMD_Carbon$");
1019   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
1020   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
1021   fAir     = gGeoManager->GetMedium("FMD_Air$");
1022   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
1023   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1024   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
1025   fSteel   = gGeoManager->GetMedium("FMD_Steel$");
1026
1027   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1028     AliError("Failed to get some or all tracking mediums");
1029     return;
1030   }    
1031   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1032   AliFMDRing* inner = fmd->GetInner();
1033   AliFMDRing* outer = fmd->GetOuter();
1034   RingGeometry(inner);
1035   RingGeometry(outer);
1036   TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1037                                                      inner->GetId()));
1038   TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1039                                                      inner->GetId()));
1040   TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1041                                                      outer->GetId()));
1042   TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1043                                                      outer->GetId()));
1044   
1045   FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1046   FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1047   FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1048 #ifndef USE_PRE_MOVE
1049   fmd->SetSectorOff(fSectorOff);
1050   fmd->SetModuleOff(fModuleOff);
1051   fmd->SetRingOff(fRingOff);
1052   fmd->SetDetectorOff(fDetectorOff);
1053   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1054 #endif
1055   // fmd->ExtractGeomInfo();
1056   
1057 }
1058
1059
1060 //____________________________________________________________________
1061 //
1062 // EOF
1063 //