]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - FMD/AliFMDGeometryBuilder.cxx
Improved FILE_PATTERNS, EXCLUDE;
[u/mrichter/AliRoot.git] / FMD / AliFMDGeometryBuilder.cxx
... / ...
CommitLineData
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/* $Id$ */
16/** @file AliFMDGeometryBuilder.cxx
17 @author Christian Holm Christensen <cholm@nbi.dk>
18 @date Mon Mar 27 12:41:17 2006
19 @brief Class to build the FMD geometry
20*/
21//____________________________________________________________________
22//
23// Builder of FMD geometry.
24//
25// This class takes care of actually building the geometry using the
26// TGeo classes. Various parameters are fecthed from the
27// AliFMDGeometry manager.
28// Forward Multiplicity Detector based on Silicon wafers. This class
29// contains the base procedures for the Forward Multiplicity detector
30// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
31// which has 1 or 2 rings of silicon sensors.
32//
33//
34
35#include <TArrayD.h> // ROOT_TArrayD
36#include <TGeoManager.h> // ROOT_TGeoManager
37#include <TGeoMatrix.h> // ROOT_TGeoMatrix
38#include <TGeoTube.h> // ROOT_TGeoTube
39#include <TGeoTube.h> // ROOT_TGeoTube
40#include <TGeoVolume.h> // ROOT_TGeoVolume
41#include <TGeoXtru.h> // ROOT_TGeoXtru
42#include <TMath.h>
43#include <TVector2.h> // ROOT_TVector2
44//#include <TGeoMaterial.h> // ROOT_TGeoMaterial
45//#include <TGeoMedium.h> // ROOT_TGeoMedium
46//#include <TGeoPcon.h> // ROOT_TGeoPcon
47//#include <TGeoPolygon.h> // ROOT_TGeoPolygon
48
49#include "AliFMDGeometryBuilder.h" // ALIFMDGEOSIMULATOR_H
50#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
51#include "AliFMDDetector.h" // ALIFMDDETECTOR_H
52#include "AliFMDRing.h" // ALIFMDRING_H
53#include "AliFMD1.h" // ALIFMD1_H
54#include "AliFMD2.h" // ALIFMD2_H
55#include "AliFMD3.h" // ALIFMD3_H
56// #include "AliFMD.h" // ALIFMD_H
57#include "AliFMDDebug.h" // ALILOG_H
58
59//====================================================================
60ClassImp(AliFMDGeometryBuilder)
61#if 0
62 ; // This is here to keep Emacs for indenting the next line
63#endif
64
65//____________________________________________________________________
66const Char_t* AliFMDGeometryBuilder::fgkActiveName = "F%cAC";
67const Char_t* AliFMDGeometryBuilder::fgkSectorName = "F%cSC";
68const Char_t* AliFMDGeometryBuilder::fgkStripName = "F%cST";
69const Char_t* AliFMDGeometryBuilder::fgkSensorName = "F%cSE";
70const Char_t* AliFMDGeometryBuilder::fgkPCBName = "F%cPB";
71const Char_t* AliFMDGeometryBuilder::fgkCuName = "F%cCU";
72const Char_t* AliFMDGeometryBuilder::fgkChipName = "F%cCH";
73const Char_t* AliFMDGeometryBuilder::fgkLongLegName = "F%cLL";
74const Char_t* AliFMDGeometryBuilder::fgkShortLegName = "F%cSL";
75const Char_t* AliFMDGeometryBuilder::fgkFrontVName = "F%cFH";
76const Char_t* AliFMDGeometryBuilder::fgkBackVName = "F%cBH";
77const Char_t* AliFMDGeometryBuilder::fgkRingTopName = "F%cTV";
78const Char_t* AliFMDGeometryBuilder::fgkRingBotName = "F%cBV";
79const Char_t* AliFMDGeometryBuilder::fgkHCName = "F%dH%c";
80const Char_t* AliFMDGeometryBuilder::fgkIHCName = "F%dI%c";
81const Char_t* AliFMDGeometryBuilder::fgkNoseName = "F3SN";
82const Char_t* AliFMDGeometryBuilder::fgkBackName = "F3SB";
83const Char_t* AliFMDGeometryBuilder::fgkBeamName = "F3SL";
84const Char_t* AliFMDGeometryBuilder::fgkFlangeName = "F3SF";
85const Char_t* AliFMDGeometryBuilder::fgkFMDName = "F%dM%c";
86
87//____________________________________________________________________
88AliFMDGeometryBuilder::AliFMDGeometryBuilder()
89 : TTask("FMD", "Geomtry builder"),
90 fActiveId(0),
91 fDetailed(kTRUE),
92 fUseAssembly(kTRUE),
93 fSectorOff(0),
94 fModuleOff(0),
95 fRingOff(0),
96 fDetectorOff(0),
97 fSi(0),
98 fC(0),
99 fAl(0),
100 fPCB(0),
101 fChip(0),
102 fAir(0),
103 fPlastic(0),
104 fCopper(0)
105{
106 // Default constructor
107 fActiveId.Set(2);
108}
109
110//____________________________________________________________________
111AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed)
112 : TTask("FMD", "Geometry builder"),
113 fActiveId(0),
114 fDetailed(detailed),
115 fUseAssembly(kTRUE),
116 fSectorOff(0),
117 fModuleOff(0),
118 fRingOff(0),
119 fDetectorOff(0),
120 fSi(0),
121 fC(0),
122 fAl(0),
123 fPCB(0),
124 fChip(0),
125 fAir(0),
126 fPlastic(0),
127 fCopper(0)
128{
129 // Normal constructor
130 //
131 // Parameters:
132 //
133 // fmd Pointer to AliFMD object
134 // detailed Whether to make a detailed simulation or not
135 //
136 fActiveId.Set(2);
137}
138
139
140//____________________________________________________________________
141TGeoVolume*
142AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r)
143{
144 // Setup the geometry of a ring. The defined TGeoVolume is
145 // returned, and should be used when setting up the rest of the
146 // volumes.
147 //
148 //
149 // Parameters:
150 //
151 // r Pointer to ring geometry object
152 //
153 // Returns:
154 // pointer to ring volume
155 //
156 if (!r) {
157 AliError("Didn't get a ring object");
158 return 0;
159 }
160 Char_t id = r->GetId();
161 Double_t siThick = r->GetSiThickness();
162 const Int_t knv = r->GetNVerticies();
163 TVector2* a = r->GetVertex(5);
164 TVector2* b = r->GetVertex(3);
165 TVector2* c = r->GetVertex(4);
166 Double_t theta = r->GetTheta();
167 Double_t off = (TMath::Tan(TMath::Pi() * theta / 180)
168 * r->GetBondingWidth());
169 Double_t rmax = b->Mod();
170 Double_t rmin = r->GetLowR();
171 Double_t pcbThick = r->GetPrintboardThickness();
172 Double_t cuThick = r->GetCopperThickness();
173 Double_t chipThick= r->GetChipThickness();
174 Double_t modSpace = r->GetModuleSpacing();
175 Double_t legr = r->GetLegRadius();
176 Double_t legl = r->GetLegLength();
177 Double_t legoff = r->GetLegOffset();
178 Int_t ns = r->GetNStrips();
179 Double_t stripoff = a->Mod();
180 Double_t dstrip = (rmax - stripoff) / ns;
181 Double_t space = r->GetSpacing();
182 TArrayD xs(knv);
183 TArrayD ys(knv);
184 for (Int_t i = 0; i < knv; i++) {
185 // Reverse the order
186 TVector2* vv = r->GetVertex(knv - 1 - i);
187 if (!vv) {
188 AliError(Form("Failed to get vertex # %d", knv - 1 - i));
189 continue;
190 }
191 xs[i] = vv->X();
192 ys[i] = vv->Y();
193 }
194
195 // Shape of actual sensor
196 TGeoXtru* sensorShape = new TGeoXtru(2);
197 sensorShape->DefinePolygon(knv, xs.fArray, ys.fArray);
198 sensorShape->DefineSection(0, - siThick/2);
199 sensorShape->DefineSection(1, siThick/2);
200 TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id),
201 sensorShape, fSi);
202 sensorVolume->VisibleDaughters(kFALSE);
203 Int_t sid = sensorVolume->GetNumber();
204 fSectorOff = -1;
205 fModuleOff = 1;
206 fRingOff = 2;
207 fDetectorOff = 3;
208 if (fDetailed) {
209 fSectorOff = 1;
210 fModuleOff = 3;
211 fRingOff = 4;
212 fDetectorOff = 5;
213 // Virtual volume shape to divide - This volume is only defined if
214 // the geometry is set to be detailed.
215 TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2,
216 - theta, theta);
217 TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
218 activeShape,fSi);
219 TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id),
220 2, 2, -theta,0,0,"N");
221 TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id),
222 1, ns, stripoff, dstrip,
223 0, "SX");
224 sid = stripVolume->GetNumber();
225 sensorVolume->AddNodeOverlap(activeVolume, 0);
226 }
227
228 switch (id) {
229 case 'i': case 'I': fActiveId[0] = sid; break;
230 case 'o': case 'O': fActiveId[1] = sid; break;
231 }
232
233 // Shape of Printed circuit Board
234 for (Int_t i = 0; i < knv / 2; i++) ys[i] -= off;
235 for (Int_t i = knv / 2; i < knv; i++) ys[i] += off;
236 TGeoXtru* pcbShape = new TGeoXtru(2);
237 pcbShape->DefinePolygon(knv, xs.fArray, ys.fArray);
238 pcbShape->DefineSection(0, - pcbThick/2);
239 pcbShape->DefineSection(1, pcbThick/2);
240 TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id),
241 pcbShape, fPCB);
242
243 // Copper layer
244 TGeoXtru* cuShape = new TGeoXtru(2);
245 cuShape->DefinePolygon(6, xs.fArray, ys.fArray);
246 cuShape->DefineSection(0, - cuThick/2);
247 cuShape->DefineSection(1, cuThick/2);
248 TGeoVolume* cuVolume = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper);
249
250 // Chip layer
251 TGeoXtru* chipShape = new TGeoXtru(2);
252 chipShape->DefinePolygon(6, xs.fArray, ys.fArray);
253 chipShape->DefineSection(0, - chipThick/2);
254 chipShape->DefineSection(1, chipThick/2);
255 TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id),
256 chipShape,fChip);
257
258 // Short leg shape
259 TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2);
260 TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id),
261 shortLegShape, fPlastic);
262
263 // Long leg shape
264 TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2);
265 TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id),
266 longLegShape, fPlastic);
267
268
269 // Back container volume
270 TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id));
271 Double_t x = 0;
272 Double_t y = 0;
273 Double_t z = pcbThick / 2;
274 backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
275 z += (pcbThick + cuThick) / 2;
276 backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
277 z += (cuThick + chipThick) / 2;
278 backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
279 x = a->X() + legoff + legr;
280 y = 0;
281 z += pcbThick / 2 + legl / 2;
282 backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z));
283 x = c->X();
284 y = c->Y() - legoff - legr - off;
285 backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z));
286 y = -y;
287 backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z));
288
289 // Front container volume
290 TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
291 x = 0;
292 y = 0;
293 z = pcbThick / 2;
294 frontVolume->AddNode(pcbVolume, 1, new TGeoTranslation(x,y,z));
295 z += (pcbThick + cuThick) / 2;
296 frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
297 z += (cuThick + chipThick) / 2;
298 frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
299 x = a->X() + legoff + legr;
300 y = 0;
301 z += pcbThick / 2 + (legl + modSpace)/ 2;
302 frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z));
303 x = c->X();
304 y = c->Y() - legoff - legr - off;
305 frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z));
306 y = -y;
307 frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z));
308
309 // Half ring mother volumes.
310 TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
311 TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
312 TGeoVolume* halfRing = ringTopVolume;
313
314 // Adding modules to half-rings
315 Int_t nmod = r->GetNModules();
316 AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
317 for (Int_t i = 0; i < nmod; i++) {
318 if (i == nmod / 2) halfRing = ringBotVolume;
319 Bool_t front = (i % 2 == 0);
320 Double_t z1 = siThick / 2 + (i % 2) * modSpace;
321 Double_t z2 = z1 + siThick / 2 + space;
322 Double_t th = (2 * i + 1) * theta;
323 TGeoVolume* vol = (front ? frontVolume : backVolume);
324 AliFMDDebug(20, ("Placing copy %d of %s and %s in %s at z=%f and %f, "
325 "and theta=%f", i, sensorVolume->GetName(),
326 vol->GetName(), halfRing->GetName(), z1, z2, th));
327 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
328 mat1->RotateZ(th);
329 halfRing->AddNode(sensorVolume, i, mat1);
330 TGeoMatrix* mat2 = new TGeoCombiTrans(0,0,z2,0);
331 mat2->RotateZ(th);
332 halfRing->AddNode(vol, i, mat2);
333 }
334
335 return 0;
336}
337
338//____________________________________________________________________
339TGeoVolume*
340AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d,
341 TGeoVolume* topMother,
342 TGeoVolume* botMother,
343 Double_t zMother,
344 TGeoVolume* innerTop,
345 TGeoVolume* innerBot,
346 TGeoVolume* outerTop,
347 TGeoVolume* outerBot)
348{
349 // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
350 // This includes putting the Honeycomb support plates and the rings
351 // into the mother volumes.
352 //
353 // Parameeters:
354 // d The detector geometry to use
355 // mother The mother volume of the detector
356 // zmother The midpoint in global coordinates of detector vol.
357 // inner Pointer to inner ring volume
358 // outer Pointer to outer ring volume
359 //
360 // Returns:
361 // Pointer to mother (detector volume)
362 //
363 if (!d) return 0;
364 // Loop over the defined rings
365 for (int i = 0; i < 2; i++) {
366 AliFMDRing* r = 0;
367 Double_t lowr = 0;
368 Double_t highr = 0;
369 Double_t rz = 0;
370 TGeoVolume* tvol = 0;
371 TGeoVolume* bvol = 0;
372 switch (i) {
373 case 0:
374 r = d->GetInner();
375 lowr = d->GetInnerHoneyLowR();
376 highr = d->GetInnerHoneyHighR();
377 rz = d->GetInnerZ();
378 tvol = innerTop;
379 bvol = innerBot;
380 break;
381 case 1:
382 r = d->GetOuter();
383 lowr = d->GetOuterHoneyLowR();
384 highr = d->GetOuterHoneyHighR();
385 rz = d->GetOuterZ();
386 tvol = outerTop;
387 bvol = outerBot;
388 break;
389 }
390 if (!r) continue;
391 Char_t c = r->GetId();
392 Int_t id = d->GetId();
393 Double_t hcThick = d->GetHoneycombThickness();
394 Double_t alThick = d->GetAlThickness();
395 Double_t z = TMath::Abs(rz - zMother);
396
397 // Place ring in mother volume
398 // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
399 AliFMDDebug(5, ("Placing volumes %s and %s in %s and %s at z=%f",
400 tvol->GetName(), bvol->GetName(),
401 topMother->GetName(), botMother->GetName(), z));
402 topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
403 botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
404
405 // Top of Honeycomb
406 TGeoTubeSeg* hcSha = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180);
407 TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
408 // Air in top of honeycomb
409 TGeoTubeSeg* ihcSha = new TGeoTubeSeg(lowr+alThick, highr - alThick,
410 (hcThick-alThick)/2, 0, 180);
411 TGeoVolume* ihcVol = new TGeoVolume(Form(fgkIHCName,id,c),ihcSha,fAir);
412 hcVol->AddNode(ihcVol, 0);
413 hcVol->VisibleDaughters(kFALSE);
414 hcVol->SetVisibility(kTRUE);
415
416 z += (r->GetSiThickness() +
417 r->GetSpacing() +
418 r->GetPrintboardThickness() +
419 r->GetCopperThickness() +
420 r->GetChipThickness() +
421 r->GetModuleSpacing() +
422 r->GetLegLength() +
423 hcThick / 2);
424
425 AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f",
426 hcVol->GetName(), topMother->GetName(),
427 botMother->GetName(), z));
428 // Add to top
429 topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
430
431 // Add to bottom
432 TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0);
433 bhcMatrix->RotateZ(180);
434 botMother->AddNode(hcVol, 1, bhcMatrix);
435 }
436 return 0;
437}
438
439//____________________________________________________________________
440TGeoVolume*
441AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1,
442 TGeoVolume* innerTop,
443 TGeoVolume* innerBot)
444{
445 // Setup the FMD1 geometry. The FMD1 only has one ring, and no
446 // special support as it is at the momement.
447 //
448 // See also AliFMDGeometryBuilder::DetectorGeometry
449 //
450 if (!fmd1 || !innerTop || !innerBot) return 0;
451 Double_t z = fmd1->GetInnerZ();
452 TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
453 fmd1->GetId(), 'T'));
454 TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
455 fmd1->GetId(), 'B'));
456
457 // Basic detector geometry
458 DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z,
459 innerTop, innerBot, 0, 0);
460
461 // Must add this after filling the assembly.
462 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
463 TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
464 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
465 fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
466 top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
467 top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
468
469 return 0;
470}
471
472//____________________________________________________________________
473TGeoVolume*
474AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2,
475 TGeoVolume* innerTop,
476 TGeoVolume* innerBot,
477 TGeoVolume* outerTop,
478 TGeoVolume* outerBot)
479{
480 // Setup the FMD2 geometry. The FMD2 has no
481 // special support as it is at the momement.
482 //
483 // See also AliFMDGeometryBuilder::DetectorGeometry
484 //
485 if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
486 Double_t z = fmd2->GetOuterZ();
487 TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
488 fmd2->GetId(), 'T'));
489 TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
490 fmd2->GetId(), 'B'));
491
492 DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z,
493 innerTop, innerBot, outerTop, outerBot);
494
495 // Must be done after filling the assemblies
496 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
497 TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
498 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
499 fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
500 top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
501 top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
502
503 return 0;
504}
505
506//____________________________________________________________________
507TGeoVolume*
508AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3,
509 TGeoVolume* innerTop,
510 TGeoVolume* innerBot,
511 TGeoVolume* outerTop,
512 TGeoVolume* outerBot)
513{
514 // Setup the FMD3 geometry. The FMD2 has a rather elaborate support
515 // structure, as the support will also support the vacuum
516 // beam-pipe.
517 //
518 // See also AliFMDGeometryBuilder::DetectorGeometry
519 //
520 if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
521 Double_t nlen = fmd3->GetNoseLength();
522 Double_t nz = fmd3->GetNoseZ();
523 Double_t noser1 = fmd3->GetNoseLowR();
524 Double_t noser2 = fmd3->GetNoseHighR();
525 Double_t conel = fmd3->GetConeLength();
526 Double_t backl = fmd3->GetBackLength();
527 Double_t backr1 = fmd3->GetBackLowR();
528 Double_t backr2 = fmd3->GetBackHighR();
529 Double_t zdist = conel - backl - nlen;
530 Double_t tdist = backr2 - noser2;
531 Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist);
532 Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
533 Double_t flanger = fmd3->GetFlangeR();
534 Double_t z = fmd3->GetInnerZ(); // fmd3->GetZ();
535 Double_t zi;
536
537 TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
538 fmd3->GetId(), 'T'));
539 TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
540 fmd3->GetId(), 'B'));
541
542
543 DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z,
544 innerTop, innerBot, outerTop, outerBot);
545
546
547 // Nose volume
548 TGeoTubeSeg* noseShape = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180);
549 TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
550 zi = -nz + nlen / 2 + z;
551
552 fmd3TopVolume->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, zi));
553 TGeoMatrix* nmatrix = new TGeoCombiTrans(0, 0, zi, 0);
554 nmatrix->RotateZ(180);
555 fmd3BotVolume->AddNode(noseVolume, 1, nmatrix);
556
557 // Back
558 TGeoTubeSeg* backShape = new TGeoTubeSeg(backr1, backr2, backl / 2, 0, 180);
559 TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC);
560 zi = -nz + conel - backl / 2 + z;
561 fmd3TopVolume->AddNode(backVolume, 0, new TGeoTranslation(0, 0, zi));
562 TGeoMatrix* bmatrix = new TGeoCombiTrans(0, 0, zi, 0);
563 bmatrix->RotateZ(180);
564 fmd3BotVolume->AddNode(backVolume, 1, bmatrix);
565
566
567 Int_t n;
568 Double_t r;
569 // The flanges
570 TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2,
571 fmd3->GetBeamWidth() / 2,
572 backl / 2);
573 TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC);
574 n = fmd3->GetNFlange();
575 r = backr2 + (flanger - backr2) / 2;
576 TGeoVolume* mother = fmd3TopVolume;
577 for (Int_t i = 0; i < n; i++) {
578 if (i >= n / 2) mother = fmd3BotVolume;
579 Double_t phi = 360. / n * i + 180. / n;
580 Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi);
581 Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi);
582 AliFMDDebug(15, ("Placing flange %d in %s at (%f,%f,%f) r=%f, phi=%f",
583 i, mother->GetName(), x, y, zi, r, phi));
584 TGeoRotation* rot = new TGeoRotation;
585 rot->RotateZ(phi);
586 TGeoMatrix* matrix = new TGeoCombiTrans(x, y, zi, rot);
587 mother->AddNode(flangeVolume, i, matrix);
588 }
589
590 // The Beams
591 TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2,
592 fmd3->GetBeamWidth() / 2 - .1,
593 beaml / 2);
594 TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC);
595 n = fmd3->GetNBeam();
596 r = noser2 + tdist / 2;
597 zi = - nz + nlen + zdist / 2 + z;
598 mother = fmd3TopVolume;
599 for (Int_t i = 0; i < n; i++) {
600 if (i >= n / 2) mother = fmd3BotVolume;
601 Double_t phi = 360. / n * i;
602 Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi);
603 Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi);
604 TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i));
605 // Order is important
606 rot->RotateY(-theta);
607 rot->RotateZ(phi);
608 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam trans %d", i),
609 x, y, zi, rot);
610 mother->AddNode(beamVolume, i, matrix);
611 }
612
613 z = fmd3->GetInnerZ();
614 TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
615 rot->RotateY(180);
616 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
617 TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
618 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
619 fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
620 top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
621 top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
622
623 return 0;
624}
625
626//____________________________________________________________________
627void
628AliFMDGeometryBuilder::Exec(Option_t*)
629{
630 // Setup up the FMD geometry.
631 AliFMDDebug(1, ("\tGeometry options: %s",
632 (fDetailed ? "divided into strips" : "one volume")));
633 if (!gGeoManager) {
634 AliFatal("No TGeoManager defined");
635 return;
636 }
637
638 fSi = gGeoManager->GetMedium("FMD_Si$");
639 fC = gGeoManager->GetMedium("FMD_Carbon$");
640 fAl = gGeoManager->GetMedium("FMD_Aluminum$");
641 fChip = gGeoManager->GetMedium("FMD_Si Chip$");
642 fAir = gGeoManager->GetMedium("FMD_Air$");
643 fPCB = gGeoManager->GetMedium("FMD_PCB$");
644 fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
645 fCopper = gGeoManager->GetMedium("FMD_Copper$");
646
647 if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper) {
648 AliError("Failed to get some or all tracking mediums");
649 return;
650 }
651 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
652 AliFMDRing* inner = fmd->GetInner();
653 AliFMDRing* outer = fmd->GetOuter();
654 RingGeometry(inner);
655 RingGeometry(outer);
656 TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
657 inner->GetId()));
658 TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
659 inner->GetId()));
660 TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
661 outer->GetId()));
662 TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
663 outer->GetId()));
664
665 FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
666 FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
667 FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
668#ifndef USE_PRE_MOVE
669 fmd->SetSectorOff(fSectorOff);
670 fmd->SetModuleOff(fModuleOff);
671 fmd->SetRingOff(fRingOff);
672 fmd->SetDetectorOff(fDetectorOff);
673 fmd->SetActive(fActiveId.fArray, fActiveId.fN);
674#endif
675 // fmd->ExtractGeomInfo();
676
677}
678
679
680//____________________________________________________________________
681//
682// EOF
683//