Commiting before moving code from `AliFMDSimulator' to `AliFMD' (and
[u/mrichter/AliRoot.git] / FMD / AliFMDGeoSimulator.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 //____________________________________________________________________
19 //                                                                          
20 // Forward Multiplicity Detector based on Silicon wafers. This class
21 // contains the base procedures for the Forward Multiplicity detector
22 // Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
23 // which has 1 or 2 rings of silicon sensors. 
24 //                                                       
25 // This is the base class for all FMD manager classes. 
26 //                    
27 // The actual code is done by various separate classes.   Below is
28 // diagram showing the relationship between the various FMD classes
29 // that handles the simulation
30 //
31 //      +--------+ 1     +-----------------+ 
32 //      | AliFMD |<>-----| AliFMDSimulator |
33 //      +--------+       +-----------------+
34 //                               ^              
35 //                               |
36 //                 +-------------+-------------+
37 //                 |                           |              
38 //        +--------------------+   +-------------------+
39 //        | AliFMDGeoSimulator |   | AliFMDG3Simulator | 
40 //        +--------------------+   +---------+---------+
41 //                                           ^
42 //                                           |
43 //                                +--------------------+
44 //                                | AliFMDOldSimulator |
45 //                                +--------------------+
46 //      
47 // *  AliFMD 
48 //    This defines the interface for the various parts of AliROOT that
49 //    uses the FMD, like AliFMDSimulator, AliFMDDigitizer, 
50 //    AliFMDReconstructor, and so on. 
51 //
52 // *  AliFMDSimulator
53 //    This is the base class for the FMD simulation tasks.   The
54 //    simulator tasks are responsible to implment the geoemtry, and
55 //    process hits. 
56 //                                                                          
57 // *  AliFMDGeoSimulator
58 //    This is a concrete implementation of the AliFMDSimulator that
59 //    uses the TGeo classes directly only.  This defines the active
60 //    volume as an ONLY XTRU shape with a divided MANY TUBS shape
61 //    inside to implement the particular shape of the silicon
62 //    sensors. 
63 //
64 // *  AliFMDG3Simulator
65 //    This is a concrete implementation of the AliFMDSimulator that
66 //    uses the TVirtualMC interface with GEANT 3.21-like messages.
67 //    This implements the active volume as a divided TUBS shape.  Hits
68 //    in the corners should be cut away at run time (but currently
69 //    isn't). 
70 //
71 // *  AliFMDOldSimulator
72 //    This is a concrete implementation of AliFMDSimulator.   It
73 //    approximates the of the rings as segmented disks. 
74 // 
75 #include "AliFMDGeoSimulator.h" // ALIFMDGEOSIMULATOR_H
76 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
77 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
78 #include "AliFMDRing.h"         // ALIFMDRING_H
79 #include "AliFMD1.h"            // ALIFMD1_H
80 #include "AliFMD2.h"            // ALIFMD2_H
81 #include "AliFMD3.h"            // ALIFMD3_H
82 #include "AliFMD.h"             // ALIFMD_H
83 #include "AliLog.h"             // ALILOG_H
84 #include <TGeoVolume.h>         // ROOT_TGeoVolume
85 #include <TGeoTube.h>           // ROOT_TGeoTube
86 #include <TGeoPcon.h>           // ROOT_TGeoPcon
87 #include <TGeoMaterial.h>       // ROOT_TGeoMaterial
88 #include <TGeoMedium.h>         // ROOT_TGeoMedium
89 #include <TGeoXtru.h>           // ROOT_TGeoXtru
90 #include <TGeoPolygon.h>        // ROOT_TGeoPolygon
91 #include <TGeoTube.h>           // ROOT_TGeoTube
92 #include <TGeoManager.h>        // ROOT_TGeoManager
93 #include <TVector2.h>           // ROOT_TVector2
94 #include <TArrayD.h>            // ROOT_TArrayD
95
96 //====================================================================
97 ClassImp(AliFMDGeoSimulator)
98 #if 0
99   ; // This is here to keep Emacs for indenting the next line
100 #endif
101
102 //____________________________________________________________________
103 AliFMDGeoSimulator::AliFMDGeoSimulator() 
104   : fSi(0),
105     fC(0),
106     fAl(0),
107     fPCB(0),
108     fChip(0),
109     fPlastic(0)
110 {
111   // Default constructor
112   fSectorOff   = 1;
113   fModuleOff   = 4;
114   fRingOff     = 5;
115   fDetectorOff = 6;
116 }
117
118 //____________________________________________________________________
119 AliFMDGeoSimulator::AliFMDGeoSimulator(AliFMD* fmd, Bool_t detailed) 
120   : AliFMDSimulator(fmd, detailed),
121     fSi(0),
122     fC(0),
123     fAl(0),
124     fPCB(0),
125     fChip(0),
126     fPlastic(0)
127 {
128   // Normal constructor
129   // 
130   // Parameters: 
131   // 
132   //      fmd           Pointer to AliFMD object 
133   //      detailed      Whether to make a detailed simulation or not 
134   // 
135   fSectorOff   = 1;
136   fModuleOff   = 4;
137   fRingOff     = 5;
138   fDetectorOff = 6;
139 }
140
141 //____________________________________________________________________
142 void
143 AliFMDGeoSimulator::DefineMaterials() 
144 {
145   // Define the materials and tracking mediums needed by the FMD
146   // simulation.   These mediums are made by sending the messages
147   // AliMaterial, AliMixture, and AliMedium to the passed AliModule
148   // object module.   The defined mediums are 
149   // 
150   //    FMD Si$         Silicon (active medium in sensors)
151   //    FMD C$          Carbon fibre (support cone for FMD3 and vacuum pipe)
152   //    FMD Al$         Aluminium (honeycomb support plates)
153   //    FMD PCB$        Printed Circuit Board (FEE board with VA1_ALICE)
154   //    FMD Chip$       Electronics chips (currently not used)
155   //    FMD Air$        Air (Air in the FMD)
156   //    FMD Plastic$    Plastic (Support legs for the hybrid cards)
157   //
158   // Pointers to TGeoMedium objects are retrived from the TGeoManager
159   // singleton.  These pointers are later used when setting up the
160   // geometry 
161   AliDebug(10, "\tCreating materials");
162
163   if (!gGeoManager) {
164     AliFatal("No TGeoManager defined");
165     return;
166   }
167   AliFMDSimulator::DefineMaterials();
168   fSi      = gGeoManager->GetMedium("FMD_Si$");
169   fC       = gGeoManager->GetMedium("FMD_Carbon$");
170   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
171   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
172   fAir     = gGeoManager->GetMedium("FMD_Air$");
173   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
174   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
175   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
176 }
177
178 //____________________________________________________________________
179 TGeoVolume*
180 AliFMDGeoSimulator::RingGeometry(AliFMDRing* r) 
181 {
182   // Setup the geometry of a ring.    The defined TGeoVolume is
183   // returned, and should be used when setting up the rest of the
184   // volumes. 
185   // 
186   // 
187   // Parameters:
188   //
189   //     r              Pointer to ring geometry object 
190   // 
191   // Returns:
192   //    pointer to ring volume 
193   //
194   if (!r) { 
195     AliError("Didn't get a ring object");
196     return 0;
197   }
198   Char_t      id       = r->GetId();
199   Double_t    siThick  = r->GetSiThickness();
200   const Int_t nv       = r->GetNVerticies();
201   TVector2*   a        = r->GetVertex(5);
202   TVector2*   b        = r->GetVertex(3);
203   TVector2*   c        = r->GetVertex(4);
204   Double_t    theta    = r->GetTheta();
205   Double_t    off      = (TMath::Tan(TMath::Pi() * theta / 180) 
206                           * r->GetBondingWidth());
207   Double_t    rmax     = b->Mod();
208   Double_t    rmin     = r->GetLowR();
209   Double_t    pcbThick = r->GetPrintboardThickness();
210   Double_t    modSpace = r->GetModuleSpacing();
211   Double_t    legr     = r->GetLegRadius();
212   Double_t    legl     = r->GetLegLength();
213   Double_t    legoff   = r->GetLegOffset();
214   Int_t       ns       = r->GetNStrips();
215   Double_t    stripoff = a->Mod();
216   Double_t    dstrip   = (rmax - stripoff) / ns;
217   Double_t    space    = r->GetSpacing();
218   TArrayD xs(nv);
219   TArrayD ys(nv);
220   for (Int_t i = 0; i < nv; i++) {
221     // Reverse the order 
222     TVector2* vv = r->GetVertex(nv - 1 - i);
223     if (!vv) {
224       AliError(Form("Failed to get vertex # %d", nv - 1 - i));
225       continue;
226     }
227     xs[i] = vv->X();
228     ys[i] = vv->Y();
229   }
230   
231   // Shape of actual sensor 
232   TGeoXtru* moduleShape = new TGeoXtru(2);
233   moduleShape->DefinePolygon(nv, xs.fArray, ys.fArray);
234   moduleShape->DefineSection(0, - siThick/2);
235   moduleShape->DefineSection(1, siThick/2);
236   TGeoVolume* moduleVolume = new TGeoVolume(Form(fgkModuleName, id), 
237                                             moduleShape, fSi);
238   Int_t sid = moduleVolume->GetNumber();
239   fSectorOff   = -1;
240   fModuleOff   = 1;
241   fRingOff     = 2;
242   fDetectorOff = 3;
243   if (fUseDivided) {
244     fSectorOff   = 1;
245     fModuleOff   = 4;
246     fRingOff     = 5;
247     fDetectorOff = 6;
248     // Virtual volume shape to divide - This volume is only defined if
249     // the geometry is set to be detailed. 
250     TGeoVolume* activeVolume = 0;
251     if (fDetailed) {
252       TGeoTubeSeg* activeShape = 
253         new TGeoTubeSeg(rmin, rmax, siThick/2, - theta, theta);
254       activeVolume = new TGeoVolume(Form(fgkActiveName, id),activeShape,fSi);
255       TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), 
256                                                       2, 2, -theta,0,0,"N");
257       TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id), 
258                                                      1, ns, stripoff, dstrip, 
259                                                      0, "SX");
260       sid = stripVolume->GetNumber();
261     }
262     // Add divived MANY volume to the true shape of the module, but only
263     // if a detailed simulation is reguested. 
264     if (activeVolume) moduleVolume->AddNodeOverlap(activeVolume, 0);
265   }
266   
267   switch (id) {
268   case 'i':
269   case 'I': fActiveId[0] = sid; break;
270   case 'o':
271   case 'O': fActiveId[2] = sid; break;
272   }
273
274   // Shape of Printed circuit Board 
275   TGeoXtru* pcbShape = new TGeoXtru(2);
276   for (Int_t i = 0;      i < nv / 2; i++) ys[i] -= off;
277   for (Int_t i = nv / 2; i < nv;     i++) ys[i] += off;
278   pcbShape->DefinePolygon(nv, xs.fArray, ys.fArray);
279   pcbShape->DefineSection(0, - pcbThick/2);
280   pcbShape->DefineSection(1, pcbThick/2);
281   TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id, 'B'), 
282                                          pcbShape, fPCB);
283
284   // Short leg shape 
285   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, legl / 2);
286   TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), 
287                                               shortLegShape, fPlastic);
288
289   // Long leg shape
290   TGeoTube*   longLegShape   = new TGeoTube(0, legr, (legl + modSpace) / 2);
291   TGeoVolume* longLegVolume  = new TGeoVolume(Form(fgkLongLegName, id), 
292                                               longLegShape, fPlastic);
293   
294   TGeoMatrix* matrix = 0;
295   // Back container volume 
296   Double_t contThick     = siThick + pcbThick + legl + space;
297   TGeoTubeSeg* backShape = new TGeoTubeSeg(rmin, rmax, contThick/2, 
298                                            - theta, theta);
299   TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackVName, id), 
300                                           backShape, fAir);
301   Double_t x = 0;
302   Double_t y = 0;
303   Double_t z = -contThick / 2 + siThick / 2;
304   matrix     = new TGeoTranslation(Form("FMD Ring  %c mod 1 transform", id), 
305                                    x, y, z);
306   backVolume->AddNode(moduleVolume, 0, matrix);
307   z          += siThick / 2 + space + pcbThick / 2;
308   matrix     =  new TGeoTranslation(Form("FMD Ring %c pcb 1 transfrom", id), 
309                                     x, y, z);
310   backVolume->AddNode(pcbVolume, 0, matrix);
311   x          =  a->X() + legoff + legr;
312   y          =  0;
313   z          += pcbThick / 2 + legl / 2;
314   matrix     = new TGeoTranslation(Form("FMD Ring %c leg 1 transfrom", id), 
315                                    x, y, z);
316   backVolume->AddNode(shortLegVolume, 0, matrix);
317   x          =  c->X();
318   y          =  c->Y() - legoff - legr - off;
319   matrix     =  new TGeoTranslation(Form("FMD Ring %c leg 2 transfrom", id), 
320                                     x, y, z);
321   backVolume->AddNode(shortLegVolume, 1, matrix);
322   y          =  -y;
323   matrix     =  new TGeoTranslation(Form("FMD Ring %c leg 3 transfrom", id), 
324                                     x, y, z);
325   backVolume->AddNode(shortLegVolume, 2, matrix);
326   // backVolume->SetVisibility(kFALSE);
327   // backVolume->VisibleDaughters(kTRUE);
328
329   // Front container volume 
330   contThick += modSpace;
331   TGeoTubeSeg* frontShape = new TGeoTubeSeg(rmin, rmax, contThick/2, 
332                                             -theta, theta);
333   TGeoVolume* frontVolume = new TGeoVolume(Form(fgkFrontVName, id),
334                                            frontShape, fAir);
335   x         =  0;
336   y         =  0;
337   z         =  -contThick / 2 + siThick / 2 ;
338   matrix    = new TGeoTranslation(Form("FMD Ring %c mod 2 transfrom", id), 
339                                   0, 0, z);
340   frontVolume->AddNode(moduleVolume, 1, matrix);
341   z         += siThick / 2 + space + pcbThick / 2;
342   matrix    =  new TGeoTranslation(Form("FMD Ring %c pcb 2 transfrom", id), 
343                                    x, y, z);
344   frontVolume->AddNode(pcbVolume, 1, matrix);
345   x         =  a->X() + legoff + legr;
346   y         =  0;
347   z         += pcbThick / 2 + (legl + modSpace)/ 2;
348   matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
349                                    x, y, z);
350   frontVolume->AddNode(longLegVolume, 0, matrix);
351   x         =  c->X();
352   y         =  c->Y() - legoff - legr - off;
353   matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
354                                    x, y, z);
355   frontVolume->AddNode(longLegVolume, 1, matrix);
356   y         =  -y;
357   matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
358                                    x, y, z);
359   frontVolume->AddNode(longLegVolume, 2, matrix);
360   // frontVolume->SetVisibility(kFALSE);
361   // frontVolume->VisibleDaughters(kTRUE);
362   
363   // Ring mother volume 
364   TGeoTube*   ringShape  = new TGeoTube(rmin, rmax, contThick / 2);
365   TGeoVolume* ringVolume = new TGeoVolume(Form(fgkRingName,id),
366                                           ringShape,fAir);
367
368   Int_t nmod = r->GetNModules();
369   AliDebug(10, Form("making %d modules in ring %c", nmod, id));
370   for (Int_t i = 0; i < nmod; i++) {
371     Bool_t isFront    = (i % 2 == 0);
372     TGeoVolume* vol   = (isFront ? frontVolume : backVolume);
373     TGeoRotation* rot =new TGeoRotation(Form("FMD Ring %c rotation %d",id,i));
374     rot->RotateZ((i + .5) * 2 * theta);
375     Double_t z = (isFront ? 0 : modSpace) / 2;
376     matrix     = new TGeoCombiTrans(Form("FMD Ring %c transform %d", id, i), 
377                                     0, 0, z, rot);
378     ringVolume->AddNode(vol, i, matrix);
379   }
380
381   ringVolume->SetVisibility(kFALSE);
382   ringVolume->VisibleDaughters(kTRUE);
383   return ringVolume;
384 }
385
386 //____________________________________________________________________
387 TGeoVolume*
388 AliFMDGeoSimulator::DetectorGeometry(AliFMDDetector* d, 
389                                      TGeoVolume* mother, 
390                                      Double_t    zmother, 
391                                      TGeoVolume* inner, 
392                                      TGeoVolume* outer) 
393 {
394   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
395   // This includes putting the Honeycomb support plates and the rings
396   // into the mother volumes.   
397   // 
398   // Parameeters:
399   //    d         The detector geometry to use 
400   //    mother    The mother volume of the detector 
401   //    zmother   The midpoint in global coordinates of detector vol.
402   //    inner     Pointer to inner ring volume 
403   //    outer     Pointer to outer ring volume
404   //
405   // Returns:
406   //    Pointer to mother (detector volume) 
407   // 
408   if (!d) return 0;
409   // Loop over the defined rings 
410   for (int i = 0; i < 2; i++) {
411     AliFMDRing* r     = 0;
412     Double_t    lowr  = 0;
413     Double_t    highr = 0;
414     Double_t    rz    = 0;
415     TGeoVolume* rvol  = 0;
416     switch (i) {
417     case 0: 
418       r      = d->GetInner();
419       lowr   = d->GetInnerHoneyLowR();
420       highr  = d->GetInnerHoneyHighR();
421       rz     = d->GetInnerZ();
422       rvol   = inner;
423       break;
424     case 1: 
425       r      = d->GetOuter();
426       lowr   = d->GetOuterHoneyLowR();
427       highr  = d->GetOuterHoneyHighR();
428       rz     = d->GetOuterZ();
429       rvol   = outer;
430       break;
431     }
432     if (!r) continue;
433     Char_t   c       = r->GetId();
434     Int_t    id      = d->GetId();
435     Double_t hcThick = d->GetHoneycombThickness();
436     Double_t alThick = d->GetAlThickness();
437     Double_t z;
438     if (zmother > 0) z = rz - zmother + r->GetRingDepth() / 2;
439     else             z = zmother - rz + r->GetRingDepth() / 2;
440     // Place ring in mother volume
441     mother->AddNode(rvol, Int_t(c), 
442                     new TGeoTranslation(Form("FMD%d%c transform", id, c), 
443                                         0, 0, z));
444
445     z += r->GetRingDepth() / 2 + hcThick / 2;
446     // Top of Honeycomb
447     TGeoTubeSeg* topHCShape  = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180);
448     TGeoVolume*  topHCVolume = new TGeoVolume(Form(fgkTopHCName, id, c), 
449                                               topHCShape, fAl);
450     TGeoMatrix*  topHCMatrix = 
451       new TGeoTranslation(Form("FMD%d%c top HC transform", id, c), 0, 0, z);
452     mother->AddNode(topHCVolume, 0, topHCMatrix);
453
454     // Air in top of honeycomb
455     TGeoTubeSeg* topIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
456                                                (hcThick-alThick)/2, 0, 180);
457     TGeoVolume*  topIHCVolume = new TGeoVolume(Form(fgkTopIHCName, id, c), 
458                                                topIHCShape, fAir);
459     topHCVolume->AddNode(topIHCVolume, 0);
460     topHCVolume->VisibleDaughters(kFALSE);    
461     topHCVolume->SetVisibility(kTRUE);
462
463
464     // Bottom of Honeycomb
465     TGeoTubeSeg* botHCShape = new TGeoTubeSeg(lowr, highr, hcThick/2, 
466                                               180, 360);
467     TGeoVolume*  botHCVolume = new TGeoVolume(Form(fgkBotHCName, id, c), 
468                                               botHCShape, fAl);
469     TGeoMatrix*  botHCMatrix = 
470       new TGeoTranslation(Form("FMD%d%c bottom HC transform", id, c), 0, 0, z);
471     mother->AddNode(botHCVolume, 0, botHCMatrix);
472
473     // Air in bot of honeycomb
474     TGeoTubeSeg* botIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
475                                                (hcThick-alThick)/2, 180, 360);
476     TGeoVolume*  botIHCVolume = new TGeoVolume(Form(fgkBotIHCName, id, c), 
477                                                botIHCShape, fAir);
478     botHCVolume->AddNode(botIHCVolume, 0);
479     botHCVolume->VisibleDaughters(kFALSE);    
480     botHCVolume->SetVisibility(kTRUE);    
481   }
482   mother->SetVisibility(kFALSE);
483   mother->VisibleDaughters(kTRUE);
484   return mother;
485 }
486
487 //____________________________________________________________________
488 TGeoVolume*
489 AliFMDGeoSimulator::FMD1Geometry(AliFMD1* fmd1, TGeoVolume* inner) 
490 {
491   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
492   // special support as it is at the momement. 
493   // 
494   // See also AliFMDGeoSimulator::DetectorGeometry 
495   // 
496   if (!fmd1 || !inner) return 0;
497   Double_t rmin    = fmd1->GetInner()->GetLowR();
498   Double_t rmax    = fmd1->GetInnerHoneyHighR();
499   Double_t hcThick = fmd1->GetHoneycombThickness();
500   Double_t w       = fmd1->GetInner()->GetRingDepth() + hcThick;
501   Double_t z       = fmd1->GetInnerZ() + w / 2;
502
503   TGeoVolume* fmd1Volume = 0;
504   if (!fUseAssembly) {
505     TGeoTube* fmd1Shape = new TGeoTube(rmin, rmax, w / 2);
506     fmd1Volume = new TGeoVolume(fmd1->GetName(), fmd1Shape, fAir);
507   }
508   else
509     fmd1Volume = new TGeoVolumeAssembly(fmd1->GetName());
510   
511   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
512   TGeoMatrix* matrix = new TGeoTranslation("FMD1 transform", 0, 0, z);
513   top->AddNode(fmd1Volume, fmd1->GetId(), matrix);
514
515   return DetectorGeometry(fmd1, fmd1Volume, z, inner, 0);
516 }
517
518 //____________________________________________________________________
519 TGeoVolume*
520 AliFMDGeoSimulator::FMD2Geometry(AliFMD2* fmd2, 
521                                  TGeoVolume* inner, 
522                                  TGeoVolume* outer) 
523 {
524   // Setup the FMD2 geometry.  The FMD2 has no
525   // special support as it is at the momement. 
526   // 
527   // See also AliFMDGeoSimulator::DetectorGeometry 
528   // 
529   if (!fmd2 || !inner || !outer) return 0;
530   Double_t rmin     = fmd2->GetInner()->GetLowR();
531   Double_t rmax     = fmd2->GetOuterHoneyHighR();
532   Double_t hcThick  = fmd2->GetHoneycombThickness();
533   Double_t ow       = fmd2->GetInner()->GetRingDepth();
534   Double_t iz       = fmd2->GetInnerZ();
535   Double_t oz       = fmd2->GetOuterZ();
536   Double_t w        = TMath::Abs(oz - iz) + ow + hcThick;
537   Double_t z        = oz + w / 2;
538   
539   TGeoVolume* fmd2Volume = 0;
540   if (!fUseAssembly) {
541     TGeoTube* fmd2Shape = new TGeoTube(rmin, rmax, w / 2);
542     fmd2Volume = new TGeoVolume(fmd2->GetName(), fmd2Shape, fAir);
543   }
544   else 
545     fmd2Volume = new TGeoVolumeAssembly(fmd2->GetName());
546   
547   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
548   TGeoMatrix* matrix = new TGeoTranslation("FMD2 transform", 0, 0, z);
549   top->AddNode(fmd2Volume, fmd2->GetId(), matrix);
550
551   return DetectorGeometry(fmd2, fmd2Volume, z, inner, outer);
552 }
553   
554 //____________________________________________________________________
555 TGeoVolume*
556 AliFMDGeoSimulator::FMD3Geometry(AliFMD3* fmd3, 
557                                  TGeoVolume* inner, 
558                                  TGeoVolume* outer) 
559 {
560   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
561   // structure, as the support will also support the vacuum
562   // beam-pipe. 
563   // 
564   // See also AliFMDGeoSimulator::DetectorGeometry 
565   // 
566   if (!fmd3 || !inner || !outer) return 0;
567   Double_t nlen    = fmd3->GetNoseLength();
568   Double_t nz      = fmd3->GetNoseZ();
569   Double_t noser1  = fmd3->GetNoseLowR();
570   Double_t noser2  = fmd3->GetNoseHighR();
571   Double_t conel   = fmd3->GetConeLength();
572   Double_t backl   = fmd3->GetBackLength();
573   Double_t backr1  = fmd3->GetBackLowR();
574   Double_t backr2  = fmd3->GetBackHighR();
575   Double_t zdist   = conel -  backl - nlen;
576   Double_t tdist   = backr2 - noser2;
577   Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
578   Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
579   Double_t innerZ  = fmd3->GetInnerZ();
580   Double_t innerZh = (innerZ - fmd3->GetInner()->GetRingDepth() 
581                       - fmd3->GetHoneycombThickness());
582   Double_t outerZ  = fmd3->GetOuterZ();
583   Double_t outerZh = (outerZ - fmd3->GetOuter()->GetRingDepth() 
584                       - fmd3->GetHoneycombThickness());
585   Double_t innerr1 = fmd3->GetInner()->GetLowR();
586   // Double_t innerr2 = fmd3->GetInner()->GetHighR();
587   Double_t outerr1 = fmd3->GetOuter()->GetLowR();
588   // Double_t outerr2 = fmd3->GetOuter()->GetHighR();
589   Double_t flanger = fmd3->GetFlangeR();
590   Double_t minZ    = TMath::Min(nz - conel, outerZh);
591   Double_t z       = fmd3->GetZ();
592   Double_t zi;
593
594   // FMD3 volume 
595   TGeoVolume* fmd3Volume = 0;
596   if (!fUseAssembly) {
597     TGeoPcon* fmd3Shape = new TGeoPcon(0, 360, 8);
598     zi = z - nz;
599     fmd3Shape->DefineSection(0, zi,  noser1,   noser2);
600     zi = z - (nz - nlen);
601     fmd3Shape->DefineSection(1, zi,  noser1,   fmd3->ConeR(z - zi)+.15);
602     zi = z - innerZ;
603     fmd3Shape->DefineSection(2, zi,  innerr1,  fmd3->ConeR(z - zi)+.15);
604     zi = z - innerZh;
605     fmd3Shape->DefineSection(3, zi,  innerr1,  fmd3->ConeR(z - zi)+.15);
606     fmd3Shape->DefineSection(4, zi,  outerr1,  fmd3->ConeR(z - zi)+.15);
607     zi = z - nz + zdist + nlen;
608     fmd3Shape->DefineSection(5, zi,  outerr1,  fmd3->ConeR(z - zi)+.15);
609     zi = z - nz + nlen + zdist;
610     fmd3Shape->DefineSection(6, zi,  outerr1,  flanger+1.5);
611     zi = z - minZ;
612     fmd3Shape->DefineSection(7, zi,  outerr1,  flanger+1.5);
613     fmd3Volume = new TGeoVolume(fmd3->GetName(), fmd3Shape, fAir);
614   }
615   else 
616     fmd3Volume = new TGeoVolumeAssembly(fmd3->GetName());
617   
618   TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
619   rot->RotateY(180);
620   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
621   TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 transform", 0, 0, z, rot);
622   top->AddNode(fmd3Volume, fmd3->GetId(), mmatrix);
623   
624   // Nose volume 
625   TGeoTube* noseShape = new TGeoTube(noser1, noser2, nlen / 2);
626   TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
627   zi = z - nz + nlen / 2;
628   TGeoMatrix* nmatrix = new TGeoTranslation("FMD3 Nose translation", 0, 0, zi);
629   // fmd3Volume->AddNodeOverlap(noseVolume, 0, nmatrix);
630   fmd3Volume->AddNode(noseVolume, 0, nmatrix);
631   
632   // Back
633   TGeoTube* backShape = new TGeoTube(backr1, backr2, backl / 2);
634   TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC);
635   zi = z - nz + conel - backl / 2;
636   TGeoMatrix* bmatrix = new TGeoTranslation("FMD3 Back translation", 0, 0, zi);
637   fmd3Volume->AddNode(backVolume, 0, bmatrix);
638   
639   Int_t n;
640   Double_t r;
641   // The flanges 
642   TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, 
643                                        fmd3->GetBeamWidth() / 2,
644                                        backl / 2);
645   TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC);
646   n = fmd3->GetNFlange();
647   r = backr2 + (flanger - backr2) / 2;
648   for (Int_t i = 0; i  < n; i++) {
649     Double_t phi = 360. / n * i + 180. / n;
650     Double_t x   = r * TMath::Cos(TMath::Pi() / 180 * phi);
651     Double_t y   = r * TMath::Sin(TMath::Pi() / 180 * phi);
652     TGeoRotation* rot = new TGeoRotation(Form("FMD3 Flange rotation %d", i));
653     rot->RotateZ(phi);
654     TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 flange transform %d", 
655                                                  i), x, y, zi, rot);
656     // fmd3Volume->AddNodeOverlap(flangeVolume, i, matrix);
657     fmd3Volume->AddNode(flangeVolume, i, matrix);
658     
659   }
660
661   // The Beams 
662   TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, 
663                                      fmd3->GetBeamWidth() / 2 - .1,
664                                      beaml / 2);
665   TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC);
666   n = fmd3->GetNBeam();
667   r = noser2 + tdist / 2;
668   zi = z - nz + nlen + zdist / 2;
669   for (Int_t i = 0; i  < n; i++) {
670     Double_t phi = 360. / n * i;
671     Double_t x   = r * TMath::Cos(TMath::Pi() / 180 * phi);
672     Double_t y   = r * TMath::Sin(TMath::Pi() / 180 * phi);
673     TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i));
674     // Order is important
675     rot->RotateY(-theta);
676     rot->RotateZ(phi);
677     TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam transform %d", i),
678                                             x, y, zi, rot);
679     fmd3Volume->AddNode(beamVolume, i, matrix);    
680   }
681   
682   
683   return DetectorGeometry(fmd3, fmd3Volume, z, inner, outer);
684 }
685
686 //____________________________________________________________________
687 void
688 AliFMDGeoSimulator::DefineGeometry() 
689 {
690   // Setup up the FMD geometry. 
691   AliDebug(1, "Setting up volumes, with ");
692
693   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
694   TGeoVolume* inner = RingGeometry(fmd->GetInner());
695   TGeoVolume* outer = RingGeometry(fmd->GetOuter());
696
697   if (!inner || !outer) {
698     AliError("Failed to create one of the ring volumes");
699     return;
700   }
701   FMD1Geometry(fmd->GetFMD1(), inner);
702   FMD2Geometry(fmd->GetFMD2(), inner, outer);
703   FMD3Geometry(fmd->GetFMD3(), inner, outer);
704 }
705
706
707 //____________________________________________________________________
708 //
709 // EOF
710 //