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