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