Added AliMpStringObjMap, AliMpDEIterator, AliMpDEManager, AliMpSegFactory
[u/mrichter/AliRoot.git] / FMD / AliFMDG3Simulator.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 <math.h>
76 #include "AliFMDG3Simulator.h"  // ALIFMDG3SIMULATOR_H
77 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
78 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
79 #include "AliFMDRing.h"         // ALIFMDRING_H
80 #include "AliFMD1.h"            // ALIFMD1_H
81 #include "AliFMD2.h"            // ALIFMD2_H
82 #include "AliFMD3.h"            // ALIFMD3_H
83 #include "AliFMD.h"             // ALIFMD_H
84 #include <AliLog.h>             // ALILOG_H
85 #include <TVector2.h>           // ROOT_TVector2
86 #include <TVirtualMC.h>         // ROOT_TVirtualMC
87 #include <TArrayI.h>            // ROOT_TArrayI
88
89 //====================================================================
90 ClassImp(AliFMDG3Simulator)
91 #if 0
92   ; // This is here to keep Emacs for indenting the next line
93 #endif
94
95 //____________________________________________________________________
96 AliFMDG3Simulator::AliFMDG3Simulator() 
97 {
98   // Default constructor
99   fSectorOff   = 1;
100   fModuleOff   = 3;
101   fRingOff     = 4;
102   fDetectorOff = 5;
103 }
104
105 //____________________________________________________________________
106 AliFMDG3Simulator::AliFMDG3Simulator(AliFMD* fmd, Bool_t detailed) 
107   : AliFMDSimulator(fmd, detailed)
108 {
109   // Normal constructor
110   // 
111   // Parameters: 
112   // 
113   //      fmd           Pointer to AliFMD object 
114   //      detailed      Whether to make a detailed simulation or not 
115   // 
116   fSectorOff   = 1;
117   fModuleOff   = 3;
118   fRingOff     = 4;
119   fDetectorOff = 5;
120 }
121
122 //____________________________________________________________________
123 Bool_t
124 AliFMDG3Simulator::RingGeometry(AliFMDRing* r) 
125 {
126   // Setup the geometry of a ring.    The defined TGeoVolume is
127   // returned, and should be used when setting up the rest of the
128   // volumes. 
129   // 
130   // Parameters:
131   //
132   //     r              Pointer to ring geometry object 
133   // 
134   // Returns:
135   //    true on success 
136   //
137   if (!r) { 
138     AliError("Didn't get a ring object");
139     return kFALSE;
140   }
141   Char_t      id       = r->GetId();
142   Double_t    siThick  = r->GetSiThickness();
143   // const Int_t nv       = r->GetNVerticies();
144   TVector2*   a        = r->GetVertex(5);
145   TVector2*   b        = r->GetVertex(3);
146   TVector2*   c        = r->GetVertex(4);
147   Double_t    theta    = r->GetTheta();
148   Double_t    off      = (TMath::Tan(TMath::Pi() * theta / 180) 
149                           * r->GetBondingWidth());
150   Double_t    rmax     = b->Mod();
151   Double_t    rmin     = r->GetLowR();
152   Double_t    pcbThick = r->GetPrintboardThickness();
153   Double_t    modSpace = r->GetModuleSpacing();
154   Double_t    legr     = r->GetLegRadius();
155   Double_t    legl     = r->GetLegLength();
156   Double_t    legoff   = r->GetLegOffset();
157   Int_t       ns       = r->GetNStrips();
158   Double_t    space    = r->GetSpacing();
159   Double_t    stripoff = a->Mod();
160   Double_t    dstrip   = (rmax - stripoff) / ns;
161   Double_t    par[10];
162   TString     name;
163   TString     name2;
164   TVirtualMC* mc       = TVirtualMC::GetMC();
165   
166   Int_t siId  = fFMD->GetIdtmed()->At(kSiId);
167   Int_t airId = fFMD->GetIdtmed()->At(kAirId);
168   Int_t pcbId = fFMD->GetIdtmed()->At(kPcbId);
169   Int_t plaId = fFMD->GetIdtmed()->At(kPlasticId);
170   // Int_t copId = fFMD->GetIdtmed()->At(kCopperId);
171   // Int_t chiId = fFMD->GetIdtmed()->At(kSiChipId);
172
173   Double_t ringWidth  = r->GetRingDepth();
174   Double_t x          = 0;
175   Double_t y          = 0;
176   Double_t z          = 0;
177   Double_t backWidth  = siThick + pcbThick + legl + space;
178   Double_t frontWidth = backWidth + modSpace;
179
180   // Ring mother volume 
181   par[0]     =  rmin;
182   par[1]     =  rmax;
183   par[2]     =  ringWidth / 2;
184   name       =  Form(fgkRingName, id);
185   mc->Gsvolu(name.Data(), "TUBE", airId, par, 3);
186
187   // Back container volume 
188   par[0] = rmin;
189   par[1] = rmax;
190   par[2] = backWidth / 2;
191   par[3] = -theta;
192   par[4] = +theta;
193   TString backName(Form(fgkBackVName, id));
194   mc->Gsvolu(backName.Data(), "TUBS", airId, par, 5);
195   
196   // Front container volume 
197   par[2]     =  frontWidth / 2;
198   TString frontName(Form(fgkFrontVName, id));
199   mc->Gsvolu(frontName.Data(), "TUBS", airId, par, 5);
200   
201   Double_t topL = (b->X() - c->X());
202   Double_t botL = (c->X() - a->X());
203   Int_t    rot;
204   mc->Matrix(rot, 90, 90, 0, 90, 90, 0);  
205
206   Double_t zFront = - frontWidth / 2 + siThick / 2;
207   Double_t zBack  = - backWidth / 2 + siThick / 2;
208   if (fUseDivided) {
209     fSectorOff   = 1;
210     fModuleOff   = 3;
211     fRingOff     = 4;
212     fDetectorOff = 5;
213
214     // Virtual volume shape to divide - This volume is only defined if
215     // the geometry is set to be detailed. 
216     par[0]     = rmin;
217     par[1]     = rmax;
218     par[2]     = siThick / 2;
219     par[3]     = -theta;
220     par[4]     = theta;
221     name       = Form(fgkActiveName, id);
222     mc->Gsvolu(name.Data(), "TUBS", (fDetailed ? airId : siId), par, 5);
223
224     mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, 0, "ONLY");
225     mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, 0, "ONLY");
226     
227     Int_t sid = -1;
228     if (fDetailed) {
229       // Divide the volume into sectors
230       name2 = name;
231       name  = Form(fgkSectorName, id);
232       mc->Gsdvn2(name.Data(), name2.Data(), 2, 2, -theta, siId);
233       
234       // Divide the volume into strips
235       name2 = name;
236       name  = Form(fgkStripName, id);
237       mc->Gsdvt2(name.Data(), name2.Data(), dstrip, 1, stripoff, siId, ns);
238       sid = mc->VolId(name.Data());
239       AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data()));
240     }
241   
242     switch (id) {
243     case 'i': case 'I': fActiveId[0] = sid; break;
244     case 'o': case 'O': fActiveId[2] = sid; break;
245     }
246   }
247   else {
248     fSectorOff   = -1;
249     fModuleOff   = 1;
250     fRingOff     = 2;
251     fDetectorOff = 3;
252
253     // Create top of module shape 
254     par[0]    = c->Y();
255     par[1]    = b->Y();
256     par[2]    = siThick / 2;
257     par[3]    = topL / 2;
258     name      = Form(fgkModuleName, id);
259     name[3]   = 'T';
260     mc->Gsvolu(name.Data(), "TRD1", siId, par, 4);
261     Int_t tid = mc->VolId(name.Data());
262     x         =  rmin + botL + topL / 2;
263     mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
264     mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
265
266
267     // Create bottom of module shape 
268     par[0]    = a->Y();
269     par[1]    = c->Y();
270     par[3]    = botL / 2;
271     name      = Form(fgkModuleName, id);
272     name[3]   = 'B';
273     mc->Gsvolu(name.Data(), "TRD1", siId, par, 4);
274     Int_t bid = mc->VolId(name.Data());
275     x         =  rmin + botL / 2;
276     z         =  - backWidth / 2 + siThick / 2;
277     mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
278     mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
279   
280     switch (id) {
281     case 'i': case 'I': fActiveId[0] = tid; fActiveId[1] = bid; break;
282     case 'o': case 'O': fActiveId[2] = tid; fActiveId[3] = bid; break;
283     }
284   }
285   
286     
287   // Shape of Printed circuit Board 
288   // Top
289   par[0] =  c->Y() - off;
290   par[1] =  b->Y() - off;
291   par[2] =  pcbThick / 2;
292   par[3] =  topL / 2;
293   x      =  rmin + botL + topL / 2;
294   zBack  += siThick / 2 + space + pcbThick / 2;
295   zFront += siThick / 2 + space + pcbThick / 2;
296   name   = Form(fgkPCBName, id, 'T');
297   mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4);
298   mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
299   mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
300   
301   // Bottom
302   par[0] = a->Y() - off;
303   par[1] = c->Y() - off;
304   par[3] = botL / 2;
305   name   = Form(fgkPCBName, id, 'B');
306   x      =  rmin + botL / 2;
307   mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4);
308   mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
309   mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
310
311   Double_t x1, y1;
312   // Short leg volume 
313   par[0] =  legr - .1;
314   par[1] =  legr;
315   par[2] =  legl / 2;
316   x      =  a->X() + legoff + legr;
317   x1     =  c->X();
318   y1     =  c->Y() - legoff - legr - off;
319   zBack  += pcbThick / 2 + legl / 2;
320   zFront += pcbThick / 2 + legl / 2 + modSpace / 2;
321   name   = Form(fgkShortLegName, id);
322   mc->Gsvolu(name.Data(),  "TUBE",  plaId, par, 3);
323   mc->Gspos(name.Data(), 0, backName.Data(), x,    y, zBack, 0, "ONLY");
324   mc->Gspos(name.Data(), 1, backName.Data(), x1,  y1, zBack, 0, "ONLY");
325   mc->Gspos(name.Data(), 2, backName.Data(), x1, -y1, zBack, 0, "ONLY");
326   
327   // Long leg volume 
328   par[2] += modSpace / 2;
329   name   = Form(fgkLongLegName, id);
330   mc->Gsvolu(name.Data(),  "TUBE",  plaId, par, 3);
331   mc->Gspos(name.Data(), 0, frontName.Data(), x,    y, zFront, 0, "ONLY");
332   mc->Gspos(name.Data(), 1, frontName.Data(), x1,  y1, zFront, 0, "ONLY");
333   mc->Gspos(name.Data(), 2, frontName.Data(), x1, -y1, zFront, 0, "ONLY");
334   
335   // Place modules+pcb+legs in ring volume 
336   Int_t nmod = r->GetNModules();
337   name2      =  Form(fgkRingName, id);
338   AliDebug(10, Form("making %d modules in ring %c", nmod, id));
339   for (Int_t i = 0; i < nmod; i++) {
340     Double_t th      = (i + .5) * 2 * theta;
341     Bool_t   isFront = (i % 2 == 0);
342     name             = (isFront ? frontName : backName);
343     z                = (isFront ? 0 : modSpace) / 2;
344     mc->Matrix(rot, 90, th, 90, fmod(90 + th, 360), 0, 0);
345     mc->Gspos(name.Data(), i, name2.Data(), 0, 0, z, rot, "ONLY");
346   }
347   
348   return kTRUE;
349 }
350
351 //____________________________________________________________________
352 Bool_t
353 AliFMDG3Simulator::DetectorGeometry(AliFMDDetector* d, Double_t zmother) 
354 {
355   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
356   // This includes putting the Honeycomb support plates and the rings
357   // into the mother volumes.   
358   // 
359   // Parameeters:
360   //    d         The detector geometry to use 
361   //    zmother   The midpoint in global coordinates of detector vol.
362   //
363   // Returns:
364   //    true on success
365   // 
366   if (!d) return kFALSE;
367
368   TString     name;
369   TString     name2;
370   TVirtualMC* mc       = TVirtualMC::GetMC();
371
372   // Loop over the defined rings 
373   for (int i = 0; i < 2; i++) {
374     AliFMDRing* r     = 0;
375     Double_t    lowr  = 0;
376     Double_t    highr = 0;
377     Double_t    rz    = 0;
378     switch (i) {
379     case 0: 
380       r      = d->GetInner();
381       lowr   = d->GetInnerHoneyLowR();
382       highr  = d->GetInnerHoneyHighR();
383       rz     = d->GetInnerZ();
384       break;
385     case 1: 
386       r      = d->GetOuter();
387       lowr   = d->GetOuterHoneyLowR();
388       highr  = d->GetOuterHoneyHighR();
389       rz     = d->GetOuterZ();
390       break;
391     }
392     if (!r) continue;
393     Char_t   c       = r->GetId();
394     Int_t    id      = d->GetId();
395     Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
396     Int_t    alId    = (fFMD->GetIdtmed()->At(kAlId));
397     Double_t hcThick = d->GetHoneycombThickness();
398     Double_t alThick = d->GetAlThickness();
399     Double_t par[10];
400     Double_t z;
401     // Place ring in mother volume
402     if (zmother > 0) z = rz - zmother + r->GetRingDepth() / 2;
403     else             z = zmother - rz + r->GetRingDepth() / 2;
404     name  = Form(fgkRingName, c);
405     name2 = d->GetName();
406     mc->Gspos(name.Data(), Int_t(c), name2.Data(), 0, 0, z, 0, "ONLY");
407     
408     // Place Top Honeycomb in mother volume 
409     z += + r->GetRingDepth() / 2 + hcThick / 2;
410     // Top of Honeycomb
411     par[0] = lowr;
412     par[1] = highr;
413     par[2] = hcThick / 2;
414     par[3] = 0;
415     par[4] = 180;
416     name   = Form(fgkTopHCName, id, c);
417     mc->Gsvolu(name.Data(), "TUBS", alId, par, 5);
418     mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, z, 0, "ONLY");
419
420     par[0] += alThick;
421     par[1] -= alThick;
422     par[2] -= alThick / 2;
423     name2  =  name;
424     name   =  Form(fgkTopIHCName, id, c);
425     mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
426     mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, 0, 0, "ONLY");
427     
428     // Bot of Honeycomb
429     par[0] = lowr;
430     par[1] = highr;
431     par[2] = hcThick / 2;
432     par[3] = 180;
433     par[4] = 360;
434     name2  = d->GetName();
435     name   = Form(fgkBotHCName, id, c);
436     mc->Gsvolu(name.Data(), "TUBS", alId, par, 5);
437     mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, z, 0, "ONLY");
438
439     par[0] += alThick;
440     par[1] -= alThick;
441     par[2] -= alThick / 2;
442     name2  =  name;
443     name   =  Form(fgkBotIHCName, id, c);
444     mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
445     mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, 0, 0, "ONLY");
446   }
447   return kTRUE;
448 }
449
450 //____________________________________________________________________
451 Bool_t
452 AliFMDG3Simulator::FMD1Geometry(AliFMD1* fmd1) 
453 {
454   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
455   // special support as it is at the momement. 
456   // 
457   // See also AliFMDG3Simulator::DetectorGeometry 
458   // 
459   if (!fmd1) return kFALSE;
460   Double_t rmin    = fmd1->GetInner()->GetLowR();
461   Double_t rmax    = fmd1->GetInnerHoneyHighR();
462   Double_t hcThick = fmd1->GetHoneycombThickness();
463   Double_t w       = fmd1->GetInner()->GetRingDepth() + hcThick;
464   Double_t z       = fmd1->GetInnerZ() + w / 2;
465   TVirtualMC* mc   = TVirtualMC::GetMC();
466   Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
467
468   Double_t par[3];
469   par[0] = rmin;
470   par[1] = rmax;
471   par[2] = w / 2;
472   mc->Gsvolu(fmd1->GetName(), "TUBE", airId, par, 3);
473   mc->Gspos(fmd1->GetName(), fmd1->GetId(), "ALIC", 0, 0, z, 0, "ONLY");
474
475   return DetectorGeometry(fmd1, z);
476 }
477
478 //____________________________________________________________________
479 Bool_t
480 AliFMDG3Simulator::FMD2Geometry(AliFMD2* fmd2) 
481 {
482   // Setup the FMD2 geometry.  The FMD2 has no
483   // special support as it is at the momement. 
484   // 
485   // See also AliFMDG3Simulator::DetectorGeometry 
486   // 
487   if (!fmd2) return kFALSE;
488   Double_t rmin     = fmd2->GetInner()->GetLowR();
489   Double_t rmax     = fmd2->GetOuterHoneyHighR();
490   Double_t hcThick  = fmd2->GetHoneycombThickness();
491   Double_t ow       = fmd2->GetInner()->GetRingDepth();
492   Double_t iz       = fmd2->GetInnerZ();
493   Double_t oz       = fmd2->GetOuterZ();
494   Double_t w        = TMath::Abs(oz - iz) + ow + hcThick;
495   Double_t z        = oz + w / 2;
496   
497   TVirtualMC* mc   = TVirtualMC::GetMC();
498   Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
499
500   Double_t par[3];
501   par[0] = rmin;
502   par[1] = rmax;
503   par[2] = w / 2;
504   mc->Gsvolu(fmd2->GetName(), "TUBE", airId, par, 3);
505   mc->Gspos(fmd2->GetName(), fmd2->GetId(), "ALIC", 0, 0, z, 0, "ONLY");
506
507   return DetectorGeometry(fmd2, z);
508 }
509   
510 //____________________________________________________________________
511 Bool_t
512 AliFMDG3Simulator::FMD3Geometry(AliFMD3* fmd3) 
513 {
514   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
515   // structure, as the support will also support the vacuum
516   // beam-pipe. 
517   // 
518   // See also AliFMDG3Simulator::DetectorGeometry 
519   // 
520   if (!fmd3) return kFALSE;
521   Double_t nlen    = fmd3->GetNoseLength();
522   Double_t nz      = fmd3->GetNoseZ();
523   Double_t noser1  = fmd3->GetNoseLowR();
524   Double_t noser2  = fmd3->GetNoseHighR();
525   Double_t conel   = fmd3->GetConeLength();
526   Double_t backl   = fmd3->GetBackLength();
527   Double_t backr1  = fmd3->GetBackLowR();
528   Double_t backr2  = fmd3->GetBackHighR();
529   Double_t zdist   = conel -  backl - nlen;
530   Double_t tdist   = backr2 - noser2;
531   Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
532   Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
533   Double_t innerZ  = fmd3->GetInnerZ();
534   Double_t innerZh = (innerZ - fmd3->GetInner()->GetRingDepth() 
535                       - fmd3->GetHoneycombThickness());
536   Double_t outerZ  = fmd3->GetOuterZ();
537   Double_t outerZh = (outerZ - fmd3->GetOuter()->GetRingDepth() 
538                       - fmd3->GetHoneycombThickness());
539   Double_t innerr1 = fmd3->GetInner()->GetLowR();
540   // Double_t innerr2 = fmd3->GetInner()->GetHighR();
541   Double_t outerr1 = fmd3->GetOuter()->GetLowR();
542   // Double_t outerr2 = fmd3->GetOuter()->GetHighR();
543   Double_t flanger = fmd3->GetFlangeR();
544   Double_t minZ    = TMath::Min(nz - conel, outerZh);
545   Double_t z       = fmd3->GetZ();
546   Double_t zi;
547   TVirtualMC* mc   = TVirtualMC::GetMC();
548   Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
549   Int_t    cId     = (fFMD->GetIdtmed()->At(kCarbonId));
550   Double_t par[27];
551   
552   // FMD3 volume 
553   par[0]  = 0;
554   par[1]  = 360;
555   par[2]  = 8;
556   // First
557   par[3]  = z - nz;
558   par[4]  = noser1;
559   par[5]  = noser2;
560   // Second
561   par[6]  = z - (nz - nlen);
562   par[7]  = noser1;
563   par[8]  = fmd3->ConeR(z - par[6])+.15;
564   // Third
565   par[9]  = z - innerZ;
566   par[10] = innerr1;
567   par[11] = fmd3->ConeR(z - par[9])+.15;
568   // Fourth
569   par[12] = z - innerZh;
570   par[13] = innerr1;
571   par[14] = fmd3->ConeR(z - par[12])+.15;
572   // Fifth
573   par[15] = par[12];
574   par[16] = outerr1;
575   par[17] = fmd3->ConeR(z - par[15])+.15;
576   // Sixth
577   par[18] = z - nz + zdist + nlen;
578   par[19] = outerr1;
579   par[20] = fmd3->ConeR(z - par[18])+.15;
580   // Seventh
581   par[21] = z - nz + nlen + zdist;
582   par[22] = outerr1;
583   par[23] = flanger+1.5;
584   // Eight
585   par[24] = z - minZ;
586   par[25] = outerr1;
587   par[26] = flanger+1.5;
588   mc->Gsvolu(fmd3->GetName(), "PCON", airId, par, 27);
589   
590   Int_t id;
591   mc->Matrix(id, 270, 180, 90, 90, 180, 0);
592   mc->Gspos(fmd3->GetName(), fmd3->GetId(), "ALIC", 0, 0, z, id, "ONLY");
593   
594   // Nose volume 
595   par[0] = noser1;
596   par[1] = noser2;
597   par[2] = nlen / 2;
598   zi = z - nz + nlen / 2;
599   mc->Gsvolu(fgkNoseName, "TUBE", cId, par, 3);
600   mc->Gspos(fgkNoseName, 0, fmd3->GetName(), 0, 0, zi, 0, "MANY");
601   
602   // Back
603   par[0] = backr1;
604   par[1] = backr2;
605   par[2] = backl / 2;
606   zi = z - nz + conel - backl / 2;
607   mc->Gsvolu(fgkBackName, "TUBE", cId, par, 3);
608   mc->Gspos(fgkBackName, 0, fmd3->GetName(), 0, 0, zi, 0, "ONLY");
609   
610   Int_t n;
611   Double_t r;
612   // The flanges 
613   par[0] = (flanger - backr2) / 2;
614   par[1] = fmd3->GetBeamWidth() / 2;
615   par[2] = backl / 2;
616   mc->Gsvolu(fgkFlangeName, "BOX", cId, par, 3);
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     Int_t    id;
624     mc->Matrix(id, 90, phi, 90, 90 + phi, 0, 0);
625     mc->Gspos(fgkFlangeName, i, fmd3->GetName(), x, y, zi, id, "ONLY");
626   }
627
628   // The Beams 
629   par[0] = fmd3->GetBeamThickness() / 2;
630   par[1] = fmd3->GetBeamWidth() / 2;    
631   par[2] = beaml / 2;              
632   mc->Gsvolu(fgkBeamName, "BOX", cId, par, 3);
633   n      = fmd3->GetNBeam();
634   r      = noser2 + tdist / 2;
635   zi     = z - nz + nlen + zdist / 2;
636   for (Int_t i = 0; i  < n; i++) {
637     Double_t phi = 360. / n * i;
638     Double_t x   = r * TMath::Cos(TMath::Pi() / 180 * phi);
639     Double_t y   = r * TMath::Sin(TMath::Pi() / 180 * phi);
640     Int_t    id;
641     (void)theta;
642     mc->Matrix(id, 90-theta, phi, 90, 90 + phi, 360 - theta, phi);
643     mc->Gspos(fgkBeamName, i, fmd3->GetName(), x, y, zi, id, "MANY");
644   }
645   
646   return DetectorGeometry(fmd3, z);
647 }
648
649 //____________________________________________________________________
650 void
651 AliFMDG3Simulator::DefineGeometry() 
652 {
653   // Setup up the FMD geometry. 
654   AliDebug(10, "Setting up volume");
655
656   AliFMDGeometry* fmd   = AliFMDGeometry::Instance();
657   if (!RingGeometry(fmd->GetInner())) {
658     AliError("Failed to create inner ring volume");
659     return;
660   }
661   if (!RingGeometry(fmd->GetOuter())) {
662     AliError("Failed to create outer ring volume");
663     return;
664   }
665   FMD1Geometry(fmd->GetFMD1());
666   FMD2Geometry(fmd->GetFMD2());
667   FMD3Geometry(fmd->GetFMD3());
668 }
669
670 //____________________________________________________________________
671 //
672 // EOF
673 //