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