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