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