1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
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
21 //____________________________________________________________________
23 // Builder of FMD geometry.
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.
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 <TGeoTrd1.h> // ROOT_TGeoTrd1
40 #include <TGeoCone.h> // ROOT_TGeoTrd1
41 #include <TGeoVolume.h> // ROOT_TGeoVolume
42 #include <TGeoXtru.h> // ROOT_TGeoXtru
43 #include <TGeoCompositeShape.h>
45 #include <TVector2.h> // ROOT_TVector2
46 //#include <TGeoMaterial.h> // ROOT_TGeoMaterial
47 //#include <TGeoMedium.h> // ROOT_TGeoMedium
48 //#include <TGeoPcon.h> // ROOT_TGeoPcon
49 //#include <TGeoPolygon.h> // ROOT_TGeoPolygon
51 #include "AliFMDGeometryBuilder.h" // ALIFMDGEOSIMULATOR_H
52 #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
53 #include "AliFMDDetector.h" // ALIFMDDETECTOR_H
54 #include "AliFMDRing.h" // ALIFMDRING_H
55 #include "AliFMD1.h" // ALIFMD1_H
56 #include "AliFMD2.h" // ALIFMD2_H
57 #include "AliFMD3.h" // ALIFMD3_H
58 // #include "AliFMD.h" // ALIFMD_H
59 #include "AliFMDDebug.h" // ALILOG_H
61 //====================================================================
62 ClassImp(AliFMDGeometryBuilder)
64 ; // This is here to keep Emacs for indenting the next line
67 //____________________________________________________________________
68 const Char_t* AliFMDGeometryBuilder::fgkActiveName = "F%cAC";
69 const Char_t* AliFMDGeometryBuilder::fgkSectorName = "F%cSC";
70 const Char_t* AliFMDGeometryBuilder::fgkStripName = "F%cST";
71 const Char_t* AliFMDGeometryBuilder::fgkSensorName = "F%cSE";
72 const Char_t* AliFMDGeometryBuilder::fgkPCBName = "F%cPB";
73 const Char_t* AliFMDGeometryBuilder::fgkCuName = "F%cCU";
74 const Char_t* AliFMDGeometryBuilder::fgkChipName = "F%cCH";
75 const Char_t* AliFMDGeometryBuilder::fgkLongLegName = "F%cLL";
76 const Char_t* AliFMDGeometryBuilder::fgkShortLegName = "F%cSL";
77 const Char_t* AliFMDGeometryBuilder::fgkFrontVName = "F%cFH";
78 const Char_t* AliFMDGeometryBuilder::fgkBackVName = "F%cBH";
79 const Char_t* AliFMDGeometryBuilder::fgkRingTopName = "F%cTV";
80 const Char_t* AliFMDGeometryBuilder::fgkRingBotName = "F%cBV";
81 const Char_t* AliFMDGeometryBuilder::fgkHCName = "F%dH%c";
82 const Char_t* AliFMDGeometryBuilder::fgkIHCName = "F%dI%c";
83 const Char_t* AliFMDGeometryBuilder::fgkNoseName = "F3SN";
84 const Char_t* AliFMDGeometryBuilder::fgkBackName = "F%dSB";
85 const Char_t* AliFMDGeometryBuilder::fgkTopName = "F%dSU";
86 const Char_t* AliFMDGeometryBuilder::fgkBeamName = "F%dSL";
87 const Char_t* AliFMDGeometryBuilder::fgkFlangeName = "F%dSF";
88 const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName = "F%cDC";
89 const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName = "F%cDP";
90 const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName = "F%cDI";
91 const Char_t* AliFMDGeometryBuilder::fgkFMDDName = "F%cDD";
92 const Char_t* AliFMDGeometryBuilder::fgkFMDName = "F%dM%c";
94 //____________________________________________________________________
95 AliFMDGeometryBuilder::AliFMDGeometryBuilder()
96 : TTask("FMD", "Geomtry builder"),
114 // Default constructor
118 //____________________________________________________________________
119 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed)
120 : TTask("FMD", "Geometry builder"),
138 // Normal constructor
142 // fmd Pointer to AliFMD object
143 // detailed Whether to make a detailed simulation or not
149 //____________________________________________________________________
151 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r)
153 // Setup the geometry of a ring. The defined TGeoVolume is
154 // returned, and should be used when setting up the rest of the
160 // r Pointer to ring geometry object
163 // pointer to ring volume
166 AliError("Didn't get a ring object");
169 Char_t id = r->GetId();
170 const Char_t* lName = (id == 'i' || id == 'I' ? "inner" : "outer");
171 Double_t siThick = r->GetSiThickness();
172 const Int_t knv = r->GetNVerticies();
173 TVector2* a = r->GetVertex(5);
174 TVector2* b = r->GetVertex(3);
175 TVector2* c = r->GetVertex(4);
176 Double_t theta = r->GetTheta();
177 Double_t off = (TMath::Tan(TMath::Pi() * theta / 180)
178 * r->GetBondingWidth());
179 Double_t rmax = b->Mod();
180 Double_t rmin = r->GetLowR();
181 Double_t pcbThick = r->GetPrintboardThickness();
182 Double_t cuThick = r->GetCopperThickness();
183 Double_t chipThick= r->GetChipThickness();
184 Double_t modSpace = r->GetModuleSpacing();
185 Double_t legr = r->GetLegRadius();
186 Double_t legl = r->GetLegLength();
187 Double_t legoff = r->GetLegOffset();
188 Int_t ns = r->GetNStrips();
189 Double_t stripoff = a->Mod();
190 Double_t dstrip = (rmax - stripoff) / ns;
191 Double_t space = r->GetSpacing();
194 for (Int_t i = 0; i < knv; i++) {
196 TVector2* vv = r->GetVertex(knv - 1 - i);
198 AliError(Form("Failed to get vertex # %d", knv - 1 - i));
205 // Shape of actual sensor
206 TGeoXtru* sensorShape = new TGeoXtru(2);
207 sensorShape->DefinePolygon(knv, xs.fArray, ys.fArray);
208 sensorShape->DefineSection(0, - siThick/2);
209 sensorShape->DefineSection(1, siThick/2);
210 sensorShape->SetName(Form(fgkSensorName, id));
211 sensorShape->SetTitle(Form("FMD %s Sensor", lName));
212 TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id),
214 sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
215 sensorVolume->VisibleDaughters(kFALSE);
216 Int_t sid = sensorVolume->GetNumber();
226 // Virtual volume shape to divide - This volume is only defined if
227 // the geometry is set to be detailed.
228 TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2,
230 activeShape->SetName(Form(fgkActiveName, id));
231 activeShape->SetTitle(Form("FMD %s active area", lName));
232 TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
234 activeVolume->SetTitle(Form("FMD %s active area", lName));
235 TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id),
236 2, 2, -theta,0,0,"N");
237 sectorVolume->SetTitle(Form("FMD %s sector", lName));
238 TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id),
239 1, ns, stripoff, dstrip,
241 stripVolume->SetTitle(Form("FMD %s strip", lName));
242 sid = stripVolume->GetNumber();
243 sensorVolume->AddNodeOverlap(activeVolume, 0);
247 case 'i': case 'I': fActiveId[0] = sid; break;
248 case 'o': case 'O': fActiveId[1] = sid; break;
251 // Shape of Printed circuit Board
252 for (Int_t i = 0; i < knv / 2; i++) ys[i] -= off;
253 for (Int_t i = knv / 2; i < knv; i++) ys[i] += off;
254 TGeoXtru* pcbShape = new TGeoXtru(2);
255 pcbShape->DefinePolygon(knv, xs.fArray, ys.fArray);
256 pcbShape->DefineSection(0, - pcbThick/2);
257 pcbShape->DefineSection(1, pcbThick/2);
258 pcbShape->SetName(Form(fgkPCBName, id));
259 pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
260 TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id),
262 pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
265 TGeoXtru* cuShape = new TGeoXtru(2);
266 cuShape->DefinePolygon(6, xs.fArray, ys.fArray);
267 cuShape->DefineSection(0, - cuThick/2);
268 cuShape->DefineSection(1, cuThick/2);
269 cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
270 TGeoVolume* cuVolume = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper);
271 cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
274 TGeoXtru* chipShape = new TGeoXtru(2);
275 chipShape->DefinePolygon(6, xs.fArray, ys.fArray);
276 chipShape->DefineSection(0, - chipThick/2);
277 chipShape->DefineSection(1, chipThick/2);
278 chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
279 TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id),
281 chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
284 TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2);
285 shortLegShape->SetName(Form(fgkShortLegName, id));
286 shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
287 TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id),
288 shortLegShape, fCopper);
289 shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
291 TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2);
292 longLegShape->SetName(Form(fgkLongLegName, id));
293 longLegShape->SetTitle(Form("FMD %s long support foot", lName));
294 TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id),
295 longLegShape, fCopper);
296 longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
299 // Back container volume
300 TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id));
301 backVolume->SetTitle(Form("FMD %s back module", lName));
304 Double_t z = siThick / 2;
305 backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
306 z += siThick / 2 + space + pcbThick / 2;
307 backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
308 z += (pcbThick + cuThick) / 2;
309 backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
310 z += (cuThick + chipThick) / 2;
311 backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
312 x = a->X() + legoff + legr;
314 z += pcbThick / 2 + legl / 2;
315 backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z));
317 y = c->Y() - legoff - legr - off;
318 backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z));
320 backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z));
322 // Front container volume
323 TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
324 frontVolume->SetTitle(Form("FMD %s front module", lName));
328 frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
329 z += siThick / 2 + space + pcbThick / 2;
330 frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
331 z += (pcbThick + cuThick) / 2;
332 frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
333 z += (cuThick + chipThick) / 2;
334 frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
335 x = a->X() + legoff + legr;
337 z += pcbThick / 2 + (legl + modSpace)/ 2;
338 frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z));
340 y = c->Y() - legoff - legr - off;
341 frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z));
343 frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z));
347 Double_t ddlr = r->GetFMDDLowR();
348 Double_t ddhr = r->GetFMDDHighR();
349 Double_t ddpt = r->GetFMDDPrintboardThickness();
350 Double_t ddct = r->GetFMDDCopperThickness();
351 Double_t ddit = r->GetFMDDChipThickness();
352 Double_t ddt = ddpt + ddct + ddit;
354 TGeoShape* fmddPcbShape = new TGeoTubeSeg(ddlr, ddhr, ddpt/2,0,180);
355 TGeoShape* fmddCuShape = new TGeoTubeSeg(ddlr, ddhr, ddct/2,0,180);
356 TGeoShape* fmddChipShape = new TGeoTubeSeg(ddlr, ddhr, ddit/2,0,180);
357 fmddPcbShape->SetName(Form(fgkFMDDPCBName, id));
358 fmddCuShape->SetName(Form(fgkFMDDCuName, id));
359 fmddChipShape->SetName(Form(fgkFMDDChipName, id));
360 if (id == 'O' || id == 'o') {
361 TString pcbName(fmddPcbShape->GetName());
362 TString cuName(fmddCuShape->GetName());
363 TString chipName(fmddChipShape->GetName());
365 fmddPcbShape->SetName(Form("%s_inner", pcbName.Data()));
366 fmddCuShape->SetName(Form("%s_inner", cuName.Data()));
367 fmddChipShape->SetName(Form("%s_inner", chipName.Data()));
368 new TGeoBBox(Form("%s_clip", pcbName.Data()), ddlr+3, ddhr/2, ddpt);
369 new TGeoBBox(Form("%s_clip", cuName.Data()), ddlr+3, ddhr/2, ddpt);
370 new TGeoBBox(Form("%s_clip", chipName.Data()),ddlr+3, ddhr/2, ddpt);
371 TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
374 trans->RegisterYourself();
375 fmddPcbShape = new TGeoCompositeShape(pcbName.Data(),
376 Form("%s_inner*%s_clip:%s_trans",
380 fmddCuShape = new TGeoCompositeShape(cuName.Data(),
381 Form("%s_inner*%s_clip:%s_trans",
385 fmddChipShape = new TGeoCompositeShape(chipName.Data(),
386 Form("%s_inner*%s_clip:%s_trans",
391 fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
392 fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
393 fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
395 TGeoVolume* fmddPcbVolume = new TGeoVolume(Form(fgkFMDDPCBName, id),
397 TGeoVolume* fmddCuVolume = new TGeoVolume(Form(fgkFMDDCuName, id),
398 fmddCuShape, fCopper);
399 TGeoVolume* fmddChipVolume= new TGeoVolume(Form(fgkFMDDChipName, id),
400 fmddChipShape, fChip);
401 fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
402 fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
403 fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
405 // Half ring mother volumes.
406 TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
407 TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
408 TGeoVolume* halfRing = ringTopVolume;
409 ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
410 ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
412 // Adding modules to half-rings
413 Int_t nmod = r->GetNModules();
414 AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
415 for (Int_t i = 0; i < nmod; i++) {
416 if (i == nmod / 2) halfRing = ringBotVolume;
417 Bool_t front = (i % 2 == 0);
418 TGeoVolume* vol = (front ? frontVolume : backVolume);
419 // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
420 Double_t z1 = (i % 2) * modSpace;
421 Double_t th = (2 * i + 1) * theta;
422 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
424 mat1->SetName(Form("FMD%c_module_%02d", id, i));
425 mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
426 halfRing->AddNode(vol, i, mat1);
428 Double_t z2 = z1 + siThick / 2 + space;
429 Double_t th = (2 * i + 1) * theta;
430 AliFMDDebug(20, ("Placing copy %d of %s and %s in %s at z=%f and %f, "
431 "and theta=%f", i, sensorVolume->GetName(),
432 vol->GetName(), halfRing->GetName(), z1, z2, th));
433 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
435 halfRing->AddNode(sensorVolume, i, mat1);
436 TGeoMatrix* mat2 = new TGeoCombiTrans(0,0,z2,0);
438 halfRing->AddNode(vol, i, mat2);
443 Double_t zi = r->GetFullDepth() - ddt;
445 for (Int_t i = 0; i < n; i++) {
446 halfRing = (i == 0 ? ringTopVolume : ringBotVolume);
447 Double_t phi = 360. / n * i;
448 TGeoRotation* rot = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
450 rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
452 halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
453 z += (ddpt + ddct) / 2;
454 halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
455 z += (ddct + ddit) / 2;
456 halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
463 //____________________________________________________________________
465 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d,
466 TGeoVolume* topMother,
467 TGeoVolume* botMother,
469 TGeoVolume* innerTop,
470 TGeoVolume* innerBot,
471 TGeoVolume* outerTop,
472 TGeoVolume* outerBot)
474 // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
475 // This includes putting the Honeycomb support plates and the rings
476 // into the mother volumes.
479 // d The detector geometry to use
480 // mother The mother volume of the detector
481 // zmother The midpoint in global coordinates of detector vol.
482 // inner Pointer to inner ring volume
483 // outer Pointer to outer ring volume
486 // Pointer to mother (detector volume)
489 // Loop over the defined rings
490 for (int i = 0; i < 2; i++) {
495 TGeoVolume* tvol = 0;
496 TGeoVolume* bvol = 0;
500 lowr = d->GetInnerHoneyLowR();
501 highr = d->GetInnerHoneyHighR();
508 lowr = d->GetOuterHoneyLowR();
509 highr = d->GetOuterHoneyHighR();
516 Char_t c = r->GetId();
517 Int_t id = d->GetId();
518 Double_t hcThick = r->GetHoneycombThickness();
519 Double_t alThick = r->GetAlThickness();
520 Double_t z = TMath::Abs(rz - zMother);
522 // Place ring in mother volume
523 // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
524 AliFMDDebug(1, ("Placing volumes %s and %s in %s and %s at z=%f",
525 tvol->GetName(), bvol->GetName(),
526 topMother->GetName(), botMother->GetName(), z));
527 topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
528 botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
531 TGeoTubeSeg* hcSha = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180);
532 hcSha->SetName(Form(fgkHCName,id,c));
533 hcSha->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
534 TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
535 hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
536 // Air in top of honeycomb
537 TGeoTubeSeg* ihcSha = new TGeoTubeSeg(lowr+alThick, highr - alThick,
538 (hcThick-alThick)/2, 0, 180);
539 ihcSha->SetName(Form(fgkIHCName,id,c));
540 ihcSha->SetTitle(Form("FMD%d%c honeycomb internal", id, c));
541 TGeoVolume* ihcVol = new TGeoVolume(Form(fgkIHCName,id,c),ihcSha,fAir);
542 ihcVol->SetTitle(Form("FMD%d%c honeycomb internal", id, c));
543 hcVol->AddNode(ihcVol, 0);
544 hcVol->VisibleDaughters(kFALSE);
545 hcVol->SetVisibility(kTRUE);
547 z += (r->GetSiThickness() +
549 r->GetPrintboardThickness() +
550 r->GetCopperThickness() +
551 r->GetChipThickness() +
552 r->GetModuleSpacing() +
554 r->GetHoneycombThickness() +
555 r->GetFMDDPrintboardThickness() -
558 AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f",
559 hcVol->GetName(), topMother->GetName(),
560 botMother->GetName(), z));
562 topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
565 TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0);
566 bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
567 bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
568 bhcMatrix->RotateZ(180);
569 botMother->AddNode(hcVol, 1, bhcMatrix);
574 //____________________________________________________________________
576 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1,
577 TGeoVolume* innerTop,
578 TGeoVolume* innerBot)
580 // Setup the FMD1 geometry. The FMD1 only has one ring, and no
581 // special support as it is at the momement.
583 // See also AliFMDGeometryBuilder::DetectorGeometry
585 if (!fmd1 || !innerTop || !innerBot) return 0;
586 AliFMDRing* r = fmd1->GetInner();
587 Double_t z = fmd1->GetInnerZ();
589 Double_t backlr = fmd1->GetInnerHoneyHighR();
590 Double_t backhr = fmd1->GetInnerHoneyHighR()+5;
591 Double_t backth = 0.2;
592 Double_t toplr = r->GetLowR();
593 Double_t tophr = fmd1->GetInnerHoneyHighR()+disce;
594 Double_t wallbh = (r->GetFullDepth() + disce);
595 Double_t wallth = wallbh+0.1;
597 TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
598 fmd1->GetId(), 'T'));
599 fmd1TopVolume->SetTitle("FMD1 top half");
600 TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
601 fmd1->GetId(), 'B'));
602 fmd1BotVolume->SetTitle("FMD1 bottom half");
604 // Basic detector geometry
605 DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z,
606 innerTop, innerBot, 0, 0);
610 TGeoTubeSeg* backShape = new TGeoTubeSeg(backlr, backhr, backth / 2, 0, 180);
611 TGeoTubeSeg* wallbShape = new TGeoTubeSeg(backlr, backlr + backth,
613 TGeoTubeSeg* topShape = new TGeoTubeSeg(toplr, tophr, backth / 2, 0, 180);
614 TGeoTubeSeg* walltShape = new TGeoTubeSeg(tophr, tophr + backth,
616 TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackName, fmd1->GetId()),
618 TGeoVolume* wallbVolume= new TGeoVolume(Form(fgkFlangeName, fmd1->GetId()),
620 TGeoVolume* topVolume = new TGeoVolume(Form(fgkTopName, fmd1->GetId()),
622 TGeoVolume* walltVolume= new TGeoVolume(Form(fgkBeamName, fmd1->GetId()),
624 backShape->SetName(Form(fgkBackName, fmd1->GetId()));
625 wallbShape->SetName(Form(fgkFlangeName, fmd1->GetId()));
626 topShape->SetName(Form(fgkTopName, fmd1->GetId()));
627 walltShape->SetName(Form(fgkBeamName, fmd1->GetId()));
628 backShape->SetTitle("FMD1 back saucer rim");
629 wallbShape->SetTitle("FMD1 back saucer wall");
630 topShape->SetTitle("FMD1 top lid");
631 walltShape->SetTitle("FMD1 top lid wall");
632 backVolume->SetFillColor(kGray);
633 topVolume->SetFillColor(kGray);
634 wallbVolume->SetFillColor(kGray);
635 walltVolume->SetFillColor(kGray);
636 backVolume->SetTitle("FMD1 back saucer rim");
637 wallbVolume->SetTitle("FMD1 back saucer wall");
638 topVolume->SetTitle("FMD1 top lid");
639 walltVolume->SetTitle("FMD1 top lid wall");
642 Double_t zb = TMath::Abs(fmd1->GetInnerZ() - z);
647 zi -= disce / 2 + backth / 2;
649 for (Int_t i = 0; i < 2; i++) {
650 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
651 Double_t phi = 360. / n * i;
652 TGeoRotation* rot = new TGeoRotation(Form("FMD1 top rotation %d",i));
654 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 top wall trans %d", i),
656 mother->AddNode(topVolume, i, matrix);
659 zi += wallth / 2 + backth / 2;
660 for (Int_t i = 0; i < 2; i++) {
661 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
662 Double_t phi = 360. / n * i;
663 TGeoRotation* rot = new TGeoRotation(Form("FMD1 outer wall rotation %d",
666 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 outer wall trans %d",
668 mother->AddNode(walltVolume, i, matrix);
671 zi += wallth / 2 + backth / 2; // + disce / 2;
672 for (Int_t i = 0; i < 2; i++) {
673 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
674 Double_t phi = 360. / n * i;
675 TGeoRotation* rot = new TGeoRotation(Form("FMD1 back rotation %d", i));
677 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 back trans %d", i),
679 mother->AddNode(backVolume, i, matrix);
682 zi -= wallbh / 2 + backth / 2; // + disce / 2;
683 for (Int_t i = 0; i < 2; i++) {
684 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
685 Double_t phi = 360. / n * i;
686 TGeoRotation* rot = new TGeoRotation(Form("FMD1 inner wall rotation %d",
689 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 inner wall trans %d",
691 mother->AddNode(wallbVolume, i, matrix);
695 // Must add this after filling the assembly.
696 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
697 // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
698 TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
700 TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
701 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
702 fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
703 top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
704 top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
709 //____________________________________________________________________
711 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2,
712 TGeoVolume* innerTop,
713 TGeoVolume* innerBot,
714 TGeoVolume* outerTop,
715 TGeoVolume* outerBot)
717 // Setup the FMD2 geometry. The FMD2 has no
718 // special support as it is at the momement.
720 // See also AliFMDGeometryBuilder::DetectorGeometry
722 if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
723 AliFMDRing* r = fmd2->GetOuter();
724 Double_t z = fmd2->GetOuterZ();
725 Double_t framelr = fmd2->GetOuterHoneyHighR()+0.5;
726 Double_t framehr = fmd2->GetOuterHoneyHighR()+1.8;
727 Double_t framelz = -1;
728 Double_t framehz = (fmd2->GetInnerZ()-z) + r->GetFullDepth() + 1;
729 Double_t framel = framehz - framelz;
730 Double_t coverlr = fmd2->GetInner()->GetLowR()+1;
731 Double_t backth = 0.05;
733 TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
734 fmd2->GetId(), 'T'));
735 TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
736 fmd2->GetId(), 'B'));
737 fmd2TopVolume->SetTitle("FMD2 top half");
738 fmd2BotVolume->SetTitle("FMD2 bottom half");
740 DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z,
741 innerTop, innerBot, outerTop, outerBot);
743 TGeoShape* cylinderShape = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
744 TGeoVolume* cylinderVolume = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
746 TGeoShape* coverShape = new TGeoTubeSeg(coverlr,framehr,backth/2,0,180);
747 TGeoVolume* coverVolume = new TGeoVolume(Form(fgkTopName, fmd2->GetId()),
749 cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
750 cylinderShape->SetTitle("FMD2 cylinder");
751 cylinderVolume->SetTitle("FMD2 cylinder");
752 cylinderVolume->SetTransparency(63);
753 coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
754 coverShape->SetTitle("FMD2 cover");
755 coverVolume->SetTitle("FMD2 cover");
756 coverVolume->SetTransparency(63);
758 for (Int_t i = 0; i < 2; i++) {
759 TGeoVolume* mother = (i == 0 ? fmd2TopVolume : fmd2BotVolume);
761 Double_t phi = 360. / 2 * i;
762 TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i));
764 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD2 cyl trans %d", i),
765 0, 0, framelz+framel/2, rot);
766 mother->AddNode(cylinderVolume, i, matrix);
767 matrix = new TGeoCombiTrans(Form("FMD2 fcov trans %d", i),
768 0, 0, framelz-backth/2, rot);
769 mother->AddNode(coverVolume, 2*i+0, matrix);
770 matrix = new TGeoCombiTrans(Form("FMD2 bcov trans %d", i),
771 0, 0, framelz+framel+backth/2,
773 mother->AddNode(coverVolume, 2*i+1, matrix);
781 TGeoBBox* flange1Shape = new TGeoBBox(f1l/2, f1w/2, f1d/2);
782 TGeoVolume* flange1Volume = new TGeoVolume(Form(fgkFlangeName, fmd2->GetId()),
784 TGeoBBox* flange2Shape = new TGeoBBox(f1w/2, f1d/2, (framel+backth)/2);
785 TGeoVolume* flange2Volume = new TGeoVolume(Form("F%dSG", fmd2->GetId()),
787 flange1Shape->SetName(Form(fgkFlangeName, fmd2->GetId()));
788 flange1Shape->SetTitle("FMD2 vertical flange");
789 flange1Volume->SetTitle("FMD2 vertical flange");
790 flange2Shape->SetName(Form("F%dSG", fmd2->GetId()));
791 flange2Shape->SetTitle("FMD2 horizontal flange");
792 flange2Volume->SetTitle("FMD2 horizontal flange ");
794 flange1Volume->SetTransparency(42);
795 for (Int_t i = 0; i < 4; i++) {
796 TGeoVolume* mother = (i < 2 ? fmd2TopVolume : fmd2BotVolume);
798 Double_t phi = 360. / 4 * i - 45;
799 Double_t rphi = TMath::Pi()*phi/180;
800 Double_t x = (framelr + f1l/2) * TMath::Sin(rphi);
801 Double_t y = (framelr + f1l/2) * TMath::Cos(rphi);
802 TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i));
804 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD2 flange 1 trans %d", i),
805 x,y, framelz-backth-f1d/2, rot);
806 mother->AddNode(flange1Volume, 2*i+0, matrix);
807 matrix = new TGeoCombiTrans(Form("FMD2 flange 2 trans %d", i),
808 x,y,framelz+framel+backth+f1d/2,
810 mother->AddNode(flange1Volume, 2*i+1, matrix);
811 Double_t x1 = x - (f1w-f1d) / 2 * TMath::Cos(rphi);
812 Double_t y1 = y + (f1w-f1d) / 2 * TMath::Sin(rphi);
813 matrix = new TGeoCombiTrans(Form("FMD2 flange 3 trans %d", i),
814 x1,y1,framelz+framel/2, rot);
815 mother->AddNode(flange2Volume, 2*i+0, matrix);
816 Double_t x2 = x + (f1w-f1d) / 2 * TMath::Cos(rphi);
817 Double_t y2 = y - (f1w-f1d) / 2 * TMath::Sin(rphi);
818 matrix = new TGeoCombiTrans(Form("FMD2 flange 4 trans %d", i),
819 x2,y2,framelz+framel/2, rot);
820 mother->AddNode(flange2Volume, 2*i+1, matrix);
823 // Must be done after filling the assemblies
824 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
825 TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
826 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
827 fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
828 top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
829 top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
835 //____________________________________________________________________
837 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3,
838 TGeoVolume* innerTop,
839 TGeoVolume* innerBot,
840 TGeoVolume* outerTop,
841 TGeoVolume* outerBot)
843 // Setup the FMD3 geometry. The FMD2 has a rather elaborate support
844 // structure, as the support will also support the vacuum
847 // See also AliFMDGeometryBuilder::DetectorGeometry
849 if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
850 Double_t nlen = fmd3->GetNoseLength();
851 Double_t nz = fmd3->GetNoseZ();
852 Double_t noser1 = fmd3->GetNoseLowR();
853 Double_t noser2 = fmd3->GetNoseHighR();
854 Double_t conet = fmd3->GetBeamThickness();
855 Double_t conel = fmd3->GetConeLength();
856 Double_t backl = fmd3->GetBackLength();
857 // Double_t backr1 = fmd3->GetBackLowR();
858 Double_t backr2 = fmd3->GetBackHighR();
859 Double_t zdist = conel - backl - nlen;
860 Double_t tdist = backr2 - noser2;
861 // Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist);
862 Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
863 Double_t flanger = fmd3->GetFlangeR();
864 Double_t z = fmd3->GetInnerZ(); // fmd3->GetZ();
866 TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
867 fmd3->GetId(), 'T'));
868 TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
869 fmd3->GetId(), 'B'));
870 fmd3TopVolume->SetTitle("FMD3 top half");
871 fmd3BotVolume->SetTitle("FMD3 bottom half");
874 DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z,
875 innerTop, innerBot, outerTop, outerBot);
878 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
879 support->SetTitle("FMD3 support");
882 TGeoTubeSeg* noseShape = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180);
883 TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
884 support->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, nlen/2));
885 noseShape->SetName(fgkNoseName);
886 noseShape->SetTitle("FMD3 nose");
887 noseVolume->SetTitle("FMD3 nose");
890 TGeoTube* boltShape = new TGeoTube("F3SB", 0, 0.3, conet / 2);
891 TGeoVolume* boltVolume = new TGeoVolume("F3SB", boltShape, fSteel);
893 Double_t x1 = (fmd3->ConeR(nz+z1));
894 TGeoRotation* r1 = new TGeoRotation();
896 TGeoCombiTrans* t = new TGeoCombiTrans("F3SB1",x1,0,-z1,r1);
897 support->AddNode(boltVolume, 1, t);
899 x1 = (fmd3->ConeR(nz+z1));
900 t = new TGeoCombiTrans("F3SB2",x1,0,-z1,r1);
901 support->AddNode(boltVolume, 2, t);
902 boltShape->SetTitle("FMD3 steering bolt");
903 boltVolume->SetTitle("FMD3 steering bolt");
906 TGeoTrd1* plateShape = new TGeoTrd1(2, 8, 0.1, (conel-2-2)/2-.1);
907 TGeoVolume* plateVolume = new TGeoVolume("F3CO", plateShape, fAl);
908 plateShape->SetName("F3C0");
909 plateShape->SetTitle("FMD3 cooling plate");
910 plateVolume->SetTitle("FMD3 cooling plate");
912 // Shape for carbon half-cone
913 TGeoConeSeg* innerCone = new TGeoConeSeg("F3SC_inner", conel/2,
914 noser2-conet, noser2,
915 backr2-conet, backr2, 0., 180.);
916 innerCone->SetTitle("FMD3 cone inner");
917 TGeoTrd1* coneHole = new TGeoTrd1("F3SC_hole",2,8,conet*3,
919 coneHole->SetTitle("FMD3 cone hole");
920 Double_t holeAng = TMath::ATan2(backr2 - noser2, conel);
921 Double_t holeX = ((conel-2) / 2 * TMath::Sin(holeAng) +
922 conet * TMath::Cos(holeAng) +
924 TGeoRotation* holeRot = new TGeoRotation();
925 holeRot->SetName("FMD3 cone hole rotation");
926 holeRot->RotateZ(90);
927 holeRot->RotateY(holeAng*180./TMath::Pi());
928 TGeoCombiTrans* holeTrans = new TGeoCombiTrans(holeX, 0, -2, holeRot);
929 holeRot->SetName("FMD3 cone hole");
931 // Build-up the composite shape for the cone, and add cooling plates
933 TString coneExp("F3SC_inner-(");
934 for (int i = 0; i < 4; i++) {
935 Double_t thisAng = 360. / 8 * (i + .5);
936 TGeoCombiTrans* thisTrans = new TGeoCombiTrans(*holeTrans);
937 thisTrans->RotateZ(thisAng);
938 thisTrans->SetName(Form("F3SC_rot%d", i));
939 thisTrans->RegisterYourself();
940 coneExp.Append(Form("F3SC_hole:F3SC_rot%d+", i));
942 const Double_t* tt = thisTrans->GetTranslation();
943 Double_t x = tt[0]+1*TMath::Cos(thisAng*TMath::Pi()/180);
944 Double_t y = tt[1]+1*TMath::Sin(thisAng*TMath::Pi()/180);
945 TGeoCombiTrans* plateTrans = new TGeoCombiTrans(x,y,tt[2]-1+nlen+conel/2,
946 thisTrans->GetRotation());
947 support->AddNode(plateVolume, i, plateTrans);
950 coneExp.Append("F3SB:F3SB1+F3SB:F3SB2)");
952 // Finalize the half-cone shape and add volume
953 TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneExp.Data());
954 TGeoVolume* coneVolume = new TGeoVolume("F3SC", coneShape, fC);
955 coneShape->SetName("F3SC");
956 coneShape->SetTitle("FMD3 cone");
957 coneVolume->SetTitle("FMD3 cone");
958 support->AddNode(coneVolume,1,new TGeoTranslation(0,0,nlen+conel/2));
961 TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2,
962 fmd3->GetBeamWidth() / 2,
964 TGeoVolume* flangeVolume = new TGeoVolume(Form(fgkFlangeName, fmd3->GetId()),
966 flangeShape->SetName(Form(fgkFlangeName, fmd3->GetId()));
967 flangeShape->SetTitle("FMD3 flange");
968 flangeVolume->SetTitle("FMD3 flange");
970 Int_t n = fmd3->GetNFlange();
971 Double_t r = backr2 + (flanger - backr2) / 2;
972 for (Int_t i = 0; i < n/2; i++) {
973 Double_t phi = 360. / n * i + 180. / n;
974 Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi);
975 Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi);
976 TGeoRotation* rot = new TGeoRotation;
978 TGeoMatrix* matrix = new TGeoCombiTrans(x, y, nlen+conel-backl/2, rot);
979 matrix->SetName(Form("FMD3_flange_%02d", i));
980 matrix->SetTitle(Form("FMD3_flange_%2d", i));
981 support->AddNode(flangeVolume, i, matrix);
984 // Place support volumes in half-detector volumes
985 z = fmd3->GetInnerZ();
987 fmd3TopVolume->AddNode(support, 1, new TGeoTranslation(0,0,z1));
988 r1 = new TGeoRotation();
990 t = new TGeoCombiTrans(0,0,z1,r1);
991 fmd3BotVolume->AddNode(support, 2, t);
993 TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
995 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
996 TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
997 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
998 fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
999 top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1000 top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1005 //____________________________________________________________________
1007 AliFMDGeometryBuilder::Exec(Option_t*)
1009 // Setup up the FMD geometry.
1010 AliFMDDebug(1, ("\tGeometry options: %s",
1011 (fDetailed ? "divided into strips" : "one volume")));
1013 AliFatal("No TGeoManager defined");
1017 fSi = gGeoManager->GetMedium("FMD_Si$");
1018 fC = gGeoManager->GetMedium("FMD_Carbon$");
1019 fAl = gGeoManager->GetMedium("FMD_Aluminum$");
1020 fChip = gGeoManager->GetMedium("FMD_Si Chip$");
1021 fAir = gGeoManager->GetMedium("FMD_Air$");
1022 fPCB = gGeoManager->GetMedium("FMD_PCB$");
1023 fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1024 fCopper = gGeoManager->GetMedium("FMD_Copper$");
1025 fSteel = gGeoManager->GetMedium("FMD_Steel$");
1027 if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1028 AliError("Failed to get some or all tracking mediums");
1031 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1032 AliFMDRing* inner = fmd->GetInner();
1033 AliFMDRing* outer = fmd->GetOuter();
1034 RingGeometry(inner);
1035 RingGeometry(outer);
1036 TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1038 TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1040 TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1042 TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1045 FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1046 FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1047 FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1048 #ifndef USE_PRE_MOVE
1049 fmd->SetSectorOff(fSectorOff);
1050 fmd->SetModuleOff(fModuleOff);
1051 fmd->SetRingOff(fRingOff);
1052 fmd->SetDetectorOff(fDetectorOff);
1053 fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1055 // fmd->ExtractGeomInfo();
1060 //____________________________________________________________________