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