Temporary reverting the changes introduced earlier to store the TGeo geometry. New...
[u/mrichter/AliRoot.git] / FMD / AliFMDGeoSimulator.cxx
CommitLineData
1a1fdef7 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//====================================================================
89ClassImp(AliFMDGeoSimulator)
90#if 0
91 ; // This is here to keep Emacs for indenting the next line
92#endif
93
94//____________________________________________________________________
95AliFMDGeoSimulator::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//____________________________________________________________________
111AliFMDGeoSimulator::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//____________________________________________________________________
134void
135AliFMDGeoSimulator::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();
b60e0f5e 160 fSi = gGeoManager->GetMedium("FMDSi$");
161 fC = gGeoManager->GetMedium("FMDCarbon$");
162 fAl = gGeoManager->GetMedium("FMDAluminum$");
163 fChip = gGeoManager->GetMedium("FMDChip$");
164 fAir = gGeoManager->GetMedium("FMDAir$");
165 fPCB = gGeoManager->GetMedium("FMDPCB$");
166 fPlastic = gGeoManager->GetMedium("FMDPlastic$");
1a1fdef7 167}
168
169//____________________________________________________________________
170TGeoVolume*
171AliFMDGeoSimulator::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//____________________________________________________________________
374TGeoVolume*
375AliFMDGeoSimulator::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//____________________________________________________________________
475TGeoVolume*
476AliFMDGeoSimulator::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//____________________________________________________________________
501TGeoVolume*
502AliFMDGeoSimulator::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//____________________________________________________________________
532TGeoVolume*
533AliFMDGeoSimulator::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//____________________________________________________________________
656void
657AliFMDGeoSimulator::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//